Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/e1000/if_em.c
Show First 20 Lines • Show All 299 Lines • ▼ Show 20 Lines | |||||
static bool em_if_vlan_filter_capable(struct e1000_softc *); | static bool em_if_vlan_filter_capable(struct e1000_softc *); | ||||
static bool em_if_vlan_filter_used(struct e1000_softc *); | static bool em_if_vlan_filter_used(struct e1000_softc *); | ||||
static void em_if_vlan_filter_enable(struct e1000_softc *); | static void em_if_vlan_filter_enable(struct e1000_softc *); | ||||
static void em_if_vlan_filter_disable(struct e1000_softc *); | static void em_if_vlan_filter_disable(struct e1000_softc *); | ||||
static void em_if_vlan_filter_write(struct e1000_softc *); | static void em_if_vlan_filter_write(struct e1000_softc *); | ||||
static void em_setup_vlan_hw_support(struct e1000_softc *); | static void em_setup_vlan_hw_support(struct e1000_softc *); | ||||
static int em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); | static int em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); | ||||
static void em_print_nvm_info(struct e1000_softc *); | static void em_print_nvm_info(struct e1000_softc *); | ||||
static void em_sbuf_fw_version(struct e1000_hw *, struct sbuf *); | |||||
static void em_print_fw_version(if_ctx_t ctx); | |||||
static int em_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS); | |||||
static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS); | static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS); | ||||
static int em_get_rs(SYSCTL_HANDLER_ARGS); | static int em_get_rs(SYSCTL_HANDLER_ARGS); | ||||
static void em_print_debug_info(struct e1000_softc *); | static void em_print_debug_info(struct e1000_softc *); | ||||
static int em_is_valid_ether_addr(u8 *); | static int em_is_valid_ether_addr(u8 *); | ||||
static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS); | static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS); | ||||
static void em_add_int_delay_sysctl(struct e1000_softc *, const char *, | static void em_add_int_delay_sysctl(struct e1000_softc *, const char *, | ||||
const char *, struct em_int_delay_info *, int, int); | const char *, struct em_int_delay_info *, int, int); | ||||
/* Management and WOL Support */ | /* Management and WOL Support */ | ||||
▲ Show 20 Lines • Show All 471 Lines • ▼ Show 20 Lines | |||||
*********************************************************************/ | *********************************************************************/ | ||||
static int | static int | ||||
em_if_attach_pre(if_ctx_t ctx) | em_if_attach_pre(if_ctx_t ctx) | ||||
{ | { | ||||
struct e1000_softc *sc; | struct e1000_softc *sc; | ||||
if_softc_ctx_t scctx; | if_softc_ctx_t scctx; | ||||
device_t dev; | device_t dev; | ||||
struct e1000_hw *hw; | struct e1000_hw *hw; | ||||
struct sysctl_oid_list *child; | |||||
struct sysctl_ctx_list *ctx_list; | |||||
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); | ||||
sc = iflib_get_softc(ctx); | sc = iflib_get_softc(ctx); | ||||
sc->ctx = sc->osdep.ctx = ctx; | sc->ctx = sc->osdep.ctx = ctx; | ||||
sc->dev = sc->osdep.dev = dev; | sc->dev = sc->osdep.dev = dev; | ||||
scctx = sc->shared = iflib_get_softc_ctx(ctx); | scctx = sc->shared = iflib_get_softc_ctx(ctx); | ||||
sc->media = iflib_get_media(ctx); | sc->media = iflib_get_media(ctx); | ||||
hw = &sc->hw; | hw = &sc->hw; | ||||
sc->tx_process_limit = scctx->isc_ntxd[0]; | sc->tx_process_limit = scctx->isc_ntxd[0]; | ||||
/* Determine hardware and mac info */ | |||||
em_identify_hardware(ctx); | |||||
/* SYSCTL stuff */ | /* SYSCTL stuff */ | ||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | ctx_list = device_get_sysctl_ctx(dev); | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); | ||||
OID_AUTO, "nvm", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | |||||
sc, 0, em_sysctl_nvm_info, "I", "NVM Information"); | |||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "nvm", | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | ||||
OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | em_sysctl_nvm_info, "I", "NVM Information"); | ||||
sc, 0, em_sysctl_debug_info, "I", "Debug Information"); | |||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fw_version", | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, | ||||
OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | em_sysctl_print_fw_version, "A", | ||||
sc, 0, em_set_flowcntl, "I", "Flow Control"); | "Prints FW/NVM Versions"); | ||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "debug", | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | ||||
OID_AUTO, "reg_dump", | em_sysctl_debug_info, "I", "Debug Information"); | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc", | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | |||||
em_set_flowcntl, "I", "Flow Control"); | |||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "reg_dump", | |||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, | ||||
em_get_regs, "A", "Dump Registers"); | em_get_regs, "A", "Dump Registers"); | ||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "rs_dump", | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | |||||
OID_AUTO, "rs_dump", | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | ||||
em_get_rs, "I", "Dump RS indexes"); | em_get_rs, "I", "Dump RS indexes"); | ||||
/* Determine hardware and mac info */ | |||||
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); | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | em_if_attach_pre(if_ctx_t ctx) | ||||
/* Check SOL/IDER usage */ | /* Check SOL/IDER usage */ | ||||
if (e1000_check_reset_block(hw)) | if (e1000_check_reset_block(hw)) | ||||
device_printf(dev, "PHY reset is blocked" | device_printf(dev, "PHY reset is blocked" | ||||
" due to SOL/IDER session.\n"); | " due to SOL/IDER session.\n"); | ||||
/* Sysctl for setting Energy Efficient Ethernet */ | /* Sysctl for setting Energy Efficient Ethernet */ | ||||
hw->dev_spec.ich8lan.eee_disable = eee_setting; | hw->dev_spec.ich8lan.eee_disable = eee_setting; | ||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_control", | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | ||||
OID_AUTO, "eee_control", | em_sysctl_eee, "I", "Disable Energy Efficient Ethernet"); | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | |||||
sc, 0, em_sysctl_eee, "I", | |||||
"Disable Energy Efficient Ethernet"); | |||||
/* | /* | ||||
** Start from a known state, this is | ** Start from a known state, this is | ||||
** important in reading the nvm and | ** important in reading the nvm and | ||||
** mac from that. | ** mac from that. | ||||
*/ | */ | ||||
e1000_reset_hw(hw); | e1000_reset_hw(hw); | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | em_if_attach_post(if_ctx_t ctx) | ||||
hw->mac.get_link_status = 1; | hw->mac.get_link_status = 1; | ||||
em_if_update_admin_status(ctx); | em_if_update_admin_status(ctx); | ||||
em_add_hw_stats(sc); | em_add_hw_stats(sc); | ||||
/* Non-AMT based hardware can now take control from firmware */ | /* Non-AMT based hardware can now take control from firmware */ | ||||
if (sc->has_manage && !sc->has_amt) | if (sc->has_manage && !sc->has_amt) | ||||
em_get_hw_control(sc); | em_get_hw_control(sc); | ||||
em_print_fw_version(ctx); | |||||
INIT_DEBUGOUT("em_if_attach_post: end"); | INIT_DEBUGOUT("em_if_attach_post: end"); | ||||
return (0); | return (0); | ||||
err_late: | err_late: | ||||
/* upon attach_post() error, iflib calls _if_detach() to free resources. */ | /* upon attach_post() error, iflib calls _if_detach() to free resources. */ | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 3,314 Lines • ▼ Show 20 Lines | #define QUEUE_NAME_LEN 32 | ||||
SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh", | SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh", | ||||
CTLFLAG_RD, &sc->stats.icrxdmtc, | CTLFLAG_RD, &sc->stats.icrxdmtc, | ||||
"Interrupt Cause Rx Desc Min Thresh Count"); | "Interrupt Cause Rx Desc Min Thresh Count"); | ||||
SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_overrun", | SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_overrun", | ||||
CTLFLAG_RD, &sc->stats.icrxoc, | CTLFLAG_RD, &sc->stats.icrxoc, | ||||
"Interrupt Cause Receiver Overrun Count"); | "Interrupt Cause Receiver Overrun Count"); | ||||
} | } | ||||
/************************************************************************ | |||||
* em_sbuf_fw_version | |||||
************************************************************************/ | |||||
static void | |||||
em_sbuf_fw_version(struct e1000_hw *hw, struct sbuf *buf) | |||||
{ | |||||
struct e1000_fw_version fw_ver = {0}; | |||||
const char *space = ""; | |||||
uint16_t eep = 0; | |||||
if (hw->mac.type >= igb_mac_min) { | |||||
/* | |||||
* Use the Shared Code for igb(4) | |||||
*/ | |||||
e1000_get_fw_version(hw, &fw_ver); | |||||
} else if (hw->mac.type >= em_mac_min) { | |||||
/* | |||||
* Otherwise, EEPROM version should be present on (almost?) all | |||||
* devices at 05h ( | |||||
*/ | |||||
if (e1000_read_nvm(hw, NVM_VERSION, 1, &eep)) | |||||
return; | |||||
gallatin: If it was me, I'd probably print something like "NVM version unknown" | |||||
fw_ver.eep_major = (eep & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; | |||||
fw_ver.eep_minor = (eep & NVM_MINOR_MASK) >> NVM_MINOR_SHIFT; | |||||
fw_ver.eep_build = (eep & NVM_IMAGE_ID_MASK); | |||||
} | |||||
if (fw_ver.eep_major) { | |||||
sbuf_printf(buf, "EEPROM V%d.%d build%d ", fw_ver.eep_major, | |||||
fw_ver.eep_minor, fw_ver.eep_build); | |||||
space = " "; | |||||
} | |||||
if (fw_ver.invm_major) { | |||||
sbuf_printf(buf, "%sNVM V%d.%d imgtype%d ", | |||||
space, fw_ver.invm_major, fw_ver.invm_minor, | |||||
fw_ver.invm_img_type); | |||||
space = " "; | |||||
} | |||||
if (fw_ver.or_valid) { | |||||
sbuf_printf(buf, "%sOption ROM V%d-b%d-p%d ", | |||||
space, fw_ver.or_major, fw_ver.or_build, | |||||
fw_ver.or_patch); | |||||
space = " "; | |||||
} | |||||
if (fw_ver.etrack_id) | |||||
sbuf_printf(buf, "%seTrack 0x%08x ", space, fw_ver.etrack_id); | |||||
} /* em_sbuf_fw_version */ | |||||
/************************************************************************ | |||||
* em_print_fw_version | |||||
************************************************************************/ | |||||
static void | |||||
em_print_fw_version(if_ctx_t ctx) | |||||
{ | |||||
struct e1000_softc *sc = iflib_get_softc(ctx); | |||||
struct e1000_hw *hw = &sc->hw; | |||||
device_t dev = sc->dev; | |||||
struct sbuf *buf; | |||||
int error = 0; | |||||
buf = sbuf_new_auto(); | |||||
if (!buf) { | |||||
device_printf(dev, "Could not allocate sbuf for output.\n"); | |||||
return; | |||||
} | |||||
em_sbuf_fw_version(hw, buf); | |||||
error = sbuf_finish(buf); | |||||
if (error) | |||||
device_printf(dev, "Error finishing sbuf: %d\n", error); | |||||
else if (sbuf_len(buf)) | |||||
device_printf(dev, "%s\n", sbuf_data(buf)); | |||||
sbuf_delete(buf); | |||||
} /* em_print_fw_version */ | |||||
/************************************************************************ | |||||
* em_sysctl_print_fw_version | |||||
************************************************************************/ | |||||
static int | |||||
em_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct e1000_softc *sc = (struct e1000_softc *)arg1; | |||||
struct e1000_hw *hw = &sc->hw; | |||||
device_t dev = sc->dev; | |||||
struct sbuf *buf; | |||||
int error = 0; | |||||
buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); | |||||
if (!buf) { | |||||
device_printf(dev, "Could not allocate sbuf for output.\n"); | |||||
return (ENOMEM); | |||||
} | |||||
em_sbuf_fw_version(hw, buf); | |||||
error = sbuf_finish(buf); | |||||
if (error) | |||||
device_printf(dev, "Error finishing sbuf: %d\n", error); | |||||
sbuf_delete(buf); | |||||
return (0); | |||||
} /* em_sysctl_print_fw_version */ | |||||
/********************************************************************** | /********************************************************************** | ||||
* | * | ||||
* This routine provides a way to dump out the adapter eeprom, | * This routine provides a way to dump out the adapter eeprom, | ||||
* often a useful debug/service tool. This only dumps the first | * often a useful debug/service tool. This only dumps the first | ||||
* 32 words, stuff that matters is in that extent. | * 32 words, stuff that matters is in that extent. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
Show All 26 Lines | |||||
{ | { | ||||
u16 eeprom_data; | u16 eeprom_data; | ||||
int i, j, row = 0; | int i, j, row = 0; | ||||
/* Its a bit crude, but it gets the job done */ | /* Its a bit crude, but it gets the job done */ | ||||
printf("\nInterface EEPROM Dump:\n"); | printf("\nInterface EEPROM Dump:\n"); | ||||
printf("Offset\n0x0000 "); | printf("Offset\n0x0000 "); | ||||
for (i = 0, j = 0; i < 32; i++, j++) { | for (i = 0, j = 0; i < 32; i++, j++) { | ||||
if (j == 8) { /* Make the offset block */ | if (j == 8) { /* Make the offset block */ | ||||
Not Done Inline ActionsThis will be committed as a separate bug fix, it prevents a KASSERT deep in the shared code kbowling: This will be committed as a separate bug fix, it prevents a KASSERT deep in the shared code | |||||
j = 0; ++row; | j = 0; ++row; | ||||
printf("\n0x00%x0 ",row); | printf("\n0x00%x0 ",row); | ||||
} | } | ||||
e1000_read_nvm(&sc->hw, i, 1, &eeprom_data); | e1000_read_nvm(&sc->hw, i, 1, &eeprom_data); | ||||
printf("%04x ", eeprom_data); | printf("%04x ", eeprom_data); | ||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 225 Lines • Show Last 20 Lines |
If it was me, I'd probably print something like "NVM version unknown"