FreeBSD/sys/dev/cxgb/cxgb_main.c
/*
 * Called on "ifconfig down", and from port_detach
 */
Called on "ifconfig down", and from port_detach
Called on " ifconfig down " and from port_detach
static int
cxgb_uninit_synchronized(struct port_info *pi)
{
	struct adapter *sc = pi->adapter;
	struct ifnet *ifp = pi->ifp;
	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
	clrbit(&sc->open_device_map, pi->port_id);
	t3_port_intr_disable(sc, pi->port_id);
	taskqueue_drain(sc->tq, &sc->slow_intr_task);
	taskqueue_drain(sc->tq, &sc->tick_task);
	callout_drain(&pi->link_check_ch);
	taskqueue_drain(sc->tq, &pi->link_check_task);
	PORT_LOCK(pi);
	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
	t3_set_reg_field(sc, A_XGM_TX_CFG + pi->mac.offset, F_TXPAUSEEN, 0);
	t3_set_reg_field(sc, A_XGM_RXFIFO_CFG +  pi->mac.offset,
			 V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM), 0);
	DELAY(100 * 1000);
	t3_wait_op_done(sc, A_XGM_TXFIFO_CFG + pi->mac.offset,
			F_TXFIFO_EMPTY, 1, 20, 5);
	DELAY(100 * 1000);
	t3_mac_disable(&pi->mac, MAC_DIRECTION_RX);
	pi->phy.ops->power_down(&pi->phy, 1);
	PORT_UNLOCK(pi);
	pi->link_config.link_ok = 0;
	t3_os_link_changed(sc, pi->port_id, 0, 0, 0, 0, 0);
	if (sc->open_device_map == 0)
		cxgb_down(pi->adapter);
	return (0);
}
static int cxgb_uninit_synchronized ( struct port_info * pi ) { struct adapter * sc = pi -> adapter ; struct ifnet * ifp = pi -> ifp ; ADAPTER_LOCK_ASSERT_NOTOWNED ( sc ) ; clrbit ( & sc -> open_device_map , pi -> port_id ) ; t3_port_intr_disable ( sc , pi -> port_id ) ; taskqueue_drain ( sc -> tq , & sc -> slow_intr_task ) ; taskqueue_drain ( sc -> tq , & sc -> tick_task ) ; callout_drain ( & pi -> link_check_ch ) ; taskqueue_drain ( sc -> tq , & pi -> link_check_task ) ; PORT_LOCK ( pi ) ; ifp -> if_drv_flags &= ~ ( IFF_DRV_RUNNING | IFF_DRV_OACTIVE ) ; t3_set_reg_field ( sc , A_XGM_TX_CFG + pi -> mac . offset , F_TXPAUSEEN , 0 ) ; t3_set_reg_field ( sc , A_XGM_RXFIFO_CFG + pi -> mac . offset , V_RXFIFOPAUSEHWM ( M_RXFIFOPAUSEHWM ) , 0 ) ; DELAY ( 100 * 1000 ) ; t3_wait_op_done ( sc , A_XGM_TXFIFO_CFG + pi -> mac . offset , F_TXFIFO_EMPTY , 1 , 20 , 5 ) ; DELAY ( 100 * 1000 ) ; t3_mac_disable ( & pi -> mac , MAC_DIRECTION_RX ) ; pi -> phy . ops -> power_down ( & pi -> phy , 1 ) ; PORT_UNLOCK ( pi ) ; pi -> link_config . link_ok = 0 ; t3_os_link_changed ( sc , pi -> port_id , 0 , 0 , 0 , 0 , 0 ) ; if ( sc -> open_device_map == 0 ) cxgb_down ( pi -> adapter ) ; return ( 0 ) ; }
Called on "ifconfig down", and from port_detach
Called on " ifconfig down " and from port_detach
/*
	 * taskqueue_drain may cause a deadlock if the adapter lock is held.
	 */ /*
	 * Clear this port's bit from the open device map, and then drain all
	 * the tasks that can access/manipulate this port's port_info or ifp.
	 * We disable this port's interrupts here and so the slow/ext
	 * interrupt tasks won't be enqueued.  The tick task will continue to
	 * be enqueued every second but the runs after this drain will not see
	 * this port in the open device map.
	 *
	 * A well behaved task must take open_device_map into account and ignore
	 * ports that are not open.
	 */ /* disable pause frames */ /* Reset RX FIFO HWM */ /* Wait for TXFIFO empty */