FreeBSD/sys/dev/e1000/if_igb.c
/*
 * Setup Either MSI/X or MSI
 */
Setup Either MSI/X or MSI
Setup Either MSI / X or MSI
static int
igb_setup_msix(struct adapter *adapter)
{
	device_t	dev = adapter->dev;
	int		bar, want, queues, msgs, maxqueues;
	if (igb_enable_msix == 0)
		goto msi;
	msgs = pci_msix_count(dev); 
	if (msgs == 0)
		goto msi;
	adapter->memrid = PCIR_BAR(IGB_MSIX_BAR);
	bar = pci_read_config(dev, adapter->memrid, 4);
	if (bar == 0) 
		adapter->memrid += 4;
	adapter->msix_mem = bus_alloc_resource_any(dev,
	    SYS_RES_MEMORY, &adapter->memrid, RF_ACTIVE);
       	if (adapter->msix_mem == NULL) {
		device_printf(adapter->dev,
		    "Unable to map MSIX table \n");
		goto msi;
	}
	queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus;
	if (igb_num_queues != 0)
		queues = igb_num_queues;
#ifdef	RSS
	if (queues > rss_getnumbuckets())
		queues = rss_getnumbuckets();
#endif
	switch (adapter->hw.mac.type) {
		case e1000_82575:
			maxqueues = 4;
			break;
		case e1000_82576:
		case e1000_82580:
		case e1000_i350:
		case e1000_i354:
			maxqueues = 8;
			break;
		case e1000_i210:
			maxqueues = 4;
			break;
		case e1000_i211:
			maxqueues = 2;
			break;
		default:  
			maxqueues = 1;
			break;
	}
	if (queues > maxqueues)
		queues = maxqueues;
	want = queues + 1;
	if (msgs >= want)
		msgs = want;
	else {
               	device_printf(adapter->dev,
		    "MSIX Configuration Problem, "
		    "%d vectors configured, but %d queues wanted!\n",
		    msgs, want);
		goto msi;
	}
	if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
               	device_printf(adapter->dev,
		    "Using MSIX interrupts with %d vectors\n", msgs);
		adapter->num_queues = queues;
		return (msgs);
	}
	pci_release_msi(dev);
msi:
       	if (adapter->msix_mem != NULL) {
		bus_release_resource(dev, SYS_RES_MEMORY,
		    PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem);
		adapter->msix_mem = NULL;
	}
       	msgs = 1;
	if (pci_alloc_msi(dev, &msgs) == 0) {
		device_printf(adapter->dev," Using an MSI interrupt\n");
		return (msgs);
	}
	device_printf(adapter->dev," Using a Legacy interrupt\n");
	return (0);
}
static int igb_setup_msix ( struct adapter * adapter ) { device_t dev = adapter -> dev ; int bar , want , queues , msgs , maxqueues ; if ( igb_enable_msix == 0 ) goto msi ; msgs = pci_msix_count ( dev ) ; if ( msgs == 0 ) goto msi ; adapter -> memrid = PCIR_BAR ( IGB_MSIX_BAR ) ; bar = pci_read_config ( dev , adapter -> memrid , 4 ) ; if ( bar == 0 ) adapter -> memrid += 4 ; adapter -> msix_mem = bus_alloc_resource_any ( dev , SYS_RES_MEMORY , & adapter -> memrid , RF_ACTIVE ) ; if ( adapter -> msix_mem == NULL ) { device_printf ( adapter -> dev , " \n " ) ; goto msi ; } queues = ( mp_ncpus > ( msgs - 1 ) ) ? ( msgs - 1 ) : mp_ncpus ; if ( igb_num_queues != 0 ) queues = igb_num_queues ; #ifdef RSS if ( queues > rss_getnumbuckets ( ) ) queues = rss_getnumbuckets ( ) ; #endif switch ( adapter -> hw . mac . type ) { case e1000_82575 : maxqueues = 4 ; break ; case e1000_82576 : case e1000_82580 : case e1000_i350 : case e1000_i354 : maxqueues = 8 ; break ; case e1000_i210 : maxqueues = 4 ; break ; case e1000_i211 : maxqueues = 2 ; break ; default : maxqueues = 1 ; break ; } if ( queues > maxqueues ) queues = maxqueues ; want = queues + 1 ; if ( msgs >= want ) msgs = want ; else { device_printf ( adapter -> dev , " " " \n " , msgs , want ) ; goto msi ; } if ( ( pci_alloc_msix ( dev , & msgs ) == 0 ) && ( msgs == want ) ) { device_printf ( adapter -> dev , " \n " , msgs ) ; adapter -> num_queues = queues ; return ( msgs ) ; } pci_release_msi ( dev ) ; msi : if ( adapter -> msix_mem != NULL ) { bus_release_resource ( dev , SYS_RES_MEMORY , PCIR_BAR ( IGB_MSIX_BAR ) , adapter -> msix_mem ) ; adapter -> msix_mem = NULL ; } msgs = 1 ; if ( pci_alloc_msi ( dev , & msgs ) == 0 ) { device_printf ( adapter -> dev , " \n " ) ; return ( msgs ) ; } device_printf ( adapter -> dev , " \n " ) ; return ( 0 ) ; }
Setup Either MSI/X or MSI
Setup Either MSI / X or MSI
/* tuneable override */ /* First try MSI/X */ /*
	** Some new devices, as with ixgbe, now may
	** use a different BAR, so we need to keep
	** track of which is used.
	*/ /* use next bar */ /* May not be enabled */ /* Override via tuneable */ /* If we're doing RSS, clamp at the number of RSS buckets */ /* Sanity check based on HW */ /* VF interfaces */ /* Final clamp on the actual hardware capability */ /*
	** One vector (RX/TX pair) per queue
	** plus an additional for Link interrupt
	*/ /*
	** If MSIX alloc failed or provided us with
	** less than needed, free and fall through to MSI
	*/