From owner-svn-src-head@FreeBSD.ORG Thu Apr 21 23:06:00 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B37F8106566B; Thu, 21 Apr 2011 23:06:00 +0000 (UTC) (envelope-from davidch@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A0BC78FC0C; Thu, 21 Apr 2011 23:06:00 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p3LN60Av016025; Thu, 21 Apr 2011 23:06:00 GMT (envelope-from davidch@svn.freebsd.org) Received: (from davidch@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p3LN60dp016020; Thu, 21 Apr 2011 23:06:00 GMT (envelope-from davidch@svn.freebsd.org) Message-Id: <201104212306.p3LN60dp016020@svn.freebsd.org> From: David Christensen Date: Thu, 21 Apr 2011 23:06:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r220932 - head/sys/dev/bxe X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 Apr 2011 23:06:00 -0000 Author: davidch Date: Thu Apr 21 23:06:00 2011 New Revision: 220932 URL: http://svn.freebsd.org/changeset/base/220932 Log: - Centralize driver tunables initialization/validation. - Centralize PCI resource allocation/release. - Enable flowid (TSS) support. - Added "per-fastpath" locks and watchdog timeouts. - Fixed problem where the CQ producer index was advanced beyond the size of the CQ ring during initialization. - Replaced hard-coded debug levels in some debug print statements. - More style(9) fixes. MFC after: Two weeks Modified: head/sys/dev/bxe/bxe_debug.h head/sys/dev/bxe/bxe_include.h head/sys/dev/bxe/if_bxe.c head/sys/dev/bxe/if_bxe.h Modified: head/sys/dev/bxe/bxe_debug.h ============================================================================== --- head/sys/dev/bxe/bxe_debug.h Thu Apr 21 21:56:28 2011 (r220931) +++ head/sys/dev/bxe/bxe_debug.h Thu Apr 21 23:06:00 2011 (r220932) @@ -159,50 +159,50 @@ extern uint32_t bxe_debug; #ifdef BXE_DEBUG /* Print a message based on the logging level and code path. */ -#define DBPRINT(sc, level, format, args...) \ - do { \ - if (BXE_LOG_MSG(level)) { \ - device_printf(sc->bxe_dev, format, ## args); \ - } \ +#define DBPRINT(sc, level, format, args...) \ + do { \ + if (BXE_LOG_MSG(level)) { \ + device_printf(sc->dev, format, ## args); \ + } \ } while (0) /* Runs a particular command when debugging is enabled. */ -#define DBRUN(args...) \ - do { \ - args; \ +#define DBRUN(args...) \ + do { \ + args; \ } while (0) /* Runs a particular command based on the logging level. */ -#define DBRUNLV(level, args...) \ - if (BXE_MSG_LEVEL(level)) { \ - args; \ +#define DBRUNLV(level, args...) \ + if (BXE_MSG_LEVEL(level)) { \ + args; \ } /* Runs a particular command based on the code path. */ -#define DBRUNCP(cp, args...) \ - if (BXE_CODE_PATH(cp)) { \ - args; \ +#define DBRUNCP(cp, args...) \ + if (BXE_CODE_PATH(cp)) { \ + args; \ } /* Runs a particular command based on a condition. */ -#define DBRUNIF(cond, args...) \ - if (cond) { \ - args; \ +#define DBRUNIF(cond, args...) \ + if (cond) { \ + args; \ } /* Runs a particular command based on the logging level and code path. */ -#define DBRUNMSG(msg, args...) \ - if (BXE_LOG_MSG(msg)) { \ - args; \ +#define DBRUNMSG(msg, args...) \ + if (BXE_LOG_MSG(msg)) { \ + args; \ } /* Announces function entry. */ -#define DBENTER(cond) \ - DBPRINT(sc, (cond), "%s(enter:%d)\n", __FUNCTION__, curcpu) \ +#define DBENTER(cond) \ + DBPRINT(sc, (cond), "%s(enter:%d)\n", __FUNCTION__, curcpu) /* Announces function exit. */ -#define DBEXIT(cond) \ - DBPRINT(sc, (cond), "%s(exit:%d)\n", __FUNCTION__, curcpu) \ +#define DBEXIT(cond) \ + DBPRINT(sc, (cond), "%s(exit:%d)\n", __FUNCTION__, curcpu) /* Needed for random() function which is only used in debugging. */ #include Modified: head/sys/dev/bxe/bxe_include.h ============================================================================== --- head/sys/dev/bxe/bxe_include.h Thu Apr 21 21:56:28 2011 (r220931) +++ head/sys/dev/bxe/bxe_include.h Thu Apr 21 23:06:00 2011 (r220932) @@ -61,21 +61,21 @@ /* * Convenience definitions used in multiple files. */ -#define BXE_PRINTF(fmt, args...) \ - do { \ - device_printf(sc->bxe_dev, fmt, ##args);\ +#define BXE_PRINTF(fmt, args...) \ + do { \ + device_printf(sc->dev, fmt, ##args); \ }while(0) #ifdef BXE_DEBUG -#define REG_WR(sc, offset, val) \ +#define REG_WR(sc, offset, val) \ bxe_reg_write32(sc, offset, val) -#define REG_WR8(sc, offset, val) \ +#define REG_WR8(sc, offset, val) \ bxe_reg_write8(sc, offset, val) -#define REG_WR16(sc, offset, val) \ +#define REG_WR16(sc, offset, val) \ bxe_reg_write16(sc, offset, val) -#define REG_WR32(sc, offset, val) \ +#define REG_WR32(sc, offset, val) \ bxe_reg_write32(sc, offset, val) #define REG_RD(sc, offset) \ @@ -87,77 +87,77 @@ #define REG_RD32(sc, offset) \ bxe_reg_read32(sc, offset) -#define REG_RD_IND(sc, offset) \ +#define REG_RD_IND(sc, offset) \ bxe_reg_rd_ind(sc, offset) -#define REG_WR_IND(sc, offset, val) \ +#define REG_WR_IND(sc, offset, val) \ bxe_reg_wr_ind(sc, offset, val) #else -#define REG_WR(sc, offset, val) \ +#define REG_WR(sc, offset, val) \ bus_space_write_4(sc->bxe_btag, sc->bxe_bhandle, offset, val) -#define REG_WR8(sc, offset, val) \ +#define REG_WR8(sc, offset, val) \ bus_space_write_1(sc->bxe_btag, sc->bxe_bhandle, offset, val) -#define REG_WR16(sc, offset, val) \ +#define REG_WR16(sc, offset, val) \ bus_space_write_2(sc->bxe_btag, sc->bxe_bhandle, offset, val) -#define REG_WR32(sc, offset, val) \ +#define REG_WR32(sc, offset, val) \ bus_space_write_4(sc->bxe_btag, sc->bxe_bhandle, offset, val) -#define REG_RD(sc, offset) \ +#define REG_RD(sc, offset) \ bus_space_read_4(sc->bxe_btag, sc->bxe_bhandle, offset) -#define REG_RD8(sc, offset) \ +#define REG_RD8(sc, offset) \ bus_space_read_1(sc->bxe_btag, sc->bxe_bhandle, offset) -#define REG_RD16(sc, offset) \ +#define REG_RD16(sc, offset) \ bus_space_read_2(sc->bxe_btag, sc->bxe_bhandle, offset) -#define REG_RD32(sc, offset) \ +#define REG_RD32(sc, offset) \ bus_space_read_4(sc->bxe_btag, sc->bxe_bhandle, offset) -#define REG_RD_IND(sc, offset) \ +#define REG_RD_IND(sc, offset) \ bxe_reg_rd_ind(sc, offset) -#define REG_WR_IND(sc, offset, val) \ +#define REG_WR_IND(sc, offset, val) \ bxe_reg_wr_ind(sc, offset, val) #endif /* BXE_DEBUG */ #define REG_RD_DMAE(sc, offset, val, len32) \ - do { \ - bxe_read_dmae(sc, offset, len32); \ - memcpy(val, BXE_SP(sc, wb_data[0]), len32 * 4); \ + do { \ + bxe_read_dmae(sc, offset, len32); \ + memcpy(val, BXE_SP(sc, wb_data[0]), len32 * 4); \ } while (0) #define REG_WR_DMAE(sc, offset, val, len32) \ - do { \ - memcpy(BXE_SP(sc, wb_data[0]), val, len32 * 4); \ - bxe_write_dmae(sc, BXE_SP_MAPPING(sc, wb_data), \ - offset, len32); \ + do { \ + memcpy(BXE_SP(sc, wb_data[0]), val, len32 * 4); \ + bxe_write_dmae(sc, BXE_SP_MAPPING(sc, wb_data), \ + offset, len32); \ } while (0) -#define SHMEM_ADDR(sc, field) (sc->common.shmem_base + \ +#define SHMEM_ADDR(sc, field) (sc->common.shmem_base + \ offsetof(struct shmem_region, field)) -#define SHMEM_RD(sc, field) \ +#define SHMEM_RD(sc, field) \ REG_RD(sc, SHMEM_ADDR(sc, field)) -#define SHMEM_RD16(sc, field) \ +#define SHMEM_RD16(sc, field) \ REG_RD16(sc, SHMEM_ADDR(sc, field)) -#define SHMEM_WR(sc, field, val) \ +#define SHMEM_WR(sc, field, val) \ REG_WR(sc, SHMEM_ADDR(sc, field), val) -#define SHMEM2_ADDR(sc, field) (sc->common.shmem2_base + \ - offsetof(struct shmem2_region, field)) +#define SHMEM2_ADDR(sc, field) (sc->common.shmem2_base + \ + offsetof(struct shmem2_region, field)) #define SHMEM2_RD(sc, field) REG_RD(sc, SHMEM2_ADDR(sc, field)) #define SHMEM2_WR(sc, field, val) REG_WR(sc, SHMEM2_ADDR(sc, field), val) -#define EMAC_RD(sc, reg) \ +#define EMAC_RD(sc, reg) \ REG_RD(sc, emac_base + (uint32_t) reg) -#define EMAC_WR(sc, reg, val) \ +#define EMAC_WR(sc, reg, val) \ REG_WR(sc, emac_base + (uint32_t) reg, val) -#define BMAC_WR(sc, reg, val) \ +#define BMAC_WR(sc, reg, val) \ REG_WR(sc, GRCBASE_NIG + bmac_addr + reg, val) #endif /* _BXE_INCLUDE_H */ Modified: head/sys/dev/bxe/if_bxe.c ============================================================================== --- head/sys/dev/bxe/if_bxe.c Thu Apr 21 21:56:28 2011 (r220931) +++ head/sys/dev/bxe/if_bxe.c Thu Apr 21 23:06:00 2011 (r220932) @@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$"); /* BXE Debug Options */ #ifdef BXE_DEBUG -uint32_t bxe_debug = BXE_INFO; +uint32_t bxe_debug = BXE_WARN; /* 0 = Never */ @@ -132,6 +132,7 @@ static int bxe_attach(device_t); static int bxe_detach(device_t); static int bxe_shutdown(device_t); +static void bxe_set_tunables(struct bxe_softc *); static void bxe_print_adapter_info(struct bxe_softc *); static void bxe_probe_pci_caps(struct bxe_softc *); static void bxe_link_settings_supported(struct bxe_softc *, uint32_t); @@ -145,6 +146,8 @@ static int bxe_stop_leading(struct bxe_ static int bxe_setup_multi(struct bxe_softc *, int); static int bxe_stop_multi(struct bxe_softc *, int); static int bxe_stop_locked(struct bxe_softc *, int); +static int bxe_alloc_buf_rings(struct bxe_softc *); +static void bxe_free_buf_rings(struct bxe_softc *); static void bxe_init_locked(struct bxe_softc *, int); static int bxe_wait_ramrod(struct bxe_softc *, int, int, int *, int); static void bxe_init_str_wr(struct bxe_softc *, uint32_t, const uint32_t *, @@ -237,6 +240,10 @@ static void bxe_stats_handle(struct bxe_ static int bxe_tx_encap(struct bxe_fastpath *, struct mbuf **); static void bxe_tx_start(struct ifnet *); static void bxe_tx_start_locked(struct ifnet *, struct bxe_fastpath *); +static int bxe_tx_mq_start(struct ifnet *, struct mbuf *); +static int bxe_tx_mq_start_locked(struct ifnet *, struct bxe_fastpath *, + struct mbuf *); +static void bxe_mq_flush(struct ifnet *ifp); static int bxe_ioctl(struct ifnet *, u_long, caddr_t); static __inline int bxe_has_rx_work(struct bxe_fastpath *); static __inline int bxe_has_tx_work(struct bxe_fastpath *); @@ -266,6 +273,8 @@ static struct mbuf *bxe_alloc_mbuf(struc static int bxe_map_mbuf(struct bxe_fastpath *, struct mbuf *, bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *); static struct mbuf *bxe_alloc_tpa_mbuf(struct bxe_fastpath *, int, int); +static void bxe_alloc_mutexes(struct bxe_softc *); +static void bxe_free_mutexes(struct bxe_softc *); static int bxe_alloc_rx_sge(struct bxe_softc *, struct bxe_fastpath *, uint16_t); static void bxe_init_rx_chains(struct bxe_softc *); @@ -322,7 +331,7 @@ static void bxe_tpa_stop(struct bxe_soft static void bxe_rxeof(struct bxe_fastpath *); static void bxe_txeof(struct bxe_fastpath *); static int bxe_get_buf(struct bxe_fastpath *, struct mbuf *, uint16_t); -static void bxe_watchdog(struct bxe_softc *); +static int bxe_watchdog(struct bxe_fastpath *fp); static int bxe_change_mtu(struct bxe_softc *, int); static void bxe_tick(void *); static void bxe_add_sysctls(struct bxe_softc *); @@ -481,8 +490,7 @@ SYSCTL_UINT(_hw_bxe, OID_AUTO, queue_cou * destination IP address and the source/destination TCP port). * */ -/* static int bxe_multi_mode = ETH_RSS_MODE_REGULAR; */ -static int bxe_multi_mode = ETH_RSS_MODE_DISABLED; +static int bxe_multi_mode = ETH_RSS_MODE_REGULAR; TUNABLE_INT("hw.bxe.multi_mode", &bxe_multi_mode); SYSCTL_UINT(_hw_bxe, OID_AUTO, multi_mode, CTLFLAG_RDTUN, &bxe_multi_mode, 0, "Multi-Queue Mode"); @@ -738,7 +746,7 @@ bxe_calc_vn_wsum(struct bxe_softc *sc) uint32_t vn_cfg, vn_min_rate; int all_zero, vn; - DBENTER(1); + DBENTER(BXE_VERBOSE_LOAD); all_zero = 1; sc->vn_wsum = 0; @@ -764,7 +772,7 @@ bxe_calc_vn_wsum(struct bxe_softc *sc) else sc->cmng.flags.cmng_enables |= CMNG_FLAGS_PER_PORT_FAIRNESS_VN; - DBEXIT(1); + DBEXIT(BXE_VERBOSE_LOAD); } /* @@ -784,7 +792,7 @@ bxe_init_vn_minmax(struct bxe_softc *sc, vn_cfg = sc->mf_config[vn]; func = 2 * vn + BP_PORT(sc); - DBENTER(1); + DBENTER(BXE_VERBOSE_LOAD); /* If function is hidden - set min and max to zeroes. */ if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) { @@ -807,7 +815,7 @@ bxe_init_vn_minmax(struct bxe_softc *sc, if (vn_max_rate == 0) return; } - DBPRINT(sc, 1, + DBPRINT(sc, BXE_INFO_LOAD, "%s(): func %d: vn_min_rate = %d, vn_max_rate = %d, wsum = %d.\n", __FUNCTION__, func, vn_min_rate, vn_max_rate, sc->vn_wsum); @@ -846,7 +854,8 @@ bxe_init_vn_minmax(struct bxe_softc *sc, REG_WR(sc, BAR_XSTORM_INTMEM + XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func) + (i * 4), ((uint32_t *)(&m_fair_vn))[i]); - DBEXIT(1); + + DBEXIT(BXE_VERBOSE_LOAD); } static void @@ -854,6 +863,8 @@ bxe_congestionmgmt(struct bxe_softc *sc, { int vn; + DBENTER(BXE_VERBOSE_LOAD); + /* Read mf conf from shmem. */ if (readshm) bxe_read_mf_cfg(sc); @@ -871,11 +882,14 @@ bxe_congestionmgmt(struct bxe_softc *sc, /* Always enable rate shaping and fairness. */ sc->cmng.flags.cmng_enables |= CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN; - DBPRINT(sc, 1, "rate shaping set\n"); + DBPRINT(sc, BXE_VERBOSE_LOAD, + "%s(): Rate shaping set\n", __FUNCTION__); if (!sc->vn_wsum) - DBPRINT(sc, 1, - "All MIN values are zeroes fairness is disabled\n"); + DBPRINT(sc, BXE_INFO_LOAD, "%s(): All MIN values " + "are zeroes, fairness is disabled\n", __FUNCTION__); + + DBEXIT(BXE_VERBOSE_LOAD); } static void @@ -883,19 +897,18 @@ bxe_dcc_event(struct bxe_softc *sc, uint { int i, port; + DBENTER(BXE_VERBOSE_LOAD); + if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) { - /* - * This is the only place besides the function initialization - * where the sc->bxe_flags can change so it is done without any - * locks - */ if (sc->mf_config[BP_E1HVN(sc)] & FUNC_MF_CFG_FUNC_DISABLED) { - DBPRINT(sc, 1, "mf_cfg function disabled\n"); - sc->bxe_flags = BXE_STATE_DISABLED; + DBPRINT(sc, BXE_INFO_LOAD, "%s(): mf_cfg function " + "disabled\n", __FUNCTION__); + sc->state = BXE_STATE_DISABLED; bxe_e1h_disable(sc); } else { - DBPRINT(sc, 1, "mf_cfg function enabled\n"); - sc->bxe_flags = BXE_STATE_OPEN; + DBPRINT(sc, BXE_INFO_LOAD, "%s(): mf_cfg function " + "enabled\n", __FUNCTION__); + sc->state = BXE_STATE_OPEN; bxe_e1h_enable(sc); } dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF; @@ -915,6 +928,8 @@ bxe_dcc_event(struct bxe_softc *sc, uint bxe_fw_command(sc, DRV_MSG_CODE_DCC_FAILURE); else bxe_fw_command(sc, DRV_MSG_CODE_DCC_OK); + + DBEXIT(BXE_VERBOSE_LOAD); } /* @@ -935,7 +950,7 @@ bxe_probe(device_t dev) uint16_t did, sdid, svid, vid; sc = device_get_softc(dev); - sc->bxe_dev = dev; + sc->dev = dev; t = bxe_devs; /* Get the data for the device to be probed. */ @@ -1028,7 +1043,7 @@ bxe_print_adapter_info(struct bxe_softc printf("TPA"); i++; } - printf(") Queues ("); + printf("); Queues ("); switch (sc->multi_mode) { case ETH_RSS_MODE_DISABLED: printf("None"); @@ -1079,7 +1094,7 @@ bxe_interrupt_allocate(struct bxe_softc int msix_count, msix_required, msix_allocated; rc = 0; - dev = sc->bxe_dev; + dev = sc->dev; msi_count = 0; msi_required = 0; msi_allocated = 0; @@ -1096,70 +1111,6 @@ bxe_interrupt_allocate(struct bxe_softc for (i = 0; i < BXE_MAX_PRIORITY; i++) sc->pri_map[i] = 0; - /* - * Get our starting point for interrupt mode/number of queues. - * We will progressively step down from MSI-X to MSI to INTx - * and reduce the number of receive queues as necessary to - * match the system capabilities. - */ - sc->multi_mode = bxe_multi_mode; - sc->int_mode = bxe_int_mode; - - /* - * Verify the Priority -> Receive Queue mappings. - */ - if (sc->int_mode > 0) { - /* Multi-queue modes require MSI/MSI-X. */ - switch (sc->multi_mode) { - case ETH_RSS_MODE_DISABLED: - /* No multi-queue mode requested. */ - sc->num_queues = 1; - break; - case ETH_RSS_MODE_REGULAR: - if (sc->int_mode > 1) { - /* - * Assume we can use MSI-X - * (max of 16 receive queues). - */ - sc->num_queues = min((bxe_queue_count ? - bxe_queue_count : mp_ncpus), MAX_CONTEXT); - } else { - /* - * Assume we can use MSI - * (max of 7 receive queues). - */ - sc->num_queues = min((bxe_queue_count ? - bxe_queue_count : mp_ncpus), - BXE_MSI_VECTOR_COUNT - 1); - } - break; - default: - BXE_PRINTF( - "%s(%d): Unsupported multi_mode parameter (%d), " - "disabling multi-queue support!\n", __FILE__, - __LINE__, sc->multi_mode); - sc->multi_mode = ETH_RSS_MODE_DISABLED; - sc->num_queues = 1; - break; - } - } else { - /* User has forced INTx mode. */ - sc->multi_mode = ETH_RSS_MODE_DISABLED; - sc->num_queues = 1; - } - - DBPRINT(sc, (BXE_VERBOSE_LOAD | BXE_VERBOSE_INTR), - "%s(): Requested: int_mode = %d, multi_mode = %d num_queues = %d\n", - __FUNCTION__, sc->int_mode, sc->multi_mode, sc->num_queues); - -#ifdef BXE_DEBUG - for (i = 0; i < BXE_MAX_PRIORITY; i++) { - DBPRINT(sc, (BXE_VERBOSE_LOAD | BXE_VERBOSE_INTR), - "%s(): sc->pri_map[%d] = %d.\n", __FUNCTION__, i, - sc->pri_map[i]); - } -#endif - /* Get the number of available MSI/MSI-X interrupts from the OS. */ if (sc->int_mode > 0) { if (sc->bxe_cap_flags & BXE_MSIX_CAPABLE_FLAG) @@ -1331,7 +1282,7 @@ bxe_interrupt_detach(struct bxe_softc *s device_t dev; int i; - dev = sc->bxe_dev; + dev = sc->dev; DBENTER(BXE_VERBOSE_RESET | BXE_VERBOSE_UNLOAD); /* Release interrupt resources. */ if ((sc->bxe_flags & BXE_USING_MSIX_FLAG) && sc->msix_count) { @@ -1381,7 +1332,7 @@ bxe_interrupt_attach(struct bxe_softc *s sc->tq = taskqueue_create_fast("bxe_spq", M_NOWAIT, taskqueue_thread_enqueue, &sc->tq); taskqueue_start_threads(&sc->tq, 1, PI_NET, "%s spq", - device_get_nameunit(sc->bxe_dev)); + device_get_nameunit(sc->dev)); #endif /* Setup interrupt handlers. */ @@ -1393,7 +1344,7 @@ bxe_interrupt_attach(struct bxe_softc *s * driver instance to the interrupt handler for the * slowpath. */ - rc = bus_setup_intr(sc->bxe_dev, + rc = bus_setup_intr(sc->dev, sc->bxe_msix_res[0], INTR_TYPE_NET | INTR_MPSAFE, NULL, @@ -1420,7 +1371,7 @@ bxe_interrupt_attach(struct bxe_softc *s * fastpath context to the interrupt handler in this * case. Also the first msix_res was used by the sp. */ - rc = bus_setup_intr(sc->bxe_dev, + rc = bus_setup_intr(sc->dev, sc->bxe_msix_res[i + 1], INTR_TYPE_NET | INTR_MPSAFE, NULL, @@ -1440,7 +1391,7 @@ bxe_interrupt_attach(struct bxe_softc *s fp->tq = taskqueue_create_fast("bxe_fpq", M_NOWAIT, taskqueue_thread_enqueue, &fp->tq); taskqueue_start_threads(&fp->tq, 1, PI_NET, "%s fpq", - device_get_nameunit(sc->bxe_dev)); + device_get_nameunit(sc->dev)); #endif fp->state = BXE_FP_STATE_IRQ; } @@ -1452,7 +1403,7 @@ bxe_interrupt_attach(struct bxe_softc *s * Setup the interrupt handler. Note that we pass the driver * instance to the interrupt handler for the slowpath. */ - rc = bus_setup_intr(sc->bxe_dev,sc->bxe_msi_res[0], + rc = bus_setup_intr(sc->dev,sc->bxe_msi_res[0], INTR_TYPE_NET | INTR_MPSAFE, NULL, bxe_intr_sp, @@ -1479,7 +1430,7 @@ bxe_interrupt_attach(struct bxe_softc *s * fastpath context to the interrupt handler in this * case. */ - rc = bus_setup_intr(sc->bxe_dev, + rc = bus_setup_intr(sc->dev, sc->bxe_msi_res[i + 1], INTR_TYPE_NET | INTR_MPSAFE, NULL, @@ -1499,7 +1450,7 @@ bxe_interrupt_attach(struct bxe_softc *s fp->tq = taskqueue_create_fast("bxe_fpq", M_NOWAIT, taskqueue_thread_enqueue, &fp->tq); taskqueue_start_threads(&fp->tq, 1, PI_NET, "%s fpq", - device_get_nameunit(sc->bxe_dev)); + device_get_nameunit(sc->dev)); #endif } @@ -1515,7 +1466,7 @@ bxe_interrupt_attach(struct bxe_softc *s * driver instance to the interrupt handler which * will handle both the slowpath and fastpath. */ - rc = bus_setup_intr(sc->bxe_dev,sc->bxe_irq_res, + rc = bus_setup_intr(sc->dev,sc->bxe_irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, bxe_intr_legacy, @@ -1529,13 +1480,10 @@ bxe_interrupt_attach(struct bxe_softc *s } #ifdef BXE_TASK TASK_INIT(&fp->task, 0, bxe_task_fp, fp); - fp->tq = taskqueue_create_fast("bxe_fpq", M_NOWAIT, - taskqueue_thread_enqueue, - &fp->tq - ); - taskqueue_start_threads(&fp->tq, 1, PI_NET, "%s fpq", - device_get_nameunit(sc->bxe_dev) - ); + fp->tq = taskqueue_create_fast("bxe_fpq", + M_NOWAIT, taskqueue_thread_enqueue, &fp->tq); + taskqueue_start_threads(&fp->tq, 1, + PI_NET, "%s fpq", device_get_nameunit(sc->dev)); #endif } @@ -1562,7 +1510,7 @@ bxe_probe_pci_caps(struct bxe_softc *sc) uint32_t reg; uint16_t link_status; - dev = sc->bxe_dev; + dev = sc->dev; DBENTER(BXE_EXTREME_LOAD); /* Check if PCI Power Management capability is enabled. */ @@ -1679,46 +1627,118 @@ bxe_init_firmware(struct bxe_softc *sc) return (0); } -/* - * Device attach function. - * - * Allocates device resources, performs secondary chip identification, - * resets and initializes the hardware, and initializes driver instance - * variables. - * - * Returns: - * 0 = Success, Positive value on failure. - */ -static int -bxe_attach(device_t dev) + +static void +bxe_set_tunables(struct bxe_softc *sc) { - struct bxe_softc *sc; - struct ifnet *ifp; - int rid, rc; + /* + * Get our starting point for interrupt mode/number of queues. + * We will progressively step down from MSI-X to MSI to INTx + * and reduce the number of receive queues as necessary to + * match the system capabilities. + */ + sc->multi_mode = bxe_multi_mode; + sc->int_mode = bxe_int_mode; + sc->tso_enable = bxe_tso_enable; - sc = device_get_softc(dev); - DBENTER(BXE_VERBOSE_LOAD | BXE_VERBOSE_RESET); + /* + * Verify the Priority -> Receive Queue mappings. + */ + if (sc->int_mode > 0) { + /* Multi-queue modes require MSI/MSI-X. */ + switch (sc->multi_mode) { + case ETH_RSS_MODE_DISABLED: + /* No multi-queue mode requested. */ + sc->num_queues = 1; + break; + case ETH_RSS_MODE_REGULAR: + if (sc->int_mode > 1) { + /* + * Assume we can use MSI-X + * (max of 16 receive queues). + */ + sc->num_queues = min((bxe_queue_count ? + bxe_queue_count : mp_ncpus), MAX_CONTEXT); + } else { + /* + * Assume we can use MSI + * (max of 7 receive queues). + */ + sc->num_queues = min((bxe_queue_count ? + bxe_queue_count : mp_ncpus), + BXE_MSI_VECTOR_COUNT - 1); + } + break; + default: + BXE_PRINTF( + "%s(%d): Unsupported multi_mode parameter (%d), " + "disabling multi-queue support!\n", __FILE__, + __LINE__, sc->multi_mode); + sc->multi_mode = ETH_RSS_MODE_DISABLED; + sc->num_queues = 1; + break; + } + } else { + /* User has forced INTx mode. */ + sc->multi_mode = ETH_RSS_MODE_DISABLED; + sc->num_queues = 1; + } - sc->bxe_dev = dev; - sc->bxe_unit = device_get_unit(dev); - sc->bxe_func = pci_get_function(dev); - sc->bxe_flags = 0; - sc->state = BXE_STATE_CLOSED; - rc = 0; + DBPRINT(sc, (BXE_VERBOSE_LOAD | BXE_VERBOSE_INTR), + "%s(): Requested: int_mode = %d, multi_mode = %d num_queues = %d\n", + __FUNCTION__, sc->int_mode, sc->multi_mode, sc->num_queues); - /* Initialize mutexes. */ - BXE_CORE_LOCK_INIT(sc, device_get_nameunit(dev)); - BXE_SP_LOCK_INIT(sc, "bxe_sp_lock"); - BXE_DMAE_LOCK_INIT(sc, "bxe_dmae_lock"); - BXE_PHY_LOCK_INIT(sc, "bxe_phy_lock"); - BXE_FWMB_LOCK_INIT(sc, "bxe_fwmb_lock"); - BXE_PRINT_LOCK_INIT(sc, "bxe_print_lock"); + /* Set transparent packet aggregation (TPA), aka LRO, flag. */ + if (bxe_tpa_enable!= FALSE) + sc->bxe_flags |= BXE_TPA_ENABLE_FLAG; - /* Prepare the tick routine. */ - callout_init(&sc->bxe_tick_callout, CALLOUT_MPSAFE); + /* Capture the stats enable/disable setting. */ + if (bxe_stats_enable == FALSE) + sc->stats_enable = FALSE; + else + sc->stats_enable = TRUE; - /* Enable bus master capability */ - pci_enable_busmaster(dev); + /* Select the host coalescing tick count values (limit values). */ + if (bxe_tx_ticks > 100) { + BXE_PRINTF("%s(%d): bxe_tx_ticks too large " + "(%d), setting default value of 50.\n", + __FILE__, __LINE__, bxe_tx_ticks); + sc->tx_ticks = 50; + } else + sc->tx_ticks = bxe_tx_ticks; + + if (bxe_rx_ticks > 100) { + BXE_PRINTF("%s(%d): bxe_rx_ticks too large " + "(%d), setting default value of 25.\n", + __FILE__, __LINE__, bxe_rx_ticks); + sc->rx_ticks = 25; + } else + sc->rx_ticks = bxe_rx_ticks; + + /* Select the PCIe maximum read request size (MRRS). */ + if (bxe_mrrs > 3) + sc->mrrs = 3; + else + sc->mrrs = bxe_mrrs; + + /* Check for DCC support. */ + if (bxe_dcc_enable == FALSE) + sc->dcc_enable = FALSE; + else + sc->dcc_enable = TRUE; +} + + +/* + * Returns: + * 0 = Success, !0 = Failure + */ +static int +bxe_alloc_pci_resources(struct bxe_softc *sc) +{ + int rid, rc = 0; + + DBENTER(BXE_VERBOSE_LOAD); /* * Allocate PCI memory resources for BAR0. @@ -1726,32 +1746,32 @@ bxe_attach(device_t dev) * processor memory. */ rid = PCIR_BAR(0); - sc->bxe_res = bus_alloc_resource_any(dev, - SYS_RES_MEMORY, &rid, RF_ACTIVE); + sc->bxe_res = bus_alloc_resource_any( + sc->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->bxe_res == NULL) { BXE_PRINTF("%s(%d):PCI BAR0 memory allocation failed\n", __FILE__, __LINE__); rc = ENXIO; - goto bxe_attach_fail; + goto bxe_alloc_pci_resources_exit; } /* Get OS resource handles for BAR0 memory. */ - sc->bxe_btag = rman_get_bustag(sc->bxe_res); - sc->bxe_bhandle = rman_get_bushandle(sc->bxe_res); - sc->bxe_vhandle = (vm_offset_t) rman_get_virtual(sc->bxe_res); + sc->bxe_btag = rman_get_bustag(sc->bxe_res); + sc->bxe_bhandle = rman_get_bushandle(sc->bxe_res); + sc->bxe_vhandle = (vm_offset_t) rman_get_virtual(sc->bxe_res); /* * Allocate PCI memory resources for BAR2. * Doorbell (DB) memory. */ rid = PCIR_BAR(2); - sc->bxe_db_res = bus_alloc_resource_any(dev, - SYS_RES_MEMORY, &rid, RF_ACTIVE); + sc->bxe_db_res = bus_alloc_resource_any( + sc->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->bxe_db_res == NULL) { BXE_PRINTF("%s(%d): PCI BAR2 memory allocation failed\n", __FILE__, __LINE__); rc = ENXIO; - goto bxe_attach_fail; + goto bxe_alloc_pci_resources_exit; } /* Get OS resource handles for BAR2 memory. */ @@ -1759,21 +1779,45 @@ bxe_attach(device_t dev) sc->bxe_db_bhandle = rman_get_bushandle(sc->bxe_db_res); sc->bxe_db_vhandle = (vm_offset_t) rman_get_virtual(sc->bxe_db_res); - /* Put indirect address registers into a sane state. */ - pci_write_config(sc->bxe_dev, PCICFG_GRC_ADDRESS, - PCICFG_VENDOR_ID_OFFSET, 4); - REG_WR(sc, PXP2_REG_PGL_ADDR_88_F0 + BP_PORT(sc) * 16, 0); - REG_WR(sc, PXP2_REG_PGL_ADDR_8C_F0 + BP_PORT(sc) * 16, 0); - REG_WR(sc, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(sc) * 16, 0); - REG_WR(sc, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(sc) * 16, 0); +bxe_alloc_pci_resources_exit: + DBEXIT(BXE_VERBOSE_LOAD); + return(rc); +} - /* Get hardware info from shared memory and validate data. */ - if (bxe_get_function_hwinfo(sc)) { - DBPRINT(sc, BXE_WARN, - "%s(): Failed to get hardware info!\n", __FUNCTION__); - rc = ENODEV; - goto bxe_attach_fail; + +/* + * Returns: + * None + */ +static void +bxe_release_pci_resources(struct bxe_softc *sc) +{ + /* Release the PCIe BAR0 mapped memory. */ + if (sc->bxe_res != NULL) { + DBPRINT(sc, (BXE_VERBOSE_LOAD | BXE_VERBOSE_RESET), + "%s(): Releasing PCI BAR0 memory.\n", __FUNCTION__); + bus_release_resource(sc->dev, + SYS_RES_MEMORY, PCIR_BAR(0), sc->bxe_res); + } + + /* Release the PCIe BAR2 (doorbell) mapped memory. */ + if (sc->bxe_db_res != NULL) { + DBPRINT(sc, (BXE_VERBOSE_LOAD | BXE_VERBOSE_RESET), + "%s(): Releasing PCI BAR2 memory.\n", __FUNCTION__); + bus_release_resource(sc->dev, + SYS_RES_MEMORY, PCIR_BAR(2), sc->bxe_db_res); } +} + + +/* + * Returns: + * 0 = Success, !0 = Failure + */ +static int +bxe_media_detect(struct bxe_softc *sc) +{ + int rc = 0; /* Identify supported media based on the PHY type. */ switch (XGXS_EXT_PHY_TYPE(sc->link_params.ext_phy_config)) { @@ -1782,21 +1826,21 @@ bxe_attach(device_t dev) "%s(): Found 10GBase-CX4 media.\n", __FUNCTION__); sc->media = IFM_10G_CX4; break; -#if 0 - /* ToDo: Configure correct media types for these PHYs. */ - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071 - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072 - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 -#endif + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: + /* Technically 10GBase-KR but report as 10GBase-SR*/ + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC: DBPRINT(sc, BXE_INFO_LOAD, "%s(): Found 10GBase-SR media.\n", __FUNCTION__); sc->media = IFM_10G_SR; break; + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: + DBPRINT(sc, BXE_INFO_LOAD, + "%s(): Found 10Gb twinax media.\n", __FUNCTION__); + sc->media = IFM_10G_TWINAX; + break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: @@ -1811,10 +1855,71 @@ bxe_attach(device_t dev) __FILE__, __LINE__); sc->media = 0; rc = ENODEV; + } + + return (rc); +} + + +/* + * Device attach function. + * + * Allocates device resources, performs secondary chip identification, + * resets and initializes the hardware, and initializes driver instance + * variables. + * + * Returns: + * 0 = Success, Positive value on failure. + */ +static int +bxe_attach(device_t dev) +{ + struct bxe_softc *sc; + struct ifnet *ifp; + int rc; + + sc = device_get_softc(dev); + DBENTER(BXE_VERBOSE_LOAD | BXE_VERBOSE_RESET); + + sc->dev = dev; + sc->bxe_unit = device_get_unit(dev); + sc->bxe_func = pci_get_function(dev); + sc->bxe_flags = 0; + sc->state = BXE_STATE_CLOSED; + rc = 0; + bxe_set_tunables(sc); + + bxe_alloc_mutexes(sc); + + /* Prepare the tick routine. */ + callout_init(&sc->bxe_tick_callout, CALLOUT_MPSAFE); + + /* Enable bus master capability */ + pci_enable_busmaster(dev); + + if ((rc = bxe_alloc_pci_resources(sc)) != 0) + goto bxe_attach_fail; + + /* Put indirect address registers into a sane state. */ + pci_write_config(sc->dev, PCICFG_GRC_ADDRESS, + PCICFG_VENDOR_ID_OFFSET, 4); + REG_WR(sc, PXP2_REG_PGL_ADDR_88_F0 + BP_PORT(sc) * 16, 0); + REG_WR(sc, PXP2_REG_PGL_ADDR_8C_F0 + BP_PORT(sc) * 16, 0); + REG_WR(sc, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(sc) * 16, 0); + REG_WR(sc, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(sc) * 16, 0); + + /* Get hardware info from shared memory and validate data. */ + if (bxe_get_function_hwinfo(sc)) { + DBPRINT(sc, BXE_WARN, + "%s(): Failed to get hardware info!\n", __FUNCTION__); + rc = ENODEV; goto bxe_attach_fail; } /* Setup supported media options. */ + if ((rc = bxe_media_detect(sc)) != 0) + goto bxe_attach_fail; + ifmedia_init(&sc->bxe_ifmedia, IFM_IMASK, bxe_ifmedia_upd, bxe_ifmedia_status); ifmedia_add(&sc->bxe_ifmedia, @@ -1823,7 +1928,8 @@ bxe_attach(device_t dev) IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->bxe_ifmedia, IFM_ETHER | IFM_AUTO); - sc->bxe_ifmedia.ifm_media = sc->bxe_ifmedia.ifm_cur->ifm_media; + sc->bxe_ifmedia.ifm_media = + sc->bxe_ifmedia.ifm_cur->ifm_media; /* Set init arrays */ rc = bxe_init_firmware(sc); @@ -1877,18 +1983,6 @@ bxe_attach(device_t dev) if (!BP_NOMCP(sc)) bxe_undi_unload(sc); - /* Set TPA flag. */ - if (bxe_tpa_enable){ - sc->bxe_flags |= BXE_TPA_ENABLE_FLAG; - }else - sc->bxe_flags &= ~BXE_TPA_ENABLE_FLAG; - - /* Select the PCIe maximum read request size. */ - if (bxe_mrrs > 3) - sc->mrrs = 3; - else - sc->mrrs = bxe_mrrs; - /* * Select the RX and TX ring sizes. The actual * ring size for TX is complicated by the fact @@ -1904,10 +1998,6 @@ bxe_attach(device_t dev) /* Assume receive IP/TCP/UDP checksum is enabled. */ sc->rx_csum = 1; - /* Select the host coalescing tick count values. */ - sc->tx_ticks = bxe_tx_ticks; - sc->rx_ticks = bxe_rx_ticks; - /* Disable WoL. */ sc->wol = 0; @@ -1915,7 +2005,7 @@ bxe_attach(device_t dev) sc->mbuf_alloc_size = MCLBYTES; /* Allocate DMA memory resources. */ - if (bxe_dma_alloc(sc->bxe_dev)) { + if (bxe_dma_alloc(sc->dev)) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***