FreeBSD/sys/dev/e1000/if_em.c
/*********************************************************************
 *
 *  Setup the MSIX Interrupt handlers
 *   This is not really Multiqueue, rather
 *   its just separate interrupt vectors
 *   for TX, RX, and Link.
 *
 **********************************************************************/
Setup the MSIX Interrupt handlers
This is not really Multiqueue, rather
its just separate interrupt vectors
for TX, RX, and Link.
Setup the MSIX Interrupt handlers This is not really Multiqueue rather its just separate interrupt vectors for TX RX and Link .
int
em_allocate_msix(struct adapter *adapter)
{
	device_t	dev = adapter->dev;
	struct		tx_ring *txr = adapter->tx_rings;
	struct		rx_ring *rxr = adapter->rx_rings;
	int		error, rid, vector = 0;
	int		cpu_id = 0;
	E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
	for (int i = 0; i < adapter->num_queues; i++, rxr++, vector++) {
		rid = vector + 1;
		rxr->res = bus_alloc_resource_any(dev,
		    SYS_RES_IRQ, &rid, RF_ACTIVE);
		if (rxr->res == NULL) {
			device_printf(dev,
			    "Unable to allocate bus resource: "
			    "RX MSIX Interrupt %d\n", i);
			return (ENXIO);
		}
		if ((error = bus_setup_intr(dev, rxr->res,
		    INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_rx,
		    rxr, &rxr->tag)) != 0) {
			device_printf(dev, "Failed to register RX handler");
			return (error);
		}
#if __FreeBSD_version >= 800504
		bus_describe_intr(dev, rxr->res, rxr->tag, "rx%d", i);
#endif
		rxr->msix = vector;
		if (em_last_bind_cpu < 0)
			em_last_bind_cpu = CPU_FIRST();
		cpu_id = em_last_bind_cpu;
		bus_bind_intr(dev, rxr->res, cpu_id);
		TASK_INIT(&rxr->rx_task, 0, em_handle_rx, rxr);
		rxr->tq = taskqueue_create_fast("em_rxq", M_NOWAIT,
		    taskqueue_thread_enqueue, &rxr->tq);
		taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq (cpuid %d)",
		    device_get_nameunit(adapter->dev), cpu_id);
		rxr->ims = 1 << (20 + i);
		adapter->ims |= rxr->ims;
		adapter->ivars |= (8 | rxr->msix) << (i * 4);
		em_last_bind_cpu = CPU_NEXT(em_last_bind_cpu);
	}
	for (int i = 0; i < adapter->num_queues; i++, txr++, vector++) {
		rid = vector + 1;
		txr->res = bus_alloc_resource_any(dev,
		    SYS_RES_IRQ, &rid, RF_ACTIVE);
		if (txr->res == NULL) {
			device_printf(dev,
			    "Unable to allocate bus resource: "
			    "TX MSIX Interrupt %d\n", i);
			return (ENXIO);
		}
		if ((error = bus_setup_intr(dev, txr->res,
		    INTR_TYPE_NET | INTR_MPSAFE, NULL, em_msix_tx,
		    txr, &txr->tag)) != 0) {
			device_printf(dev, "Failed to register TX handler");
			return (error);
		}
#if __FreeBSD_version >= 800504
		bus_describe_intr(dev, txr->res, txr->tag, "tx%d", i);
#endif
		txr->msix = vector;
                if (em_last_bind_cpu < 0)
                        em_last_bind_cpu = CPU_FIRST();
                cpu_id = em_last_bind_cpu;
                bus_bind_intr(dev, txr->res, cpu_id);
		TASK_INIT(&txr->tx_task, 0, em_handle_tx, txr);
		txr->tq = taskqueue_create_fast("em_txq", M_NOWAIT,
		    taskqueue_thread_enqueue, &txr->tq);
		taskqueue_start_threads(&txr->tq, 1, PI_NET, "%s txq (cpuid %d)",
		    device_get_nameunit(adapter->dev), cpu_id);
		txr->ims = 1 << (22 + i);
		adapter->ims |= txr->ims;
		adapter->ivars |= (8 | txr->msix) << (8 + (i * 4));
		em_last_bind_cpu = CPU_NEXT(em_last_bind_cpu);
	}
	rid = vector + 1;
	adapter->res = bus_alloc_resource_any(dev,
	    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
	if (!adapter->res) {
		device_printf(dev,"Unable to allocate "
		    "bus resource: Link interrupt [%d]\n", rid);
		return (ENXIO);
        }
	error = bus_setup_intr(dev, adapter->res,
	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
	    em_msix_link, adapter, &adapter->tag);
	if (error) {
		adapter->res = NULL;
		device_printf(dev, "Failed to register LINK handler");
		return (error);
	}
#if __FreeBSD_version >= 800504
	bus_describe_intr(dev, adapter->res, adapter->tag, "link");
#endif
	adapter->linkvec = vector;
	adapter->ivars |=  (8 | vector) << 16;
	adapter->ivars |= 0x80000000;
	return (0);
}
int em_allocate_msix ( struct adapter * adapter ) { device_t dev = adapter -> dev ; struct tx_ring * txr = adapter -> tx_rings ; struct rx_ring * rxr = adapter -> rx_rings ; int error , rid , vector = 0 ; int cpu_id = 0 ; E1000_WRITE_REG ( & adapter -> hw , E1000_IMC , 0xffffffff ) ; for ( int i = 0 ; i < adapter -> num_queues ; i ++ , rxr ++ , vector ++ ) { rid = vector + 1 ; rxr -> res = bus_alloc_resource_any ( dev , SYS_RES_IRQ , & rid , RF_ACTIVE ) ; if ( rxr -> res == NULL ) { device_printf ( dev , " " " \n " , i ) ; return ( ENXIO ) ; } if ( ( error = bus_setup_intr ( dev , rxr -> res , INTR_TYPE_NET | INTR_MPSAFE , NULL , em_msix_rx , rxr , & rxr -> tag ) ) != 0 ) { device_printf ( dev , " " ) ; return ( error ) ; } #if __FreeBSD_version >= 800504 bus_describe_intr ( dev , rxr -> res , rxr -> tag , " " , i ) ; #endif rxr -> msix = vector ; if ( em_last_bind_cpu < 0 ) em_last_bind_cpu = CPU_FIRST ( ) ; cpu_id = em_last_bind_cpu ; bus_bind_intr ( dev , rxr -> res , cpu_id ) ; TASK_INIT ( & rxr -> rx_task , 0 , em_handle_rx , rxr ) ; rxr -> tq = taskqueue_create_fast ( " " , M_NOWAIT , taskqueue_thread_enqueue , & rxr -> tq ) ; taskqueue_start_threads ( & rxr -> tq , 1 , PI_NET , " " , device_get_nameunit ( adapter -> dev ) , cpu_id ) ; rxr -> ims = 1 << ( 20 + i ) ; adapter -> ims |= rxr -> ims ; adapter -> ivars |= ( 8 | rxr -> msix ) << ( i * 4 ) ; em_last_bind_cpu = CPU_NEXT ( em_last_bind_cpu ) ; } for ( int i = 0 ; i < adapter -> num_queues ; i ++ , txr ++ , vector ++ ) { rid = vector + 1 ; txr -> res = bus_alloc_resource_any ( dev , SYS_RES_IRQ , & rid , RF_ACTIVE ) ; if ( txr -> res == NULL ) { device_printf ( dev , " " " \n " , i ) ; return ( ENXIO ) ; } if ( ( error = bus_setup_intr ( dev , txr -> res , INTR_TYPE_NET | INTR_MPSAFE , NULL , em_msix_tx , txr , & txr -> tag ) ) != 0 ) { device_printf ( dev , " " ) ; return ( error ) ; } #if __FreeBSD_version >= 800504 bus_describe_intr ( dev , txr -> res , txr -> tag , " " , i ) ; #endif txr -> msix = vector ; if ( em_last_bind_cpu < 0 ) em_last_bind_cpu = CPU_FIRST ( ) ; cpu_id = em_last_bind_cpu ; bus_bind_intr ( dev , txr -> res , cpu_id ) ; TASK_INIT ( & txr -> tx_task , 0 , em_handle_tx , txr ) ; txr -> tq = taskqueue_create_fast ( " " , M_NOWAIT , taskqueue_thread_enqueue , & txr -> tq ) ; taskqueue_start_threads ( & txr -> tq , 1 , PI_NET , " " , device_get_nameunit ( adapter -> dev ) , cpu_id ) ; txr -> ims = 1 << ( 22 + i ) ; adapter -> ims |= txr -> ims ; adapter -> ivars |= ( 8 | txr -> msix ) << ( 8 + ( i * 4 ) ) ; em_last_bind_cpu = CPU_NEXT ( em_last_bind_cpu ) ; } rid = vector + 1 ; adapter -> res = bus_alloc_resource_any ( dev , SYS_RES_IRQ , & rid , RF_SHAREABLE | RF_ACTIVE ) ; if ( ! adapter -> res ) { device_printf ( dev , " " " \n " , rid ) ; return ( ENXIO ) ; } error = bus_setup_intr ( dev , adapter -> res , INTR_TYPE_NET | INTR_MPSAFE , NULL , em_msix_link , adapter , & adapter -> tag ) ; if ( error ) { adapter -> res = NULL ; device_printf ( dev , " " ) ; return ( error ) ; } #if __FreeBSD_version >= 800504 bus_describe_intr ( dev , adapter -> res , adapter -> tag , " " ) ; #endif adapter -> linkvec = vector ; adapter -> ivars |= ( 8 | vector ) << 16 ; adapter -> ivars |= 0x80000000 ; return ( 0 ) ; }
Setup the MSIX Interrupt handlers
   This is not really Multiqueue, rather
   its just separate interrupt vectors
   for TX, RX, and Link.
Setup the MSIX Interrupt handlers This is not really Multiqueue rather its just separate interrupt vectors for TX RX and Link .
/* Make sure all interrupts are disabled */ /* First set up ring resources */ /* RX ring */ /*
		** Set the bit to enable interrupt
		** in E1000_IMS -- bits 20 and 21
		** are for RX0 and RX1, note this has
		** NOTHING to do with the MSIX vector
		*/ /* TX ring */ /*
		** Set the bit to enable interrupt
		** in E1000_IMS -- bits 22 and 23
		** are for TX0 and TX1, note this has
		** NOTHING to do with the MSIX vector
		*/ /* Link interrupt */ /* Set the link handler function */