Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/bnxt/if_bnxt.c
Show First 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | |||||
static void bnxt_stop(if_ctx_t ctx); | static void bnxt_stop(if_ctx_t ctx); | ||||
static void bnxt_multi_set(if_ctx_t ctx); | static void bnxt_multi_set(if_ctx_t ctx); | ||||
static int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu); | static int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu); | ||||
static void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); | static void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); | ||||
static int bnxt_media_change(if_ctx_t ctx); | static int bnxt_media_change(if_ctx_t ctx); | ||||
static int bnxt_promisc_set(if_ctx_t ctx, int flags); | static int bnxt_promisc_set(if_ctx_t ctx, int flags); | ||||
static uint64_t bnxt_get_counter(if_ctx_t, ift_counter); | static uint64_t bnxt_get_counter(if_ctx_t, ift_counter); | ||||
static void bnxt_update_admin_status(if_ctx_t ctx); | static void bnxt_update_admin_status(if_ctx_t ctx); | ||||
static void bnxt_if_timer(if_ctx_t ctx, uint16_t qid); | |||||
/* Interrupt enable / disable */ | /* Interrupt enable / disable */ | ||||
static void bnxt_intr_enable(if_ctx_t ctx); | static void bnxt_intr_enable(if_ctx_t ctx); | ||||
static int bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid); | static int bnxt_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); | ||||
static int bnxt_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); | |||||
static void bnxt_disable_intr(if_ctx_t ctx); | static void bnxt_disable_intr(if_ctx_t ctx); | ||||
static int bnxt_msix_intr_assign(if_ctx_t ctx, int msix); | static int bnxt_msix_intr_assign(if_ctx_t ctx, int msix); | ||||
/* vlan support */ | /* vlan support */ | ||||
static void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag); | static void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag); | ||||
static void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag); | static void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag); | ||||
/* ioctl */ | /* ioctl */ | ||||
static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); | static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); | ||||
static int bnxt_shutdown(if_ctx_t ctx); | |||||
static int bnxt_suspend(if_ctx_t ctx); | |||||
static int bnxt_resume(if_ctx_t ctx); | |||||
/* Internal support functions */ | /* Internal support functions */ | ||||
static int bnxt_probe_phy(struct bnxt_softc *softc); | static int bnxt_probe_phy(struct bnxt_softc *softc); | ||||
static void bnxt_add_media_types(struct bnxt_softc *softc); | static void bnxt_add_media_types(struct bnxt_softc *softc); | ||||
static int bnxt_pci_mapping(struct bnxt_softc *softc); | static int bnxt_pci_mapping(struct bnxt_softc *softc); | ||||
static void bnxt_pci_mapping_free(struct bnxt_softc *softc); | static void bnxt_pci_mapping_free(struct bnxt_softc *softc); | ||||
static int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state); | static int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state); | ||||
static int bnxt_handle_def_cp(void *arg); | static int bnxt_handle_def_cp(void *arg); | ||||
static int bnxt_handle_rx_cp(void *arg); | static int bnxt_handle_rx_cp(void *arg); | ||||
static void bnxt_clear_ids(struct bnxt_softc *softc); | static void bnxt_clear_ids(struct bnxt_softc *softc); | ||||
static void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr); | static void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr); | ||||
static void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr); | static void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr); | ||||
static void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr); | static void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr); | ||||
static void bnxt_def_cp_task(void *context); | static void bnxt_def_cp_task(void *context); | ||||
static void bnxt_handle_async_event(struct bnxt_softc *softc, | static void bnxt_handle_async_event(struct bnxt_softc *softc, | ||||
struct cmpl_base *cmpl); | struct cmpl_base *cmpl); | ||||
static uint8_t get_phy_type(struct bnxt_softc *softc); | static uint8_t get_phy_type(struct bnxt_softc *softc); | ||||
static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); | static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); | ||||
static void bnxt_get_wol_settings(struct bnxt_softc *softc); | |||||
static int bnxt_wol_config(if_ctx_t ctx); | |||||
/* | /* | ||||
* Device Interface Declaration | * Device Interface Declaration | ||||
*/ | */ | ||||
static device_method_t bnxt_methods[] = { | static device_method_t bnxt_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_register, bnxt_register), | DEVMETHOD(device_register, bnxt_register), | ||||
Show All 12 Lines | |||||
devclass_t bnxt_devclass; | devclass_t bnxt_devclass; | ||||
DRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0); | DRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0); | ||||
MODULE_DEPEND(bnxt, pci, 1, 1, 1); | MODULE_DEPEND(bnxt, pci, 1, 1, 1); | ||||
MODULE_DEPEND(bnxt, ether, 1, 1, 1); | MODULE_DEPEND(bnxt, ether, 1, 1, 1); | ||||
MODULE_DEPEND(bnxt, iflib, 1, 1, 1); | MODULE_DEPEND(bnxt, iflib, 1, 1, 1); | ||||
IFLIB_PNP_INFO(pci, bnxt, bnxt_vendor_info_array); | |||||
static device_method_t bnxt_iflib_methods[] = { | static device_method_t bnxt_iflib_methods[] = { | ||||
DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc), | DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc), | ||||
DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc), | DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc), | ||||
DEVMETHOD(ifdi_queues_free, bnxt_queues_free), | DEVMETHOD(ifdi_queues_free, bnxt_queues_free), | ||||
DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre), | DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre), | ||||
DEVMETHOD(ifdi_attach_post, bnxt_attach_post), | DEVMETHOD(ifdi_attach_post, bnxt_attach_post), | ||||
DEVMETHOD(ifdi_detach, bnxt_detach), | DEVMETHOD(ifdi_detach, bnxt_detach), | ||||
DEVMETHOD(ifdi_init, bnxt_init), | DEVMETHOD(ifdi_init, bnxt_init), | ||||
DEVMETHOD(ifdi_stop, bnxt_stop), | DEVMETHOD(ifdi_stop, bnxt_stop), | ||||
DEVMETHOD(ifdi_multi_set, bnxt_multi_set), | DEVMETHOD(ifdi_multi_set, bnxt_multi_set), | ||||
DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set), | DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set), | ||||
DEVMETHOD(ifdi_media_status, bnxt_media_status), | DEVMETHOD(ifdi_media_status, bnxt_media_status), | ||||
DEVMETHOD(ifdi_media_change, bnxt_media_change), | DEVMETHOD(ifdi_media_change, bnxt_media_change), | ||||
DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set), | DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set), | ||||
DEVMETHOD(ifdi_get_counter, bnxt_get_counter), | DEVMETHOD(ifdi_get_counter, bnxt_get_counter), | ||||
DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status), | DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status), | ||||
DEVMETHOD(ifdi_timer, bnxt_if_timer), | |||||
DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable), | DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable), | ||||
DEVMETHOD(ifdi_queue_intr_enable, bnxt_queue_intr_enable), | DEVMETHOD(ifdi_tx_queue_intr_enable, bnxt_tx_queue_intr_enable), | ||||
DEVMETHOD(ifdi_rx_queue_intr_enable, bnxt_rx_queue_intr_enable), | |||||
DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr), | DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr), | ||||
DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign), | DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign), | ||||
DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register), | DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register), | ||||
DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister), | DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister), | ||||
DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl), | DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl), | ||||
DEVMETHOD(ifdi_suspend, bnxt_suspend), | |||||
DEVMETHOD(ifdi_shutdown, bnxt_shutdown), | |||||
DEVMETHOD(ifdi_resume, bnxt_resume), | |||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t bnxt_iflib_driver = { | static driver_t bnxt_iflib_driver = { | ||||
"bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc) | "bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc) | ||||
}; | }; | ||||
/* | /* | ||||
* iflib shared context | * iflib shared context | ||||
*/ | */ | ||||
char bnxt_driver_version[] = "FreeBSD base"; | #define BNXT_DRIVER_VERSION "1.0.0.2" | ||||
char bnxt_driver_version[] = BNXT_DRIVER_VERSION; | |||||
extern struct if_txrx bnxt_txrx; | extern struct if_txrx bnxt_txrx; | ||||
static struct if_shared_ctx bnxt_sctx_init = { | static struct if_shared_ctx bnxt_sctx_init = { | ||||
.isc_magic = IFLIB_MAGIC, | .isc_magic = IFLIB_MAGIC, | ||||
.isc_txrx = &bnxt_txrx, | |||||
.isc_driver = &bnxt_iflib_driver, | .isc_driver = &bnxt_iflib_driver, | ||||
.isc_nfl = 2, // Number of Free Lists | .isc_nfl = 2, // Number of Free Lists | ||||
.isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ, | .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ | IFLIB_NEED_ETHER_PAD, | ||||
.isc_q_align = PAGE_SIZE, | .isc_q_align = PAGE_SIZE, | ||||
.isc_tx_maxsize = BNXT_TSO_SIZE, | .isc_tx_maxsize = BNXT_TSO_SIZE, | ||||
.isc_tx_maxsegsize = BNXT_TSO_SIZE, | .isc_tx_maxsegsize = BNXT_TSO_SIZE, | ||||
.isc_rx_maxsize = BNXT_TSO_SIZE, | .isc_rx_maxsize = BNXT_TSO_SIZE, | ||||
.isc_rx_maxsegsize = BNXT_TSO_SIZE, | .isc_rx_maxsegsize = BNXT_TSO_SIZE, | ||||
// Only use a single segment to avoid page size constraints | // Only use a single segment to avoid page size constraints | ||||
.isc_rx_nsegments = 1, | .isc_rx_nsegments = 1, | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | bnxt_queues_free(if_ctx_t ctx) | ||||
free(softc->tx_rings, M_DEVBUF); | free(softc->tx_rings, M_DEVBUF); | ||||
softc->tx_rings = NULL; | softc->tx_rings = NULL; | ||||
free(softc->tx_cp_rings, M_DEVBUF); | free(softc->tx_cp_rings, M_DEVBUF); | ||||
softc->tx_cp_rings = NULL; | softc->tx_cp_rings = NULL; | ||||
softc->ntxqsets = 0; | softc->ntxqsets = 0; | ||||
// Free RX queues | // Free RX queues | ||||
iflib_dma_free(&softc->rx_stats); | iflib_dma_free(&softc->rx_stats); | ||||
iflib_dma_free(&softc->hw_tx_port_stats); | |||||
iflib_dma_free(&softc->hw_rx_port_stats); | |||||
free(softc->grp_info, M_DEVBUF); | free(softc->grp_info, M_DEVBUF); | ||||
free(softc->ag_rings, M_DEVBUF); | free(softc->ag_rings, M_DEVBUF); | ||||
free(softc->rx_rings, M_DEVBUF); | free(softc->rx_rings, M_DEVBUF); | ||||
free(softc->rx_cp_rings, M_DEVBUF); | free(softc->rx_cp_rings, M_DEVBUF); | ||||
} | } | ||||
static int | static int | ||||
bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, | bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, | ||||
Show All 40 Lines | bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, | ||||
rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets, | rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets, | ||||
&softc->rx_stats, 0); | &softc->rx_stats, 0); | ||||
if (rc) | if (rc) | ||||
goto hw_stats_alloc_fail; | goto hw_stats_alloc_fail; | ||||
bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map, | bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map, | ||||
BUS_DMASYNC_PREREAD); | BUS_DMASYNC_PREREAD); | ||||
/* | |||||
* Additional 512 bytes for future expansion. | |||||
* To prevent corruption when loaded with newer firmwares with added counters. | |||||
* This can be deleted when there will be no further additions of counters. | |||||
*/ | |||||
#define BNXT_PORT_STAT_PADDING 512 | |||||
rc = iflib_dma_alloc(ctx, sizeof(struct rx_port_stats) + BNXT_PORT_STAT_PADDING, | |||||
&softc->hw_rx_port_stats, 0); | |||||
if (rc) | |||||
goto hw_port_rx_stats_alloc_fail; | |||||
bus_dmamap_sync(softc->hw_rx_port_stats.idi_tag, | |||||
softc->hw_rx_port_stats.idi_map, BUS_DMASYNC_PREREAD); | |||||
rc = iflib_dma_alloc(ctx, sizeof(struct tx_port_stats) + BNXT_PORT_STAT_PADDING, | |||||
&softc->hw_tx_port_stats, 0); | |||||
if (rc) | |||||
goto hw_port_tx_stats_alloc_fail; | |||||
bus_dmamap_sync(softc->hw_tx_port_stats.idi_tag, | |||||
softc->hw_tx_port_stats.idi_map, BUS_DMASYNC_PREREAD); | |||||
softc->rx_port_stats = (void *) softc->hw_rx_port_stats.idi_vaddr; | |||||
softc->tx_port_stats = (void *) softc->hw_tx_port_stats.idi_vaddr; | |||||
for (i = 0; i < nrxqsets; i++) { | for (i = 0; i < nrxqsets; i++) { | ||||
/* Allocation the completion ring */ | /* Allocation the completion ring */ | ||||
softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; | softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; | ||||
softc->rx_cp_rings[i].ring.phys_id = | softc->rx_cp_rings[i].ring.phys_id = | ||||
(uint16_t)HWRM_NA_SIGNATURE; | (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->rx_cp_rings[i].ring.softc = softc; | softc->rx_cp_rings[i].ring.softc = softc; | ||||
softc->rx_cp_rings[i].ring.id = i + 1; | softc->rx_cp_rings[i].ring.id = i + 1; | ||||
softc->rx_cp_rings[i].ring.doorbell = | softc->rx_cp_rings[i].ring.doorbell = | ||||
Show All 10 Lines | for (i = 0; i < nrxqsets; i++) { | ||||
softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; | softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->rx_rings[i].softc = softc; | softc->rx_rings[i].softc = softc; | ||||
softc->rx_rings[i].id = i + 1; | softc->rx_rings[i].id = i + 1; | ||||
softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80; | softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80; | ||||
softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1]; | softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1]; | ||||
softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1]; | softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1]; | ||||
softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1]; | softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1]; | ||||
/* Allocate the TPA start buffer */ | |||||
softc->rx_rings[i].tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) * | |||||
(RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT), | |||||
M_DEVBUF, M_NOWAIT | M_ZERO); | |||||
if (softc->rx_rings[i].tpa_start == NULL) { | |||||
rc = -ENOMEM; | |||||
device_printf(softc->dev, | |||||
"Unable to allocate space for TPA\n"); | |||||
goto tpa_alloc_fail; | |||||
} | |||||
/* Allocate the AG ring */ | /* Allocate the AG ring */ | ||||
softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; | softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->ag_rings[i].softc = softc; | softc->ag_rings[i].softc = softc; | ||||
softc->ag_rings[i].id = nrxqsets + i + 1; | softc->ag_rings[i].id = nrxqsets + i + 1; | ||||
softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80; | softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80; | ||||
softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2]; | softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2]; | ||||
softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2]; | softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2]; | ||||
softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2]; | softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2]; | ||||
/* Allocate the ring group */ | /* Allocate the ring group */ | ||||
softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; | softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->grp_info[i].stats_ctx = | softc->grp_info[i].stats_ctx = | ||||
softc->rx_cp_rings[i].stats_ctx_id; | softc->rx_cp_rings[i].stats_ctx_id; | ||||
softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; | softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; | ||||
softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; | softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; | ||||
softc->grp_info[i].cp_ring_id = | softc->grp_info[i].cp_ring_id = | ||||
softc->rx_cp_rings[i].ring.phys_id; | softc->rx_cp_rings[i].ring.phys_id; | ||||
bnxt_create_rx_sysctls(softc, i); | bnxt_create_rx_sysctls(softc, i); | ||||
} | } | ||||
/* | |||||
* When SR-IOV is enabled, avoid each VF sending PORT_QSTATS | |||||
* HWRM every sec with which firmware timeouts can happen | |||||
*/ | |||||
if (BNXT_PF(softc)) | |||||
bnxt_create_port_stats_sysctls(softc); | |||||
/* And finally, the VNIC */ | /* And finally, the VNIC */ | ||||
softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; | softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE; | softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->vnic_info.filter_id = -1; | softc->vnic_info.filter_id = -1; | ||||
softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE; | softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE; | softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE; | softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST; | softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST; | ||||
Show All 28 Lines | #define BNXT_PORT_STAT_PADDING 512 | ||||
softc->nrxqsets = nrxqsets; | softc->nrxqsets = nrxqsets; | ||||
return rc; | return rc; | ||||
rss_grp_alloc_fail: | rss_grp_alloc_fail: | ||||
iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); | iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); | ||||
rss_hash_alloc_fail: | rss_hash_alloc_fail: | ||||
iflib_dma_free(&softc->vnic_info.mc_list); | iflib_dma_free(&softc->vnic_info.mc_list); | ||||
tpa_alloc_fail: | |||||
mc_list_alloc_fail: | mc_list_alloc_fail: | ||||
for (i = i - 1; i >= 0; i--) | |||||
free(softc->rx_rings[i].tpa_start, M_DEVBUF); | |||||
iflib_dma_free(&softc->hw_tx_port_stats); | |||||
hw_port_tx_stats_alloc_fail: | |||||
iflib_dma_free(&softc->hw_rx_port_stats); | |||||
hw_port_rx_stats_alloc_fail: | |||||
iflib_dma_free(&softc->rx_stats); | iflib_dma_free(&softc->rx_stats); | ||||
hw_stats_alloc_fail: | hw_stats_alloc_fail: | ||||
free(softc->grp_info, M_DEVBUF); | free(softc->grp_info, M_DEVBUF); | ||||
grp_alloc_fail: | grp_alloc_fail: | ||||
free(softc->ag_rings, M_DEVBUF); | free(softc->ag_rings, M_DEVBUF); | ||||
ag_alloc_fail: | ag_alloc_fail: | ||||
free(softc->rx_rings, M_DEVBUF); | free(softc->rx_rings, M_DEVBUF); | ||||
ring_alloc_fail: | ring_alloc_fail: | ||||
free(softc->rx_cp_rings, M_DEVBUF); | free(softc->rx_cp_rings, M_DEVBUF); | ||||
cp_alloc_fail: | cp_alloc_fail: | ||||
return rc; | return rc; | ||||
} | } | ||||
static void bnxt_free_hwrm_short_cmd_req(struct bnxt_softc *softc) | |||||
{ | |||||
if (softc->hwrm_short_cmd_req_addr.idi_vaddr) | |||||
iflib_dma_free(&softc->hwrm_short_cmd_req_addr); | |||||
softc->hwrm_short_cmd_req_addr.idi_vaddr = NULL; | |||||
} | |||||
static int bnxt_alloc_hwrm_short_cmd_req(struct bnxt_softc *softc) | |||||
{ | |||||
int rc; | |||||
rc = iflib_dma_alloc(softc->ctx, softc->hwrm_max_req_len, | |||||
&softc->hwrm_short_cmd_req_addr, BUS_DMA_NOWAIT); | |||||
return rc; | |||||
} | |||||
/* Device setup and teardown */ | /* Device setup and teardown */ | ||||
static int | static int | ||||
bnxt_attach_pre(if_ctx_t ctx) | bnxt_attach_pre(if_ctx_t ctx) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
if_softc_ctx_t scctx; | if_softc_ctx_t scctx; | ||||
int rc = 0; | int rc = 0; | ||||
softc->ctx = ctx; | softc->ctx = ctx; | ||||
softc->dev = iflib_get_dev(ctx); | softc->dev = iflib_get_dev(ctx); | ||||
softc->media = iflib_get_media(ctx); | softc->media = iflib_get_media(ctx); | ||||
softc->scctx = iflib_get_softc_ctx(ctx); | softc->scctx = iflib_get_softc_ctx(ctx); | ||||
softc->sctx = iflib_get_sctx(ctx); | softc->sctx = iflib_get_sctx(ctx); | ||||
scctx = softc->scctx; | scctx = softc->scctx; | ||||
/* TODO: Better way of detecting NPAR/VF is needed */ | /* TODO: Better way of detecting NPAR/VF is needed */ | ||||
switch (softc->sctx->isc_vendor_info->pvi_device_id) { | switch (pci_get_device(softc->dev)) { | ||||
case BCM57402_NPAR: | case BCM57402_NPAR: | ||||
case BCM57404_NPAR: | case BCM57404_NPAR: | ||||
case BCM57406_NPAR: | case BCM57406_NPAR: | ||||
case BCM57407_NPAR: | case BCM57407_NPAR: | ||||
case BCM57412_NPAR1: | case BCM57412_NPAR1: | ||||
case BCM57412_NPAR2: | case BCM57412_NPAR2: | ||||
case BCM57414_NPAR1: | case BCM57414_NPAR1: | ||||
case BCM57414_NPAR2: | case BCM57414_NPAR2: | ||||
Show All 17 Lines | if (bnxt_pci_mapping(softc)) | ||||
return (ENXIO); | return (ENXIO); | ||||
/* HWRM setup/init */ | /* HWRM setup/init */ | ||||
BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); | BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); | ||||
rc = bnxt_alloc_hwrm_dma_mem(softc); | rc = bnxt_alloc_hwrm_dma_mem(softc); | ||||
if (rc) | if (rc) | ||||
goto dma_fail; | goto dma_fail; | ||||
/* Allocate the TPA start buffer */ | |||||
softc->tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) * | |||||
(RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT), | |||||
M_DEVBUF, M_NOWAIT | M_ZERO); | |||||
if (softc->tpa_start == NULL) { | |||||
rc = ENOMEM; | |||||
device_printf(softc->dev, | |||||
"Unable to allocate space for TPA\n"); | |||||
goto tpa_failed; | |||||
} | |||||
/* Get firmware version and compare with driver */ | /* Get firmware version and compare with driver */ | ||||
softc->ver_info = malloc(sizeof(struct bnxt_ver_info), | softc->ver_info = malloc(sizeof(struct bnxt_ver_info), | ||||
M_DEVBUF, M_NOWAIT | M_ZERO); | M_DEVBUF, M_NOWAIT | M_ZERO); | ||||
if (softc->ver_info == NULL) { | if (softc->ver_info == NULL) { | ||||
rc = ENOMEM; | rc = ENOMEM; | ||||
device_printf(softc->dev, | device_printf(softc->dev, | ||||
"Unable to allocate space for version info\n"); | "Unable to allocate space for version info\n"); | ||||
goto ver_alloc_fail; | goto ver_alloc_fail; | ||||
} | } | ||||
/* Default minimum required HWRM version */ | /* Default minimum required HWRM version */ | ||||
softc->ver_info->hwrm_min_major = 1; | softc->ver_info->hwrm_min_major = 1; | ||||
softc->ver_info->hwrm_min_minor = 2; | softc->ver_info->hwrm_min_minor = 2; | ||||
softc->ver_info->hwrm_min_update = 2; | softc->ver_info->hwrm_min_update = 2; | ||||
rc = bnxt_hwrm_ver_get(softc); | rc = bnxt_hwrm_ver_get(softc); | ||||
if (rc) { | if (rc) { | ||||
device_printf(softc->dev, "attach: hwrm ver get failed\n"); | device_printf(softc->dev, "attach: hwrm ver get failed\n"); | ||||
goto ver_fail; | goto ver_fail; | ||||
} | } | ||||
if (softc->flags & BNXT_FLAG_SHORT_CMD) { | |||||
rc = bnxt_alloc_hwrm_short_cmd_req(softc); | |||||
if (rc) | |||||
goto hwrm_short_cmd_alloc_fail; | |||||
} | |||||
/* Get NVRAM info */ | /* Get NVRAM info */ | ||||
if (BNXT_PF(softc)) { | |||||
softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), | softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), | ||||
M_DEVBUF, M_NOWAIT | M_ZERO); | M_DEVBUF, M_NOWAIT | M_ZERO); | ||||
if (softc->nvm_info == NULL) { | if (softc->nvm_info == NULL) { | ||||
rc = ENOMEM; | rc = ENOMEM; | ||||
device_printf(softc->dev, | device_printf(softc->dev, | ||||
"Unable to allocate space for NVRAM info\n"); | "Unable to allocate space for NVRAM info\n"); | ||||
goto nvm_alloc_fail; | goto nvm_alloc_fail; | ||||
} | } | ||||
rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, | rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, | ||||
&softc->nvm_info->device_id, &softc->nvm_info->sector_size, | &softc->nvm_info->device_id, &softc->nvm_info->sector_size, | ||||
&softc->nvm_info->size, &softc->nvm_info->reserved_size, | &softc->nvm_info->size, &softc->nvm_info->reserved_size, | ||||
&softc->nvm_info->available_size); | &softc->nvm_info->available_size); | ||||
} | |||||
/* Register the driver with the FW */ | /* Register the driver with the FW */ | ||||
rc = bnxt_hwrm_func_drv_rgtr(softc); | rc = bnxt_hwrm_func_drv_rgtr(softc); | ||||
if (rc) { | if (rc) { | ||||
device_printf(softc->dev, "attach: hwrm drv rgtr failed\n"); | device_printf(softc->dev, "attach: hwrm drv rgtr failed\n"); | ||||
goto drv_rgtr_fail; | goto drv_rgtr_fail; | ||||
} | } | ||||
rc = bnxt_hwrm_func_rgtr_async_events(softc, NULL, 0); | |||||
if (rc) { | |||||
device_printf(softc->dev, "attach: hwrm rgtr async evts failed\n"); | |||||
goto drv_rgtr_fail; | |||||
} | |||||
/* Get the HW capabilities */ | /* Get the HW capabilities */ | ||||
rc = bnxt_hwrm_func_qcaps(softc); | rc = bnxt_hwrm_func_qcaps(softc); | ||||
if (rc) | if (rc) | ||||
goto failed; | goto failed; | ||||
/* Get the current configuration of this function */ | |||||
rc = bnxt_hwrm_func_qcfg(softc); | |||||
if (rc) { | |||||
device_printf(softc->dev, "attach: hwrm func qcfg failed\n"); | |||||
goto failed; | |||||
} | |||||
iflib_set_mac(ctx, softc->func.mac_addr); | iflib_set_mac(ctx, softc->func.mac_addr); | ||||
scctx->isc_txrx = &bnxt_txrx; | |||||
scctx->isc_tx_csum_flags = (CSUM_IP | CSUM_TCP | CSUM_UDP | | |||||
CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_TSO); | |||||
scctx->isc_capenable = | |||||
/* These are translated to hwassit bits */ | |||||
IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 | | |||||
/* These are checked by iflib */ | |||||
IFCAP_LRO | IFCAP_VLAN_HWFILTER | | |||||
/* These are part of the iflib mask */ | |||||
IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU | | |||||
IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | | |||||
/* These likely get lost... */ | |||||
IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU; | |||||
if (bnxt_wol_supported(softc)) | |||||
scctx->isc_capenable |= IFCAP_WOL_MAGIC; | |||||
/* Get the queue config */ | /* Get the queue config */ | ||||
rc = bnxt_hwrm_queue_qportcfg(softc); | rc = bnxt_hwrm_queue_qportcfg(softc); | ||||
if (rc) { | if (rc) { | ||||
device_printf(softc->dev, "attach: hwrm qportcfg failed\n"); | device_printf(softc->dev, "attach: hwrm qportcfg failed\n"); | ||||
goto failed; | goto failed; | ||||
} | } | ||||
bnxt_get_wol_settings(softc); | |||||
/* Now perform a function reset */ | /* Now perform a function reset */ | ||||
rc = bnxt_hwrm_func_reset(softc); | rc = bnxt_hwrm_func_reset(softc); | ||||
bnxt_clear_ids(softc); | bnxt_clear_ids(softc); | ||||
if (rc) | if (rc) | ||||
goto failed; | goto failed; | ||||
/* Now set up iflib sc */ | /* Now set up iflib sc */ | ||||
scctx->isc_tx_nsegments = 31, | scctx->isc_tx_nsegments = 31, | ||||
scctx->isc_tx_tso_segments_max = 31; | scctx->isc_tx_tso_segments_max = 31; | ||||
scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE; | scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE; | ||||
scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE; | scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE; | ||||
scctx->isc_vectors = softc->func.max_cp_rings; | scctx->isc_vectors = softc->func.max_cp_rings; | ||||
scctx->isc_min_frame_size = BNXT_MIN_FRAME_SIZE; | |||||
scctx->isc_txrx = &bnxt_txrx; | |||||
if (scctx->isc_nrxd[0] < | if (scctx->isc_nrxd[0] < | ||||
((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2])) | ((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2])) | ||||
device_printf(softc->dev, | device_printf(softc->dev, | ||||
"WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d). Driver may be unstable\n", | "WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d). Driver may be unstable\n", | ||||
scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]); | scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]); | ||||
if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2) | if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2) | ||||
device_printf(softc->dev, | device_printf(softc->dev, | ||||
"WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d). Driver may be unstable\n", | "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d). Driver may be unstable\n", | ||||
scctx->isc_ntxd[0], scctx->isc_ntxd[1]); | scctx->isc_ntxd[0], scctx->isc_ntxd[1]); | ||||
scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0]; | scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0]; | ||||
scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) * | scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) * | ||||
scctx->isc_ntxd[1]; | scctx->isc_ntxd[1]; | ||||
scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0]; | scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0]; | ||||
scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) * | scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) * | ||||
scctx->isc_nrxd[1]; | scctx->isc_nrxd[1]; | ||||
scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) * | scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) * | ||||
scctx->isc_nrxd[2]; | scctx->isc_nrxd[2]; | ||||
scctx->isc_max_rxqsets = min(pci_msix_count(softc->dev)-1, | |||||
softc->func.max_cp_rings - 1); | scctx->isc_nrxqsets_max = min(pci_msix_count(softc->dev)-1, | ||||
scctx->isc_max_rxqsets = min(scctx->isc_max_rxqsets, | softc->fn_qcfg.alloc_completion_rings - 1); | ||||
softc->func.max_rx_rings); | scctx->isc_nrxqsets_max = min(scctx->isc_nrxqsets_max, | ||||
scctx->isc_max_txqsets = min(softc->func.max_rx_rings, | softc->fn_qcfg.alloc_rx_rings); | ||||
softc->func.max_cp_rings - scctx->isc_max_rxqsets - 1); | scctx->isc_nrxqsets_max = min(scctx->isc_nrxqsets_max, | ||||
softc->fn_qcfg.alloc_vnics); | |||||
scctx->isc_ntxqsets_max = min(softc->fn_qcfg.alloc_tx_rings, | |||||
softc->fn_qcfg.alloc_completion_rings - scctx->isc_nrxqsets_max - 1); | |||||
scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE; | scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE; | ||||
scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1; | scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1; | ||||
/* iflib will map and release this bar */ | /* iflib will map and release this bar */ | ||||
scctx->isc_msix_bar = pci_msix_table_bar(softc->dev); | scctx->isc_msix_bar = pci_msix_table_bar(softc->dev); | ||||
/* | |||||
* Default settings for HW LRO (TPA): | |||||
* Disable HW LRO by default | |||||
* Can be enabled after taking care of 'packet forwarding' | |||||
*/ | |||||
softc->hw_lro.enable = 0; | |||||
softc->hw_lro.is_mode_gro = 0; | |||||
softc->hw_lro.max_agg_segs = 5; /* 2^5 = 32 segs */ | |||||
softc->hw_lro.max_aggs = HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX; | |||||
softc->hw_lro.min_agg_len = 512; | |||||
/* Allocate the default completion ring */ | /* Allocate the default completion ring */ | ||||
softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; | softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; | ||||
softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; | softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; | ||||
softc->def_cp_ring.ring.softc = softc; | softc->def_cp_ring.ring.softc = softc; | ||||
softc->def_cp_ring.ring.id = 0; | softc->def_cp_ring.ring.id = 0; | ||||
softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80; | softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80; | ||||
softc->def_cp_ring.ring.ring_size = PAGE_SIZE / | softc->def_cp_ring.ring.ring_size = PAGE_SIZE / | ||||
sizeof(struct cmpl_base); | sizeof(struct cmpl_base); | ||||
rc = iflib_dma_alloc(ctx, | rc = iflib_dma_alloc(ctx, | ||||
sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size, | sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size, | ||||
&softc->def_cp_ring_mem, 0); | &softc->def_cp_ring_mem, 0); | ||||
softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr; | softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr; | ||||
softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr; | softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr; | ||||
iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task, | iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task, | ||||
"dflt_cp"); | "dflt_cp"); | ||||
rc = bnxt_init_sysctl_ctx(softc); | rc = bnxt_init_sysctl_ctx(softc); | ||||
if (rc) | if (rc) | ||||
goto init_sysctl_failed; | goto init_sysctl_failed; | ||||
if (BNXT_PF(softc)) { | |||||
rc = bnxt_create_nvram_sysctls(softc->nvm_info); | rc = bnxt_create_nvram_sysctls(softc->nvm_info); | ||||
if (rc) | if (rc) | ||||
goto failed; | goto failed; | ||||
} | |||||
arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0); | arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0); | ||||
softc->vnic_info.rss_hash_type = | softc->vnic_info.rss_hash_type = | ||||
HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 | | HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 | | ||||
HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 | | HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 | | ||||
HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 | | HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 | | ||||
HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 | | HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 | | ||||
HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 | | HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 | | ||||
HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6; | HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6; | ||||
rc = bnxt_create_config_sysctls_pre(softc); | rc = bnxt_create_config_sysctls_pre(softc); | ||||
if (rc) | if (rc) | ||||
goto failed; | goto failed; | ||||
rc = bnxt_create_hw_lro_sysctls(softc); | |||||
if (rc) | |||||
goto failed; | |||||
rc = bnxt_create_pause_fc_sysctls(softc); | |||||
if (rc) | |||||
goto failed; | |||||
/* Initialize the vlan list */ | /* Initialize the vlan list */ | ||||
SLIST_INIT(&softc->vnic_info.vlan_tags); | SLIST_INIT(&softc->vnic_info.vlan_tags); | ||||
softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; | softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; | ||||
return (rc); | return (rc); | ||||
failed: | failed: | ||||
bnxt_free_sysctl_ctx(softc); | bnxt_free_sysctl_ctx(softc); | ||||
init_sysctl_failed: | init_sysctl_failed: | ||||
bnxt_hwrm_func_drv_unrgtr(softc, false); | bnxt_hwrm_func_drv_unrgtr(softc, false); | ||||
drv_rgtr_fail: | drv_rgtr_fail: | ||||
if (BNXT_PF(softc)) | |||||
free(softc->nvm_info, M_DEVBUF); | free(softc->nvm_info, M_DEVBUF); | ||||
nvm_alloc_fail: | nvm_alloc_fail: | ||||
bnxt_free_hwrm_short_cmd_req(softc); | |||||
hwrm_short_cmd_alloc_fail: | |||||
ver_fail: | ver_fail: | ||||
free(softc->ver_info, M_DEVBUF); | free(softc->ver_info, M_DEVBUF); | ||||
ver_alloc_fail: | ver_alloc_fail: | ||||
free(softc->tpa_start, M_DEVBUF); | |||||
tpa_failed: | |||||
bnxt_free_hwrm_dma_mem(softc); | bnxt_free_hwrm_dma_mem(softc); | ||||
dma_fail: | dma_fail: | ||||
BNXT_HWRM_LOCK_DESTROY(softc); | BNXT_HWRM_LOCK_DESTROY(softc); | ||||
bnxt_pci_mapping_free(softc); | bnxt_pci_mapping_free(softc); | ||||
pci_disable_busmaster(softc->dev); | pci_disable_busmaster(softc->dev); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
static int | static int | ||||
bnxt_attach_post(if_ctx_t ctx) | bnxt_attach_post(if_ctx_t ctx) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
if_t ifp = iflib_get_ifp(ctx); | if_t ifp = iflib_get_ifp(ctx); | ||||
int capabilities, enabling; | |||||
int rc; | int rc; | ||||
bnxt_create_config_sysctls_post(softc); | bnxt_create_config_sysctls_post(softc); | ||||
/* Update link state etc... */ | /* Update link state etc... */ | ||||
rc = bnxt_probe_phy(softc); | rc = bnxt_probe_phy(softc); | ||||
if (rc) | if (rc) | ||||
goto failed; | goto failed; | ||||
/* Needs to be done after probing the phy */ | /* Needs to be done after probing the phy */ | ||||
bnxt_create_ver_sysctls(softc); | bnxt_create_ver_sysctls(softc); | ||||
bnxt_add_media_types(softc); | bnxt_add_media_types(softc); | ||||
ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); | ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); | ||||
if_sethwassist(ifp, (CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 | | |||||
CSUM_UDP_IPV6 | CSUM_TSO)); | |||||
capabilities = | |||||
/* These are translated to hwassit bits */ | |||||
IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 | | |||||
/* These are checked by iflib */ | |||||
IFCAP_LRO | IFCAP_VLAN_HWFILTER | | |||||
/* These are part of the iflib mask */ | |||||
IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU | | |||||
IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | | |||||
/* These likely get lost... */ | |||||
IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU; | |||||
if_setcapabilities(ifp, capabilities); | |||||
enabling = capabilities; | |||||
if_setcapenable(ifp, enabling); | |||||
softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + | softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + | ||||
ETHER_CRC_LEN; | ETHER_CRC_LEN; | ||||
failed: | failed: | ||||
return rc; | return rc; | ||||
} | } | ||||
static int | static int | ||||
bnxt_detach(if_ctx_t ctx) | bnxt_detach(if_ctx_t ctx) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
struct bnxt_vlan_tag *tag; | struct bnxt_vlan_tag *tag; | ||||
struct bnxt_vlan_tag *tmp; | struct bnxt_vlan_tag *tmp; | ||||
int i; | int i; | ||||
bnxt_wol_config(ctx); | |||||
bnxt_do_disable_intr(&softc->def_cp_ring); | bnxt_do_disable_intr(&softc->def_cp_ring); | ||||
bnxt_free_sysctl_ctx(softc); | bnxt_free_sysctl_ctx(softc); | ||||
bnxt_hwrm_func_reset(softc); | bnxt_hwrm_func_reset(softc); | ||||
bnxt_clear_ids(softc); | bnxt_clear_ids(softc); | ||||
iflib_irq_free(ctx, &softc->def_cp_ring.irq); | iflib_irq_free(ctx, &softc->def_cp_ring.irq); | ||||
iflib_config_gtask_deinit(&softc->def_cp_task); | iflib_config_gtask_deinit(&softc->def_cp_task); | ||||
/* We need to free() these here... */ | /* We need to free() these here... */ | ||||
for (i = softc->nrxqsets-1; i>=0; i--) { | for (i = softc->nrxqsets-1; i>=0; i--) { | ||||
iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); | iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); | ||||
} | } | ||||
iflib_dma_free(&softc->vnic_info.mc_list); | iflib_dma_free(&softc->vnic_info.mc_list); | ||||
iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); | iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); | ||||
iflib_dma_free(&softc->vnic_info.rss_grp_tbl); | iflib_dma_free(&softc->vnic_info.rss_grp_tbl); | ||||
if (softc->vnic_info.vlan_tag_list.idi_vaddr) | if (softc->vnic_info.vlan_tag_list.idi_vaddr) | ||||
iflib_dma_free(&softc->vnic_info.vlan_tag_list); | iflib_dma_free(&softc->vnic_info.vlan_tag_list); | ||||
SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp) | SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp) | ||||
free(tag, M_DEVBUF); | free(tag, M_DEVBUF); | ||||
iflib_dma_free(&softc->def_cp_ring_mem); | iflib_dma_free(&softc->def_cp_ring_mem); | ||||
free(softc->tpa_start, M_DEVBUF); | for (i = 0; i < softc->nrxqsets; i++) | ||||
free(softc->rx_rings[i].tpa_start, M_DEVBUF); | |||||
free(softc->ver_info, M_DEVBUF); | free(softc->ver_info, M_DEVBUF); | ||||
if (BNXT_PF(softc)) | |||||
free(softc->nvm_info, M_DEVBUF); | free(softc->nvm_info, M_DEVBUF); | ||||
bnxt_hwrm_func_drv_unrgtr(softc, false); | bnxt_hwrm_func_drv_unrgtr(softc, false); | ||||
bnxt_free_hwrm_dma_mem(softc); | bnxt_free_hwrm_dma_mem(softc); | ||||
bnxt_free_hwrm_short_cmd_req(softc); | |||||
BNXT_HWRM_LOCK_DESTROY(softc); | BNXT_HWRM_LOCK_DESTROY(softc); | ||||
pci_disable_busmaster(softc->dev); | pci_disable_busmaster(softc->dev); | ||||
bnxt_pci_mapping_free(softc); | bnxt_pci_mapping_free(softc); | ||||
return 0; | return 0; | ||||
} | } | ||||
Show All 11 Lines | if (rc) | ||||
return; | return; | ||||
bnxt_clear_ids(softc); | bnxt_clear_ids(softc); | ||||
/* Allocate the default completion ring */ | /* Allocate the default completion ring */ | ||||
softc->def_cp_ring.cons = UINT32_MAX; | softc->def_cp_ring.cons = UINT32_MAX; | ||||
softc->def_cp_ring.v_bit = 1; | softc->def_cp_ring.v_bit = 1; | ||||
bnxt_mark_cpr_invalid(&softc->def_cp_ring); | bnxt_mark_cpr_invalid(&softc->def_cp_ring); | ||||
rc = bnxt_hwrm_ring_alloc(softc, | rc = bnxt_hwrm_ring_alloc(softc, | ||||
HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, | HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, | ||||
&softc->def_cp_ring.ring, | &softc->def_cp_ring.ring, | ||||
(uint16_t)HWRM_NA_SIGNATURE, | (uint16_t)HWRM_NA_SIGNATURE, | ||||
HWRM_NA_SIGNATURE, true); | HWRM_NA_SIGNATURE, true); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
/* And now set the default CP ring as the async CP ring */ | /* And now set the default CP ring as the async CP ring */ | ||||
rc = bnxt_hwrm_func_cfg(softc); | rc = bnxt_cfg_async_cr(softc); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
for (i = 0; i < softc->nrxqsets; i++) { | for (i = 0; i < softc->nrxqsets; i++) { | ||||
/* Allocate the statistics context */ | /* Allocate the statistics context */ | ||||
rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i], | rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i], | ||||
softc->rx_stats.idi_paddr + | softc->rx_stats.idi_paddr + | ||||
(sizeof(struct ctx_hw_stats) * i)); | (sizeof(struct ctx_hw_stats) * i)); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
/* Allocate the completion ring */ | /* Allocate the completion ring */ | ||||
softc->rx_cp_rings[i].cons = UINT32_MAX; | softc->rx_cp_rings[i].cons = UINT32_MAX; | ||||
softc->rx_cp_rings[i].v_bit = 1; | softc->rx_cp_rings[i].v_bit = 1; | ||||
softc->rx_cp_rings[i].last_idx = UINT32_MAX; | softc->rx_cp_rings[i].last_idx = UINT32_MAX; | ||||
bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]); | bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]); | ||||
rc = bnxt_hwrm_ring_alloc(softc, | rc = bnxt_hwrm_ring_alloc(softc, | ||||
HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, | HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, | ||||
&softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, | &softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, | ||||
HWRM_NA_SIGNATURE, true); | HWRM_NA_SIGNATURE, true); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
/* Allocate the RX ring */ | /* Allocate the RX ring */ | ||||
rc = bnxt_hwrm_ring_alloc(softc, | rc = bnxt_hwrm_ring_alloc(softc, | ||||
HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, | HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | if (++j == softc->nrxqsets) | ||||
j = 0; | j = 0; | ||||
} | } | ||||
rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, | rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, | ||||
softc->vnic_info.rss_hash_type); | softc->vnic_info.rss_hash_type); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
#ifdef notyet | rc = bnxt_hwrm_vnic_tpa_cfg(softc); | ||||
/* Enable LRO/TPA/GRO */ | |||||
rc = bnxt_hwrm_vnic_tpa_cfg(softc, &softc->vnic_info, | |||||
(if_getcapenable(iflib_get_ifp(ctx)) & IFCAP_LRO) ? | |||||
HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA : 0); | |||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
#endif | |||||
for (i = 0; i < softc->ntxqsets; i++) { | for (i = 0; i < softc->ntxqsets; i++) { | ||||
/* Allocate the statistics context */ | /* Allocate the statistics context */ | ||||
rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i], | rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i], | ||||
softc->tx_stats.idi_paddr + | softc->tx_stats.idi_paddr + | ||||
(sizeof(struct ctx_hw_stats) * i)); | (sizeof(struct ctx_hw_stats) * i)); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
/* Allocate the completion ring */ | /* Allocate the completion ring */ | ||||
softc->tx_cp_rings[i].cons = UINT32_MAX; | softc->tx_cp_rings[i].cons = UINT32_MAX; | ||||
softc->tx_cp_rings[i].v_bit = 1; | softc->tx_cp_rings[i].v_bit = 1; | ||||
bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]); | bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]); | ||||
rc = bnxt_hwrm_ring_alloc(softc, | rc = bnxt_hwrm_ring_alloc(softc, | ||||
HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, | HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, | ||||
&softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, | &softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, | ||||
HWRM_NA_SIGNATURE, false); | HWRM_NA_SIGNATURE, false); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
/* Allocate the TX ring */ | /* Allocate the TX ring */ | ||||
rc = bnxt_hwrm_ring_alloc(softc, | rc = bnxt_hwrm_ring_alloc(softc, | ||||
HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, | HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, | ||||
&softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id, | &softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id, | ||||
softc->tx_cp_rings[i].stats_ctx_id, false); | softc->tx_cp_rings[i].stats_ctx_id, false); | ||||
if (rc) | if (rc) | ||||
goto fail; | goto fail; | ||||
BNXT_TX_DB(&softc->tx_rings[i], 0); | BNXT_TX_DB(&softc->tx_rings[i], 0); | ||||
/* TODO: Cumulus+ doesn't need the double doorbell */ | /* TODO: Cumulus+ doesn't need the double doorbell */ | ||||
BNXT_TX_DB(&softc->tx_rings[i], 0); | BNXT_TX_DB(&softc->tx_rings[i], 0); | ||||
} | } | ||||
bnxt_do_enable_intr(&softc->def_cp_ring); | bnxt_do_enable_intr(&softc->def_cp_ring); | ||||
bnxt_media_status(softc->ctx, &ifmr); | bnxt_media_status(softc->ctx, &ifmr); | ||||
bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); | |||||
return; | return; | ||||
fail: | fail: | ||||
bnxt_hwrm_func_reset(softc); | bnxt_hwrm_func_reset(softc); | ||||
bnxt_clear_ids(softc); | bnxt_clear_ids(softc); | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu) | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static void | ||||
bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) | bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
struct bnxt_link_info *link_info = &softc->link_info; | struct bnxt_link_info *link_info = &softc->link_info; | ||||
uint8_t phy_type = get_phy_type(softc); | struct ifmedia_entry *next; | ||||
uint64_t target_baudrate = bnxt_get_baudrate(link_info); | |||||
int active_media = IFM_UNKNOWN; | |||||
bnxt_update_link(softc, true); | bnxt_update_link(softc, true); | ||||
ifmr->ifm_status = IFM_AVALID; | ifmr->ifm_status = IFM_AVALID; | ||||
ifmr->ifm_active = IFM_ETHER; | ifmr->ifm_active = IFM_ETHER; | ||||
if (link_info->link_up) | if (link_info->link_up) | ||||
ifmr->ifm_status |= IFM_ACTIVE; | ifmr->ifm_status |= IFM_ACTIVE; | ||||
else | else | ||||
ifmr->ifm_status &= ~IFM_ACTIVE; | ifmr->ifm_status &= ~IFM_ACTIVE; | ||||
if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL) | if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_CFG_FULL) | ||||
ifmr->ifm_active |= IFM_FDX; | ifmr->ifm_active |= IFM_FDX; | ||||
else | else | ||||
ifmr->ifm_active |= IFM_HDX; | ifmr->ifm_active |= IFM_HDX; | ||||
switch (link_info->link_speed) { | /* | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB: | * Go through the list of supported media which got prepared | ||||
ifmr->ifm_active |= IFM_100_T; | * as part of bnxt_add_media_types() using api ifmedia_add(). | ||||
*/ | |||||
LIST_FOREACH(next, &(iflib_get_media(ctx)->ifm_list), ifm_list) { | |||||
if (ifmedia_baudrate(next->ifm_media) == target_baudrate) { | |||||
active_media = next->ifm_media; | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: | |||||
ifmr->ifm_active |= IFM_1000_KX; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: | |||||
ifmr->ifm_active |= IFM_1000_T; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: | |||||
ifmr->ifm_active |= IFM_1000_SGMII; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | } | ||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: | |||||
ifmr->ifm_active |= IFM_2500_KX; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: | |||||
ifmr->ifm_active |= IFM_2500_T; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | } | ||||
break; | ifmr->ifm_active |= active_media; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | |||||
ifmr->ifm_active |= IFM_10G_CR1; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | |||||
ifmr->ifm_active |= IFM_10G_KR; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: | |||||
ifmr->ifm_active |= IFM_10G_LR; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: | |||||
ifmr->ifm_active |= IFM_10G_SR; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: | |||||
ifmr->ifm_active |= IFM_10G_KX4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: | |||||
ifmr->ifm_active |= IFM_10G_T; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: | |||||
ifmr->ifm_active |= IFM_20G_KR2; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | |||||
ifmr->ifm_active |= IFM_25G_CR; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | |||||
ifmr->ifm_active |= IFM_25G_KR; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: | |||||
ifmr->ifm_active |= IFM_25G_SR; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | |||||
ifmr->ifm_active |= IFM_40G_CR4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | |||||
ifmr->ifm_active |= IFM_40G_KR4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: | |||||
ifmr->ifm_active |= IFM_40G_LR4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: | |||||
ifmr->ifm_active |= IFM_40G_SR4; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | |||||
ifmr->ifm_active |= IFM_50G_CR2; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | |||||
ifmr->ifm_active |= IFM_50G_KR2; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: | |||||
switch (phy_type) { | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | |||||
ifmr->ifm_active |= IFM_100G_CR4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | |||||
ifmr->ifm_active |= IFM_100G_KR4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: | |||||
ifmr->ifm_active |= IFM_100G_LR4; | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: | |||||
ifmr->ifm_active |= IFM_100G_SR4; | |||||
break; | |||||
default: | |||||
ifmr->ifm_active |= IFM_UNKNOWN; | |||||
break; | |||||
} | |||||
default: | |||||
return; | |||||
} | |||||
if (link_info->pause == (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | | if (link_info->flow_ctrl.rx) | ||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) | |||||
ifmr->ifm_active |= (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); | |||||
else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) | |||||
ifmr->ifm_active |= IFM_ETH_TXPAUSE; | |||||
else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) | |||||
ifmr->ifm_active |= IFM_ETH_RXPAUSE; | ifmr->ifm_active |= IFM_ETH_RXPAUSE; | ||||
if (link_info->flow_ctrl.tx) | |||||
ifmr->ifm_active |= IFM_ETH_TXPAUSE; | |||||
bnxt_report_link(softc); | bnxt_report_link(softc); | ||||
return; | return; | ||||
} | } | ||||
static int | static int | ||||
bnxt_media_change(if_ctx_t ctx) | bnxt_media_change(if_ctx_t ctx) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | default: | ||||
device_printf(softc->dev, | device_printf(softc->dev, | ||||
"Unsupported media type! Using auto\n"); | "Unsupported media type! Using auto\n"); | ||||
/* Fall-through */ | /* Fall-through */ | ||||
case IFM_AUTO: | case IFM_AUTO: | ||||
// Auto | // Auto | ||||
softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; | softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; | ||||
break; | break; | ||||
} | } | ||||
rc = bnxt_hwrm_set_link_setting(softc, true, true); | rc = bnxt_hwrm_set_link_setting(softc, true, true, true); | ||||
bnxt_media_status(softc->ctx, &ifmr); | bnxt_media_status(softc->ctx, &ifmr); | ||||
return rc; | return rc; | ||||
} | } | ||||
static int | static int | ||||
bnxt_promisc_set(if_ctx_t ctx, int flags) | bnxt_promisc_set(if_ctx_t ctx, int flags) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
Show All 31 Lines | if (cnt < IFCOUNTERS) | ||||
return if_get_counter_default(ifp, cnt); | return if_get_counter_default(ifp, cnt); | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static void | ||||
bnxt_update_admin_status(if_ctx_t ctx) | bnxt_update_admin_status(if_ctx_t ctx) | ||||
{ | { | ||||
/* TODO: do we need to do anything here? */ | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
/* | |||||
* When SR-IOV is enabled, avoid each VF sending this HWRM | |||||
* request every sec with which firmware timeouts can happen | |||||
*/ | |||||
if (BNXT_PF(softc)) { | |||||
bnxt_hwrm_port_qstats(softc); | |||||
} | |||||
return; | return; | ||||
} | } | ||||
static void | |||||
bnxt_if_timer(if_ctx_t ctx, uint16_t qid) | |||||
{ | |||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | |||||
uint64_t ticks_now = ticks; | |||||
/* Schedule bnxt_update_admin_status() once per sec */ | |||||
if (ticks_now - softc->admin_ticks >= hz) { | |||||
softc->admin_ticks = ticks_now; | |||||
iflib_admin_intr_deferred(ctx); | |||||
} | |||||
return; | |||||
} | |||||
static void inline | static void inline | ||||
bnxt_do_enable_intr(struct bnxt_cp_ring *cpr) | bnxt_do_enable_intr(struct bnxt_cp_ring *cpr) | ||||
{ | { | ||||
if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) { | if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) { | ||||
/* First time enabling, do not set index */ | /* First time enabling, do not set index */ | ||||
if (cpr->cons == UINT32_MAX) | if (cpr->cons == UINT32_MAX) | ||||
BNXT_CP_ENABLE_DB(&cpr->ring); | BNXT_CP_ENABLE_DB(&cpr->ring); | ||||
else | else | ||||
Show All 19 Lines | bnxt_intr_enable(if_ctx_t ctx) | ||||
for (i = 0; i < softc->nrxqsets; i++) | for (i = 0; i < softc->nrxqsets; i++) | ||||
bnxt_do_enable_intr(&softc->rx_cp_rings[i]); | bnxt_do_enable_intr(&softc->rx_cp_rings[i]); | ||||
return; | return; | ||||
} | } | ||||
/* Enable interrupt for a single queue */ | /* Enable interrupt for a single queue */ | ||||
static int | static int | ||||
bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid) | bnxt_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
bnxt_do_enable_intr(&softc->tx_cp_rings[qid]); | |||||
return 0; | |||||
} | |||||
static int | |||||
bnxt_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) | |||||
{ | |||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | |||||
bnxt_do_enable_intr(&softc->rx_cp_rings[qid]); | bnxt_do_enable_intr(&softc->rx_cp_rings[qid]); | ||||
return 0; | return 0; | ||||
} | } | ||||
/* Disable all interrupts */ | /* Disable all interrupts */ | ||||
static void | static void | ||||
bnxt_disable_intr(if_ctx_t ctx) | bnxt_disable_intr(if_ctx_t ctx) | ||||
{ | { | ||||
Show All 13 Lines | |||||
} | } | ||||
static int | static int | ||||
bnxt_msix_intr_assign(if_ctx_t ctx, int msix) | bnxt_msix_intr_assign(if_ctx_t ctx, int msix) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
int rc; | int rc; | ||||
int i; | int i; | ||||
char irq_name[16]; | |||||
rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq, | rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq, | ||||
softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN, | softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN, | ||||
bnxt_handle_def_cp, softc, 0, "def_cp"); | bnxt_handle_def_cp, softc, 0, "def_cp"); | ||||
if (rc) { | if (rc) { | ||||
device_printf(iflib_get_dev(ctx), | device_printf(iflib_get_dev(ctx), | ||||
"Failed to register default completion ring handler\n"); | "Failed to register default completion ring handler\n"); | ||||
return rc; | return rc; | ||||
} | } | ||||
for (i=0; i<softc->scctx->isc_nrxqsets; i++) { | for (i=0; i<softc->scctx->isc_nrxqsets; i++) { | ||||
snprintf(irq_name, sizeof(irq_name), "rxq%d", i); | |||||
rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq, | rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq, | ||||
softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX, | softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX, | ||||
bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, "rx_cp"); | bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, irq_name); | ||||
if (rc) { | if (rc) { | ||||
device_printf(iflib_get_dev(ctx), | device_printf(iflib_get_dev(ctx), | ||||
"Failed to register RX completion ring handler\n"); | "Failed to register RX completion ring handler\n"); | ||||
i--; | i--; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
} | } | ||||
for (i=0; i<softc->scctx->isc_ntxqsets; i++) | for (i=0; i<softc->scctx->isc_ntxqsets; i++) | ||||
iflib_softirq_alloc_generic(ctx, i + 1, IFLIB_INTR_TX, NULL, i, | iflib_softirq_alloc_generic(ctx, NULL, IFLIB_INTR_TX, NULL, i, "tx_cp"); | ||||
"tx_cp"); | |||||
return rc; | return rc; | ||||
fail: | fail: | ||||
for (; i>=0; i--) | for (; i>=0; i--) | ||||
iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); | iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); | ||||
iflib_irq_free(ctx, &softc->def_cp_ring.irq); | iflib_irq_free(ctx, &softc->def_cp_ring.irq); | ||||
return rc; | return rc; | ||||
Show All 29 Lines | if (vlan_tag->tag == vtag) { | ||||
bnxt_vlan_tag, next); | bnxt_vlan_tag, next); | ||||
free(vlan_tag, M_DEVBUF); | free(vlan_tag, M_DEVBUF); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
bnxt_wol_config(if_ctx_t ctx) | |||||
{ | |||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | |||||
if_t ifp = iflib_get_ifp(ctx); | |||||
if (!softc) | |||||
return -EBUSY; | |||||
if (!bnxt_wol_supported(softc)) | |||||
return -ENOTSUP; | |||||
if (if_getcapabilities(ifp) & IFCAP_WOL_MAGIC) { | |||||
if (!softc->wol) { | |||||
if (bnxt_hwrm_alloc_wol_fltr(softc)) | |||||
return -EBUSY; | |||||
softc->wol = 1; | |||||
} | |||||
} else { | |||||
if (softc->wol) { | |||||
if (bnxt_hwrm_free_wol_fltr(softc)) | |||||
return -EBUSY; | |||||
softc->wol = 0; | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
static int | |||||
bnxt_shutdown(if_ctx_t ctx) | |||||
{ | |||||
bnxt_wol_config(ctx); | |||||
return 0; | |||||
} | |||||
static int | |||||
bnxt_suspend(if_ctx_t ctx) | |||||
{ | |||||
bnxt_wol_config(ctx); | |||||
return 0; | |||||
} | |||||
static int | |||||
bnxt_resume(if_ctx_t ctx) | |||||
{ | |||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | |||||
bnxt_get_wol_settings(softc); | |||||
return 0; | |||||
} | |||||
static int | |||||
bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) | bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) | ||||
{ | { | ||||
struct bnxt_softc *softc = iflib_get_softc(ctx); | struct bnxt_softc *softc = iflib_get_softc(ctx); | ||||
struct ifreq *ifr = (struct ifreq *)data; | struct ifreq *ifr = (struct ifreq *)data; | ||||
struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer; | struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer; | ||||
struct bnxt_ioctl_header *ioh = | struct bnxt_ioctl_header *ioh = | ||||
(struct bnxt_ioctl_header *)(ifbuf->buffer); | (struct bnxt_ioctl_header *)(ifbuf->buffer); | ||||
int rc = ENOTSUP; | int rc = ENOTSUP; | ||||
▲ Show 20 Lines • Show All 332 Lines • ▼ Show 20 Lines | device_printf(softc->dev, | ||||
"Probe phy can't update link (rc: %x)\n", rc); | "Probe phy can't update link (rc: %x)\n", rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
/*initialize the ethool setting copy with NVM settings */ | /*initialize the ethool setting copy with NVM settings */ | ||||
if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) | if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) | ||||
link_info->autoneg |= BNXT_AUTONEG_SPEED; | link_info->autoneg |= BNXT_AUTONEG_SPEED; | ||||
if (link_info->auto_pause & (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | | |||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) { | |||||
if (link_info->auto_pause == ( | |||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | | |||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) | |||||
link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; | |||||
link_info->req_flow_ctrl = link_info->auto_pause; | |||||
} else if (link_info->force_pause & ( | |||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | | |||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) { | |||||
link_info->req_flow_ctrl = link_info->force_pause; | |||||
} | |||||
link_info->req_duplex = link_info->duplex_setting; | link_info->req_duplex = link_info->duplex_setting; | ||||
if (link_info->autoneg & BNXT_AUTONEG_SPEED) | if (link_info->autoneg & BNXT_AUTONEG_SPEED) | ||||
link_info->req_link_speed = link_info->auto_link_speed; | link_info->req_link_speed = link_info->auto_link_speed; | ||||
else | else | ||||
link_info->req_link_speed = link_info->force_link_speed; | link_info->req_link_speed = link_info->force_link_speed; | ||||
return (rc); | return (rc); | ||||
} | } | ||||
static void | static void | ||||
bnxt_add_media_types(struct bnxt_softc *softc) | bnxt_add_media_types(struct bnxt_softc *softc) | ||||
{ | { | ||||
struct bnxt_link_info *link_info = &softc->link_info; | struct bnxt_link_info *link_info = &softc->link_info; | ||||
uint16_t supported; | uint16_t supported; | ||||
uint8_t phy_type = get_phy_type(softc); | uint8_t phy_type = get_phy_type(softc); | ||||
supported = link_info->support_speeds; | supported = link_info->support_speeds; | ||||
/* Auto is always supported */ | /* Auto is always supported */ | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ||||
if (softc->flags & BNXT_FLAG_NPAR) | if (softc->flags & BNXT_FLAG_NPAR) | ||||
return; | return; | ||||
switch (phy_type) { | switch (phy_type) { | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASECR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_L: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_S: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_N: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_CR4); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_100G_CR4, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_CR2); | ||||
NULL); | BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_CR4); | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_CR); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_50G_CR2, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_CR1); | ||||
NULL); | BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_T); | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_40G_CR4, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_25G_CR, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10G_CR1, 0, | |||||
NULL); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: | |||||
/* Auto only */ | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR4: | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASELR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_LR4); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_LR4); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_LR); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_LR); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_LX); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR10: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASESR4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASEER4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER4: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASESR: | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASESX: | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_SR4); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_SR4); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_SR); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_SR); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SX); | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_KR4); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_100G_KR4, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR2); | ||||
NULL); | BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_KR4); | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_KR); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_50G_KR2, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_20GB, IFM_20G_KR2); | ||||
NULL); | BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_40G_KR4, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_25G_KR, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_20G_KR2, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KR, 0, | |||||
NULL); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_ACTIVE_CABLE: | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_100G_LR4, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_ACC); | ||||
NULL); | BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_AOC); | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_40G_LR4, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10G_LR, 0, | |||||
NULL); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASECX: | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_100G_SR4, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_1GBHD, IFM_1000_CX); | ||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_25G_SR, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10G_SR, 0, | |||||
NULL); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET: | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KX4, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_2500_KX, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_1000_KX, 0, | |||||
NULL); | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE: | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_T); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10_T, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_T); | ||||
NULL); | BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_T); | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_100MB, IFM_100_T); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_100_T, 0, | BNXT_IFMEDIA_ADD(supported, SPEEDS_10MB, IFM_10_T); | ||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_1000_T, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_2500_T, 0, | |||||
NULL); | |||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) | |||||
ifmedia_add(softc->media, IFM_ETHER | IFM_10G_T, 0, | |||||
NULL); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_KX); | |||||
BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); | |||||
break; | |||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: | case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: | ||||
if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) | BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SGMII); | ||||
ifmedia_add(softc->media, IFM_ETHER | IFM_1000_SGMII, 0, | |||||
NULL); | |||||
break; | break; | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: | |||||
/* Only Autoneg is supported for TYPE_UNKNOWN */ | |||||
device_printf(softc->dev, "Unknown phy type\n"); | |||||
break; | |||||
default: | |||||
/* Only Autoneg is supported for new phy type values */ | |||||
device_printf(softc->dev, "phy type %d not supported by driver\n", phy_type); | |||||
break; | |||||
} | } | ||||
return; | return; | ||||
} | } | ||||
static int | static int | ||||
bnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable) | bnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
exit: | exit: | ||||
return rc; | return rc; | ||||
} | } | ||||
void | void | ||||
bnxt_report_link(struct bnxt_softc *softc) | bnxt_report_link(struct bnxt_softc *softc) | ||||
{ | { | ||||
struct bnxt_link_info *link_info = &softc->link_info; | |||||
const char *duplex = NULL, *flow_ctrl = NULL; | const char *duplex = NULL, *flow_ctrl = NULL; | ||||
if (softc->link_info.link_up == softc->link_info.last_link_up) { | if (link_info->link_up == link_info->last_link_up) { | ||||
if (!softc->link_info.link_up) | if (!link_info->link_up) | ||||
return; | return; | ||||
if (softc->link_info.pause == softc->link_info.last_pause && | if ((link_info->duplex == link_info->last_duplex) && | ||||
softc->link_info.duplex == softc->link_info.last_duplex) | (!(BNXT_IS_FLOW_CTRL_CHANGED(link_info)))) | ||||
return; | return; | ||||
} | } | ||||
if (softc->link_info.link_up) { | if (link_info->link_up) { | ||||
if (softc->link_info.duplex == | if (link_info->duplex == | ||||
HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL) | HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_CFG_FULL) | ||||
duplex = "full duplex"; | duplex = "full duplex"; | ||||
else | else | ||||
duplex = "half duplex"; | duplex = "half duplex"; | ||||
if (softc->link_info.pause == ( | if (link_info->flow_ctrl.tx & link_info->flow_ctrl.rx) | ||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | | |||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) | |||||
flow_ctrl = "FC - receive & transmit"; | flow_ctrl = "FC - receive & transmit"; | ||||
else if (softc->link_info.pause == | else if (link_info->flow_ctrl.tx) | ||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) | |||||
flow_ctrl = "FC - transmit"; | flow_ctrl = "FC - transmit"; | ||||
else if (softc->link_info.pause == | else if (link_info->flow_ctrl.rx) | ||||
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) | |||||
flow_ctrl = "FC - receive"; | flow_ctrl = "FC - receive"; | ||||
else | else | ||||
flow_ctrl = "none"; | flow_ctrl = "FC - none"; | ||||
iflib_link_state_change(softc->ctx, LINK_STATE_UP, | iflib_link_state_change(softc->ctx, LINK_STATE_UP, | ||||
IF_Gbps(100)); | IF_Gbps(100)); | ||||
device_printf(softc->dev, "Link is UP %s, %s\n", duplex, | device_printf(softc->dev, "Link is UP %s, %s - %d Mbps \n", duplex, | ||||
flow_ctrl); | flow_ctrl, (link_info->link_speed * 100)); | ||||
} else { | } else { | ||||
iflib_link_state_change(softc->ctx, LINK_STATE_DOWN, | iflib_link_state_change(softc->ctx, LINK_STATE_DOWN, | ||||
bnxt_get_baudrate(&softc->link_info)); | bnxt_get_baudrate(&softc->link_info)); | ||||
device_printf(softc->dev, "Link is Down\n"); | device_printf(softc->dev, "Link is Down\n"); | ||||
} | } | ||||
softc->link_info.last_link_up = softc->link_info.link_up; | link_info->last_link_up = link_info->link_up; | ||||
softc->link_info.last_pause = softc->link_info.pause; | link_info->last_duplex = link_info->duplex; | ||||
softc->link_info.last_duplex = softc->link_info.duplex; | link_info->last_flow_ctrl.tx = link_info->flow_ctrl.tx; | ||||
link_info->last_flow_ctrl.rx = link_info->flow_ctrl.rx; | |||||
link_info->last_flow_ctrl.autoneg = link_info->flow_ctrl.autoneg; | |||||
/* update media types */ | |||||
ifmedia_removeall(softc->media); | |||||
bnxt_add_media_types(softc); | |||||
ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); | |||||
} | } | ||||
static int | static int | ||||
bnxt_handle_rx_cp(void *arg) | bnxt_handle_rx_cp(void *arg) | ||||
{ | { | ||||
struct bnxt_cp_ring *cpr = arg; | struct bnxt_cp_ring *cpr = arg; | ||||
/* Disable further interrupts for this queue */ | /* Disable further interrupts for this queue */ | ||||
▲ Show 20 Lines • Show All 233 Lines • ▼ Show 20 Lines | bnxt_get_baudrate(struct bnxt_link_info *link) | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: | case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: | ||||
return IF_Gbps(50); | return IF_Gbps(50); | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: | case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: | ||||
return IF_Gbps(100); | return IF_Gbps(100); | ||||
case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB: | case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB: | ||||
return IF_Mbps(10); | return IF_Mbps(10); | ||||
} | } | ||||
return IF_Gbps(100); | return IF_Gbps(100); | ||||
} | |||||
static void | |||||
bnxt_get_wol_settings(struct bnxt_softc *softc) | |||||
{ | |||||
uint16_t wol_handle = 0; | |||||
if (!bnxt_wol_supported(softc)) | |||||
return; | |||||
do { | |||||
wol_handle = bnxt_hwrm_get_wol_fltrs(softc, wol_handle); | |||||
} while (wol_handle && wol_handle != BNXT_NO_MORE_WOL_FILTERS); | |||||
} | } |