Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/e1000/if_em.c
Show First 20 Lines • Show All 768 Lines • ▼ Show 20 Lines | |||||
* and initializes the hardware. | * and initializes the hardware. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
*********************************************************************/ | *********************************************************************/ | ||||
static int | static int | ||||
em_if_attach_pre(if_ctx_t ctx) | em_if_attach_pre(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter; | struct adapter *adapter; | ||||
struct e1000_hw *hw; | |||||
if_softc_ctx_t scctx; | if_softc_ctx_t scctx; | ||||
device_t dev; | device_t dev; | ||||
struct e1000_hw *hw; | |||||
int error = 0; | int error = 0; | ||||
INIT_DEBUGOUT("em_if_attach_pre: begin"); | INIT_DEBUGOUT("em_if_attach_pre: begin"); | ||||
dev = iflib_get_dev(ctx); | dev = iflib_get_dev(ctx); | ||||
adapter = iflib_get_softc(ctx); | adapter = iflib_get_softc(ctx); | ||||
adapter->ctx = adapter->osdep.ctx = ctx; | adapter->ctx = adapter->osdep.ctx = ctx; | ||||
adapter->dev = adapter->osdep.dev = dev; | adapter->dev = adapter->osdep.dev = dev; | ||||
Show All 35 Lines | em_if_attach_pre(if_ctx_t ctx) | ||||
em_identify_hardware(ctx); | em_identify_hardware(ctx); | ||||
scctx->isc_tx_nsegments = EM_MAX_SCATTER; | scctx->isc_tx_nsegments = EM_MAX_SCATTER; | ||||
scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx); | scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, "attach_pre capping queues at %d\n", | device_printf(dev, "attach_pre capping queues at %d\n", | ||||
scctx->isc_ntxqsets_max); | scctx->isc_ntxqsets_max); | ||||
if (hw.mac.type >= igb_mac_min) { | if (hw->mac.type >= igb_mac_min) { | ||||
scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * sizeof(union e1000_adv_tx_desc), EM_DBA_ALIGN); | scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * sizeof(union e1000_adv_tx_desc), EM_DBA_ALIGN); | ||||
scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_adv_rx_desc), EM_DBA_ALIGN); | scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_adv_rx_desc), EM_DBA_ALIGN); | ||||
scctx->isc_txd_size[0] = sizeof(union e1000_adv_tx_desc); | scctx->isc_txd_size[0] = sizeof(union e1000_adv_tx_desc); | ||||
scctx->isc_rxd_size[0] = sizeof(union e1000_adv_rx_desc); | scctx->isc_rxd_size[0] = sizeof(union e1000_adv_rx_desc); | ||||
scctx->isc_txrx = &igb_txrx; | scctx->isc_txrx = &igb_txrx; | ||||
scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER; | scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER; | ||||
scctx->isc_tx_tso_size_max = EM_TSO_SIZE; | scctx->isc_tx_tso_size_max = EM_TSO_SIZE; | ||||
scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; | scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; | ||||
scctx->isc_capabilities = scctx->isc_capenable = IGB_CAPS; | scctx->isc_capabilities = scctx->isc_capenable = IGB_CAPS; | ||||
scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO | | scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO | | ||||
CSUM_IP6_TCP | CSUM_IP6_UDP; | CSUM_IP6_TCP | CSUM_IP6_UDP; | ||||
if (hw.mac.type != e1000_82575) | if (hw->mac.type != e1000_82575) | ||||
scctx->isc_tx_csum_flags |= CSUM_SCTP | CSUM_IP6_SCTP; | scctx->isc_tx_csum_flags |= CSUM_SCTP | CSUM_IP6_SCTP; | ||||
/* | /* | ||||
** Some new devices, as with ixgbe, now may | ** Some new devices, as with ixgbe, now may | ||||
** use a different BAR, so we need to keep | ** use a different BAR, so we need to keep | ||||
** track of which is used. | ** track of which is used. | ||||
*/ | */ | ||||
scctx->isc_msix_bar = pci_msix_table_bar(dev); | scctx->isc_msix_bar = pci_msix_table_bar(dev); | ||||
} else if (hw.mac.type >= em_mac_min) { | } else if (hw->mac.type >= em_mac_min) { | ||||
scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]* sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); | scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]* sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); | ||||
scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_rx_desc_extended), EM_DBA_ALIGN); | scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_rx_desc_extended), EM_DBA_ALIGN); | ||||
scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc); | scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc); | ||||
scctx->isc_rxd_size[0] = sizeof(union e1000_rx_desc_extended); | scctx->isc_rxd_size[0] = sizeof(union e1000_rx_desc_extended); | ||||
scctx->isc_txrx = &em_txrx; | scctx->isc_txrx = &em_txrx; | ||||
scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER; | scctx->isc_tx_tso_segments_max = EM_MAX_SCATTER; | ||||
scctx->isc_tx_tso_size_max = EM_TSO_SIZE; | scctx->isc_tx_tso_size_max = EM_TSO_SIZE; | ||||
scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; | scctx->isc_tx_tso_segsize_max = EM_TSO_SEG_SIZE; | ||||
Show All 15 Lines | if (hw->mac.type >= igb_mac_min) { | ||||
* with Gigabit - in which case users may enable TSO manually. | * with Gigabit - in which case users may enable TSO manually. | ||||
*/ | */ | ||||
scctx->isc_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO); | scctx->isc_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO); | ||||
scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; | scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; | ||||
/* | /* | ||||
* We support MSI-X with 82574 only, but indicate to iflib(4) | * We support MSI-X with 82574 only, but indicate to iflib(4) | ||||
* that it shall give MSI at least a try with other devices. | * that it shall give MSI at least a try with other devices. | ||||
*/ | */ | ||||
if (hw.mac.type == e1000_82574) { | if (hw->mac.type == e1000_82574) { | ||||
scctx->isc_msix_bar = pci_msix_table_bar(dev);; | scctx->isc_msix_bar = pci_msix_table_bar(dev);; | ||||
} else { | } else { | ||||
scctx->isc_msix_bar = -1; | scctx->isc_msix_bar = -1; | ||||
scctx->isc_disable_msix = 1; | scctx->isc_disable_msix = 1; | ||||
} | } | ||||
} else { | } else { | ||||
scctx->isc_txqsizes[0] = roundup2((scctx->isc_ntxd[0] + 1) * sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); | scctx->isc_txqsizes[0] = roundup2((scctx->isc_ntxd[0] + 1) * sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); | ||||
scctx->isc_rxqsizes[0] = roundup2((scctx->isc_nrxd[0] + 1) * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN); | scctx->isc_rxqsizes[0] = roundup2((scctx->isc_nrxd[0] + 1) * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN); | ||||
scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc); | scctx->isc_txd_size[0] = sizeof(struct e1000_tx_desc); | ||||
scctx->isc_rxd_size[0] = sizeof(struct e1000_rx_desc); | scctx->isc_rxd_size[0] = sizeof(struct e1000_rx_desc); | ||||
scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP; | scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP; | ||||
scctx->isc_txrx = &lem_txrx; | scctx->isc_txrx = &lem_txrx; | ||||
scctx->isc_capabilities = scctx->isc_capenable = LEM_CAPS; | scctx->isc_capabilities = scctx->isc_capenable = LEM_CAPS; | ||||
if (hw.mac.type < e1000_82543) | if (hw->mac.type < e1000_82543) | ||||
scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM); | scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM); | ||||
/* INTx only */ | /* INTx only */ | ||||
scctx->isc_msix_bar = 0; | scctx->isc_msix_bar = 0; | ||||
} | } | ||||
/* Setup PCI resources */ | /* Setup PCI resources */ | ||||
if (em_allocate_pci_resources(ctx)) { | if (em_allocate_pci_resources(ctx)) { | ||||
device_printf(dev, "Allocation of PCI resources failed\n"); | device_printf(dev, "Allocation of PCI resources failed\n"); | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | em_add_int_delay_sysctl(adapter, "itr", | ||||
&adapter->tx_itr, | &adapter->tx_itr, | ||||
E1000_REGISTER(hw, E1000_ITR), | E1000_REGISTER(hw, E1000_ITR), | ||||
DEFAULT_ITR); | DEFAULT_ITR); | ||||
hw->mac.autoneg = DO_AUTO_NEG; | hw->mac.autoneg = DO_AUTO_NEG; | ||||
hw->phy.autoneg_wait_to_complete = FALSE; | hw->phy.autoneg_wait_to_complete = FALSE; | ||||
hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; | hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; | ||||
if (hw.mac.type < em_mac_min) { | if (hw->mac.type < em_mac_min) { | ||||
e1000_init_script_state_82541(hw, TRUE); | e1000_init_script_state_82541(hw, TRUE); | ||||
e1000_set_tbi_compatibility_82543(hw, TRUE); | e1000_set_tbi_compatibility_82543(hw, TRUE); | ||||
} | } | ||||
/* Copper options */ | /* Copper options */ | ||||
if (hw->phy.media_type == e1000_media_type_copper) { | if (hw->phy.media_type == e1000_media_type_copper) { | ||||
hw->phy.mdix = AUTO_ALL_MODES; | hw->phy.mdix = AUTO_ALL_MODES; | ||||
hw->phy.disable_polarity_correction = FALSE; | hw->phy.disable_polarity_correction = FALSE; | ||||
hw->phy.ms_type = EM_MASTER_SLAVE; | hw->phy.ms_type = EM_MASTER_SLAVE; | ||||
} | } | ||||
/* | /* | ||||
* Set the frame limits assuming | * Set the frame limits assuming | ||||
* standard ethernet sized frames. | * standard ethernet sized frames. | ||||
*/ | */ | ||||
scctx->isc_max_frame_size = hw.mac.max_frame_size = | scctx->isc_max_frame_size = hw->mac.max_frame_size = | ||||
ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; | ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; | ||||
/* | /* | ||||
* This controls when hardware reports transmit completion | * This controls when hardware reports transmit completion | ||||
* status. | * status. | ||||
*/ | */ | ||||
hw->mac.report_tx_early = 1; | hw->mac.report_tx_early = 1; | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | em_if_resume(if_ctx_t ctx) | ||||
return(0); | return(0); | ||||
} | } | ||||
static int | static int | ||||
em_if_mtu_set(if_ctx_t ctx, uint32_t mtu) | em_if_mtu_set(if_ctx_t ctx, uint32_t mtu) | ||||
{ | { | ||||
int max_frame_size; | int max_frame_size; | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
if_softc_ctx_t scctx = iflib_get_softc_ctx(ctx); | if_softc_ctx_t scctx = iflib_get_softc_ctx(ctx); | ||||
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); | IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); | ||||
switch (adapter->hw.mac.type) { | switch (hw->mac.type) { | ||||
case e1000_82571: | case e1000_82571: | ||||
case e1000_82572: | case e1000_82572: | ||||
case e1000_ich9lan: | case e1000_ich9lan: | ||||
case e1000_ich10lan: | case e1000_ich10lan: | ||||
case e1000_pch2lan: | case e1000_pch2lan: | ||||
case e1000_pch_lpt: | case e1000_pch_lpt: | ||||
case e1000_pch_spt: | case e1000_pch_spt: | ||||
case e1000_pch_cnp: | case e1000_pch_cnp: | ||||
case e1000_82574: | case e1000_82574: | ||||
case e1000_82583: | case e1000_82583: | ||||
case e1000_80003es2lan: | case e1000_80003es2lan: | ||||
/* 9K Jumbo Frame size */ | /* 9K Jumbo Frame size */ | ||||
max_frame_size = 9234; | max_frame_size = 9234; | ||||
break; | break; | ||||
case e1000_pchlan: | case e1000_pchlan: | ||||
max_frame_size = 4096; | max_frame_size = 4096; | ||||
break; | break; | ||||
case e1000_82542: | case e1000_82542: | ||||
case e1000_ich8lan: | case e1000_ich8lan: | ||||
/* Adapters that do not support jumbo frames */ | /* Adapters that do not support jumbo frames */ | ||||
max_frame_size = ETHER_MAX_LEN; | max_frame_size = ETHER_MAX_LEN; | ||||
break; | break; | ||||
default: | default: | ||||
if (adapter->hw.mac.type >= igb_mac_min) | if (hw->mac.type >= igb_mac_min) | ||||
max_frame_size = 9234; | max_frame_size = 9234; | ||||
else /* lem */ | else /* lem */ | ||||
max_frame_size = MAX_JUMBO_FRAME_SIZE; | max_frame_size = MAX_JUMBO_FRAME_SIZE; | ||||
} | } | ||||
if (mtu > max_frame_size - ETHER_HDR_LEN - ETHER_CRC_LEN) { | if (mtu > max_frame_size - ETHER_HDR_LEN - ETHER_CRC_LEN) { | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
scctx->isc_max_frame_size = adapter->hw.mac.max_frame_size = | scctx->isc_max_frame_size = hw->mac.max_frame_size = | ||||
mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; | mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; | ||||
return (0); | return (0); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* Init entry point | * Init entry point | ||||
* | * | ||||
* This routine is used in two ways. It is used by the stack as | * This routine is used in two ways. It is used by the stack as | ||||
* init entry point in network interface structure. It is also used | * init entry point in network interface structure. It is also used | ||||
* by the driver as a hw/sw initialization routine to get to a | * by the driver as a hw/sw initialization routine to get to a | ||||
* consistent state. | * consistent state. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_if_init(if_ctx_t ctx) | em_if_init(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = adapter->shared; | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct em_tx_queue *tx_que; | struct em_tx_queue *tx_que; | ||||
int i; | int i; | ||||
INIT_DEBUGOUT("em_if_init: begin"); | INIT_DEBUGOUT("em_if_init: begin"); | ||||
/* Get the latest mac address, User can use a LAA */ | /* Get the latest mac address, User can use a LAA */ | ||||
bcopy(if_getlladdr(ifp), adapter->hw.mac.addr, | bcopy(if_getlladdr(ifp), hw->mac.addr, | ||||
ETHER_ADDR_LEN); | ETHER_ADDR_LEN); | ||||
/* Put the address into the Receive Address Array */ | /* Put the address into the Receive Address Array */ | ||||
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); | e1000_rar_set(hw, hw->mac.addr, 0); | ||||
/* | /* | ||||
* With the 82571 adapter, RAR[0] may be overwritten | * With the 82571 adapter, RAR[0] may be overwritten | ||||
* when the other port is reset, we make a duplicate | * when the other port is reset, we make a duplicate | ||||
* in RAR[14] for that eventuality, this assures | * in RAR[14] for that eventuality, this assures | ||||
* the interface continues to function. | * the interface continues to function. | ||||
*/ | */ | ||||
if (adapter->hw.mac.type == e1000_82571) { | if (hw->mac.type == e1000_82571) { | ||||
e1000_set_laa_state_82571(&adapter->hw, TRUE); | e1000_set_laa_state_82571(hw, TRUE); | ||||
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, | e1000_rar_set(hw, hw->mac.addr, | ||||
E1000_RAR_ENTRIES - 1); | E1000_RAR_ENTRIES - 1); | ||||
} | } | ||||
/* Initialize the hardware */ | /* Initialize the hardware */ | ||||
em_reset(ctx); | em_reset(ctx); | ||||
em_if_update_admin_status(ctx); | em_if_update_admin_status(ctx); | ||||
for (i = 0, tx_que = adapter->tx_queues; i < adapter->tx_num_queues; i++, tx_que++) { | for (i = 0, tx_que = adapter->tx_queues; i < adapter->tx_num_queues; i++, tx_que++) { | ||||
struct tx_ring *txr = &tx_que->txr; | struct tx_ring *txr = &tx_que->txr; | ||||
txr->tx_rs_cidx = txr->tx_rs_pidx; | txr->tx_rs_cidx = txr->tx_rs_pidx; | ||||
/* Initialize the last processed descriptor to be the end of | /* Initialize the last processed descriptor to be the end of | ||||
* the ring, rather than the start, so that we avoid an | * the ring, rather than the start, so that we avoid an | ||||
* off-by-one error when calculating how many descriptors are | * off-by-one error when calculating how many descriptors are | ||||
* done in the credits_update function. | * done in the credits_update function. | ||||
*/ | */ | ||||
txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1; | txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1; | ||||
} | } | ||||
/* Setup VLAN support, basic and offload if available */ | /* Setup VLAN support, basic and offload if available */ | ||||
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); | E1000_WRITE_REG(hw, E1000_VET, ETHERTYPE_VLAN); | ||||
/* Clear bad data from Rx FIFOs */ | /* Clear bad data from Rx FIFOs */ | ||||
if (adapter->hw.mac.type >= igb_mac_min) | if (hw->mac.type >= igb_mac_min) | ||||
e1000_rx_fifo_flush_82575(&adapter->hw); | e1000_rx_fifo_flush_82575(hw); | ||||
/* Configure for OS presence */ | /* Configure for OS presence */ | ||||
em_init_manageability(adapter); | em_init_manageability(adapter); | ||||
/* Prepare transmit descriptors and buffers */ | /* Prepare transmit descriptors and buffers */ | ||||
em_initialize_transmit_unit(ctx); | em_initialize_transmit_unit(ctx); | ||||
/* Setup Multicast table */ | /* Setup Multicast table */ | ||||
em_if_multi_set(ctx); | em_if_multi_set(ctx); | ||||
adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); | adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); | ||||
em_initialize_receive_unit(ctx); | em_initialize_receive_unit(ctx); | ||||
/* Use real VLAN Filter support? */ | /* Use real VLAN Filter support? */ | ||||
if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) { | if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) { | ||||
if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) | if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) | ||||
/* Use real VLAN Filter support */ | /* Use real VLAN Filter support */ | ||||
em_setup_vlan_hw_support(adapter); | em_setup_vlan_hw_support(adapter); | ||||
else { | else { | ||||
u32 ctrl; | u32 ctrl; | ||||
ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); | ctrl = E1000_READ_REG(hw, E1000_CTRL); | ||||
ctrl |= E1000_CTRL_VME; | ctrl |= E1000_CTRL_VME; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); | E1000_WRITE_REG(hw, E1000_CTRL, ctrl); | ||||
} | } | ||||
} else { | } else { | ||||
u32 ctrl; | u32 ctrl; | ||||
ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); | ctrl = E1000_READ_REG(hw, E1000_CTRL); | ||||
ctrl &= ~E1000_CTRL_VME; | ctrl &= ~E1000_CTRL_VME; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); | E1000_WRITE_REG(hw, E1000_CTRL, ctrl); | ||||
} | } | ||||
/* Don't lose promiscuous settings */ | /* Don't lose promiscuous settings */ | ||||
em_if_set_promisc(ctx, if_getflags(ifp)); | em_if_set_promisc(ctx, if_getflags(ifp)); | ||||
e1000_clear_hw_cntrs_base_generic(&adapter->hw); | e1000_clear_hw_cntrs_base_generic(hw); | ||||
/* MSI-X configuration for 82574 */ | /* MSI-X configuration for 82574 */ | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (hw->mac.type == e1000_82574) { | ||||
int tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); | int tmp = E1000_READ_REG(hw, E1000_CTRL_EXT); | ||||
tmp |= E1000_CTRL_EXT_PBA_CLR; | tmp |= E1000_CTRL_EXT_PBA_CLR; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, tmp); | E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp); | ||||
/* Set the IVAR - interrupt vector routing. */ | /* Set the IVAR - interrupt vector routing. */ | ||||
E1000_WRITE_REG(&adapter->hw, E1000_IVAR, adapter->ivars); | E1000_WRITE_REG(hw, E1000_IVAR, adapter->ivars); | ||||
} else if (adapter->intr_type == IFLIB_INTR_MSIX) /* Set up queue routing */ | } else if (adapter->intr_type == IFLIB_INTR_MSIX) /* Set up queue routing */ | ||||
igb_configure_queues(adapter); | igb_configure_queues(adapter); | ||||
/* this clears any pending interrupts */ | /* this clears any pending interrupts */ | ||||
E1000_READ_REG(&adapter->hw, E1000_ICR); | E1000_READ_REG(hw, E1000_ICR); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC); | E1000_WRITE_REG(hw, E1000_ICS, E1000_ICS_LSC); | ||||
/* AMT based hardware can now take control from firmware */ | /* AMT based hardware can now take control from firmware */ | ||||
if (adapter->has_manage && adapter->has_amt) | if (adapter->has_manage && adapter->has_amt) | ||||
em_get_hw_control(adapter); | em_get_hw_control(adapter); | ||||
/* Set Energy Efficient Ethernet */ | /* Set Energy Efficient Ethernet */ | ||||
if (adapter->hw.mac.type >= igb_mac_min && | if (hw->mac.type >= igb_mac_min && | ||||
adapter->hw.phy.media_type == e1000_media_type_copper) { | hw->phy.media_type == e1000_media_type_copper) { | ||||
if (adapter->hw.mac.type == e1000_i354) | if (hw->mac.type == e1000_i354) | ||||
e1000_set_eee_i354(&adapter->hw, TRUE, TRUE); | e1000_set_eee_i354(hw, TRUE, TRUE); | ||||
else | else | ||||
e1000_set_eee_i350(&adapter->hw, TRUE, TRUE); | e1000_set_eee_i350(hw, TRUE, TRUE); | ||||
} | } | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Fast Legacy/MSI Combined Interrupt Service routine | * Fast Legacy/MSI Combined Interrupt Service routine | ||||
* | * | ||||
*********************************************************************/ | *********************************************************************/ | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* MSI-X Link Fast Interrupt Service routine | * MSI-X Link Fast Interrupt Service routine | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static int | static int | ||||
em_msix_link(void *arg) | em_msix_link(void *arg) | ||||
{ | { | ||||
struct adapter *adapter = arg; | struct adapter *adapter = arg; | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u32 reg_icr; | u32 reg_icr; | ||||
++adapter->link_irq; | ++adapter->link_irq; | ||||
MPASS(adapter->hw.back != NULL); | MPASS(hw->back != NULL); | ||||
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); | reg_icr = E1000_READ_REG(hw, E1000_ICR); | ||||
if (reg_icr & E1000_ICR_RXO) | if (reg_icr & E1000_ICR_RXO) | ||||
adapter->rx_overruns++; | adapter->rx_overruns++; | ||||
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { | if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { | ||||
em_handle_link(adapter->ctx); | em_handle_link(adapter->ctx); | ||||
} else if (adapter->hw.mac.type == e1000_82574) { | } else if (hw->mac.type == e1000_82574) { | ||||
/* Only re-arm 82574 if em_if_update_admin_status() won't. */ | /* Only re-arm 82574 if em_if_update_admin_status() won't. */ | ||||
E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | | E1000_WRITE_REG(hw, E1000_IMS, EM_MSIX_LINK | | ||||
E1000_IMS_LSC); | E1000_IMS_LSC); | ||||
} | } | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (hw->mac.type == e1000_82574) { | ||||
/* | /* | ||||
* Because we must read the ICR for this interrupt it may | * Because we must read the ICR for this interrupt it may | ||||
* clear other causes using autoclear, for this reason we | * clear other causes using autoclear, for this reason we | ||||
* simply create a soft interrupt for all these vectors. | * simply create a soft interrupt for all these vectors. | ||||
*/ | */ | ||||
if (reg_icr) | if (reg_icr) | ||||
E1000_WRITE_REG(&adapter->hw, E1000_ICS, adapter->ims); | E1000_WRITE_REG(hw, E1000_ICS, adapter->ims); | ||||
} else { | } else { | ||||
/* Re-arm unconditionally */ | /* Re-arm unconditionally */ | ||||
E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); | E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask); | E1000_WRITE_REG(hw, E1000_EIMS, adapter->link_mask); | ||||
} | } | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} | } | ||||
static void | static void | ||||
em_handle_link(void *context) | em_handle_link(void *context) | ||||
{ | { | ||||
Show All 11 Lines | |||||
* This routine is called whenever the user queries the status of | * This routine is called whenever the user queries the status of | ||||
* the interface using ifconfig. | * the interface using ifconfig. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) | em_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u_char fiber_type = IFM_1000_SX; | u_char fiber_type = IFM_1000_SX; | ||||
INIT_DEBUGOUT("em_if_media_status: begin"); | INIT_DEBUGOUT("em_if_media_status: begin"); | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
ifmr->ifm_status = IFM_AVALID; | ifmr->ifm_status = IFM_AVALID; | ||||
ifmr->ifm_active = IFM_ETHER; | ifmr->ifm_active = IFM_ETHER; | ||||
if (!adapter->link_active) { | if (!adapter->link_active) { | ||||
return; | return; | ||||
} | } | ||||
ifmr->ifm_status |= IFM_ACTIVE; | ifmr->ifm_status |= IFM_ACTIVE; | ||||
if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || | if ((hw->phy.media_type == e1000_media_type_fiber) || | ||||
(adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { | (hw->phy.media_type == e1000_media_type_internal_serdes)) { | ||||
if (adapter->hw.mac.type == e1000_82545) | if (hw->mac.type == e1000_82545) | ||||
fiber_type = IFM_1000_LX; | fiber_type = IFM_1000_LX; | ||||
ifmr->ifm_active |= fiber_type | IFM_FDX; | ifmr->ifm_active |= fiber_type | IFM_FDX; | ||||
} else { | } else { | ||||
switch (adapter->link_speed) { | switch (adapter->link_speed) { | ||||
case 10: | case 10: | ||||
ifmr->ifm_active |= IFM_10_T; | ifmr->ifm_active |= IFM_10_T; | ||||
break; | break; | ||||
case 100: | case 100: | ||||
Show All 17 Lines | |||||
* This routine is called when the user changes speed/duplex using | * This routine is called when the user changes speed/duplex using | ||||
* media/mediopt option with ifconfig. | * media/mediopt option with ifconfig. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static int | static int | ||||
em_if_media_change(if_ctx_t ctx) | em_if_media_change(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
struct ifmedia *ifm = iflib_get_media(ctx); | struct ifmedia *ifm = iflib_get_media(ctx); | ||||
INIT_DEBUGOUT("em_if_media_change: begin"); | INIT_DEBUGOUT("em_if_media_change: begin"); | ||||
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) | if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) | ||||
return (EINVAL); | return (EINVAL); | ||||
switch (IFM_SUBTYPE(ifm->ifm_media)) { | switch (IFM_SUBTYPE(ifm->ifm_media)) { | ||||
case IFM_AUTO: | case IFM_AUTO: | ||||
adapter->hw.mac.autoneg = DO_AUTO_NEG; | hw->mac.autoneg = DO_AUTO_NEG; | ||||
adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; | hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; | ||||
break; | break; | ||||
case IFM_1000_LX: | case IFM_1000_LX: | ||||
case IFM_1000_SX: | case IFM_1000_SX: | ||||
case IFM_1000_T: | case IFM_1000_T: | ||||
adapter->hw.mac.autoneg = DO_AUTO_NEG; | hw->mac.autoneg = DO_AUTO_NEG; | ||||
adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; | hw->phy.autoneg_advertised = ADVERTISE_1000_FULL; | ||||
break; | break; | ||||
case IFM_100_TX: | case IFM_100_TX: | ||||
adapter->hw.mac.autoneg = FALSE; | hw->mac.autoneg = FALSE; | ||||
adapter->hw.phy.autoneg_advertised = 0; | hw->phy.autoneg_advertised = 0; | ||||
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) | if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) | ||||
adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL; | hw->mac.forced_speed_duplex = ADVERTISE_100_FULL; | ||||
else | else | ||||
adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF; | hw->mac.forced_speed_duplex = ADVERTISE_100_HALF; | ||||
break; | break; | ||||
case IFM_10_T: | case IFM_10_T: | ||||
adapter->hw.mac.autoneg = FALSE; | hw->mac.autoneg = FALSE; | ||||
adapter->hw.phy.autoneg_advertised = 0; | hw->phy.autoneg_advertised = 0; | ||||
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) | if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) | ||||
adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL; | hw->mac.forced_speed_duplex = ADVERTISE_10_FULL; | ||||
else | else | ||||
adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF; | hw->mac.forced_speed_duplex = ADVERTISE_10_HALF; | ||||
break; | break; | ||||
default: | default: | ||||
device_printf(adapter->dev, "Unsupported media type\n"); | device_printf(adapter->dev, "Unsupported media type\n"); | ||||
} | } | ||||
em_if_init(ctx); | em_if_init(ctx); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
em_if_set_promisc(if_ctx_t ctx, int flags) | em_if_set_promisc(if_ctx_t ctx, int flags) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u32 reg_rctl; | u32 reg_rctl; | ||||
em_disable_promisc(ctx); | em_disable_promisc(ctx); | ||||
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); | reg_rctl = E1000_READ_REG(hw, E1000_RCTL); | ||||
if (flags & IFF_PROMISC) { | if (flags & IFF_PROMISC) { | ||||
reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); | reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); | ||||
/* Turn this on if you want to see bad packets */ | /* Turn this on if you want to see bad packets */ | ||||
if (em_debug_sbp) | if (em_debug_sbp) | ||||
reg_rctl |= E1000_RCTL_SBP; | reg_rctl |= E1000_RCTL_SBP; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | E1000_WRITE_REG(hw, E1000_RCTL, reg_rctl); | ||||
} else if (flags & IFF_ALLMULTI) { | } else if (flags & IFF_ALLMULTI) { | ||||
reg_rctl |= E1000_RCTL_MPE; | reg_rctl |= E1000_RCTL_MPE; | ||||
reg_rctl &= ~E1000_RCTL_UPE; | reg_rctl &= ~E1000_RCTL_UPE; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | E1000_WRITE_REG(hw, E1000_RCTL, reg_rctl); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
em_disable_promisc(if_ctx_t ctx) | em_disable_promisc(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
Show All 34 Lines | |||||
* This routine is called whenever multicast address list is updated. | * This routine is called whenever multicast address list is updated. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_if_multi_set(if_ctx_t ctx) | em_if_multi_set(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
u32 reg_rctl = 0; | u32 reg_rctl = 0; | ||||
u8 *mta; /* Multicast array memory */ | u8 *mta; /* Multicast array memory */ | ||||
int mcnt = 0; | int mcnt = 0; | ||||
IOCTL_DEBUGOUT("em_set_multi: begin"); | IOCTL_DEBUGOUT("em_set_multi: begin"); | ||||
mta = adapter->mta; | mta = adapter->mta; | ||||
bzero(mta, sizeof(u8) * ETHER_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); | bzero(mta, sizeof(u8) * ETHER_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); | ||||
if (adapter->hw.mac.type == e1000_82542 && | if (hw->mac.type == e1000_82542 && | ||||
adapter->hw.revision_id == E1000_REVISION_2) { | hw->revision_id == E1000_REVISION_2) { | ||||
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); | reg_rctl = E1000_READ_REG(hw, E1000_RCTL); | ||||
if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) | if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) | ||||
e1000_pci_clear_mwi(&adapter->hw); | e1000_pci_clear_mwi(hw); | ||||
reg_rctl |= E1000_RCTL_RST; | reg_rctl |= E1000_RCTL_RST; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | E1000_WRITE_REG(hw, E1000_RCTL, reg_rctl); | ||||
msec_delay(5); | msec_delay(5); | ||||
} | } | ||||
mcnt = if_foreach_llmaddr(ifp, em_copy_maddr, mta); | mcnt = if_foreach_llmaddr(ifp, em_copy_maddr, mta); | ||||
if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { | if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { | ||||
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); | reg_rctl = E1000_READ_REG(hw, E1000_RCTL); | ||||
reg_rctl |= E1000_RCTL_MPE; | reg_rctl |= E1000_RCTL_MPE; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | E1000_WRITE_REG(hw, E1000_RCTL, reg_rctl); | ||||
} else | } else | ||||
e1000_update_mc_addr_list(&adapter->hw, mta, mcnt); | e1000_update_mc_addr_list(hw, mta, mcnt); | ||||
if (adapter->hw.mac.type == e1000_82542 && | if (hw->mac.type == e1000_82542 && | ||||
adapter->hw.revision_id == E1000_REVISION_2) { | hw->revision_id == E1000_REVISION_2) { | ||||
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); | reg_rctl = E1000_READ_REG(hw, E1000_RCTL); | ||||
reg_rctl &= ~E1000_RCTL_RST; | reg_rctl &= ~E1000_RCTL_RST; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | E1000_WRITE_REG(hw, E1000_RCTL, reg_rctl); | ||||
msec_delay(5); | msec_delay(5); | ||||
if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) | if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) | ||||
e1000_pci_set_mwi(&adapter->hw); | e1000_pci_set_mwi(hw); | ||||
} | } | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* Timer routine | * Timer routine | ||||
* | * | ||||
* This routine schedules em_if_update_admin_status() to check for | * This routine schedules em_if_update_admin_status() to check for | ||||
* link status and to gather statistics as well as to perform some | * link status and to gather statistics as well as to perform some | ||||
Show All 36 Lines | case e1000_media_type_copper: | ||||
break; | break; | ||||
case e1000_media_type_fiber: | case e1000_media_type_fiber: | ||||
e1000_check_for_link(hw); | e1000_check_for_link(hw); | ||||
link_check = (E1000_READ_REG(hw, E1000_STATUS) & | link_check = (E1000_READ_REG(hw, E1000_STATUS) & | ||||
E1000_STATUS_LU); | E1000_STATUS_LU); | ||||
break; | break; | ||||
case e1000_media_type_internal_serdes: | case e1000_media_type_internal_serdes: | ||||
e1000_check_for_link(hw); | e1000_check_for_link(hw); | ||||
link_check = hw.mac.serdes_has_link; | link_check = hw->mac.serdes_has_link; | ||||
break; | break; | ||||
/* VF device is type_unknown */ | /* VF device is type_unknown */ | ||||
case e1000_media_type_unknown: | case e1000_media_type_unknown: | ||||
e1000_check_for_link(hw); | e1000_check_for_link(hw); | ||||
link_check = !hw->mac.get_link_status; | link_check = !hw->mac.get_link_status; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
default: | default: | ||||
break; | break; | ||||
Show All 31 Lines | if ((ctrl & E1000_CTRL_EXT_LINK_MODE_MASK) == | ||||
device_printf(dev, "Link: thermal downshift\n"); | device_printf(dev, "Link: thermal downshift\n"); | ||||
/* Delay Link Up for Phy update */ | /* Delay Link Up for Phy update */ | ||||
if (((hw->mac.type == e1000_i210) || | if (((hw->mac.type == e1000_i210) || | ||||
(hw->mac.type == e1000_i211)) && | (hw->mac.type == e1000_i211)) && | ||||
(hw->phy.id == I210_I_PHY_ID)) | (hw->phy.id == I210_I_PHY_ID)) | ||||
msec_delay(I210_LINK_DELAY); | msec_delay(I210_LINK_DELAY); | ||||
/* Reset if the media type changed. */ | /* Reset if the media type changed. */ | ||||
if (hw->dev_spec._82575.media_changed && | if (hw->dev_spec._82575.media_changed && | ||||
hw.mac.type >= igb_mac_min) { | hw->mac.type >= igb_mac_min) { | ||||
hw->dev_spec._82575.media_changed = false; | hw->dev_spec._82575.media_changed = false; | ||||
adapter->flags |= IGB_MEDIA_RESET; | adapter->flags |= IGB_MEDIA_RESET; | ||||
em_reset(ctx); | em_reset(ctx); | ||||
} | } | ||||
iflib_link_state_change(ctx, LINK_STATE_UP, | iflib_link_state_change(ctx, LINK_STATE_UP, | ||||
IF_Mbps(adapter->link_speed)); | IF_Mbps(adapter->link_speed)); | ||||
} else if (!link_check && (adapter->link_active == 1)) { | } else if (!link_check && (adapter->link_active == 1)) { | ||||
adapter->link_speed = 0; | adapter->link_speed = 0; | ||||
Show All 31 Lines | |||||
* This routine disables all traffic on the adapter by issuing a | * This routine disables all traffic on the adapter by issuing a | ||||
* global reset on the MAC. | * global reset on the MAC. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_if_stop(if_ctx_t ctx) | em_if_stop(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
INIT_DEBUGOUT("em_if_stop: begin"); | INIT_DEBUGOUT("em_if_stop: begin"); | ||||
e1000_reset_hw(&adapter->hw); | e1000_reset_hw(hw); | ||||
if (adapter->hw.mac.type >= e1000_82544) | if (hw->mac.type >= e1000_82544) | ||||
E1000_WRITE_REG(&adapter->hw, E1000_WUFC, 0); | E1000_WRITE_REG(hw, E1000_WUFC, 0); | ||||
e1000_led_off(&adapter->hw); | e1000_led_off(hw); | ||||
e1000_cleanup_led(&adapter->hw); | e1000_cleanup_led(hw); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Determine hardware revision. | * Determine hardware revision. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_identify_hardware(if_ctx_t ctx) | em_identify_hardware(if_ctx_t ctx) | ||||
{ | { | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
/* Make sure our PCI config space has the necessary stuff set */ | /* Make sure our PCI config space has the necessary stuff set */ | ||||
adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); | hw->bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); | ||||
/* Save off the information about this board */ | /* Save off the information about this board */ | ||||
adapter->hw.vendor_id = pci_get_vendor(dev); | hw->vendor_id = pci_get_vendor(dev); | ||||
adapter->hw.device_id = pci_get_device(dev); | hw->device_id = pci_get_device(dev); | ||||
adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); | hw->revision_id = pci_read_config(dev, PCIR_REVID, 1); | ||||
adapter->hw.subsystem_vendor_id = | hw->subsystem_vendor_id = | ||||
pci_read_config(dev, PCIR_SUBVEND_0, 2); | pci_read_config(dev, PCIR_SUBVEND_0, 2); | ||||
adapter->hw.subsystem_device_id = | hw->subsystem_device_id = | ||||
pci_read_config(dev, PCIR_SUBDEV_0, 2); | pci_read_config(dev, PCIR_SUBDEV_0, 2); | ||||
/* Do Shared Code Init and Setup */ | /* Do Shared Code Init and Setup */ | ||||
if (e1000_set_mac_type(&adapter->hw)) { | if (e1000_set_mac_type(hw)) { | ||||
device_printf(dev, "Setup init failure\n"); | device_printf(dev, "Setup init failure\n"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
em_allocate_pci_resources(if_ctx_t ctx) | em_allocate_pci_resources(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
int rid, val; | int rid, val; | ||||
rid = PCIR_BAR(0); | rid = PCIR_BAR(0); | ||||
adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, | adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, | ||||
&rid, RF_ACTIVE); | &rid, RF_ACTIVE); | ||||
if (adapter->memory == NULL) { | if (adapter->memory == NULL) { | ||||
device_printf(dev, "Unable to allocate bus resource: memory\n"); | device_printf(dev, "Unable to allocate bus resource: memory\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->memory); | adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->memory); | ||||
adapter->osdep.mem_bus_space_handle = | adapter->osdep.mem_bus_space_handle = | ||||
rman_get_bushandle(adapter->memory); | rman_get_bushandle(adapter->memory); | ||||
adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; | hw->hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; | ||||
/* Only older adapters use IO mapping */ | /* Only older adapters use IO mapping */ | ||||
if (adapter->hw.mac.type < em_mac_min && | if (hw->mac.type < em_mac_min && | ||||
adapter->hw.mac.type > e1000_82543) { | hw->mac.type > e1000_82543) { | ||||
/* Figure our where our IO BAR is ? */ | /* Figure our where our IO BAR is ? */ | ||||
for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { | for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { | ||||
val = pci_read_config(dev, rid, 4); | val = pci_read_config(dev, rid, 4); | ||||
if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { | if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { | ||||
break; | break; | ||||
} | } | ||||
rid += 4; | rid += 4; | ||||
/* check for 64bit BAR */ | /* check for 64bit BAR */ | ||||
if (EM_BAR_MEM_TYPE(val) == EM_BAR_MEM_TYPE_64BIT) | if (EM_BAR_MEM_TYPE(val) == EM_BAR_MEM_TYPE_64BIT) | ||||
rid += 4; | rid += 4; | ||||
} | } | ||||
if (rid >= PCIR_CIS) { | if (rid >= PCIR_CIS) { | ||||
device_printf(dev, "Unable to locate IO BAR\n"); | device_printf(dev, "Unable to locate IO BAR\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
adapter->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, | adapter->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, | ||||
&rid, RF_ACTIVE); | &rid, RF_ACTIVE); | ||||
if (adapter->ioport == NULL) { | if (adapter->ioport == NULL) { | ||||
device_printf(dev, "Unable to allocate bus resource: " | device_printf(dev, "Unable to allocate bus resource: " | ||||
"ioport\n"); | "ioport\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
adapter->hw.io_base = 0; | hw->io_base = 0; | ||||
adapter->osdep.io_bus_space_tag = | adapter->osdep.io_bus_space_tag = | ||||
rman_get_bustag(adapter->ioport); | rman_get_bustag(adapter->ioport); | ||||
adapter->osdep.io_bus_space_handle = | adapter->osdep.io_bus_space_handle = | ||||
rman_get_bushandle(adapter->ioport); | rman_get_bushandle(adapter->ioport); | ||||
} | } | ||||
adapter->hw.back = &adapter->osdep; | hw->back = &adapter->osdep; | ||||
return (0); | return (0); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Set up the MSI-X Interrupt handlers | * Set up the MSI-X Interrupt handlers | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static int | static int | ||||
em_if_msix_intr_assign(if_ctx_t ctx, int msix) | em_if_msix_intr_assign(if_ctx_t ctx, int msix) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
struct em_rx_queue *rx_que = adapter->rx_queues; | struct em_rx_queue *rx_que = adapter->rx_queues; | ||||
struct em_tx_queue *tx_que = adapter->tx_queues; | struct em_tx_queue *tx_que = adapter->tx_queues; | ||||
int error, rid, i, vector = 0, rx_vectors; | int error, rid, i, vector = 0, rx_vectors; | ||||
char buf[16]; | char buf[16]; | ||||
/* First set up ring resources */ | /* First set up ring resources */ | ||||
for (i = 0; i < adapter->rx_num_queues; i++, rx_que++, vector++) { | for (i = 0; i < adapter->rx_num_queues; i++, rx_que++, vector++) { | ||||
rid = vector + 1; | rid = vector + 1; | ||||
snprintf(buf, sizeof(buf), "rxq%d", i); | snprintf(buf, sizeof(buf), "rxq%d", i); | ||||
error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, IFLIB_INTR_RXTX, em_msix_que, rx_que, rx_que->me, buf); | error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, IFLIB_INTR_RXTX, em_msix_que, rx_que, rx_que->me, buf); | ||||
if (error) { | if (error) { | ||||
device_printf(iflib_get_dev(ctx), "Failed to allocate que int %d err: %d", i, error); | device_printf(iflib_get_dev(ctx), "Failed to allocate que int %d err: %d", i, error); | ||||
adapter->rx_num_queues = i + 1; | adapter->rx_num_queues = i + 1; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
rx_que->msix = vector; | rx_que->msix = vector; | ||||
/* | /* | ||||
* Set the bit to enable interrupt | * Set the bit to enable interrupt | ||||
* in E1000_IMS -- bits 20 and 21 | * in E1000_IMS -- bits 20 and 21 | ||||
* are for RX0 and RX1, note this has | * are for RX0 and RX1, note this has | ||||
* NOTHING to do with the MSI-X vector | * NOTHING to do with the MSI-X vector | ||||
*/ | */ | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (hw->mac.type == e1000_82574) { | ||||
rx_que->eims = 1 << (20 + i); | rx_que->eims = 1 << (20 + i); | ||||
adapter->ims |= rx_que->eims; | adapter->ims |= rx_que->eims; | ||||
adapter->ivars |= (8 | rx_que->msix) << (i * 4); | adapter->ivars |= (8 | rx_que->msix) << (i * 4); | ||||
} else if (adapter->hw.mac.type == e1000_82575) | } else if (hw->mac.type == e1000_82575) | ||||
rx_que->eims = E1000_EICR_TX_QUEUE0 << vector; | rx_que->eims = E1000_EICR_TX_QUEUE0 << vector; | ||||
else | else | ||||
rx_que->eims = 1 << vector; | rx_que->eims = 1 << vector; | ||||
} | } | ||||
rx_vectors = vector; | rx_vectors = vector; | ||||
vector = 0; | vector = 0; | ||||
for (i = 0; i < adapter->tx_num_queues; i++, tx_que++, vector++) { | for (i = 0; i < adapter->tx_num_queues; i++, tx_que++, vector++) { | ||||
snprintf(buf, sizeof(buf), "txq%d", i); | snprintf(buf, sizeof(buf), "txq%d", i); | ||||
tx_que = &adapter->tx_queues[i]; | tx_que = &adapter->tx_queues[i]; | ||||
iflib_softirq_alloc_generic(ctx, | iflib_softirq_alloc_generic(ctx, | ||||
&adapter->rx_queues[i % adapter->rx_num_queues].que_irq, | &adapter->rx_queues[i % adapter->rx_num_queues].que_irq, | ||||
IFLIB_INTR_TX, tx_que, tx_que->me, buf); | IFLIB_INTR_TX, tx_que, tx_que->me, buf); | ||||
tx_que->msix = (vector % adapter->rx_num_queues); | tx_que->msix = (vector % adapter->rx_num_queues); | ||||
/* | /* | ||||
* Set the bit to enable interrupt | * Set the bit to enable interrupt | ||||
* in E1000_IMS -- bits 22 and 23 | * in E1000_IMS -- bits 22 and 23 | ||||
* are for TX0 and TX1, note this has | * are for TX0 and TX1, note this has | ||||
* NOTHING to do with the MSI-X vector | * NOTHING to do with the MSI-X vector | ||||
*/ | */ | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (hw->mac.type == e1000_82574) { | ||||
tx_que->eims = 1 << (22 + i); | tx_que->eims = 1 << (22 + i); | ||||
adapter->ims |= tx_que->eims; | adapter->ims |= tx_que->eims; | ||||
adapter->ivars |= (8 | tx_que->msix) << (8 + (i * 4)); | adapter->ivars |= (8 | tx_que->msix) << (8 + (i * 4)); | ||||
} else if (adapter->hw.mac.type == e1000_82575) { | } else if (hw->mac.type == e1000_82575) { | ||||
tx_que->eims = E1000_EICR_TX_QUEUE0 << i; | tx_que->eims = E1000_EICR_TX_QUEUE0 << i; | ||||
} else { | } else { | ||||
tx_que->eims = 1 << i; | tx_que->eims = 1 << i; | ||||
} | } | ||||
} | } | ||||
/* Link interrupt */ | /* Link interrupt */ | ||||
rid = rx_vectors + 1; | rid = rx_vectors + 1; | ||||
error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid, IFLIB_INTR_ADMIN, em_msix_link, adapter, 0, "aq"); | error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid, IFLIB_INTR_ADMIN, em_msix_link, adapter, 0, "aq"); | ||||
if (error) { | if (error) { | ||||
device_printf(iflib_get_dev(ctx), "Failed to register admin handler"); | device_printf(iflib_get_dev(ctx), "Failed to register admin handler"); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
adapter->linkvec = rx_vectors; | adapter->linkvec = rx_vectors; | ||||
if (adapter->hw.mac.type < igb_mac_min) { | if (hw->mac.type < igb_mac_min) { | ||||
adapter->ivars |= (8 | rx_vectors) << 16; | adapter->ivars |= (8 | rx_vectors) << 16; | ||||
adapter->ivars |= 0x80000000; | adapter->ivars |= 0x80000000; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
iflib_irq_free(ctx, &adapter->irq); | iflib_irq_free(ctx, &adapter->irq); | ||||
rx_que = adapter->rx_queues; | rx_que = adapter->rx_queues; | ||||
for (int i = 0; i < adapter->rx_num_queues; i++, rx_que++) | for (int i = 0; i < adapter->rx_num_queues; i++, rx_que++) | ||||
iflib_irq_free(ctx, &rx_que->que_irq); | iflib_irq_free(ctx, &rx_que->que_irq); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
igb_configure_queues(struct adapter *adapter) | igb_configure_queues(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | struct e1000_hw *hw = &adapter->hw; | ||||
struct em_rx_queue *rx_que; | struct em_rx_queue *rx_que; | ||||
struct em_tx_queue *tx_que; | struct em_tx_queue *tx_que; | ||||
u32 tmp, ivar = 0, newitr = 0; | u32 tmp, ivar = 0, newitr = 0; | ||||
/* First turn on RSS capability */ | /* First turn on RSS capability */ | ||||
if (hw.mac.type != e1000_82575) | if (hw->mac.type != e1000_82575) | ||||
E1000_WRITE_REG(hw, E1000_GPIE, | E1000_WRITE_REG(hw, E1000_GPIE, | ||||
E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME | | E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME | | ||||
E1000_GPIE_PBA | E1000_GPIE_NSICR); | E1000_GPIE_PBA | E1000_GPIE_NSICR); | ||||
/* Turn on MSI-X */ | /* Turn on MSI-X */ | ||||
switch (hw.mac.type) { | switch (hw->mac.type) { | ||||
case e1000_82580: | case e1000_82580: | ||||
case e1000_i350: | case e1000_i350: | ||||
case e1000_i354: | case e1000_i354: | ||||
case e1000_i210: | case e1000_i210: | ||||
case e1000_i211: | case e1000_i211: | ||||
case e1000_vfadapt: | case e1000_vfadapt: | ||||
case e1000_vfadapt_i350: | case e1000_vfadapt_i350: | ||||
/* RX entries */ | /* RX entries */ | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | |||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Workaround for SmartSpeed on 82541 and 82547 controllers | * Workaround for SmartSpeed on 82541 and 82547 controllers | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
lem_smartspeed(struct adapter *adapter) | lem_smartspeed(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u16 phy_tmp; | u16 phy_tmp; | ||||
if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) || | if (adapter->link_active || (hw->phy.type != e1000_phy_igp) || | ||||
adapter->hw.mac.autoneg == 0 || | hw->mac.autoneg == 0 || | ||||
(adapter->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) | (hw->phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) | ||||
return; | return; | ||||
if (adapter->smartspeed == 0) { | if (adapter->smartspeed == 0) { | ||||
/* If Master/Slave config fault is asserted twice, | /* If Master/Slave config fault is asserted twice, | ||||
* we assume back-to-back */ | * we assume back-to-back */ | ||||
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); | e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp); | ||||
if (!(phy_tmp & SR_1000T_MS_CONFIG_FAULT)) | if (!(phy_tmp & SR_1000T_MS_CONFIG_FAULT)) | ||||
return; | return; | ||||
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); | e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp); | ||||
if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) { | if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) { | ||||
e1000_read_phy_reg(&adapter->hw, | e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_tmp); | ||||
PHY_1000T_CTRL, &phy_tmp); | |||||
if(phy_tmp & CR_1000T_MS_ENABLE) { | if(phy_tmp & CR_1000T_MS_ENABLE) { | ||||
phy_tmp &= ~CR_1000T_MS_ENABLE; | phy_tmp &= ~CR_1000T_MS_ENABLE; | ||||
e1000_write_phy_reg(&adapter->hw, | e1000_write_phy_reg(hw, | ||||
PHY_1000T_CTRL, phy_tmp); | PHY_1000T_CTRL, phy_tmp); | ||||
adapter->smartspeed++; | adapter->smartspeed++; | ||||
if(adapter->hw.mac.autoneg && | if(hw->mac.autoneg && | ||||
!e1000_copper_link_autoneg(&adapter->hw) && | !e1000_copper_link_autoneg(hw) && | ||||
!e1000_read_phy_reg(&adapter->hw, | !e1000_read_phy_reg(hw, | ||||
PHY_CONTROL, &phy_tmp)) { | PHY_CONTROL, &phy_tmp)) { | ||||
phy_tmp |= (MII_CR_AUTO_NEG_EN | | phy_tmp |= (MII_CR_AUTO_NEG_EN | | ||||
MII_CR_RESTART_AUTO_NEG); | MII_CR_RESTART_AUTO_NEG); | ||||
e1000_write_phy_reg(&adapter->hw, | e1000_write_phy_reg(hw, | ||||
PHY_CONTROL, phy_tmp); | PHY_CONTROL, phy_tmp); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return; | return; | ||||
} else if(adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) { | } else if(adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) { | ||||
/* If still no link, perhaps using 2/3 pair cable */ | /* If still no link, perhaps using 2/3 pair cable */ | ||||
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp); | e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_tmp); | ||||
phy_tmp |= CR_1000T_MS_ENABLE; | phy_tmp |= CR_1000T_MS_ENABLE; | ||||
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_tmp); | e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_tmp); | ||||
if(adapter->hw.mac.autoneg && | if(hw->mac.autoneg && | ||||
!e1000_copper_link_autoneg(&adapter->hw) && | !e1000_copper_link_autoneg(hw) && | ||||
!e1000_read_phy_reg(&adapter->hw, PHY_CONTROL, &phy_tmp)) { | !e1000_read_phy_reg(hw, PHY_CONTROL, &phy_tmp)) { | ||||
phy_tmp |= (MII_CR_AUTO_NEG_EN | | phy_tmp |= (MII_CR_AUTO_NEG_EN | | ||||
MII_CR_RESTART_AUTO_NEG); | MII_CR_RESTART_AUTO_NEG); | ||||
e1000_write_phy_reg(&adapter->hw, PHY_CONTROL, phy_tmp); | e1000_write_phy_reg(hw, PHY_CONTROL, phy_tmp); | ||||
} | } | ||||
} | } | ||||
/* Restart process after EM_SMARTSPEED_MAX iterations */ | /* Restart process after EM_SMARTSPEED_MAX iterations */ | ||||
if(adapter->smartspeed++ == EM_SMARTSPEED_MAX) | if(adapter->smartspeed++ == EM_SMARTSPEED_MAX) | ||||
adapter->smartspeed = 0; | adapter->smartspeed = 0; | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | |||||
* adapter structure. | * adapter structure. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_reset(if_ctx_t ctx) | em_reset(if_ctx_t ctx) | ||||
{ | { | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | |||||
struct e1000_hw *hw = &adapter->hw; | struct e1000_hw *hw = &adapter->hw; | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | |||||
u16 rx_buffer_size; | u16 rx_buffer_size; | ||||
u32 pba; | u32 pba; | ||||
INIT_DEBUGOUT("em_reset: begin"); | INIT_DEBUGOUT("em_reset: begin"); | ||||
/* Let the firmware know the OS is in control */ | /* Let the firmware know the OS is in control */ | ||||
em_get_hw_control(adapter); | em_get_hw_control(adapter); | ||||
/* Set up smart power down as default off on newer adapters. */ | /* Set up smart power down as default off on newer adapters. */ | ||||
Show All 27 Lines | case e1000_82583: | ||||
pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */ | pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */ | ||||
break; | break; | ||||
case e1000_ich8lan: | case e1000_ich8lan: | ||||
pba = E1000_PBA_8K; | pba = E1000_PBA_8K; | ||||
break; | break; | ||||
case e1000_ich9lan: | case e1000_ich9lan: | ||||
case e1000_ich10lan: | case e1000_ich10lan: | ||||
/* Boost Receive side for jumbo frames */ | /* Boost Receive side for jumbo frames */ | ||||
if (hw.mac.max_frame_size > 4096) | if (hw->mac.max_frame_size > 4096) | ||||
pba = E1000_PBA_14K; | pba = E1000_PBA_14K; | ||||
else | else | ||||
pba = E1000_PBA_10K; | pba = E1000_PBA_10K; | ||||
break; | break; | ||||
case e1000_pchlan: | case e1000_pchlan: | ||||
case e1000_pch2lan: | case e1000_pch2lan: | ||||
case e1000_pch_lpt: | case e1000_pch_lpt: | ||||
case e1000_pch_spt: | case e1000_pch_spt: | ||||
Show All 15 Lines | case e1000_vfadapt_i350: | ||||
pba = E1000_READ_REG(hw, E1000_RXPBS); | pba = E1000_READ_REG(hw, E1000_RXPBS); | ||||
pba = e1000_rxpbs_adjust_82580(pba); | pba = e1000_rxpbs_adjust_82580(pba); | ||||
break; | break; | ||||
case e1000_i210: | case e1000_i210: | ||||
case e1000_i211: | case e1000_i211: | ||||
pba = E1000_PBA_34K; | pba = E1000_PBA_34K; | ||||
break; | break; | ||||
default: | default: | ||||
if (hw.mac.max_frame_size > 8192) | if (hw->mac.max_frame_size > 8192) | ||||
pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ | pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ | ||||
else | else | ||||
pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */ | pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */ | ||||
} | } | ||||
/* Special needs in case of Jumbo frames */ | /* Special needs in case of Jumbo frames */ | ||||
if ((hw->mac.type == e1000_82575) && (ifp->if_mtu > ETHERMTU)) { | if ((hw->mac.type == e1000_82575) && (ifp->if_mtu > ETHERMTU)) { | ||||
u32 tx_space, min_tx, min_rx; | u32 tx_space, min_tx, min_rx; | ||||
pba = E1000_READ_REG(hw, E1000_PBA); | pba = E1000_READ_REG(hw, E1000_PBA); | ||||
tx_space = pba >> 16; | tx_space = pba >> 16; | ||||
pba &= 0xffff; | pba &= 0xffff; | ||||
min_tx = (hw.mac.max_frame_size + | min_tx = (hw->mac.max_frame_size + | ||||
sizeof(struct e1000_tx_desc) - ETHERNET_FCS_SIZE) * 2; | sizeof(struct e1000_tx_desc) - ETHERNET_FCS_SIZE) * 2; | ||||
min_tx = roundup2(min_tx, 1024); | min_tx = roundup2(min_tx, 1024); | ||||
min_tx >>= 10; | min_tx >>= 10; | ||||
min_rx = hw.mac.max_frame_size; | min_rx = hw->mac.max_frame_size; | ||||
min_rx = roundup2(min_rx, 1024); | min_rx = roundup2(min_rx, 1024); | ||||
min_rx >>= 10; | min_rx >>= 10; | ||||
if (tx_space < min_tx && | if (tx_space < min_tx && | ||||
((min_tx - tx_space) < pba)) { | ((min_tx - tx_space) < pba)) { | ||||
pba = pba - (min_tx - tx_space); | pba = pba - (min_tx - tx_space); | ||||
/* | /* | ||||
* if short on rx space, rx wins | * if short on rx space, rx wins | ||||
* and must trump tx adjustment | * and must trump tx adjustment | ||||
Show All 20 Lines | em_reset(if_ctx_t ctx) | ||||
* restart after one full frame is pulled from the buffer. There | * restart after one full frame is pulled from the buffer. There | ||||
* could be several smaller frames in the buffer and if so they will | * could be several smaller frames in the buffer and if so they will | ||||
* not trigger the XON until their total number reduces the buffer | * not trigger the XON until their total number reduces the buffer | ||||
* by 1500. | * by 1500. | ||||
* - The pause time is fairly large at 1000 x 512ns = 512 usec. | * - The pause time is fairly large at 1000 x 512ns = 512 usec. | ||||
*/ | */ | ||||
rx_buffer_size = (pba & 0xffff) << 10; | rx_buffer_size = (pba & 0xffff) << 10; | ||||
hw->fc.high_water = rx_buffer_size - | hw->fc.high_water = rx_buffer_size - | ||||
roundup2(hw.mac.max_frame_size, 1024); | roundup2(hw->mac.max_frame_size, 1024); | ||||
hw->fc.low_water = hw->fc.high_water - 1500; | hw->fc.low_water = hw->fc.high_water - 1500; | ||||
if (adapter->fc) /* locally set flow control value? */ | if (adapter->fc) /* locally set flow control value? */ | ||||
hw->fc.requested_mode = adapter->fc; | hw->fc.requested_mode = adapter->fc; | ||||
else | else | ||||
hw->fc.requested_mode = e1000_fc_full; | hw->fc.requested_mode = e1000_fc_full; | ||||
if (hw->mac.type == e1000_80003es2lan) | if (hw->mac.type == e1000_80003es2lan) | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | em_reset(if_ctx_t ctx) | ||||
default: | default: | ||||
if (hw->mac.type == e1000_80003es2lan) | if (hw->mac.type == e1000_80003es2lan) | ||||
hw->fc.pause_time = 0xFFFF; | hw->fc.pause_time = 0xFFFF; | ||||
break; | break; | ||||
} | } | ||||
/* Issue a global reset */ | /* Issue a global reset */ | ||||
e1000_reset_hw(hw); | e1000_reset_hw(hw); | ||||
if (hw.mac.type >= igb_mac_min) { | if (hw->mac.type >= igb_mac_min) { | ||||
E1000_WRITE_REG(hw, E1000_WUC, 0); | E1000_WRITE_REG(hw, E1000_WUC, 0); | ||||
} else { | } else { | ||||
E1000_WRITE_REG(hw, E1000_WUFC, 0); | E1000_WRITE_REG(hw, E1000_WUFC, 0); | ||||
em_disable_aspm(adapter); | em_disable_aspm(adapter); | ||||
} | } | ||||
if (adapter->flags & IGB_MEDIA_RESET) { | if (adapter->flags & IGB_MEDIA_RESET) { | ||||
e1000_setup_init_funcs(hw, TRUE); | e1000_setup_init_funcs(hw, TRUE); | ||||
e1000_get_bus_info(hw); | e1000_get_bus_info(hw); | ||||
adapter->flags &= ~IGB_MEDIA_RESET; | adapter->flags &= ~IGB_MEDIA_RESET; | ||||
} | } | ||||
/* and a re-init */ | /* and a re-init */ | ||||
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"); | ||||
return; | return; | ||||
} | } | ||||
if (hw.mac.type >= igb_mac_min) | if (hw->mac.type >= igb_mac_min) | ||||
igb_init_dmac(adapter, pba); | igb_init_dmac(adapter, pba); | ||||
E1000_WRITE_REG(hw, E1000_VET, ETHERTYPE_VLAN); | E1000_WRITE_REG(hw, E1000_VET, ETHERTYPE_VLAN); | ||||
e1000_get_phy_info(hw); | e1000_get_phy_info(hw); | ||||
e1000_check_for_link(hw); | e1000_check_for_link(hw); | ||||
} | } | ||||
/* | /* | ||||
* Initialise the RSS mapping for NICs that support multiple transmit/ | * Initialise the RSS mapping for NICs that support multiple transmit/ | ||||
* receive rings. | * receive rings. | ||||
*/ | */ | ||||
#define RSSKEYLEN 10 | #define RSSKEYLEN 10 | ||||
static void | static void | ||||
em_initialize_rss_mapping(struct adapter *adapter) | em_initialize_rss_mapping(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
uint8_t rss_key[4 * RSSKEYLEN]; | uint8_t rss_key[4 * RSSKEYLEN]; | ||||
uint32_t reta = 0; | uint32_t reta = 0; | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
int i; | int i; | ||||
/* | /* | ||||
* Configure RSS key | * Configure RSS key | ||||
*/ | */ | ||||
arc4rand(rss_key, sizeof(rss_key), 0); | arc4rand(rss_key, sizeof(rss_key), 0); | ||||
for (i = 0; i < RSSKEYLEN; ++i) { | for (i = 0; i < RSSKEYLEN; ++i) { | ||||
uint32_t rssrk = 0; | uint32_t rssrk = 0; | ||||
Show All 29 Lines | |||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | struct e1000_hw *hw = &adapter->hw; | ||||
int i; | int i; | ||||
int queue_id; | int queue_id; | ||||
u32 reta; | u32 reta; | ||||
u32 rss_key[10], mrqc, shift = 0; | u32 rss_key[10], mrqc, shift = 0; | ||||
/* XXX? */ | /* XXX? */ | ||||
if (hw.mac.type == e1000_82575) | if (hw->mac.type == e1000_82575) | ||||
shift = 6; | shift = 6; | ||||
/* | /* | ||||
* The redirection table controls which destination | * The redirection table controls which destination | ||||
* queue each bucket redirects traffic to. | * queue each bucket redirects traffic to. | ||||
* Each DWORD represents four queues, with the LSB | * Each DWORD represents four queues, with the LSB | ||||
* being the first queue in the DWORD. | * being the first queue in the DWORD. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | |||||
* Setup networking device structure and register interface media. | * Setup networking device structure and register interface media. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static int | static int | ||||
em_setup_interface(if_ctx_t ctx) | em_setup_interface(if_ctx_t ctx) | ||||
{ | { | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = adapter->shared; | ||||
INIT_DEBUGOUT("em_setup_interface: begin"); | INIT_DEBUGOUT("em_setup_interface: begin"); | ||||
/* Single Queue */ | /* Single Queue */ | ||||
if (adapter->tx_num_queues == 1) { | if (adapter->tx_num_queues == 1) { | ||||
if_setsendqlen(ifp, scctx->isc_ntxd[0] - 1); | if_setsendqlen(ifp, scctx->isc_ntxd[0] - 1); | ||||
if_setsendqready(ifp); | if_setsendqready(ifp); | ||||
} | } | ||||
/* | /* | ||||
* Specify the media types supported by this adapter and register | * Specify the media types supported by this adapter and register | ||||
* callbacks to update media and link information | * callbacks to update media and link information | ||||
*/ | */ | ||||
if (hw.phy.media_type == e1000_media_type_fiber || | if (hw->phy.media_type == e1000_media_type_fiber || | ||||
hw.phy.media_type == e1000_media_type_internal_serdes) { | hw->phy.media_type == e1000_media_type_internal_serdes) { | ||||
u_char fiber_type = IFM_1000_SX; /* default type */ | u_char fiber_type = IFM_1000_SX; /* default type */ | ||||
if (hw.mac.type == e1000_82545) | if (hw->mac.type == e1000_82545) | ||||
fiber_type = IFM_1000_LX; | fiber_type = IFM_1000_LX; | ||||
ifmedia_add(adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 0, NULL); | ||||
ifmedia_add(adapter->media, IFM_ETHER | fiber_type, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | fiber_type, 0, NULL); | ||||
} else { | } else { | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); | ||||
if (hw.phy.type != e1000_phy_ife) { | if (hw->phy.type != e1000_phy_ife) { | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); | ||||
} | } | ||||
} | } | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ||||
ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); | ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* Enable transmit unit. | * Enable transmit unit. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_initialize_transmit_unit(if_ctx_t ctx) | em_initialize_transmit_unit(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = adapter->shared; | ||||
struct em_tx_queue *que; | struct em_tx_queue *que; | ||||
struct tx_ring *txr; | struct tx_ring *txr; | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u32 tctl, txdctl = 0, tarc, tipg = 0; | u32 tctl, txdctl = 0, tarc, tipg = 0; | ||||
INIT_DEBUGOUT("em_initialize_transmit_unit: begin"); | INIT_DEBUGOUT("em_initialize_transmit_unit: begin"); | ||||
for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { | for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { | ||||
u64 bus_addr; | u64 bus_addr; | ||||
caddr_t offp, endp; | caddr_t offp, endp; | ||||
Show All 28 Lines | for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { | ||||
txdctl |= 1 << 22; /* Reserved bit 22 must always be 1 */ | txdctl |= 1 << 22; /* Reserved bit 22 must always be 1 */ | ||||
txdctl |= E1000_TXDCTL_GRAN; | txdctl |= E1000_TXDCTL_GRAN; | ||||
txdctl |= 1 << 25; /* LWTHRESH */ | txdctl |= 1 << 25; /* LWTHRESH */ | ||||
E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); | E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); | ||||
} | } | ||||
/* Set the default values for the Tx Inter Packet Gap timer */ | /* Set the default values for the Tx Inter Packet Gap timer */ | ||||
switch (hw.mac.type) { | switch (hw->mac.type) { | ||||
case e1000_80003es2lan: | case e1000_80003es2lan: | ||||
tipg = DEFAULT_82543_TIPG_IPGR1; | tipg = DEFAULT_82543_TIPG_IPGR1; | ||||
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 << | tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 << | ||||
E1000_TIPG_IPGR2_SHIFT; | E1000_TIPG_IPGR2_SHIFT; | ||||
break; | break; | ||||
case e1000_82542: | case e1000_82542: | ||||
tipg = DEFAULT_82542_TIPG_IPGT; | tipg = DEFAULT_82542_TIPG_IPGT; | ||||
tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; | tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; | ||||
tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; | tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; | ||||
break; | break; | ||||
default: | default: | ||||
if (hw.phy.media_type == e1000_media_type_fiber || | if (hw->phy.media_type == e1000_media_type_fiber || | ||||
hw.phy.media_type == e1000_media_type_internal_serdes) | hw->phy.media_type == e1000_media_type_internal_serdes) | ||||
tipg = DEFAULT_82543_TIPG_IPGT_FIBER; | tipg = DEFAULT_82543_TIPG_IPGT_FIBER; | ||||
else | else | ||||
tipg = DEFAULT_82543_TIPG_IPGT_COPPER; | tipg = DEFAULT_82543_TIPG_IPGT_COPPER; | ||||
tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; | tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; | ||||
tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; | tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; | ||||
} | } | ||||
E1000_WRITE_REG(hw, E1000_TIPG, tipg); | E1000_WRITE_REG(hw, E1000_TIPG, tipg); | ||||
E1000_WRITE_REG(hw, E1000_TIDV, adapter->tx_int_delay.value); | E1000_WRITE_REG(hw, E1000_TIDV, adapter->tx_int_delay.value); | ||||
if(hw.mac.type >= e1000_82540) | if(hw->mac.type >= e1000_82540) | ||||
E1000_WRITE_REG(hw, E1000_TADV, | E1000_WRITE_REG(hw, E1000_TADV, | ||||
adapter->tx_abs_int_delay.value); | adapter->tx_abs_int_delay.value); | ||||
if (hw.mac.type == e1000_82571 || hw.mac.type == e1000_82572) { | if (hw->mac.type == e1000_82571 || hw->mac.type == e1000_82572) { | ||||
tarc = E1000_READ_REG(hw, E1000_TARC(0)); | tarc = E1000_READ_REG(hw, E1000_TARC(0)); | ||||
tarc |= TARC_SPEED_MODE_BIT; | tarc |= TARC_SPEED_MODE_BIT; | ||||
E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | ||||
} else if (hw.mac.type == e1000_80003es2lan) { | } else if (hw->mac.type == e1000_80003es2lan) { | ||||
/* errata: program both queues to unweighted RR */ | /* errata: program both queues to unweighted RR */ | ||||
tarc = E1000_READ_REG(hw, E1000_TARC(0)); | tarc = E1000_READ_REG(hw, E1000_TARC(0)); | ||||
tarc |= 1; | tarc |= 1; | ||||
E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | ||||
tarc = E1000_READ_REG(hw, E1000_TARC(1)); | tarc = E1000_READ_REG(hw, E1000_TARC(1)); | ||||
tarc |= 1; | tarc |= 1; | ||||
E1000_WRITE_REG(hw, E1000_TARC(1), tarc); | E1000_WRITE_REG(hw, E1000_TARC(1), tarc); | ||||
} else if (hw.mac.type == e1000_82574) { | } else if (hw->mac.type == e1000_82574) { | ||||
tarc = E1000_READ_REG(hw, E1000_TARC(0)); | tarc = E1000_READ_REG(hw, E1000_TARC(0)); | ||||
tarc |= TARC_ERRATA_BIT; | tarc |= TARC_ERRATA_BIT; | ||||
if ( adapter->tx_num_queues > 1) { | if ( adapter->tx_num_queues > 1) { | ||||
tarc |= (TARC_COMPENSATION_MODE | TARC_MQ_FIX); | tarc |= (TARC_COMPENSATION_MODE | TARC_MQ_FIX); | ||||
E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | ||||
E1000_WRITE_REG(hw, E1000_TARC(1), tarc); | E1000_WRITE_REG(hw, E1000_TARC(1), tarc); | ||||
} else | } else | ||||
E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | E1000_WRITE_REG(hw, E1000_TARC(0), tarc); | ||||
} | } | ||||
if (adapter->tx_int_delay.value > 0) | if (adapter->tx_int_delay.value > 0) | ||||
adapter->txd_cmd |= E1000_TXD_CMD_IDE; | adapter->txd_cmd |= E1000_TXD_CMD_IDE; | ||||
/* Program the Transmit Control Register */ | /* Program the Transmit Control Register */ | ||||
tctl = E1000_READ_REG(hw, E1000_TCTL); | tctl = E1000_READ_REG(hw, E1000_TCTL); | ||||
tctl &= ~E1000_TCTL_CT; | tctl &= ~E1000_TCTL_CT; | ||||
tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | | tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | | ||||
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); | ||||
if (hw.mac.type >= e1000_82571) | if (hw->mac.type >= e1000_82571) | ||||
tctl |= E1000_TCTL_MULR; | tctl |= E1000_TCTL_MULR; | ||||
/* This write will effectively turn on the transmit unit. */ | /* This write will effectively turn on the transmit unit. */ | ||||
E1000_WRITE_REG(hw, E1000_TCTL, tctl); | E1000_WRITE_REG(hw, E1000_TCTL, tctl); | ||||
/* SPT and KBL errata workarounds */ | /* SPT and KBL errata workarounds */ | ||||
if (hw->mac.type == e1000_pch_spt) { | if (hw->mac.type == e1000_pch_spt) { | ||||
u32 reg; | u32 reg; | ||||
Show All 13 Lines | |||||
* Enable receive unit. | * Enable receive unit. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_initialize_receive_unit(if_ctx_t ctx) | em_initialize_receive_unit(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = adapter->shared; | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
struct em_rx_queue *que; | struct em_rx_queue *que; | ||||
int i; | int i; | ||||
u32 rctl, rxcsum, rfctl; | u32 rctl, rxcsum, rfctl; | ||||
INIT_DEBUGOUT("em_initialize_receive_units: begin"); | INIT_DEBUGOUT("em_initialize_receive_units: begin"); | ||||
/* | /* | ||||
* Make sure receives are disabled while setting | * Make sure receives are disabled while setting | ||||
Show All 18 Lines | if (if_getmtu(ifp) > ETHERMTU) | ||||
rctl |= E1000_RCTL_LPE; | rctl |= E1000_RCTL_LPE; | ||||
else | else | ||||
rctl &= ~E1000_RCTL_LPE; | rctl &= ~E1000_RCTL_LPE; | ||||
/* Strip the CRC */ | /* Strip the CRC */ | ||||
if (!em_disable_crc_stripping) | if (!em_disable_crc_stripping) | ||||
rctl |= E1000_RCTL_SECRC; | rctl |= E1000_RCTL_SECRC; | ||||
if (hw.mac.type >= e1000_82540) { | if (hw->mac.type >= e1000_82540) { | ||||
E1000_WRITE_REG(hw, E1000_RADV, | E1000_WRITE_REG(hw, E1000_RADV, | ||||
adapter->rx_abs_int_delay.value); | adapter->rx_abs_int_delay.value); | ||||
/* | /* | ||||
* Set the interrupt throttling rate. Value is calculated | * Set the interrupt throttling rate. Value is calculated | ||||
* as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) | * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) | ||||
*/ | */ | ||||
E1000_WRITE_REG(hw, E1000_ITR, DEFAULT_ITR); | E1000_WRITE_REG(hw, E1000_ITR, DEFAULT_ITR); | ||||
Show All 13 Lines | for (int i = 0; i < 4; i++) | ||||
DEFAULT_ITR); | DEFAULT_ITR); | ||||
/* Disable accelerated acknowledge */ | /* Disable accelerated acknowledge */ | ||||
rfctl |= E1000_RFCTL_ACK_DIS; | rfctl |= E1000_RFCTL_ACK_DIS; | ||||
} | } | ||||
E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); | E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); | ||||
rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); | rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); | ||||
if (if_getcapenable(ifp) & IFCAP_RXCSUM && | if (if_getcapenable(ifp) & IFCAP_RXCSUM && | ||||
hw.mac.type >= e1000_82543) { | hw->mac.type >= e1000_82543) { | ||||
if (adapter->tx_num_queues > 1) { | if (adapter->tx_num_queues > 1) { | ||||
if (hw.mac.type >= igb_mac_min) { | if (hw->mac.type >= igb_mac_min) { | ||||
rxcsum |= E1000_RXCSUM_PCSD; | rxcsum |= E1000_RXCSUM_PCSD; | ||||
if (hw->mac.type != e1000_82575) | if (hw->mac.type != e1000_82575) | ||||
rxcsum |= E1000_RXCSUM_CRCOFL; | rxcsum |= E1000_RXCSUM_CRCOFL; | ||||
} else | } else | ||||
rxcsum |= E1000_RXCSUM_TUOFL | | rxcsum |= E1000_RXCSUM_TUOFL | | ||||
E1000_RXCSUM_IPOFL | | E1000_RXCSUM_IPOFL | | ||||
E1000_RXCSUM_PCSD; | E1000_RXCSUM_PCSD; | ||||
} else { | } else { | ||||
if (hw.mac.type >= igb_mac_min) | if (hw->mac.type >= igb_mac_min) | ||||
rxcsum |= E1000_RXCSUM_IPPCSE; | rxcsum |= E1000_RXCSUM_IPPCSE; | ||||
else | else | ||||
rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL; | rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL; | ||||
if (hw.mac.type > e1000_82575) | if (hw->mac.type > e1000_82575) | ||||
rxcsum |= E1000_RXCSUM_CRCOFL; | rxcsum |= E1000_RXCSUM_CRCOFL; | ||||
} | } | ||||
} else | } else | ||||
rxcsum &= ~E1000_RXCSUM_TUOFL; | rxcsum &= ~E1000_RXCSUM_TUOFL; | ||||
E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); | E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); | ||||
if (adapter->rx_num_queues > 1) { | if (adapter->rx_num_queues > 1) { | ||||
if (hw.mac.type >= igb_mac_min) | if (hw->mac.type >= igb_mac_min) | ||||
igb_initialize_rss_mapping(adapter); | igb_initialize_rss_mapping(adapter); | ||||
else | else | ||||
em_initialize_rss_mapping(adapter); | em_initialize_rss_mapping(adapter); | ||||
} | } | ||||
/* | /* | ||||
* XXX TEMPORARY WORKAROUND: on some systems with 82573 | * XXX TEMPORARY WORKAROUND: on some systems with 82573 | ||||
* long latencies are observed, like Lenovo X60. This | * long latencies are observed, like Lenovo X60. This | ||||
Show All 23 Lines | #endif | ||||
/* | /* | ||||
* Set PTHRESH for improved jumbo performance | * Set PTHRESH for improved jumbo performance | ||||
* According to 10.2.5.11 of Intel 82574 Datasheet, | * According to 10.2.5.11 of Intel 82574 Datasheet, | ||||
* RXDCTL(1) is written whenever RXDCTL(0) is written. | * RXDCTL(1) is written whenever RXDCTL(0) is written. | ||||
* Only write to RXDCTL(1) if there is a need for different | * Only write to RXDCTL(1) if there is a need for different | ||||
* settings. | * settings. | ||||
*/ | */ | ||||
if ((hw.mac.type == e1000_ich9lan || hw.mac.type == e1000_pch2lan || | if ((hw->mac.type == e1000_ich9lan || hw->mac.type == e1000_pch2lan || | ||||
hw.mac.type == e1000_ich10lan) && (if_getmtu(ifp) > ETHERMTU)) { | hw->mac.type == e1000_ich10lan) && (if_getmtu(ifp) > ETHERMTU)) { | ||||
u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); | u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); | ||||
E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3); | E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3); | ||||
} else if (hw.mac.type == e1000_82574) { | } else if (hw->mac.type == e1000_82574) { | ||||
for (int i = 0; i < adapter->rx_num_queues; i++) { | for (int i = 0; i < adapter->rx_num_queues; i++) { | ||||
u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); | u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); | ||||
rxdctl |= 0x20; /* PTHRESH */ | rxdctl |= 0x20; /* PTHRESH */ | ||||
rxdctl |= 4 << 8; /* HTHRESH */ | rxdctl |= 4 << 8; /* HTHRESH */ | ||||
rxdctl |= 4 << 16;/* WTHRESH */ | rxdctl |= 4 << 16;/* WTHRESH */ | ||||
rxdctl |= 1 << 24; /* Switch to granularity */ | rxdctl |= 1 << 24; /* Switch to granularity */ | ||||
E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); | E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); | ||||
} | } | ||||
} else if (hw.mac.type >= igb_mac_min) { | } else if (hw->mac.type >= igb_mac_min) { | ||||
u32 psize, srrctl = 0; | u32 psize, srrctl = 0; | ||||
if (if_getmtu(ifp) > ETHERMTU) { | if (if_getmtu(ifp) > ETHERMTU) { | ||||
/* Set maximum packet len */ | /* Set maximum packet len */ | ||||
if (adapter->rx_mbuf_sz <= 4096) { | if (adapter->rx_mbuf_sz <= 4096) { | ||||
srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT; | srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT; | ||||
rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; | rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; | ||||
} else if (adapter->rx_mbuf_sz > 4096) { | } else if (adapter->rx_mbuf_sz > 4096) { | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | #endif | ||||
rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); | rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); | ||||
rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; | rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; | ||||
rxdctl &= 0xFFF00000; | rxdctl &= 0xFFF00000; | ||||
rxdctl |= IGB_RX_PTHRESH; | rxdctl |= IGB_RX_PTHRESH; | ||||
rxdctl |= IGB_RX_HTHRESH << 8; | rxdctl |= IGB_RX_HTHRESH << 8; | ||||
rxdctl |= IGB_RX_WTHRESH << 16; | rxdctl |= IGB_RX_WTHRESH << 16; | ||||
E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); | E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); | ||||
} | } | ||||
} else if (hw.mac.type >= e1000_pch2lan) { | } else if (hw->mac.type >= e1000_pch2lan) { | ||||
if (if_getmtu(ifp) > ETHERMTU) | if (if_getmtu(ifp) > ETHERMTU) | ||||
e1000_lv_jumbo_workaround_ich8lan(hw, TRUE); | e1000_lv_jumbo_workaround_ich8lan(hw, TRUE); | ||||
else | else | ||||
e1000_lv_jumbo_workaround_ich8lan(hw, FALSE); | e1000_lv_jumbo_workaround_ich8lan(hw, FALSE); | ||||
} | } | ||||
/* Make sure VLAN Filters are off */ | /* Make sure VLAN Filters are off */ | ||||
rctl &= ~E1000_RCTL_VFE; | rctl &= ~E1000_RCTL_VFE; | ||||
if (hw.mac.type < igb_mac_min) { | if (hw->mac.type < igb_mac_min) { | ||||
if (adapter->rx_mbuf_sz == MCLBYTES) | if (adapter->rx_mbuf_sz == MCLBYTES) | ||||
rctl |= E1000_RCTL_SZ_2048; | rctl |= E1000_RCTL_SZ_2048; | ||||
else if (adapter->rx_mbuf_sz == MJUMPAGESIZE) | else if (adapter->rx_mbuf_sz == MJUMPAGESIZE) | ||||
rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; | rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; | ||||
else if (adapter->rx_mbuf_sz > MJUMPAGESIZE) | else if (adapter->rx_mbuf_sz > MJUMPAGESIZE) | ||||
rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; | rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; | ||||
/* ensure we clear use DTYPE of 00 here */ | /* ensure we clear use DTYPE of 00 here */ | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Bit of a misnomer, what this really means is | * Bit of a misnomer, what this really means is | ||||
* to enable OS management of the system... aka | * to enable OS management of the system... aka | ||||
* to disable special hardware management features | * to disable special hardware management features | ||||
*/ | */ | ||||
static void | static void | ||||
em_init_manageability(struct adapter *adapter) | em_init_manageability(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
/* A shared code workaround */ | /* A shared code workaround */ | ||||
#define E1000_82542_MANC2H E1000_MANC2H | #define E1000_82542_MANC2H E1000_MANC2H | ||||
if (adapter->has_manage) { | if (adapter->has_manage) { | ||||
int manc2h = E1000_READ_REG(&adapter->hw, E1000_MANC2H); | int manc2h = E1000_READ_REG(hw, E1000_MANC2H); | ||||
int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); | int manc = E1000_READ_REG(hw, E1000_MANC); | ||||
/* disable hardware interception of ARP */ | /* disable hardware interception of ARP */ | ||||
manc &= ~(E1000_MANC_ARP_EN); | manc &= ~(E1000_MANC_ARP_EN); | ||||
/* enable receiving management packets to the host */ | /* enable receiving management packets to the host */ | ||||
manc |= E1000_MANC_EN_MNG2HOST; | manc |= E1000_MANC_EN_MNG2HOST; | ||||
#define E1000_MNG2HOST_PORT_623 (1 << 5) | #define E1000_MNG2HOST_PORT_623 (1 << 5) | ||||
#define E1000_MNG2HOST_PORT_664 (1 << 6) | #define E1000_MNG2HOST_PORT_664 (1 << 6) | ||||
manc2h |= E1000_MNG2HOST_PORT_623; | manc2h |= E1000_MNG2HOST_PORT_623; | ||||
manc2h |= E1000_MNG2HOST_PORT_664; | manc2h |= E1000_MNG2HOST_PORT_664; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_MANC2H, manc2h); | E1000_WRITE_REG(hw, E1000_MANC2H, manc2h); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); | E1000_WRITE_REG(hw, E1000_MANC, manc); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Give control back to hardware management | * Give control back to hardware management | ||||
* controller if there is one. | * controller if there is one. | ||||
*/ | */ | ||||
static void | static void | ||||
Show All 14 Lines | |||||
* em_get_hw_control sets the {CTRL_EXT|FWSM}:DRV_LOAD bit. | * em_get_hw_control sets the {CTRL_EXT|FWSM}:DRV_LOAD bit. | ||||
* For ASF and Pass Through versions of f/w this means | * For ASF and Pass Through versions of f/w this means | ||||
* that the driver is loaded. For AMT version type f/w | * that the driver is loaded. For AMT version type f/w | ||||
* this means that the network i/f is open. | * this means that the network i/f is open. | ||||
*/ | */ | ||||
static void | static void | ||||
em_get_hw_control(struct adapter *adapter) | em_get_hw_control(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u32 ctrl_ext, swsm; | u32 ctrl_ext, swsm; | ||||
if (adapter->vf_ifp) | if (adapter->vf_ifp) | ||||
return; | return; | ||||
if (adapter->hw.mac.type == e1000_82573) { | if (hw->mac.type == e1000_82573) { | ||||
swsm = E1000_READ_REG(&adapter->hw, E1000_SWSM); | swsm = E1000_READ_REG(hw, E1000_SWSM); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_SWSM, | E1000_WRITE_REG(hw, E1000_SWSM, | ||||
swsm | E1000_SWSM_DRV_LOAD); | swsm | E1000_SWSM_DRV_LOAD); | ||||
return; | return; | ||||
} | } | ||||
/* else */ | /* else */ | ||||
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); | ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, | E1000_WRITE_REG(hw, E1000_CTRL_EXT, | ||||
ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); | ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); | ||||
} | } | ||||
/* | /* | ||||
* em_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. | * em_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. | ||||
* For ASF and Pass Through versions of f/w this means that | * For ASF and Pass Through versions of f/w this means that | ||||
* the driver is no longer loaded. For AMT versions of the | * the driver is no longer loaded. For AMT versions of the | ||||
* f/w this means that the network i/f is closed. | * f/w this means that the network i/f is closed. | ||||
*/ | */ | ||||
static void | static void | ||||
em_release_hw_control(struct adapter *adapter) | em_release_hw_control(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u32 ctrl_ext, swsm; | u32 ctrl_ext, swsm; | ||||
if (!adapter->has_manage) | if (!adapter->has_manage) | ||||
return; | return; | ||||
if (adapter->hw.mac.type == e1000_82573) { | if (hw->mac.type == e1000_82573) { | ||||
swsm = E1000_READ_REG(&adapter->hw, E1000_SWSM); | swsm = E1000_READ_REG(hw, E1000_SWSM); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_SWSM, | E1000_WRITE_REG(hw, E1000_SWSM, | ||||
swsm & ~E1000_SWSM_DRV_LOAD); | swsm & ~E1000_SWSM_DRV_LOAD); | ||||
return; | return; | ||||
} | } | ||||
/* else */ | /* else */ | ||||
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); | ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, | E1000_WRITE_REG(hw, E1000_CTRL_EXT, | ||||
ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); | ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); | ||||
return; | return; | ||||
} | } | ||||
static int | static int | ||||
em_is_valid_ether_addr(u8 *addr) | em_is_valid_ether_addr(u8 *addr) | ||||
{ | { | ||||
char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; | char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; | ||||
Show All 9 Lines | |||||
** Parse the interface capabilities with regard | ** Parse the interface capabilities with regard | ||||
** to both system management and wake-on-lan for | ** to both system management and wake-on-lan for | ||||
** later use. | ** later use. | ||||
*/ | */ | ||||
static void | static void | ||||
em_get_wakeup(if_ctx_t ctx) | em_get_wakeup(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
u16 eeprom_data = 0, device_id, apme_mask; | u16 eeprom_data = 0, device_id, apme_mask; | ||||
adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw); | adapter->has_manage = e1000_enable_mng_pass_thru(hw); | ||||
apme_mask = EM_EEPROM_APME; | apme_mask = EM_EEPROM_APME; | ||||
switch (adapter->hw.mac.type) { | switch (hw->mac.type) { | ||||
case e1000_82542: | case e1000_82542: | ||||
case e1000_82543: | case e1000_82543: | ||||
break; | break; | ||||
case e1000_82544: | case e1000_82544: | ||||
e1000_read_nvm(&adapter->hw, | e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &eeprom_data); | ||||
NVM_INIT_CONTROL2_REG, 1, &eeprom_data); | |||||
apme_mask = EM_82544_APME; | apme_mask = EM_82544_APME; | ||||
break; | break; | ||||
case e1000_82546: | case e1000_82546: | ||||
case e1000_82546_rev_3: | case e1000_82546_rev_3: | ||||
if (adapter->hw.bus.func == 1) { | if (hw->bus.func == 1) { | ||||
e1000_read_nvm(&adapter->hw, | e1000_read_nvm(hw, | ||||
NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); | NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); | ||||
break; | break; | ||||
} else | } else | ||||
e1000_read_nvm(&adapter->hw, | e1000_read_nvm(hw, | ||||
NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); | NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); | ||||
break; | break; | ||||
case e1000_82573: | case e1000_82573: | ||||
case e1000_82583: | case e1000_82583: | ||||
adapter->has_amt = TRUE; | adapter->has_amt = TRUE; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case e1000_82571: | case e1000_82571: | ||||
case e1000_82572: | case e1000_82572: | ||||
case e1000_80003es2lan: | case e1000_80003es2lan: | ||||
if (adapter->hw.bus.func == 1) { | if (hw->bus.func == 1) { | ||||
e1000_read_nvm(&adapter->hw, | e1000_read_nvm(hw, | ||||
NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); | NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); | ||||
break; | break; | ||||
} else | } else | ||||
e1000_read_nvm(&adapter->hw, | e1000_read_nvm(hw, | ||||
NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); | NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); | ||||
break; | break; | ||||
case e1000_ich8lan: | case e1000_ich8lan: | ||||
case e1000_ich9lan: | case e1000_ich9lan: | ||||
case e1000_ich10lan: | case e1000_ich10lan: | ||||
case e1000_pchlan: | case e1000_pchlan: | ||||
case e1000_pch2lan: | case e1000_pch2lan: | ||||
case e1000_pch_lpt: | case e1000_pch_lpt: | ||||
case e1000_pch_spt: | case e1000_pch_spt: | ||||
case e1000_82575: /* listing all igb devices */ | case e1000_82575: /* listing all igb devices */ | ||||
case e1000_82576: | case e1000_82576: | ||||
case e1000_82580: | case e1000_82580: | ||||
case e1000_i350: | case e1000_i350: | ||||
case e1000_i354: | case e1000_i354: | ||||
case e1000_i210: | case e1000_i210: | ||||
case e1000_i211: | case e1000_i211: | ||||
case e1000_vfadapt: | case e1000_vfadapt: | ||||
case e1000_vfadapt_i350: | case e1000_vfadapt_i350: | ||||
apme_mask = E1000_WUC_APME; | apme_mask = E1000_WUC_APME; | ||||
adapter->has_amt = TRUE; | adapter->has_amt = TRUE; | ||||
eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC); | eeprom_data = E1000_READ_REG(hw, E1000_WUC); | ||||
break; | break; | ||||
default: | default: | ||||
e1000_read_nvm(&adapter->hw, | e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); | ||||
NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); | |||||
break; | break; | ||||
} | } | ||||
if (eeprom_data & apme_mask) | if (eeprom_data & apme_mask) | ||||
adapter->wol = (E1000_WUFC_MAG | E1000_WUFC_MC); | adapter->wol = (E1000_WUFC_MAG | E1000_WUFC_MC); | ||||
/* | /* | ||||
* We have the eeprom settings, now apply the special cases | * We have the eeprom settings, now apply the special cases | ||||
* where the eeprom may be wrong or the board won't support | * where the eeprom may be wrong or the board won't support | ||||
* wake on lan on a particular port | * wake on lan on a particular port | ||||
*/ | */ | ||||
device_id = pci_get_device(dev); | device_id = pci_get_device(dev); | ||||
switch (device_id) { | switch (device_id) { | ||||
case E1000_DEV_ID_82546GB_PCIE: | case E1000_DEV_ID_82546GB_PCIE: | ||||
adapter->wol = 0; | adapter->wol = 0; | ||||
break; | break; | ||||
case E1000_DEV_ID_82546EB_FIBER: | case E1000_DEV_ID_82546EB_FIBER: | ||||
case E1000_DEV_ID_82546GB_FIBER: | case E1000_DEV_ID_82546GB_FIBER: | ||||
/* Wake events only supported on port A for dual fiber | /* Wake events only supported on port A for dual fiber | ||||
* regardless of eeprom setting */ | * regardless of eeprom setting */ | ||||
if (E1000_READ_REG(&adapter->hw, E1000_STATUS) & | if (E1000_READ_REG(hw, E1000_STATUS) & | ||||
E1000_STATUS_FUNC_1) | E1000_STATUS_FUNC_1) | ||||
adapter->wol = 0; | adapter->wol = 0; | ||||
break; | break; | ||||
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | ||||
/* if quad port adapter, disable WoL on all but port A */ | /* if quad port adapter, disable WoL on all but port A */ | ||||
if (global_quad_port_a != 0) | if (global_quad_port_a != 0) | ||||
adapter->wol = 0; | adapter->wol = 0; | ||||
/* Reset for multiple quad port adapters */ | /* Reset for multiple quad port adapters */ | ||||
if (++global_quad_port_a == 4) | if (++global_quad_port_a == 4) | ||||
global_quad_port_a = 0; | global_quad_port_a = 0; | ||||
break; | break; | ||||
case E1000_DEV_ID_82571EB_FIBER: | case E1000_DEV_ID_82571EB_FIBER: | ||||
/* Wake events only supported on port A for dual fiber | /* Wake events only supported on port A for dual fiber | ||||
* regardless of eeprom setting */ | * regardless of eeprom setting */ | ||||
if (E1000_READ_REG(&adapter->hw, E1000_STATUS) & | if (E1000_READ_REG(hw, E1000_STATUS) & | ||||
E1000_STATUS_FUNC_1) | E1000_STATUS_FUNC_1) | ||||
adapter->wol = 0; | adapter->wol = 0; | ||||
break; | break; | ||||
case E1000_DEV_ID_82571EB_QUAD_COPPER: | case E1000_DEV_ID_82571EB_QUAD_COPPER: | ||||
case E1000_DEV_ID_82571EB_QUAD_FIBER: | case E1000_DEV_ID_82571EB_QUAD_FIBER: | ||||
case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: | case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: | ||||
/* if quad port adapter, disable WoL on all but port A */ | /* if quad port adapter, disable WoL on all but port A */ | ||||
if (global_quad_port_a != 0) | if (global_quad_port_a != 0) | ||||
Show All 9 Lines | |||||
/* | /* | ||||
* Enable PCI Wake On Lan capability | * Enable PCI Wake On Lan capability | ||||
*/ | */ | ||||
static void | static void | ||||
em_enable_wakeup(if_ctx_t ctx) | em_enable_wakeup(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
if_t ifp = iflib_get_ifp(ctx); | if_t ifp = iflib_get_ifp(ctx); | ||||
int error = 0; | int error = 0; | ||||
u32 pmc, ctrl, ctrl_ext, rctl; | u32 pmc, ctrl, ctrl_ext, rctl; | ||||
u16 status; | u16 status; | ||||
if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0) | if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0) | ||||
return; | return; | ||||
/* | /* | ||||
* Determine type of Wakeup: note that wol | * Determine type of Wakeup: note that wol | ||||
* is set with all bits on by default. | * is set with all bits on by default. | ||||
*/ | */ | ||||
if ((if_getcapenable(ifp) & IFCAP_WOL_MAGIC) == 0) | if ((if_getcapenable(ifp) & IFCAP_WOL_MAGIC) == 0) | ||||
adapter->wol &= ~E1000_WUFC_MAG; | adapter->wol &= ~E1000_WUFC_MAG; | ||||
if ((if_getcapenable(ifp) & IFCAP_WOL_UCAST) == 0) | if ((if_getcapenable(ifp) & IFCAP_WOL_UCAST) == 0) | ||||
adapter->wol &= ~E1000_WUFC_EX; | adapter->wol &= ~E1000_WUFC_EX; | ||||
if ((if_getcapenable(ifp) & IFCAP_WOL_MCAST) == 0) | if ((if_getcapenable(ifp) & IFCAP_WOL_MCAST) == 0) | ||||
adapter->wol &= ~E1000_WUFC_MC; | adapter->wol &= ~E1000_WUFC_MC; | ||||
else { | else { | ||||
rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); | rctl = E1000_READ_REG(hw, E1000_RCTL); | ||||
rctl |= E1000_RCTL_MPE; | rctl |= E1000_RCTL_MPE; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); | E1000_WRITE_REG(hw, E1000_RCTL, rctl); | ||||
} | } | ||||
if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC))) | if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC))) | ||||
goto pme; | goto pme; | ||||
/* Advertise the wakeup capability */ | /* Advertise the wakeup capability */ | ||||
ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); | ctrl = E1000_READ_REG(hw, E1000_CTRL); | ||||
ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); | ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); | E1000_WRITE_REG(hw, E1000_CTRL, ctrl); | ||||
/* Keep the laser running on Fiber adapters */ | /* Keep the laser running on Fiber adapters */ | ||||
if (adapter->hw.phy.media_type == e1000_media_type_fiber || | if (hw->phy.media_type == e1000_media_type_fiber || | ||||
adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { | hw->phy.media_type == e1000_media_type_internal_serdes) { | ||||
ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); | ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); | ||||
ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; | ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); | E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); | ||||
} | } | ||||
if ((adapter->hw.mac.type == e1000_ich8lan) || | if ((hw->mac.type == e1000_ich8lan) || | ||||
(adapter->hw.mac.type == e1000_pchlan) || | (hw->mac.type == e1000_pchlan) || | ||||
(adapter->hw.mac.type == e1000_ich9lan) || | (hw->mac.type == e1000_ich9lan) || | ||||
(adapter->hw.mac.type == e1000_ich10lan)) | (hw->mac.type == e1000_ich10lan)) | ||||
e1000_suspend_workarounds_ich8lan(&adapter->hw); | e1000_suspend_workarounds_ich8lan(hw); | ||||
if ( adapter->hw.mac.type >= e1000_pchlan) { | if (hw->mac.type >= e1000_pchlan) { | ||||
error = em_enable_phy_wakeup(adapter); | error = em_enable_phy_wakeup(adapter); | ||||
if (error) | if (error) | ||||
goto pme; | goto pme; | ||||
} else { | } else { | ||||
/* Enable wakeup by the MAC */ | /* Enable wakeup by the MAC */ | ||||
E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); | E1000_WRITE_REG(hw, E1000_WUC, E1000_WUC_PME_EN); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol); | E1000_WRITE_REG(hw, E1000_WUFC, adapter->wol); | ||||
} | } | ||||
if (adapter->hw.phy.type == e1000_phy_igp_3) | if (hw->phy.type == e1000_phy_igp_3) | ||||
e1000_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); | e1000_igp3_phy_powerdown_workaround_ich8lan(hw); | ||||
pme: | pme: | ||||
status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); | status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); | ||||
status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); | status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); | ||||
if (!error && (if_getcapenable(ifp) & IFCAP_WOL)) | if (!error && (if_getcapenable(ifp) & IFCAP_WOL)) | ||||
status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; | status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; | ||||
pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); | pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); | ||||
Show All 10 Lines | em_enable_phy_wakeup(struct adapter *adapter) | ||||
struct e1000_hw *hw = &adapter->hw; | struct e1000_hw *hw = &adapter->hw; | ||||
u32 mreg, ret = 0; | u32 mreg, ret = 0; | ||||
u16 preg; | u16 preg; | ||||
/* copy MAC RARs to PHY RARs */ | /* copy MAC RARs to PHY RARs */ | ||||
e1000_copy_rx_addrs_to_phy_ich8lan(hw); | e1000_copy_rx_addrs_to_phy_ich8lan(hw); | ||||
/* copy MAC MTA to PHY MTA */ | /* copy MAC MTA to PHY MTA */ | ||||
for (int i = 0; i < hw.mac.mta_reg_count; i++) { | for (int i = 0; i < hw->mac.mta_reg_count; i++) { | ||||
mreg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); | mreg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); | ||||
e1000_write_phy_reg(hw, BM_MTA(i), (u16)(mreg & 0xFFFF)); | e1000_write_phy_reg(hw, BM_MTA(i), (u16)(mreg & 0xFFFF)); | ||||
e1000_write_phy_reg(hw, BM_MTA(i) + 1, | e1000_write_phy_reg(hw, BM_MTA(i) + 1, | ||||
(u16)((mreg >> 16) & 0xFFFF)); | (u16)((mreg >> 16) & 0xFFFF)); | ||||
} | } | ||||
/* configure PHY Rx Control register */ | /* configure PHY Rx Control register */ | ||||
e1000_read_phy_reg(hw, BM_RCTL, &preg); | e1000_read_phy_reg(hw, BM_RCTL, &preg); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | out: | ||||
return ret; | return ret; | ||||
} | } | ||||
static void | static void | ||||
em_if_led_func(if_ctx_t ctx, int onoff) | em_if_led_func(if_ctx_t ctx, int onoff) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
if (onoff) { | if (onoff) { | ||||
e1000_setup_led(&adapter->hw); | e1000_setup_led(hw); | ||||
e1000_led_on(&adapter->hw); | e1000_led_on(hw); | ||||
} else { | } else { | ||||
e1000_led_off(&adapter->hw); | e1000_led_off(hw); | ||||
e1000_cleanup_led(&adapter->hw); | e1000_cleanup_led(hw); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Disable the L0S and L1 LINK states | * Disable the L0S and L1 LINK states | ||||
*/ | */ | ||||
static void | static void | ||||
em_disable_aspm(struct adapter *adapter) | em_disable_aspm(struct adapter *adapter) | ||||
Show All 26 Lines | |||||
/********************************************************************** | /********************************************************************** | ||||
* | * | ||||
* Update the board statistics counters. | * Update the board statistics counters. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_update_stats_counters(struct adapter *adapter) | em_update_stats_counters(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
u64 prev_xoffrxc = adapter->stats.xoffrxc; | u64 prev_xoffrxc = adapter->stats.xoffrxc; | ||||
if(adapter->hw.phy.media_type == e1000_media_type_copper || | if(hw->phy.media_type == e1000_media_type_copper || | ||||
(E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) { | (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { | ||||
adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, E1000_SYMERRS); | adapter->stats.symerrs += E1000_READ_REG(hw, E1000_SYMERRS); | ||||
adapter->stats.sec += E1000_READ_REG(&adapter->hw, E1000_SEC); | adapter->stats.sec += E1000_READ_REG(hw, E1000_SEC); | ||||
} | } | ||||
adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, E1000_CRCERRS); | adapter->stats.crcerrs += E1000_READ_REG(hw, E1000_CRCERRS); | ||||
adapter->stats.mpc += E1000_READ_REG(&adapter->hw, E1000_MPC); | adapter->stats.mpc += E1000_READ_REG(hw, E1000_MPC); | ||||
adapter->stats.scc += E1000_READ_REG(&adapter->hw, E1000_SCC); | adapter->stats.scc += E1000_READ_REG(hw, E1000_SCC); | ||||
adapter->stats.ecol += E1000_READ_REG(&adapter->hw, E1000_ECOL); | adapter->stats.ecol += E1000_READ_REG(hw, E1000_ECOL); | ||||
adapter->stats.mcc += E1000_READ_REG(&adapter->hw, E1000_MCC); | adapter->stats.mcc += E1000_READ_REG(hw, E1000_MCC); | ||||
adapter->stats.latecol += E1000_READ_REG(&adapter->hw, E1000_LATECOL); | adapter->stats.latecol += E1000_READ_REG(hw, E1000_LATECOL); | ||||
adapter->stats.colc += E1000_READ_REG(&adapter->hw, E1000_COLC); | adapter->stats.colc += E1000_READ_REG(hw, E1000_COLC); | ||||
adapter->stats.dc += E1000_READ_REG(&adapter->hw, E1000_DC); | adapter->stats.dc += E1000_READ_REG(hw, E1000_DC); | ||||
adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC); | adapter->stats.rlec += E1000_READ_REG(hw, E1000_RLEC); | ||||
adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC); | adapter->stats.xonrxc += E1000_READ_REG(hw, E1000_XONRXC); | ||||
adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC); | adapter->stats.xontxc += E1000_READ_REG(hw, E1000_XONTXC); | ||||
adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC); | adapter->stats.xoffrxc += E1000_READ_REG(hw, E1000_XOFFRXC); | ||||
/* | /* | ||||
** For watchdog management we need to know if we have been | ** For watchdog management we need to know if we have been | ||||
** paused during the last interval, so capture that here. | ** paused during the last interval, so capture that here. | ||||
*/ | */ | ||||
if (adapter->stats.xoffrxc != prev_xoffrxc) | if (adapter->stats.xoffrxc != prev_xoffrxc) | ||||
adapter->shared->isc_pause_frames = 1; | adapter->shared->isc_pause_frames = 1; | ||||
adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC); | adapter->stats.xofftxc += E1000_READ_REG(hw, E1000_XOFFTXC); | ||||
adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC); | adapter->stats.fcruc += E1000_READ_REG(hw, E1000_FCRUC); | ||||
adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64); | adapter->stats.prc64 += E1000_READ_REG(hw, E1000_PRC64); | ||||
adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, E1000_PRC127); | adapter->stats.prc127 += E1000_READ_REG(hw, E1000_PRC127); | ||||
adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, E1000_PRC255); | adapter->stats.prc255 += E1000_READ_REG(hw, E1000_PRC255); | ||||
adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, E1000_PRC511); | adapter->stats.prc511 += E1000_READ_REG(hw, E1000_PRC511); | ||||
adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, E1000_PRC1023); | adapter->stats.prc1023 += E1000_READ_REG(hw, E1000_PRC1023); | ||||
adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, E1000_PRC1522); | adapter->stats.prc1522 += E1000_READ_REG(hw, E1000_PRC1522); | ||||
adapter->stats.gprc += E1000_READ_REG(&adapter->hw, E1000_GPRC); | adapter->stats.gprc += E1000_READ_REG(hw, E1000_GPRC); | ||||
adapter->stats.bprc += E1000_READ_REG(&adapter->hw, E1000_BPRC); | adapter->stats.bprc += E1000_READ_REG(hw, E1000_BPRC); | ||||
adapter->stats.mprc += E1000_READ_REG(&adapter->hw, E1000_MPRC); | adapter->stats.mprc += E1000_READ_REG(hw, E1000_MPRC); | ||||
adapter->stats.gptc += E1000_READ_REG(&adapter->hw, E1000_GPTC); | adapter->stats.gptc += E1000_READ_REG(hw, E1000_GPTC); | ||||
/* For the 64-bit byte counters the low dword must be read first. */ | /* For the 64-bit byte counters the low dword must be read first. */ | ||||
/* Both registers clear on the read of the high dword */ | /* Both registers clear on the read of the high dword */ | ||||
adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCL) + | adapter->stats.gorc += E1000_READ_REG(hw, E1000_GORCL) + | ||||
((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); | ((u64)E1000_READ_REG(hw, E1000_GORCH) << 32); | ||||
adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCL) + | adapter->stats.gotc += E1000_READ_REG(hw, E1000_GOTCL) + | ||||
((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32); | ((u64)E1000_READ_REG(hw, E1000_GOTCH) << 32); | ||||
adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC); | adapter->stats.rnbc += E1000_READ_REG(hw, E1000_RNBC); | ||||
adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC); | adapter->stats.ruc += E1000_READ_REG(hw, E1000_RUC); | ||||
adapter->stats.rfc += E1000_READ_REG(&adapter->hw, E1000_RFC); | adapter->stats.rfc += E1000_READ_REG(hw, E1000_RFC); | ||||
adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC); | adapter->stats.roc += E1000_READ_REG(hw, E1000_ROC); | ||||
adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC); | adapter->stats.rjc += E1000_READ_REG(hw, E1000_RJC); | ||||
adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH); | adapter->stats.tor += E1000_READ_REG(hw, E1000_TORH); | ||||
adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH); | adapter->stats.tot += E1000_READ_REG(hw, E1000_TOTH); | ||||
adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR); | adapter->stats.tpr += E1000_READ_REG(hw, E1000_TPR); | ||||
adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT); | adapter->stats.tpt += E1000_READ_REG(hw, E1000_TPT); | ||||
adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, E1000_PTC64); | adapter->stats.ptc64 += E1000_READ_REG(hw, E1000_PTC64); | ||||
adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, E1000_PTC127); | adapter->stats.ptc127 += E1000_READ_REG(hw, E1000_PTC127); | ||||
adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, E1000_PTC255); | adapter->stats.ptc255 += E1000_READ_REG(hw, E1000_PTC255); | ||||
adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, E1000_PTC511); | adapter->stats.ptc511 += E1000_READ_REG(hw, E1000_PTC511); | ||||
adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, E1000_PTC1023); | adapter->stats.ptc1023 += E1000_READ_REG(hw, E1000_PTC1023); | ||||
adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, E1000_PTC1522); | adapter->stats.ptc1522 += E1000_READ_REG(hw, E1000_PTC1522); | ||||
adapter->stats.mptc += E1000_READ_REG(&adapter->hw, E1000_MPTC); | adapter->stats.mptc += E1000_READ_REG(hw, E1000_MPTC); | ||||
adapter->stats.bptc += E1000_READ_REG(&adapter->hw, E1000_BPTC); | adapter->stats.bptc += E1000_READ_REG(hw, E1000_BPTC); | ||||
/* Interrupt Counts */ | /* Interrupt Counts */ | ||||
adapter->stats.iac += E1000_READ_REG(&adapter->hw, E1000_IAC); | adapter->stats.iac += E1000_READ_REG(hw, E1000_IAC); | ||||
adapter->stats.icrxptc += E1000_READ_REG(&adapter->hw, E1000_ICRXPTC); | adapter->stats.icrxptc += E1000_READ_REG(hw, E1000_ICRXPTC); | ||||
adapter->stats.icrxatc += E1000_READ_REG(&adapter->hw, E1000_ICRXATC); | adapter->stats.icrxatc += E1000_READ_REG(hw, E1000_ICRXATC); | ||||
adapter->stats.ictxptc += E1000_READ_REG(&adapter->hw, E1000_ICTXPTC); | adapter->stats.ictxptc += E1000_READ_REG(hw, E1000_ICTXPTC); | ||||
adapter->stats.ictxatc += E1000_READ_REG(&adapter->hw, E1000_ICTXATC); | adapter->stats.ictxatc += E1000_READ_REG(hw, E1000_ICTXATC); | ||||
adapter->stats.ictxqec += E1000_READ_REG(&adapter->hw, E1000_ICTXQEC); | adapter->stats.ictxqec += E1000_READ_REG(hw, E1000_ICTXQEC); | ||||
adapter->stats.ictxqmtc += E1000_READ_REG(&adapter->hw, E1000_ICTXQMTC); | adapter->stats.ictxqmtc += E1000_READ_REG(hw, E1000_ICTXQMTC); | ||||
adapter->stats.icrxdmtc += E1000_READ_REG(&adapter->hw, E1000_ICRXDMTC); | adapter->stats.icrxdmtc += E1000_READ_REG(hw, E1000_ICRXDMTC); | ||||
adapter->stats.icrxoc += E1000_READ_REG(&adapter->hw, E1000_ICRXOC); | adapter->stats.icrxoc += E1000_READ_REG(hw, E1000_ICRXOC); | ||||
if (adapter->hw.mac.type >= e1000_82543) { | if (hw->mac.type >= e1000_82543) { | ||||
adapter->stats.algnerrc += | adapter->stats.algnerrc += | ||||
E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); | E1000_READ_REG(hw, E1000_ALGNERRC); | ||||
adapter->stats.rxerrc += | adapter->stats.rxerrc += | ||||
E1000_READ_REG(&adapter->hw, E1000_RXERRC); | E1000_READ_REG(hw, E1000_RXERRC); | ||||
adapter->stats.tncrs += | adapter->stats.tncrs += | ||||
E1000_READ_REG(&adapter->hw, E1000_TNCRS); | E1000_READ_REG(hw, E1000_TNCRS); | ||||
adapter->stats.cexterr += | adapter->stats.cexterr += | ||||
E1000_READ_REG(&adapter->hw, E1000_CEXTERR); | E1000_READ_REG(hw, E1000_CEXTERR); | ||||
adapter->stats.tsctc += | adapter->stats.tsctc += | ||||
E1000_READ_REG(&adapter->hw, E1000_TSCTC); | E1000_READ_REG(hw, E1000_TSCTC); | ||||
adapter->stats.tsctfc += | adapter->stats.tsctfc += | ||||
E1000_READ_REG(&adapter->hw, E1000_TSCTFC); | E1000_READ_REG(hw, E1000_TSCTFC); | ||||
} | } | ||||
} | } | ||||
static uint64_t | static uint64_t | ||||
em_if_get_counter(if_ctx_t ctx, ift_counter cnt) | em_if_get_counter(if_ctx_t ctx, ift_counter cnt) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | |||||
* 3 - full | * 3 - full | ||||
*/ | */ | ||||
static int | static int | ||||
em_set_flowcntl(SYSCTL_HANDLER_ARGS) | em_set_flowcntl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
int error; | int error; | ||||
static int input = 3; /* default is full */ | static int input = 3; /* default is full */ | ||||
struct adapter *adapter = (struct adapter *) arg1; | struct adapter *adapter = (struct adapter *) arg1; | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
error = sysctl_handle_int(oidp, &input, 0, req); | error = sysctl_handle_int(oidp, &input, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
if (input == adapter->fc) /* no change? */ | if (input == adapter->fc) /* no change? */ | ||||
return (error); | return (error); | ||||
switch (input) { | switch (input) { | ||||
case e1000_fc_rx_pause: | case e1000_fc_rx_pause: | ||||
case e1000_fc_tx_pause: | case e1000_fc_tx_pause: | ||||
case e1000_fc_full: | case e1000_fc_full: | ||||
case e1000_fc_none: | case e1000_fc_none: | ||||
adapter->hw.fc.requested_mode = input; | hw->fc.requested_mode = input; | ||||
adapter->fc = input; | adapter->fc = input; | ||||
break; | break; | ||||
default: | default: | ||||
/* Do nothing */ | /* Do nothing */ | ||||
return (error); | return (error); | ||||
} | } | ||||
adapter->hw.fc.current_mode = adapter->hw.fc.requested_mode; | hw->fc.current_mode = hw->fc.requested_mode; | ||||
e1000_force_mac_fc(&adapter->hw); | e1000_force_mac_fc(hw); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Manage Energy Efficient Ethernet: | * Manage Energy Efficient Ethernet: | ||||
* Control values: | * Control values: | ||||
* 0/1 - enabled/disabled | * 0/1 - enabled/disabled | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* This routine is meant to be fluid, add whatever is | * This routine is meant to be fluid, add whatever is | ||||
* needed for debugging a problem. -jfv | * needed for debugging a problem. -jfv | ||||
*/ | */ | ||||
static void | static void | ||||
em_print_debug_info(struct adapter *adapter) | em_print_debug_info(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | |||||
device_t dev = iflib_get_dev(adapter->ctx); | device_t dev = iflib_get_dev(adapter->ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(adapter->ctx); | struct ifnet *ifp = iflib_get_ifp(adapter->ctx); | ||||
struct tx_ring *txr = &adapter->tx_queues->txr; | struct tx_ring *txr = &adapter->tx_queues->txr; | ||||
struct rx_ring *rxr = &adapter->rx_queues->rxr; | struct rx_ring *rxr = &adapter->rx_queues->rxr; | ||||
if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | ||||
printf("Interface is RUNNING "); | printf("Interface is RUNNING "); | ||||
else | else | ||||
printf("Interface is NOT RUNNING\n"); | printf("Interface is NOT RUNNING\n"); | ||||
if (if_getdrvflags(ifp) & IFF_DRV_OACTIVE) | if (if_getdrvflags(ifp) & IFF_DRV_OACTIVE) | ||||
printf("and INACTIVE\n"); | printf("and INACTIVE\n"); | ||||
else | else | ||||
printf("and ACTIVE\n"); | printf("and ACTIVE\n"); | ||||
for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { | for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { | ||||
device_printf(dev, "TX Queue %d ------\n", i); | device_printf(dev, "TX Queue %d ------\n", i); | ||||
device_printf(dev, "hw tdh = %d, hw tdt = %d\n", | device_printf(dev, "hw tdh = %d, hw tdt = %d\n", | ||||
E1000_READ_REG(&adapter->hw, E1000_TDH(i)), | E1000_READ_REG(hw, E1000_TDH(i)), | ||||
E1000_READ_REG(&adapter->hw, E1000_TDT(i))); | E1000_READ_REG(hw, E1000_TDT(i))); | ||||
} | } | ||||
for (int j=0; j < adapter->rx_num_queues; j++, rxr++) { | for (int j=0; j < adapter->rx_num_queues; j++, rxr++) { | ||||
device_printf(dev, "RX Queue %d ------\n", j); | device_printf(dev, "RX Queue %d ------\n", j); | ||||
device_printf(dev, "hw rdh = %d, hw rdt = %d\n", | device_printf(dev, "hw rdh = %d, hw rdt = %d\n", | ||||
E1000_READ_REG(&adapter->hw, E1000_RDH(j)), | E1000_READ_REG(hw, E1000_RDH(j)), | ||||
E1000_READ_REG(&adapter->hw, E1000_RDT(j))); | E1000_READ_REG(hw, E1000_RDT(j))); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* 82574 only: | * 82574 only: | ||||
* Write a new value to the EEPROM increasing the number of MSI-X | * Write a new value to the EEPROM increasing the number of MSI-X | ||||
* vectors from 3 to 5, for proper multiqueue support. | * vectors from 3 to 5, for proper multiqueue support. | ||||
*/ | */ | ||||
Show All 21 Lines |