FreeBSD/sys/dev/ixl/if_ixlv.c
/*
 * Allocate MSI/X vectors, setup the AQ vector early
 */
Allocate MSI/X vectors, setup the AQ vector early
Allocate MSI / X vectors setup the AQ vector early
static int
ixlv_init_msix(struct ixlv_sc *sc)
{
	device_t dev = sc->dev;
	int rid, want, vectors, queues, available;
	int auto_max_queues;
	rid = PCIR_BAR(IXL_BAR);
	sc->msix_mem = bus_alloc_resource_any(dev,
	    SYS_RES_MEMORY, &rid, RF_ACTIVE);
       	if (!sc->msix_mem) {
		device_printf(sc->dev,
		    "Unable to map MSIX table\n");
		goto fail;
	}
	available = pci_msix_count(dev); 
	if (available == 0) { 
		bus_release_resource(dev, SYS_RES_MEMORY,
		    rid, sc->msix_mem);
		sc->msix_mem = NULL;
		goto fail;
	}
	auto_max_queues = min(mp_ncpus, available - 1);
	auto_max_queues = min(auto_max_queues, sc->vf_res->num_queue_pairs);
	if ((ixlv_max_queues != 0) && (ixlv_max_queues <= auto_max_queues))
		queues = ixlv_max_queues;
	else if ((ixlv_max_queues != 0) && (ixlv_max_queues > auto_max_queues)) {
		device_printf(dev, "ixlv_max_queues (%d) is too large, using "
		    "autoconfig amount (%d)...\n",
		    ixlv_max_queues, auto_max_queues);
		queues = auto_max_queues;
	}
	else
		queues = min(auto_max_queues, 8);
#ifdef  RSS
	if (queues > rss_getnumbuckets())
		queues = rss_getnumbuckets();
#endif
	want = queues + 1;
	if (want <= available)	
		vectors = want;
	else {
		device_printf(sc->dev,
		    "MSIX Configuration Problem, "
		    "%d vectors available but %d wanted!\n",
		    available, want);
		goto fail;
	}
#ifdef RSS
	if (queues != rss_getnumbuckets()) {
		device_printf(dev,
		    "%s: queues (%d) != RSS buckets (%d)"
		    "; performance will be impacted.\n",
		     __func__, queues, rss_getnumbuckets());
	}
#endif
	if (pci_alloc_msix(dev, &vectors) == 0) {
		device_printf(sc->dev,
		    "Using MSIX interrupts with %d vectors\n", vectors);
		sc->msix = vectors;
		sc->vsi.num_queues = queues;
	}
	rid = 1;	
	sc->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &rid, RF_SHAREABLE | RF_ACTIVE);
	if (sc->res == NULL) {
		device_printf(dev,"Unable to allocate"
		    " bus resource: AQ interrupt \n");
		goto fail;
	}
	if (bus_setup_intr(dev, sc->res,
	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
	    ixlv_msix_adminq, sc, &sc->tag)) {
		sc->res = NULL;
		device_printf(dev, "Failed to register AQ handler");
		goto fail;
	}
	bus_describe_intr(dev, sc->res, sc->tag, "adminq");
	return (vectors);
fail:
	return (0);
}
static int ixlv_init_msix ( struct ixlv_sc * sc ) { device_t dev = sc -> dev ; int rid , want , vectors , queues , available ; int auto_max_queues ; rid = PCIR_BAR ( IXL_BAR ) ; sc -> msix_mem = bus_alloc_resource_any ( dev , SYS_RES_MEMORY , & rid , RF_ACTIVE ) ; if ( ! sc -> msix_mem ) { device_printf ( sc -> dev , " \n " ) ; goto fail ; } available = pci_msix_count ( dev ) ; if ( available == 0 ) { bus_release_resource ( dev , SYS_RES_MEMORY , rid , sc -> msix_mem ) ; sc -> msix_mem = NULL ; goto fail ; } auto_max_queues = min ( mp_ncpus , available - 1 ) ; auto_max_queues = min ( auto_max_queues , sc -> vf_res -> num_queue_pairs ) ; if ( ( ixlv_max_queues != 0 ) && ( ixlv_max_queues <= auto_max_queues ) ) queues = ixlv_max_queues ; else if ( ( ixlv_max_queues != 0 ) && ( ixlv_max_queues > auto_max_queues ) ) { device_printf ( dev , " " " \n " , ixlv_max_queues , auto_max_queues ) ; queues = auto_max_queues ; } else queues = min ( auto_max_queues , 8 ) ; #ifdef RSS if ( queues > rss_getnumbuckets ( ) ) queues = rss_getnumbuckets ( ) ; #endif want = queues + 1 ; if ( want <= available ) vectors = want ; else { device_printf ( sc -> dev , " " " \n " , available , want ) ; goto fail ; } #ifdef RSS if ( queues != rss_getnumbuckets ( ) ) { device_printf ( dev , " " " \n " , __func__ , queues , rss_getnumbuckets ( ) ) ; } #endif if ( pci_alloc_msix ( dev , & vectors ) == 0 ) { device_printf ( sc -> dev , " \n " , vectors ) ; sc -> msix = vectors ; sc -> vsi . num_queues = queues ; } rid = 1 ; sc -> res = bus_alloc_resource_any ( dev , SYS_RES_IRQ , & rid , RF_SHAREABLE | RF_ACTIVE ) ; if ( sc -> res == NULL ) { device_printf ( dev , " " " \n " ) ; goto fail ; } if ( bus_setup_intr ( dev , sc -> res , INTR_TYPE_NET | INTR_MPSAFE , NULL , ixlv_msix_adminq , sc , & sc -> tag ) ) { sc -> res = NULL ; device_printf ( dev , " " ) ; goto fail ; } bus_describe_intr ( dev , sc -> res , sc -> tag , " " ) ; return ( vectors ) ; fail : return ( 0 ) ; }
Allocate MSI/X vectors, setup the AQ vector early
Allocate MSI / X vectors setup the AQ vector early
/* May not be enabled */ /* system has msix disabled */ /* Clamp queues to number of CPUs and # of MSI-X vectors available */ /* Clamp queues to # assigned to VF by PF */ /* Override with tunable value if tunable is less than autoconfig count */ /* Use autoconfig amount if that's lower */ /* Limit maximum auto-configured queues to 8 if no user value is set */ /* If we're doing RSS, clamp at the number of RSS buckets */ /*
	** Want one vector (RX/TX pair) per queue
	** plus an additional for the admin queue.
	*/ /* Have enough */ /*
	* 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.
	*/ /* Next we need to setup the vector for the Admin Queue */ // zero vector + 1 /* The VF driver MUST use MSIX */