Changeset View
Standalone View
sys/dev/e1000/if_em.c
Show First 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | |||||
static void em_if_init(if_ctx_t ctx); | static void em_if_init(if_ctx_t ctx); | ||||
static void em_if_stop(if_ctx_t ctx); | static void em_if_stop(if_ctx_t ctx); | ||||
static void em_if_media_status(if_ctx_t, struct ifmediareq *); | static void em_if_media_status(if_ctx_t, struct ifmediareq *); | ||||
static int em_if_media_change(if_ctx_t ctx); | static int em_if_media_change(if_ctx_t ctx); | ||||
static int em_if_mtu_set(if_ctx_t ctx, uint32_t mtu); | static int em_if_mtu_set(if_ctx_t ctx, uint32_t mtu); | ||||
static void em_if_timer(if_ctx_t ctx, uint16_t qid); | static void em_if_timer(if_ctx_t ctx, uint16_t qid); | ||||
static void em_if_vlan_register(if_ctx_t ctx, u16 vtag); | static void em_if_vlan_register(if_ctx_t ctx, u16 vtag); | ||||
static void em_if_vlan_unregister(if_ctx_t ctx, u16 vtag); | static void em_if_vlan_unregister(if_ctx_t ctx, u16 vtag); | ||||
static void em_if_watchdog_reset(if_ctx_t ctx); | |||||
static void em_identify_hardware(if_ctx_t ctx); | static void em_identify_hardware(if_ctx_t ctx); | ||||
static int em_allocate_pci_resources(if_ctx_t ctx); | static int em_allocate_pci_resources(if_ctx_t ctx); | ||||
static void em_free_pci_resources(if_ctx_t ctx); | static void em_free_pci_resources(if_ctx_t ctx); | ||||
static void em_reset(if_ctx_t ctx); | static void em_reset(if_ctx_t ctx); | ||||
static int em_setup_interface(if_ctx_t ctx); | static int em_setup_interface(if_ctx_t ctx); | ||||
static int em_setup_msix(if_ctx_t ctx); | static int em_setup_msix(if_ctx_t ctx); | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | static device_method_t em_if_methods[] = { | ||||
DEVMETHOD(ifdi_queues_free, em_if_queues_free), | DEVMETHOD(ifdi_queues_free, em_if_queues_free), | ||||
DEVMETHOD(ifdi_update_admin_status, em_if_update_admin_status), | DEVMETHOD(ifdi_update_admin_status, em_if_update_admin_status), | ||||
DEVMETHOD(ifdi_multi_set, em_if_multi_set), | DEVMETHOD(ifdi_multi_set, em_if_multi_set), | ||||
DEVMETHOD(ifdi_media_status, em_if_media_status), | DEVMETHOD(ifdi_media_status, em_if_media_status), | ||||
DEVMETHOD(ifdi_media_change, em_if_media_change), | DEVMETHOD(ifdi_media_change, em_if_media_change), | ||||
DEVMETHOD(ifdi_mtu_set, em_if_mtu_set), | DEVMETHOD(ifdi_mtu_set, em_if_mtu_set), | ||||
DEVMETHOD(ifdi_promisc_set, em_if_set_promisc), | DEVMETHOD(ifdi_promisc_set, em_if_set_promisc), | ||||
DEVMETHOD(ifdi_timer, em_if_timer), | DEVMETHOD(ifdi_timer, em_if_timer), | ||||
DEVMETHOD(ifdi_watchdog_reset, em_if_watchdog_reset), | |||||
DEVMETHOD(ifdi_vlan_register, em_if_vlan_register), | DEVMETHOD(ifdi_vlan_register, em_if_vlan_register), | ||||
DEVMETHOD(ifdi_vlan_unregister, em_if_vlan_unregister), | DEVMETHOD(ifdi_vlan_unregister, em_if_vlan_unregister), | ||||
DEVMETHOD(ifdi_get_counter, em_if_get_counter), | DEVMETHOD(ifdi_get_counter, em_if_get_counter), | ||||
DEVMETHOD(ifdi_led_func, em_if_led_func), | DEVMETHOD(ifdi_led_func, em_if_led_func), | ||||
DEVMETHOD(ifdi_rx_queue_intr_enable, em_if_rx_queue_intr_enable), | DEVMETHOD(ifdi_rx_queue_intr_enable, em_if_rx_queue_intr_enable), | ||||
DEVMETHOD(ifdi_tx_queue_intr_enable, em_if_tx_queue_intr_enable), | DEVMETHOD(ifdi_tx_queue_intr_enable, em_if_tx_queue_intr_enable), | ||||
DEVMETHOD(ifdi_debug, em_if_debug), | DEVMETHOD(ifdi_debug, em_if_debug), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | |||||
* Device initialization routine | * Device initialization routine | ||||
* | * | ||||
* The attach entry point is called when the driver is being loaded. | * The attach entry point is called when the driver is being loaded. | ||||
* This routine identifies the type of hardware, allocates all resources | * This routine identifies the type of hardware, allocates all resources | ||||
* 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; | ||||
if_softc_ctx_t scctx; | if_softc_ctx_t scctx; | ||||
device_t dev; | device_t dev; | ||||
struct e1000_hw *hw; | 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); | ||||
if (resource_disabled("em", device_get_unit(dev))) { | |||||
device_printf(dev, "Disabled by device hint\n"); | |||||
return (ENXIO); | |||||
} | |||||
adapter->ctx = adapter->osdep.ctx = ctx; | adapter->ctx = adapter->osdep.ctx = ctx; | ||||
adapter->dev = adapter->osdep.dev = dev; | adapter->dev = adapter->osdep.dev = dev; | ||||
scctx = adapter->shared = iflib_get_softc_ctx(ctx); | scctx = adapter->shared = iflib_get_softc_ctx(ctx); | ||||
adapter->media = iflib_get_media(ctx); | adapter->media = iflib_get_media(ctx); | ||||
hw = &adapter->hw; | hw = &adapter->hw; | ||||
adapter->tx_process_limit = scctx->isc_ntxd[0]; | adapter->tx_process_limit = scctx->isc_ntxd[0]; | ||||
Show All 21 Lines | em_if_attach_pre(if_ctx_t ctx) | ||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | ||||
OID_AUTO, "rs_dump", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, | OID_AUTO, "rs_dump", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, | ||||
em_get_rs, "I", "Dump RS indexes"); | em_get_rs, "I", "Dump RS indexes"); | ||||
/* Determine hardware and mac info */ | /* Determine hardware and mac info */ | ||||
em_identify_hardware(ctx); | em_identify_hardware(ctx); | ||||
scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); | |||||
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 (adapter->hw.mac.type >= igb_mac_min) { | if (adapter->hw.mac.type >= igb_mac_min) { | ||||
int try_second_bar; | |||||
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 (adapter->hw.mac.type != e1000_82575) | if (adapter->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. | ||||
*/ | */ | ||||
try_second_bar = pci_read_config(dev, scctx->isc_msix_bar, 4); | scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); | ||||
if (try_second_bar == 0) | if (pci_read_config(dev, scctx->isc_msix_bar, 4) == 0) | ||||
scctx->isc_msix_bar += 4; | scctx->isc_msix_bar += 4; | ||||
} else if (adapter->hw.mac.type >= em_mac_min) { | } else if (adapter->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; | ||||
Show All 13 Lines | if (adapter->hw.mac.type >= igb_mac_min) { | ||||
* TSO workarounds implemented. Generally, the penality of | * TSO workarounds implemented. Generally, the penality of | ||||
* these workarounds is rather high and may involve copying | * these workarounds is rather high and may involve copying | ||||
* mbuf data around so advantages of TSO lapse. Still, TSO may | * mbuf data around so advantages of TSO lapse. Still, TSO may | ||||
* work for a few MACs of this class - at least when sticking | * work for a few MACs of this class - at least when sticking | ||||
* 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) | |||||
* that it shall give MSI at least a try with other devices. | |||||
*/ | |||||
if (adapter->hw.mac.type == e1000_82574) { | |||||
erj: This is good!
It's bizarre that 82583 reports MSI-X support. | |||||
scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); | |||||
} else { | } else { | ||||
scctx->isc_msix_bar = -1; | |||||
scctx->isc_disable_msix = 1; | |||||
} | |||||
} 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 (adapter->hw.mac.type < e1000_82543) | if (adapter->hw.mac.type < e1000_82543) | ||||
scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM); | scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM); | ||||
/* 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"); | ||||
error = ENXIO; | error = ENXIO; | ||||
goto err_pci; | goto err_pci; | ||||
▲ Show 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | |||||
* Device removal routine | * Device removal routine | ||||
* | * | ||||
* The detach entry point is called when the driver is being removed. | * The detach entry point is called when the driver is being removed. | ||||
* This routine stops the adapter and deallocates all the resources | * This routine stops the adapter and deallocates all the resources | ||||
* that were allocated for driver operation. | * that were allocated for driver operation. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
*********************************************************************/ | *********************************************************************/ | ||||
static int | static int | ||||
em_if_detach(if_ctx_t ctx) | em_if_detach(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
INIT_DEBUGOUT("em_detach: begin"); | INIT_DEBUGOUT("em_if_detach: begin"); | ||||
e1000_phy_hw_reset(&adapter->hw); | e1000_phy_hw_reset(&adapter->hw); | ||||
em_release_manageability(adapter); | em_release_manageability(adapter); | ||||
em_release_hw_control(adapter); | em_release_hw_control(adapter); | ||||
em_free_pci_resources(ctx); | em_free_pci_resources(ctx); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
/********************************************************************* | /********************************************************************* | ||||
* 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. | ||||
* | * | ||||
* return 0 on success, positive on failure | |||||
**********************************************************************/ | **********************************************************************/ | ||||
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); | ||||
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), adapter->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(&adapter->hw, adapter->hw.mac.addr, 0); | ||||
▲ Show 20 Lines • Show All 467 Lines • ▼ Show 20 Lines | if (adapter->hw.mac.type == e1000_82542 && | ||||
reg_rctl &= ~E1000_RCTL_RST; | reg_rctl &= ~E1000_RCTL_RST; | ||||
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); | ||||
msec_delay(5); | msec_delay(5); | ||||
if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) | if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) | ||||
e1000_pci_set_mwi(&adapter->hw); | e1000_pci_set_mwi(&adapter->hw); | ||||
} | } | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* Timer routine | * Timer routine | ||||
* | * | ||||
* This routine checks for link status and updates statistics. | * This routine schedules em_if_update_admin_status() to check for | ||||
* link status and to gather statistics as well as to perform some | |||||
* controller-specific hardware patting. | |||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
em_if_timer(if_ctx_t ctx, uint16_t qid) | em_if_timer(if_ctx_t ctx, uint16_t qid) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | |||||
struct em_rx_queue *que; | |||||
int i; | |||||
int trigger = 0; | |||||
if (qid != 0) | if (qid != 0) | ||||
return; | return; | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
/* Mask to use in the irq trigger */ | |||||
if (adapter->intr_type == IFLIB_INTR_MSIX) { | |||||
for (i = 0, que = adapter->rx_queues; i < adapter->rx_num_queues; i++, que++) | |||||
trigger |= que->eims; | |||||
} else { | |||||
trigger = E1000_ICS_RXDMT0; | |||||
} | } | ||||
} | |||||
static void | static void | ||||
em_if_update_admin_status(if_ctx_t ctx) | em_if_update_admin_status(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 e1000_hw *hw = &adapter->hw; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
u32 link_check, thstat, ctrl; | u32 link_check, thstat, ctrl; | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | if ((adapter->hw.mac.type == e1000_82571) && | ||||
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); | e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); | ||||
if (adapter->hw.mac.type < em_mac_min) | if (adapter->hw.mac.type < em_mac_min) | ||||
lem_smartspeed(adapter); | lem_smartspeed(adapter); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | E1000_IMS_LSC); | E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | E1000_IMS_LSC); | ||||
} | } | ||||
static void | |||||
em_if_watchdog_reset(if_ctx_t ctx) | |||||
{ | |||||
struct adapter *adapter = iflib_get_softc(ctx); | |||||
/* | |||||
* Just count the event; iflib(4) will already trigger a | |||||
Not Done Inline ActionsI think the actual reset happens in _task_fn_admin(), where it sees the "do_reset" flag and calls iflib_if_init_locked() and that's supposed to fix whatever triggered the watchdog. I don't think the details of this comment matter, but saying the hardware is reset in em_if_update_admin_status() doesn't look right; that only seems to handle statistics and link status. erj: I think the actual reset happens in _task_fn_admin(), where it sees the "do_reset" flag and… | |||||
Done Inline ActionsWell, the comment doesn't say "resetting" but "patting". What I mean are things like the LAA reset for 82571 (which well, actually is a kind of reset) and the smartspeed handling for the LEM-class. Prior to the iflib(4) conversion, these latter were initiated by the {l,}em_local_timer() watchdog routines. Thus, my first thought when looking at the current if_em.c was that these tasks had accidentally been dropped as they are neither performed by the ifdi_timer or the ifdi_watchdog_reset method. Thus, the intent of this comment was kind of to say "look closer in em_if_update_admin_status() for non-link and non-statistical parts". So while it seems like you missed those controller-specific parts of em_if_update_admin_status() at a quick glance, too, I now think that in fact it's better to hint at these in the description of em_if_timer(). I still think that em_if_watchdog_reset() should bear a comment indicating that no further action in case of a reset is required so it doesn't look like code is missing there. marius: Well, the comment doesn't say "resetting" but "patting". What I mean are things like the LAA… | |||||
* sufficient reset of the controller. | |||||
*/ | |||||
adapter->watchdog_events++; | |||||
} | |||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* 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 and deallocates TX/RX buffers. | * global reset on the MAC. | ||||
* | * | ||||
* This routine should always be called with BOTH the CORE | |||||
* and TX locks. | |||||
**********************************************************************/ | **********************************************************************/ | ||||
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); | ||||
INIT_DEBUGOUT("em_stop: begin"); | INIT_DEBUGOUT("em_if_stop: begin"); | ||||
e1000_reset_hw(&adapter->hw); | e1000_reset_hw(&adapter->hw); | ||||
if (adapter->hw.mac.type >= e1000_82544) | if (adapter->hw.mac.type >= e1000_82544) | ||||
E1000_WRITE_REG(&adapter->hw, E1000_WUFC, 0); | E1000_WRITE_REG(&adapter->hw, E1000_WUFC, 0); | ||||
e1000_led_off(&adapter->hw); | e1000_led_off(&adapter->hw); | ||||
e1000_cleanup_led(&adapter->hw); | e1000_cleanup_led(&adapter->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) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 352 Lines • ▼ Show 20 Lines | em_setup_msix(if_ctx_t ctx) | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (adapter->hw.mac.type == e1000_82574) { | ||||
em_enable_vectors_82574(ctx); | em_enable_vectors_82574(ctx); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Initialize the hardware to a configuration | * Workaround for SmartSpeed on 82541 and 82547 controllers | ||||
* as specified by the adapter structure. | |||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
lem_smartspeed(struct adapter *adapter) | lem_smartspeed(struct adapter *adapter) | ||||
{ | { | ||||
u16 phy_tmp; | u16 phy_tmp; | ||||
if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) || | if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) || | ||||
adapter->hw.mac.autoneg == 0 || | adapter->hw.mac.autoneg == 0 || | ||||
(adapter->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) | (adapter->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | igb_init_dmac(struct adapter *adapter, u32 pba) | ||||
} else if (hw->mac.type == e1000_82580) { | } else if (hw->mac.type == e1000_82580) { | ||||
u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC); | u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC); | ||||
E1000_WRITE_REG(hw, E1000_PCIEMISC, | E1000_WRITE_REG(hw, E1000_PCIEMISC, | ||||
reg & ~E1000_PCIEMISC_LX_DECISION); | reg & ~E1000_PCIEMISC_LX_DECISION); | ||||
E1000_WRITE_REG(hw, E1000_DMACR, 0); | E1000_WRITE_REG(hw, E1000_DMACR, 0); | ||||
} | } | ||||
} | } | ||||
/********************************************************************* | |||||
* | |||||
* Initialize the hardware to a configuration as specified by the | |||||
* 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 ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct e1000_hw *hw = &adapter->hw; | struct e1000_hw *hw = &adapter->hw; | ||||
u16 rx_buffer_size; | u16 rx_buffer_size; | ||||
▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | em_reset(if_ctx_t ctx) | ||||
if (adapter->hw.mac.type >= igb_mac_min) | if (adapter->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/ | |||||
* 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) | ||||
{ | { | ||||
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; | struct e1000_hw *hw = &adapter->hw; | ||||
int i; | int i; | ||||
Show All 24 Lines | for (i = 0; i < 32; ++i) | ||||
E1000_WRITE_REG(hw, E1000_RETA(i), reta); | E1000_WRITE_REG(hw, E1000_RETA(i), reta); | ||||
E1000_WRITE_REG(hw, E1000_MRQC, E1000_MRQC_RSS_ENABLE_2Q | | E1000_WRITE_REG(hw, E1000_MRQC, E1000_MRQC_RSS_ENABLE_2Q | | ||||
E1000_MRQC_RSS_FIELD_IPV4_TCP | | E1000_MRQC_RSS_FIELD_IPV4_TCP | | ||||
E1000_MRQC_RSS_FIELD_IPV4 | | E1000_MRQC_RSS_FIELD_IPV4 | | ||||
E1000_MRQC_RSS_FIELD_IPV6_TCP_EX | | E1000_MRQC_RSS_FIELD_IPV6_TCP_EX | | ||||
E1000_MRQC_RSS_FIELD_IPV6_EX | | E1000_MRQC_RSS_FIELD_IPV6_EX | | ||||
E1000_MRQC_RSS_FIELD_IPV6); | E1000_MRQC_RSS_FIELD_IPV6); | ||||
} | } | ||||
static void | static void | ||||
igb_initialize_rss_mapping(struct adapter *adapter) | igb_initialize_rss_mapping(struct adapter *adapter) | ||||
{ | { | ||||
struct e1000_hw *hw = &adapter->hw; | struct e1000_hw *hw = &adapter->hw; | ||||
int i; | int i; | ||||
int queue_id; | int queue_id; | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | #endif | ||||
mrqc |=( E1000_MRQC_RSS_FIELD_IPV6_UDP_EX | | mrqc |=( E1000_MRQC_RSS_FIELD_IPV6_UDP_EX | | ||||
E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); | E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); | ||||
E1000_WRITE_REG(hw, E1000_MRQC, mrqc); | E1000_WRITE_REG(hw, E1000_MRQC, mrqc); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Setup networking device structure and register an interface. | * 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); | ||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = adapter->shared; | ||||
▲ Show 20 Lines • Show All 1,229 Lines • ▼ Show 20 Lines | #define QUEUE_NAME_LEN 32 | ||||
/* Driver Statistics */ | /* Driver Statistics */ | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", | ||||
CTLFLAG_RD, &adapter->dropped_pkts, | CTLFLAG_RD, &adapter->dropped_pkts, | ||||
"Driver dropped packets"); | "Driver dropped packets"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", | ||||
CTLFLAG_RD, &adapter->link_irq, | CTLFLAG_RD, &adapter->link_irq, | ||||
"Link MSI-X IRQ Handled"); | "Link MSI-X IRQ Handled"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail", | |||||
CTLFLAG_RD, &adapter->mbuf_defrag_failed, | |||||
"Defragmenting mbuf chain failed"); | |||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", | |||||
CTLFLAG_RD, &adapter->no_tx_dma_setup, | |||||
"Driver tx dma failure in xmit"); | |||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", | ||||
CTLFLAG_RD, &adapter->rx_overruns, | CTLFLAG_RD, &adapter->rx_overruns, | ||||
"RX overruns"); | "RX overruns"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", | ||||
CTLFLAG_RD, &adapter->watchdog_events, | CTLFLAG_RD, &adapter->watchdog_events, | ||||
"Watchdog timeouts"); | "Watchdog timeouts"); | ||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", | SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", | ||||
CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL, | CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL, | ||||
▲ Show 20 Lines • Show All 506 Lines • ▼ Show 20 Lines | |||||
em_enable_vectors_82574(if_ctx_t ctx) | em_enable_vectors_82574(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 e1000_hw *hw = &adapter->hw; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
u16 edata; | u16 edata; | ||||
e1000_read_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); | e1000_read_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); | ||||
printf("Current cap: %#06x\n", edata); | if (bootverbose) | ||||
device_printf(dev, "EM_NVM_PCIE_CTRL = %#06x\n", edata); | |||||
Not Done Inline ActionsIt's less clear what the number means when you replace "Current cap" with the generic-sounding NVM word name. But OTOH, this value is only interesting if you're debugging, in which case you'd want the NVM word name directly, so I'm ok with this change. erj: It's less clear what the number means when you replace "Current cap" with the generic-sounding… | |||||
if (((edata & EM_NVM_MSIX_N_MASK) >> EM_NVM_MSIX_N_SHIFT) != 4) { | if (((edata & EM_NVM_MSIX_N_MASK) >> EM_NVM_MSIX_N_SHIFT) != 4) { | ||||
device_printf(dev, "Writing to eeprom: increasing " | device_printf(dev, "Writing to eeprom: increasing " | ||||
"reported MSI-X vectors from 3 to 5...\n"); | "reported MSI-X vectors from 3 to 5...\n"); | ||||
edata &= ~(EM_NVM_MSIX_N_MASK); | edata &= ~(EM_NVM_MSIX_N_MASK); | ||||
edata |= 4 << EM_NVM_MSIX_N_SHIFT; | edata |= 4 << EM_NVM_MSIX_N_SHIFT; | ||||
e1000_write_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); | e1000_write_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); | ||||
e1000_update_nvm_checksum(hw); | e1000_update_nvm_checksum(hw); | ||||
device_printf(dev, "Writing to eeprom: done\n"); | device_printf(dev, "Writing to eeprom: done\n"); | ||||
} | } | ||||
} | } |
This is good!
It's bizarre that 82583 reports MSI-X support.