diff options
author | des <des@FreeBSD.org> | 2009-09-25 22:45:59 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2009-09-25 22:45:59 +0000 |
commit | bf5117185e83a178d672946c3f7053d0ef92be27 (patch) | |
tree | 394fcfe01b613c0b5b5edbfc414a17c73481ad5d /sys/dev/mxge/if_mxge.c | |
parent | b79ff8160af6fa640e29ce784e59acd49cd1e7fc (diff) | |
parent | 5c2742e3dae3ef549329b770ec44b16ca930dc1f (diff) | |
download | FreeBSD-src-bf5117185e83a178d672946c3f7053d0ef92be27.zip FreeBSD-src-bf5117185e83a178d672946c3f7053d0ef92be27.tar.gz |
Sync with head
Diffstat (limited to 'sys/dev/mxge/if_mxge.c')
-rw-r--r-- | sys/dev/mxge/if_mxge.c | 158 |
1 files changed, 129 insertions, 29 deletions
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index 88c3489..6e8ca67 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -106,6 +106,7 @@ static int mxge_max_slices = 1; static int mxge_rss_hash_type = MXGEFW_RSS_HASH_TYPE_SRC_PORT; static int mxge_always_promisc = 0; static int mxge_initial_mtu = ETHERMTU_JUMBO; +static int mxge_throttle = 0; static char *mxge_fw_unaligned = "mxge_ethp_z8e"; static char *mxge_fw_aligned = "mxge_eth_z8e"; static char *mxge_fw_rss_aligned = "mxge_rss_eth_z8e"; @@ -143,7 +144,7 @@ MODULE_DEPEND(mxge, zlib, 1, 1, 1); static int mxge_load_firmware(mxge_softc_t *sc, int adopt); static int mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data); -static int mxge_close(mxge_softc_t *sc); +static int mxge_close(mxge_softc_t *sc, int down); static int mxge_open(mxge_softc_t *sc); static void mxge_tick(void *arg); @@ -596,10 +597,13 @@ static int mxge_select_firmware(mxge_softc_t *sc) { int aligned = 0; + int force_firmware = mxge_force_firmware; + if (sc->throttle) + force_firmware = sc->throttle; - if (mxge_force_firmware != 0) { - if (mxge_force_firmware == 1) + if (force_firmware != 0) { + if (force_firmware == 1) aligned = 1; else aligned = 0; @@ -1305,8 +1309,7 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup) ss->lro_queued = 0; ss->lro_flushed = 0; if (ss->fw_stats != NULL) { - ss->fw_stats->valid = 0; - ss->fw_stats->send_done_count = 0; + bzero(ss->fw_stats, sizeof *ss->fw_stats); } } sc->rdma_tags_available = 15; @@ -1314,10 +1317,48 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup) mxge_change_promisc(sc, sc->ifp->if_flags & IFF_PROMISC); mxge_change_pause(sc, sc->pause); mxge_set_multicast_list(sc); + if (sc->throttle) { + cmd.data0 = sc->throttle; + if (mxge_send_cmd(sc, MXGEFW_CMD_SET_THROTTLE_FACTOR, + &cmd)) { + device_printf(sc->dev, + "can't enable throttle\n"); + } + } return status; } static int +mxge_change_throttle(SYSCTL_HANDLER_ARGS) +{ + mxge_cmd_t cmd; + mxge_softc_t *sc; + int err; + unsigned int throttle; + + sc = arg1; + throttle = sc->throttle; + err = sysctl_handle_int(oidp, &throttle, arg2, req); + if (err != 0) { + return err; + } + + if (throttle == sc->throttle) + return 0; + + if (throttle < MXGE_MIN_THROTTLE || throttle > MXGE_MAX_THROTTLE) + return EINVAL; + + mtx_lock(&sc->driver_mtx); + cmd.data0 = throttle; + err = mxge_send_cmd(sc, MXGEFW_CMD_SET_THROTTLE_FACTOR, &cmd); + if (err == 0) + sc->throttle = throttle; + mtx_unlock(&sc->driver_mtx); + return err; +} + +static int mxge_change_intr_coal(SYSCTL_HANDLER_ARGS) { mxge_softc_t *sc; @@ -1379,7 +1420,7 @@ mxge_change_lro_locked(mxge_softc_t *sc, int lro_cnt) ifp->if_capenable |= IFCAP_LRO; sc->lro_cnt = lro_cnt; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); + mxge_close(sc, 0); err = mxge_open(sc); } return err; @@ -1495,6 +1536,10 @@ mxge_add_sysctls(mxge_softc_t *sc) "read_write_dma_MBs", CTLFLAG_RD, &sc->read_write_dma, 0, "DMA concurrent Read/Write speed in MB/s"); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "watchdog_resets", + CTLFLAG_RD, &sc->watchdog_resets, + 0, "Number of times NIC was reset"); /* performance related tunables */ @@ -1505,6 +1550,12 @@ mxge_add_sysctls(mxge_softc_t *sc) "I", "interrupt coalescing delay in usecs"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, + "throttle", + CTLTYPE_INT|CTLFLAG_RW, sc, + 0, mxge_change_throttle, + "I", "transmit throttling"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "flow_control_enabled", CTLTYPE_INT|CTLFLAG_RW, sc, 0, mxge_change_flow_control, @@ -3600,7 +3651,7 @@ abort: } static int -mxge_close(mxge_softc_t *sc) +mxge_close(mxge_softc_t *sc, int down) { mxge_cmd_t cmd; int err, old_down_cnt; @@ -3617,21 +3668,23 @@ mxge_close(mxge_softc_t *sc) } #endif sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - old_down_cnt = sc->down_cnt; - wmb(); - err = mxge_send_cmd(sc, MXGEFW_CMD_ETHERNET_DOWN, &cmd); - if (err) { - device_printf(sc->dev, "Couldn't bring down link\n"); - } - if (old_down_cnt == sc->down_cnt) { - /* wait for down irq */ - DELAY(10 * sc->intr_coal_delay); - } - wmb(); - if (old_down_cnt == sc->down_cnt) { - device_printf(sc->dev, "never got down irq\n"); + if (!down) { + old_down_cnt = sc->down_cnt; + wmb(); + err = mxge_send_cmd(sc, MXGEFW_CMD_ETHERNET_DOWN, &cmd); + if (err) { + device_printf(sc->dev, + "Couldn't bring down link\n"); + } + if (old_down_cnt == sc->down_cnt) { + /* wait for down irq */ + DELAY(10 * sc->intr_coal_delay); + } + wmb(); + if (old_down_cnt == sc->down_cnt) { + device_printf(sc->dev, "never got down irq\n"); + } } - mxge_free_mbufs(sc); return 0; @@ -3684,8 +3737,9 @@ static int mxge_watchdog_reset(mxge_softc_t *sc, int slice) { struct pci_devinfo *dinfo; + struct mxge_slice_state *ss; mxge_tx_ring_t *tx; - int err; + int err, running, s, num_tx_slices = 1; uint32_t reboot; uint16_t cmd; @@ -3719,6 +3773,30 @@ mxge_watchdog_reset(mxge_softc_t *sc, int slice) reboot = mxge_read_reboot(sc); device_printf(sc->dev, "NIC rebooted, status = 0x%x\n", reboot); + running = sc->ifp->if_drv_flags & IFF_DRV_RUNNING; + if (running) { + + /* + * quiesce NIC so that TX routines will not try to + * xmit after restoration of BAR + */ + + /* Mark the link as down */ + if (sc->link_state) { + sc->link_state = 0; + if_link_state_change(sc->ifp, + LINK_STATE_DOWN); + } +#ifdef IFNET_BUF_RING + num_tx_slices = sc->num_slices; +#endif + /* grab all TX locks to ensure no tx */ + for (s = 0; s < num_tx_slices; s++) { + ss = &sc->ss[s]; + mtx_lock(&ss->tx.mtx); + } + mxge_close(sc, 1); + } /* restore PCI configuration space */ dinfo = device_get_ivars(sc->dev); pci_cfg_restore(sc->dev, dinfo); @@ -3726,10 +3804,22 @@ mxge_watchdog_reset(mxge_softc_t *sc, int slice) /* and redo any changes we made to our config space */ mxge_setup_cfg_space(sc); - if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); - err = mxge_open(sc); + /* reload f/w */ + err = mxge_load_firmware(sc, 0); + if (err) { + device_printf(sc->dev, + "Unable to re-load f/w\n"); } + if (running) { + if (!err) + err = mxge_open(sc); + /* release all TX locks */ + for (s = 0; s < num_tx_slices; s++) { + ss = &sc->ss[s]; + mtx_unlock(&ss->tx.mtx); + } + } + sc->watchdog_resets++; } else { tx = &sc->ss[slice].tx; device_printf(sc->dev, @@ -3745,6 +3835,9 @@ mxge_watchdog_reset(mxge_softc_t *sc, int slice) be32toh(sc->ss->fw_stats->send_done_count)); device_printf(sc->dev, "not resetting\n"); } + if (err) + device_printf(sc->dev, "watchdog reset failed\n"); + return (err); } @@ -3860,11 +3953,11 @@ mxge_change_mtu(mxge_softc_t *sc, int mtu) old_mtu = ifp->if_mtu; ifp->if_mtu = mtu; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); + mxge_close(sc, 0); err = mxge_open(sc); if (err != 0) { ifp->if_mtu = old_mtu; - mxge_close(sc); + mxge_close(sc, 0); (void) mxge_open(sc); } } @@ -3922,7 +4015,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc); + mxge_close(sc, 0); } } mtx_unlock(&sc->driver_mtx); @@ -4016,6 +4109,7 @@ mxge_fetch_tunables(mxge_softc_t *sc) TUNABLE_INT_FETCH("hw.mxge.rss_hash_type", &mxge_rss_hash_type); TUNABLE_INT_FETCH("hw.mxge.rss_hashtype", &mxge_rss_hash_type); TUNABLE_INT_FETCH("hw.mxge.initial_mtu", &mxge_initial_mtu); + TUNABLE_INT_FETCH("hw.mxge.throttle", &mxge_throttle); if (sc->lro_cnt != 0) mxge_lro_cnt = sc->lro_cnt; @@ -4033,6 +4127,12 @@ mxge_fetch_tunables(mxge_softc_t *sc) if (mxge_initial_mtu > ETHERMTU_JUMBO || mxge_initial_mtu < ETHER_MIN_LEN) mxge_initial_mtu = ETHERMTU_JUMBO; + + if (mxge_throttle && mxge_throttle > MXGE_MAX_THROTTLE) + mxge_throttle = MXGE_MAX_THROTTLE; + if (mxge_throttle && mxge_throttle < MXGE_MIN_THROTTLE) + mxge_throttle = MXGE_MIN_THROTTLE; + sc->throttle = mxge_throttle; } @@ -4645,7 +4745,7 @@ mxge_detach(device_t dev) mtx_lock(&sc->driver_mtx); sc->dying = 1; if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) - mxge_close(sc); + mxge_close(sc, 0); mtx_unlock(&sc->driver_mtx); ether_ifdetach(sc->ifp); callout_drain(&sc->co_hdl); |