FreeBSD/sys/dev/bxe/bxe.c
/* periodic timer callout routine, only runs when the interface is up */
periodic timer callout routine, only runs when the interface is up
periodic timer callout routine only runs when the interface is up
static void
bxe_periodic_callout_func(void *xsc)
{
    struct bxe_softc *sc = (struct bxe_softc *)xsc;
    struct bxe_fastpath *fp;
    uint16_t tx_bd_avail;
    int i;
    if (!BXE_CORE_TRYLOCK(sc)) {
        if ((sc->state == BXE_STATE_OPEN) &&
            (atomic_load_acq_long(&sc->periodic_flags) == PERIODIC_GO)) {
            callout_reset(&sc->periodic_callout, hz,
                          bxe_periodic_callout_func, sc);
        }
        return;
    }
    if ((sc->state != BXE_STATE_OPEN) ||
        (atomic_load_acq_long(&sc->periodic_flags) == PERIODIC_STOP)) {
        BLOGW(sc, "periodic callout exit (state=0x%x)\n", sc->state);
        BXE_CORE_UNLOCK(sc);
        return;
    }
#if __FreeBSD_version >= 800000
    FOR_EACH_QUEUE(sc, i) {
        fp = &sc->fp[i];
        if (BXE_FP_TX_TRYLOCK(fp)) {
            if_t ifp = sc->ifp;
            (void) bxe_txeof(sc, fp);
            tx_bd_avail = bxe_tx_avail(sc, fp);
            if (tx_bd_avail >= BXE_TX_CLEANUP_THRESHOLD) {
                bxe_tx_mq_start_locked(sc, ifp, fp, NULL);
            }
            BXE_FP_TX_UNLOCK(fp);
        }
    }
#else
    fp = &sc->fp[0];
    if (BXE_FP_TX_TRYLOCK(fp)) {
        struct ifnet *ifp = sc->ifnet;
        (void) bxe_txeof(sc, fp);
        tx_bd_avail = bxe_tx_avail(sc, fp);
        if (tx_bd_avail >= BXE_TX_CLEANUP_THRESHOLD) {
            bxe_tx_start_locked(sc, ifp, fp);
        }
        BXE_FP_TX_UNLOCK(fp);
    }
#endif 
    FOR_EACH_QUEUE(sc, i) {
        if (bxe_watchdog(sc, &sc->fp[i]) != 0) {
            break;
        }
    }
    if (!CHIP_REV_IS_SLOW(sc)) {
        mb();
        if (sc->port.pmf) {
	    bxe_acquire_phy_lock(sc);
            elink_period_func(&sc->link_params, &sc->link_vars);
	    bxe_release_phy_lock(sc);
        }
    }
    if (IS_PF(sc) && !(sc->flags & BXE_NO_PULSE)) {
        int mb_idx = SC_FW_MB_IDX(sc);
        uint32_t drv_pulse;
        uint32_t mcp_pulse;
        ++sc->fw_drv_pulse_wr_seq;
        sc->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
        drv_pulse = sc->fw_drv_pulse_wr_seq;
        bxe_drv_pulse(sc);
        mcp_pulse = (SHMEM_RD(sc, func_mb[mb_idx].mcp_pulse_mb) &
                     MCP_PULSE_SEQ_MASK);
        if ((drv_pulse != mcp_pulse) &&
            (drv_pulse != ((mcp_pulse + 1) & MCP_PULSE_SEQ_MASK))) {
            BLOGE(sc, "drv_pulse (0x%x) != mcp_pulse (0x%x)\n",
                  drv_pulse, mcp_pulse);
        }
    }
    bxe_stats_handle(sc, STATS_EVENT_UPDATE);
    BXE_CORE_UNLOCK(sc);
    if ((sc->state == BXE_STATE_OPEN) &&
        (atomic_load_acq_long(&sc->periodic_flags) == PERIODIC_GO)) {
        callout_reset(&sc->periodic_callout, hz,
                      bxe_periodic_callout_func, sc);
    }
}
static void bxe_periodic_callout_func ( void * xsc ) { struct bxe_softc * sc = ( struct bxe_softc * ) xsc ; struct bxe_fastpath * fp ; uint16_t tx_bd_avail ; int i ; if ( ! BXE_CORE_TRYLOCK ( sc ) ) { if ( ( sc -> state == BXE_STATE_OPEN ) && ( atomic_load_acq_long ( & sc -> periodic_flags ) == PERIODIC_GO ) ) { callout_reset ( & sc -> periodic_callout , hz , bxe_periodic_callout_func , sc ) ; } return ; } if ( ( sc -> state != BXE_STATE_OPEN ) || ( atomic_load_acq_long ( & sc -> periodic_flags ) == PERIODIC_STOP ) ) { BLOGW ( sc , " \n " , sc -> state ) ; BXE_CORE_UNLOCK ( sc ) ; return ; } #if __FreeBSD_version >= 800000 FOR_EACH_QUEUE ( sc , i ) { fp = & sc -> fp [ i ] ; if ( BXE_FP_TX_TRYLOCK ( fp ) ) { if_t ifp = sc -> ifp ; ( void ) bxe_txeof ( sc , fp ) ; tx_bd_avail = bxe_tx_avail ( sc , fp ) ; if ( tx_bd_avail >= BXE_TX_CLEANUP_THRESHOLD ) { bxe_tx_mq_start_locked ( sc , ifp , fp , NULL ) ; } BXE_FP_TX_UNLOCK ( fp ) ; } } #else fp = & sc -> fp [ 0 ] ; if ( BXE_FP_TX_TRYLOCK ( fp ) ) { struct ifnet * ifp = sc -> ifnet ; ( void ) bxe_txeof ( sc , fp ) ; tx_bd_avail = bxe_tx_avail ( sc , fp ) ; if ( tx_bd_avail >= BXE_TX_CLEANUP_THRESHOLD ) { bxe_tx_start_locked ( sc , ifp , fp ) ; } BXE_FP_TX_UNLOCK ( fp ) ; } #endif FOR_EACH_QUEUE ( sc , i ) { if ( bxe_watchdog ( sc , & sc -> fp [ i ] ) != 0 ) { break ; } } if ( ! CHIP_REV_IS_SLOW ( sc ) ) { mb ( ) ; if ( sc -> port . pmf ) { bxe_acquire_phy_lock ( sc ) ; elink_period_func ( & sc -> link_params , & sc -> link_vars ) ; bxe_release_phy_lock ( sc ) ; } } if ( IS_PF ( sc ) && ! ( sc -> flags & BXE_NO_PULSE ) ) { int mb_idx = SC_FW_MB_IDX ( sc ) ; uint32_t drv_pulse ; uint32_t mcp_pulse ; ++ sc -> fw_drv_pulse_wr_seq ; sc -> fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK ; drv_pulse = sc -> fw_drv_pulse_wr_seq ; bxe_drv_pulse ( sc ) ; mcp_pulse = ( SHMEM_RD ( sc , func_mb [ mb_idx ] . mcp_pulse_mb ) & MCP_PULSE_SEQ_MASK ) ; if ( ( drv_pulse != mcp_pulse ) && ( drv_pulse != ( ( mcp_pulse + 1 ) & MCP_PULSE_SEQ_MASK ) ) ) { BLOGE ( sc , " \n " , drv_pulse , mcp_pulse ) ; } } bxe_stats_handle ( sc , STATS_EVENT_UPDATE ) ; BXE_CORE_UNLOCK ( sc ) ; if ( ( sc -> state == BXE_STATE_OPEN ) && ( atomic_load_acq_long ( & sc -> periodic_flags ) == PERIODIC_GO ) ) { callout_reset ( & sc -> periodic_callout , hz , bxe_periodic_callout_func , sc ) ; } }
periodic timer callout routine, only runs when the interface is up
periodic timer callout routine only runs when the interface is up
/* just bail and try again next time */ /* schedule the next periodic callout */ /*
             * If interface was stopped due to unavailable
             * bds, try to process some tx completions
             */ /*
         * If interface was stopped due to unavailable
         * bds, try to process some tx completions
         */ /* #if __FreeBSD_version >= 800000 */ /* Check for TX timeouts on any fastpath. */ /* Ruh-Roh, chip was reset! */ /*
         * This barrier is needed to ensure the ordering between the writing
         * to the sc->port.pmf in the bxe_nic_load() or bxe_pmf_update() and
         * the reading here.
         */ /*
         * The delta between driver pulse and mcp response should
         * be 1 (before mcp response) or 0 (after mcp response).
         */ /* someone lost a heartbeat... */ /* state is BXE_STATE_OPEN */ /* schedule the next periodic callout */