FreeBSD/sys/dev/e1000/if_igb.c
/*********************************************************************
 *
 *  Setup the MSIX Queue Interrupt handlers: 
 *
 **********************************************************************/
Setup the MSIX Queue Interrupt handlers.
Setup the MSIX Queue Interrupt handlers .
static int
igb_allocate_msix(struct adapter *adapter)
{
	device_t		dev = adapter->dev;
	struct igb_queue	*que = adapter->queues;
	int			error, rid, vector = 0;
	int			cpu_id = 0;
#ifdef	RSS
	cpuset_t cpu_mask;
#endif
	E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0);
	E1000_WRITE_FLUSH(&adapter->hw);
#ifdef	RSS
	if (adapter->num_queues != rss_getnumbuckets()) {
		device_printf(dev,
		    "%s: number of queues (%d) != number of RSS buckets (%d)"
		    "; performance will be impacted.\n",
		    __func__,
		    adapter->num_queues,
		    rss_getnumbuckets());
	}
#endif
	for (int i = 0; i < adapter->num_queues; i++, vector++, que++) {
		rid = vector +1;
		que->res = bus_alloc_resource_any(dev,
		    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
		if (que->res == NULL) {
			device_printf(dev,
			    "Unable to allocate bus resource: "
			    "MSIX Queue Interrupt\n");
			return (ENXIO);
		}
		error = bus_setup_intr(dev, que->res,
	    	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
		    igb_msix_que, que, &que->tag);
		if (error) {
			que->res = NULL;
			device_printf(dev, "Failed to register Queue handler");
			return (error);
		}
#if __FreeBSD_version >= 800504
		bus_describe_intr(dev, que->res, que->tag, "que %d", i);
#endif
		que->msix = vector;
		if (adapter->hw.mac.type == e1000_82575)
			que->eims = E1000_EICR_TX_QUEUE0 << i;
		else
			que->eims = 1 << vector;
#ifdef	RSS
		cpu_id = rss_getcpu(i % rss_getnumbuckets());
#else
		if (adapter->num_queues > 1) {
			if (igb_last_bind_cpu < 0)
				igb_last_bind_cpu = CPU_FIRST();
			cpu_id = igb_last_bind_cpu;
		}
#endif
		if (adapter->num_queues > 1) {
			bus_bind_intr(dev, que->res, cpu_id);
#ifdef	RSS
			device_printf(dev,
				"Bound queue %d to RSS bucket %d\n",
				i, cpu_id);
#else
			device_printf(dev,
				"Bound queue %d to cpu %d\n",
				i, cpu_id);
#endif
		}
#ifndef IGB_LEGACY_TX
		TASK_INIT(&que->txr->txq_task, 0, igb_deferred_mq_start,
		    que->txr);
#endif
		TASK_INIT(&que->que_task, 0, igb_handle_que, que);
		que->tq = taskqueue_create("igb_que", M_NOWAIT,
		    taskqueue_thread_enqueue, &que->tq);
		if (adapter->num_queues > 1) {
#ifdef	RSS
			CPU_SETOF(cpu_id, &cpu_mask);
			taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
			    &cpu_mask,
			    "%s que (bucket %d)",
			    device_get_nameunit(adapter->dev),
			    cpu_id);
#else
			taskqueue_start_threads(&que->tq, 1, PI_NET,
			    "%s que (qid %d)",
			    device_get_nameunit(adapter->dev),
			    cpu_id);
#endif
		} else {
			taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
			    device_get_nameunit(adapter->dev));
		}
		if (adapter->num_queues > 1)
			igb_last_bind_cpu = CPU_NEXT(igb_last_bind_cpu);
	}
	rid = vector + 1;
	adapter->res = bus_alloc_resource_any(dev,
	    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
	if (adapter->res == NULL) {
		device_printf(dev,
		    "Unable to allocate bus resource: "
		    "MSIX Link Interrupt\n");
		return (ENXIO);
	}
	if ((error = bus_setup_intr(dev, adapter->res,
	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
	    igb_msix_link, adapter, &adapter->tag)) != 0) {
		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;
	return (0);
}
static int igb_allocate_msix ( struct adapter * adapter ) { device_t dev = adapter -> dev ; struct igb_queue * que = adapter -> queues ; int error , rid , vector = 0 ; int cpu_id = 0 ; #ifdef RSS cpuset_t cpu_mask ; #endif E1000_WRITE_REG ( & adapter -> hw , E1000_IMC , ~ 0 ) ; E1000_WRITE_FLUSH ( & adapter -> hw ) ; #ifdef RSS if ( adapter -> num_queues != rss_getnumbuckets ( ) ) { device_printf ( dev , " " " \n " , __func__ , adapter -> num_queues , rss_getnumbuckets ( ) ) ; } #endif for ( int i = 0 ; i < adapter -> num_queues ; i ++ , vector ++ , que ++ ) { rid = vector + 1 ; que -> res = bus_alloc_resource_any ( dev , SYS_RES_IRQ , & rid , RF_SHAREABLE | RF_ACTIVE ) ; if ( que -> res == NULL ) { device_printf ( dev , " " " \n " ) ; return ( ENXIO ) ; } error = bus_setup_intr ( dev , que -> res , INTR_TYPE_NET | INTR_MPSAFE , NULL , igb_msix_que , que , & que -> tag ) ; if ( error ) { que -> res = NULL ; device_printf ( dev , " " ) ; return ( error ) ; } #if __FreeBSD_version >= 800504 bus_describe_intr ( dev , que -> res , que -> tag , " " , i ) ; #endif que -> msix = vector ; if ( adapter -> hw . mac . type == e1000_82575 ) que -> eims = E1000_EICR_TX_QUEUE0 << i ; else que -> eims = 1 << vector ; #ifdef RSS cpu_id = rss_getcpu ( i % rss_getnumbuckets ( ) ) ; #else if ( adapter -> num_queues > 1 ) { if ( igb_last_bind_cpu < 0 ) igb_last_bind_cpu = CPU_FIRST ( ) ; cpu_id = igb_last_bind_cpu ; } #endif if ( adapter -> num_queues > 1 ) { bus_bind_intr ( dev , que -> res , cpu_id ) ; #ifdef RSS device_printf ( dev , " \n " , i , cpu_id ) ; #else device_printf ( dev , " \n " , i , cpu_id ) ; #endif } #ifndef IGB_LEGACY_TX TASK_INIT ( & que -> txr -> txq_task , 0 , igb_deferred_mq_start , que -> txr ) ; #endif TASK_INIT ( & que -> que_task , 0 , igb_handle_que , que ) ; que -> tq = taskqueue_create ( " " , M_NOWAIT , taskqueue_thread_enqueue , & que -> tq ) ; if ( adapter -> num_queues > 1 ) { #ifdef RSS CPU_SETOF ( cpu_id , & cpu_mask ) ; taskqueue_start_threads_cpuset ( & que -> tq , 1 , PI_NET , & cpu_mask , " " , device_get_nameunit ( adapter -> dev ) , cpu_id ) ; #else taskqueue_start_threads ( & que -> tq , 1 , PI_NET , " " , device_get_nameunit ( adapter -> dev ) , cpu_id ) ; #endif } else { taskqueue_start_threads ( & que -> tq , 1 , PI_NET , " " , device_get_nameunit ( adapter -> dev ) ) ; } if ( adapter -> num_queues > 1 ) igb_last_bind_cpu = CPU_NEXT ( igb_last_bind_cpu ) ; } rid = vector + 1 ; adapter -> res = bus_alloc_resource_any ( dev , SYS_RES_IRQ , & rid , RF_SHAREABLE | RF_ACTIVE ) ; if ( adapter -> res == NULL ) { device_printf ( dev , " " " \n " ) ; return ( ENXIO ) ; } if ( ( error = bus_setup_intr ( dev , adapter -> res , INTR_TYPE_NET | INTR_MPSAFE , NULL , igb_msix_link , adapter , & adapter -> tag ) ) != 0 ) { device_printf ( dev , " " ) ; return ( error ) ; } #if __FreeBSD_version >= 800504 bus_describe_intr ( dev , adapter -> res , adapter -> tag , " " ) ; #endif adapter -> linkvec = vector ; return ( 0 ) ; }
Setup the MSIX Queue Interrupt handlers:
Setup the MSIX Queue Interrupt handlers :
/* Be sure to start with all interrupts disabled */ /*
	 * If we're doing RSS, the number of queues needs to
	 * match the number of RSS buckets that are configured.
	 *
	 * + If there's more queues than RSS buckets, we'll end
	 *   up with queues that get no traffic.
	 *
	 * + If there's more RSS buckets than queues, we'll end
	 *   up having multiple RSS buckets map to the same queue,
	 *   so there'll be some contention.
	 */ /*
		 * The queue ID is used as the RSS layer bucket ID.
		 * We look up the queue ID -> RSS CPU ID and select
		 * that.
		 */ /*
		 * Bind the msix vector, and thus the
		 * rings to the corresponding cpu.
		 *
		 * This just happens to match the default RSS round-robin
		 * bucket -> queue -> CPU allocation.
		 */ /* Make tasklet for deferred handling */ /*
			 * Only pin the taskqueue thread to a CPU if
			 * RSS is in use.
			 *
			 * This again just happens to match the default RSS
			 * round-robin bucket -> queue -> CPU allocation.
			 */ /* Finally update the last bound CPU id */ /* And Link */