Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/e1000/if_em.c
Show First 20 Lines • Show All 477 Lines • ▼ Show 20 Lines | static struct if_shared_ctx em_sctx_init = { | ||||
.isc_rx_maxsegsize = MJUM9BYTES, | .isc_rx_maxsegsize = MJUM9BYTES, | ||||
.isc_nfl = 1, | .isc_nfl = 1, | ||||
.isc_nrxqs = 1, | .isc_nrxqs = 1, | ||||
.isc_ntxqs = 1, | .isc_ntxqs = 1, | ||||
.isc_admin_intrcnt = 1, | .isc_admin_intrcnt = 1, | ||||
.isc_vendor_info = em_vendor_info_array, | .isc_vendor_info = em_vendor_info_array, | ||||
.isc_driver_version = em_driver_version, | .isc_driver_version = em_driver_version, | ||||
.isc_driver = &em_if_driver, | .isc_driver = &em_if_driver, | ||||
.isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP, | .isc_flags = IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, | ||||
.isc_nrxd_min = {EM_MIN_RXD}, | .isc_nrxd_min = {EM_MIN_RXD}, | ||||
.isc_ntxd_min = {EM_MIN_TXD}, | .isc_ntxd_min = {EM_MIN_TXD}, | ||||
.isc_nrxd_max = {EM_MAX_RXD}, | .isc_nrxd_max = {EM_MAX_RXD}, | ||||
.isc_ntxd_max = {EM_MAX_TXD}, | .isc_ntxd_max = {EM_MAX_TXD}, | ||||
.isc_nrxd_default = {EM_DEFAULT_RXD}, | .isc_nrxd_default = {EM_DEFAULT_RXD}, | ||||
.isc_ntxd_default = {EM_DEFAULT_TXD}, | .isc_ntxd_default = {EM_DEFAULT_TXD}, | ||||
}; | }; | ||||
Show All 11 Lines | static struct if_shared_ctx igb_sctx_init = { | ||||
.isc_rx_maxsegsize = MJUM9BYTES, | .isc_rx_maxsegsize = MJUM9BYTES, | ||||
.isc_nfl = 1, | .isc_nfl = 1, | ||||
.isc_nrxqs = 1, | .isc_nrxqs = 1, | ||||
.isc_ntxqs = 1, | .isc_ntxqs = 1, | ||||
.isc_admin_intrcnt = 1, | .isc_admin_intrcnt = 1, | ||||
.isc_vendor_info = igb_vendor_info_array, | .isc_vendor_info = igb_vendor_info_array, | ||||
.isc_driver_version = em_driver_version, | .isc_driver_version = em_driver_version, | ||||
.isc_driver = &em_if_driver, | .isc_driver = &em_if_driver, | ||||
.isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP, | .isc_flags = IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, | ||||
.isc_nrxd_min = {EM_MIN_RXD}, | .isc_nrxd_min = {EM_MIN_RXD}, | ||||
.isc_ntxd_min = {EM_MIN_TXD}, | .isc_ntxd_min = {EM_MIN_TXD}, | ||||
.isc_nrxd_max = {IGB_MAX_RXD}, | .isc_nrxd_max = {IGB_MAX_RXD}, | ||||
.isc_ntxd_max = {IGB_MAX_TXD}, | .isc_ntxd_max = {IGB_MAX_TXD}, | ||||
.isc_nrxd_default = {EM_DEFAULT_RXD}, | .isc_nrxd_default = {EM_DEFAULT_RXD}, | ||||
.isc_ntxd_default = {EM_DEFAULT_TXD}, | .isc_ntxd_default = {EM_DEFAULT_TXD}, | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | em_if_attach_pre(if_ctx_t ctx) | ||||
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))) { | if (resource_disabled("em", device_get_unit(dev))) { | ||||
device_printf(dev, "Disabled by device hint\n"); | device_printf(dev, "Disabled by device hint\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
adapter->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]; | ||||
/* SYSCTL stuff */ | /* SYSCTL stuff */ | ||||
▲ Show 20 Lines • Show All 665 Lines • ▼ Show 20 Lines | |||||
* MSIX Link Fast Interrupt Service routine | * MSIX 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; | ||||
u32 reg_icr; | u32 reg_icr; | ||||
int is_igb; | |||||
is_igb = (adapter->hw.mac.type >= igb_mac_min); | |||||
++adapter->link_irq; | ++adapter->link_irq; | ||||
MPASS(adapter->hw.back != NULL); | MPASS(adapter->hw.back != NULL); | ||||
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); | reg_icr = E1000_READ_REG(&adapter->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 (is_igb) { | ||||
if (reg_icr & E1000_ICR_LSC) | |||||
em_handle_link(adapter->ctx); | em_handle_link(adapter->ctx); | ||||
E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); | |||||
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask); | |||||
} else { | } else { | ||||
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { | |||||
em_handle_link(adapter->ctx); | |||||
} | |||||
E1000_WRITE_REG(&adapter->hw, E1000_IMS, | E1000_WRITE_REG(&adapter->hw, E1000_IMS, | ||||
EM_MSIX_LINK | E1000_IMS_LSC); | EM_MSIX_LINK | E1000_IMS_LSC); | ||||
if (adapter->hw.mac.type >= igb_mac_min) | |||||
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask); | |||||
} | |||||
/* | /* | ||||
* Because we must read the ICR for this interrupt | * Because we must read the ICR for this interrupt | ||||
* it may clear other causes using autoclear, for | * it may clear other causes using autoclear, for | ||||
* this reason we simply create a soft interrupt | * this reason we simply create a soft interrupt | ||||
* for all these vectors. | * for all these vectors. | ||||
*/ | */ | ||||
if (reg_icr && adapter->hw.mac.type < igb_mac_min) { | if (reg_icr) { | ||||
E1000_WRITE_REG(&adapter->hw, | E1000_WRITE_REG(&adapter->hw, | ||||
E1000_ICS, adapter->ims); | E1000_ICS, adapter->ims); | ||||
} | } | ||||
} | |||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} | } | ||||
static void | static void | ||||
em_handle_link(void *context) | em_handle_link(void *context) | ||||
{ | { | ||||
if_ctx_t ctx = context; | if_ctx_t ctx = context; | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct adapter *adapter = iflib_get_softc(ctx); | ||||
▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | em_if_timer(if_ctx_t ctx, uint16_t qid) | ||||
struct em_rx_queue *que; | struct em_rx_queue *que; | ||||
int i; | int i; | ||||
int trigger = 0; | int trigger = 0; | ||||
if (qid != 0) | if (qid != 0) | ||||
return; | return; | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
/* Reset LAA into RAR[0] on 82571 */ | |||||
if ((adapter->hw.mac.type == e1000_82571) && | |||||
e1000_get_laa_state_82571(&adapter->hw)) | |||||
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); | |||||
if (adapter->hw.mac.type < em_mac_min) | |||||
lem_smartspeed(adapter); | |||||
/* Mask to use in the irq trigger */ | /* Mask to use in the irq trigger */ | ||||
if (adapter->intr_type == IFLIB_INTR_MSIX) { | if (adapter->intr_type == IFLIB_INTR_MSIX) { | ||||
for (i = 0, que = adapter->rx_queues; i < adapter->rx_num_queues; i++, que++) | for (i = 0, que = adapter->rx_queues; i < adapter->rx_num_queues; i++, que++) | ||||
trigger |= que->eims; | trigger |= que->eims; | ||||
} else { | } else { | ||||
trigger = E1000_ICS_RXDMT0; | trigger = E1000_ICS_RXDMT0; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | if (link_check && (adapter->link_active == 0)) { | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, "Link is Down\n"); | device_printf(dev, "Link is Down\n"); | ||||
adapter->link_active = 0; | adapter->link_active = 0; | ||||
iflib_link_state_change(ctx, LINK_STATE_DOWN, ifp->if_baudrate); | iflib_link_state_change(ctx, LINK_STATE_DOWN, ifp->if_baudrate); | ||||
printf("link state changed to down\n"); | printf("link state changed to down\n"); | ||||
} | } | ||||
em_update_stats_counters(adapter); | em_update_stats_counters(adapter); | ||||
/* Reset LAA into RAR[0] on 82571 */ | |||||
if ((adapter->hw.mac.type == e1000_82571) && | |||||
e1000_get_laa_state_82571(&adapter->hw)) | |||||
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); | |||||
if (adapter->hw.mac.type < em_mac_min) | |||||
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); | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* 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 and deallocates TX/RX buffers. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | adapter->osdep.io_bus_space_handle = | ||||
rman_get_bushandle(adapter->ioport); | rman_get_bushandle(adapter->ioport); | ||||
} | } | ||||
adapter->hw.back = &adapter->osdep; | adapter->hw.back = &adapter->osdep; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | |||||
igb_intr_assign(if_ctx_t ctx, int msix) | |||||
{ | |||||
struct adapter *adapter = iflib_get_softc(ctx); | |||||
struct em_rx_queue *rx_que = adapter->rx_queues; | |||||
struct em_tx_queue *tx_que = adapter->tx_queues; | |||||
int error, rid, i, vector = 0, rx_vectors; | |||||
char buf[16]; | |||||
/* First set up ring resources */ | |||||
for (i = 0; i < adapter->rx_num_queues; i++, rx_que++, vector++) { | |||||
rid = vector + 1; | |||||
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); | |||||
if (error) { | |||||
device_printf(iflib_get_dev(ctx), "Failed to allocate que int %d err: %d\n", i, error); | |||||
adapter->rx_num_queues = i; | |||||
goto fail; | |||||
} | |||||
rx_que->msix = vector; | |||||
/* | |||||
* Set the bit to enable interrupt | |||||
* in E1000_IMS -- bits 20 and 21 | |||||
* are for RX0 and RX1, note this has | |||||
* NOTHING to do with the MSIX vector | |||||
*/ | |||||
if (adapter->hw.mac.type == e1000_82574) { | |||||
rx_que->eims = 1 << (20 + i); | |||||
adapter->ims |= rx_que->eims; | |||||
adapter->ivars |= (8 | rx_que->msix) << (i * 4); | |||||
} else if (adapter->hw.mac.type == e1000_82575) | |||||
rx_que->eims = E1000_EICR_TX_QUEUE0 << vector; | |||||
else | |||||
rx_que->eims = 1 << vector; | |||||
} | |||||
rx_vectors = vector; | |||||
vector = 0; | |||||
for (i = 0; i < adapter->tx_num_queues; i++, tx_que++, vector++) { | |||||
snprintf(buf, sizeof(buf), "txq%d", i); | |||||
tx_que = &adapter->tx_queues[i]; | |||||
tx_que->msix = adapter->rx_queues[i % adapter->rx_num_queues].msix; | |||||
rid = rman_get_start(adapter->rx_queues[i % adapter->rx_num_queues].que_irq.ii_res); | |||||
iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_TX, tx_que, tx_que->me, buf); | |||||
if (adapter->hw.mac.type == e1000_82574) { | |||||
tx_que->eims = 1 << (22 + i); | |||||
adapter->ims |= tx_que->eims; | |||||
adapter->ivars |= (8 | tx_que->msix) << (8 + (i * 4)); | |||||
} else if (adapter->hw.mac.type == e1000_82575) { | |||||
tx_que->eims = E1000_EICR_TX_QUEUE0 << (i % adapter->tx_num_queues); | |||||
} else { | |||||
tx_que->eims = 1 << (i % adapter->tx_num_queues); | |||||
} | |||||
} | |||||
/* Link interrupt */ | |||||
rid = rx_vectors + 1; | |||||
error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid, IFLIB_INTR_ADMIN, em_msix_link, adapter, 0, "aq"); | |||||
if (error) { | |||||
device_printf(iflib_get_dev(ctx), "Failed to register admin handler"); | |||||
goto fail; | |||||
} | |||||
adapter->linkvec = rx_vectors; | |||||
if (adapter->hw.mac.type < igb_mac_min) { | |||||
adapter->ivars |= (8 | rx_vectors) << 16; | |||||
adapter->ivars |= 0x80000000; | |||||
} | |||||
return (0); | |||||
fail: | |||||
iflib_irq_free(ctx, &adapter->irq); | |||||
rx_que = adapter->rx_queues; | |||||
for (int i = 0; i < adapter->rx_num_queues; i++, rx_que++) | |||||
iflib_irq_free(ctx, &rx_que->que_irq); | |||||
return (error); | |||||
} | |||||
/********************************************************************* | /********************************************************************* | ||||
* | * | ||||
* Setup the MSIX Interrupt handlers | * Setup the MSIX 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 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; | ||||
char buf[16]; | char buf[16]; | ||||
if (adapter->hw.mac.type >= igb_mac_min) { | |||||
return igb_intr_assign(ctx, msix); | |||||
} | |||||
/* 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_RX, 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 MSIX vector | * NOTHING to do with the MSIX vector | ||||
*/ | */ | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (adapter->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 (adapter->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; | |||||
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++) { | ||||
rid = vector + 1; | rid = vector + 1; | ||||
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, rid, IFLIB_INTR_TX, tx_que, tx_que->me, buf); | |||||
tx_que->msix = (vector % adapter->tx_num_queues); | error = iflib_irq_alloc_generic(ctx, &tx_que->que_irq, rid, IFLIB_INTR_TX, em_msix_que, tx_que, tx_que->me, buf); | ||||
if (error) { | |||||
device_printf(iflib_get_dev(ctx), "Failed to allocate que int %d err: %d", i, error); | |||||
adapter->tx_num_queues = i + 1; | |||||
goto fail; | |||||
} | |||||
tx_que->msix = vector; | |||||
/* | /* | ||||
* 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 MSIX vector | * NOTHING to do with the MSIX vector | ||||
*/ | */ | ||||
if (adapter->hw.mac.type == e1000_82574) { | if (adapter->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 (adapter->hw.mac.type == e1000_82575) { | ||||
tx_que->eims = E1000_EICR_TX_QUEUE0 << (i % adapter->tx_num_queues); | tx_que->eims = E1000_EICR_TX_QUEUE0 << vector; | ||||
} else { | } else { | ||||
tx_que->eims = 1 << (i % adapter->tx_num_queues); | tx_que->eims = 1 << vector; | ||||
} | } | ||||
} | } | ||||
/* Link interrupt */ | /* Link interrupt */ | ||||
rid = rx_vectors + 1; | rid = vector + 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 = vector; | |||||
if (adapter->hw.mac.type < igb_mac_min) { | if (adapter->hw.mac.type < igb_mac_min) { | ||||
adapter->ivars |= (8 | rx_vectors) << 16; | adapter->ivars |= (8 | vector) << 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); | ||||
▲ Show 20 Lines • Show All 2,545 Lines • Show Last 20 Lines |