FreeBSD/sys/dev/ixl/if_ixlv.c
/*********************************************************************
 *  Device initialization routine
 *
 *  The attach entry point is called when the driver is being loaded.
 *  This routine identifies the type of hardware, allocates all resources
 *  and initializes the hardware.
 *
 *  return 0 on success, positive on failure
 *********************************************************************/
Device initialization routine
The attach entry point is called when the driver is being loaded.
This routine identifies the type of hardware, allocates all resources
and initializes the hardware.

return 0 on success, positive on failure
Device initialization routine The attach entry point is called when the driver is being loaded . This routine identifies the type of hardware allocates all resources and initializes the hardware . return 0 on success positive on failure
static int
ixlv_attach(device_t dev)
{
	struct ixlv_sc	*sc;
	struct i40e_hw	*hw;
	struct ixl_vsi 	*vsi;
	int            	error = 0;
	INIT_DBG_DEV(dev, "begin");
	sc = device_get_softc(dev);
	sc->dev = sc->osdep.dev = dev;
	hw = &sc->hw;
	vsi = &sc->vsi;
	vsi->dev = dev;
	ixlv_init_hw(sc);
	ixlv_init_filters(sc);
	mtx_init(&sc->mtx, device_get_nameunit(dev),
	    "IXL SC Lock", MTX_DEF);
	callout_init_mtx(&sc->timer, &sc->mtx, 0);
	if (ixlv_allocate_pci_resources(sc)) {
		device_printf(dev, "%s: Allocation of PCI resources failed\n",
		    __func__);
		error = ENXIO;
		goto err_early;
	}
	INIT_DBG_DEV(dev, "Allocated PCI resources and MSIX vectors");
	error = i40e_set_mac_type(hw);
	if (error) {
		device_printf(dev, "%s: set_mac_type failed: %d\n",
		    __func__, error);
		goto err_pci_res;
	}
	error = ixlv_reset_complete(hw);
	if (error) {
		device_printf(dev, "%s: Device is still being reset\n",
		    __func__);
		goto err_pci_res;
	}
	INIT_DBG_DEV(dev, "VF Device is ready for configuration");
	error = ixlv_setup_vc(sc);
	if (error) {
		device_printf(dev, "%s: Error setting up PF comms, %d\n",
		    __func__, error);
		goto err_pci_res;
	}
	INIT_DBG_DEV(dev, "PF API version verified");
	error = ixlv_reset(sc);
	if (error) {
		device_printf(dev, "VF reset failed; reload the driver\n");
		goto err_aq;
	}
	INIT_DBG_DEV(dev, "VF reset complete");
	error = ixlv_vf_config(sc);
	if (error) {
		device_printf(dev, "Error getting configuration from PF: %d\n",
		    error);
		goto err_aq;
	}
	device_printf(dev, "VSIs %d, QPs %d, MSIX %d, RSS sizes: key %d lut %d\n",
	    sc->vf_res->num_vsis,
	    sc->vf_res->num_queue_pairs,
	    sc->vf_res->max_vectors,
	    sc->vf_res->rss_key_size,
	    sc->vf_res->rss_lut_size);
#ifdef IXL_DEBUG
	device_printf(dev, "Offload flags: 0x%b\n",
	    sc->vf_res->vf_offload_flags, IXLV_PRINTF_VF_OFFLOAD_FLAGS);
#endif
	for (int i = 0; i < sc->vf_res->num_vsis; i++) {
		if (sc->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV)
			sc->vsi_res = &sc->vf_res->vsi_res[i];
	}
	if (!sc->vsi_res) {
		device_printf(dev, "%s: no LAN VSI found\n", __func__);
		error = EIO;
		goto err_res_buf;
	}
	INIT_DBG_DEV(dev, "Resource Acquisition complete");
	if (!ixlv_check_ether_addr(hw->mac.addr)) {
		u8 addr[ETHER_ADDR_LEN];
		arc4rand(&addr, sizeof(addr), 0);
		addr[0] &= 0xFE;
		addr[0] |= 0x02;
		bcopy(addr, hw->mac.addr, sizeof(addr));
	}
	sc->msix = ixlv_init_msix(sc);
	if (sc->msix == 0) {
		error = ENXIO;
		goto err_res_buf;
	}
	vsi->id = sc->vsi_res->vsi_id;
	vsi->back = (void *)sc;
	sc->link_up = TRUE;
	if (ixlv_setup_queues(sc) != 0) {
		device_printf(dev, "%s: setup queues failed!\n",
		    __func__);
		error = EIO;
		goto out;
	}
	if (ixlv_setup_interface(dev, sc) != 0) {
		device_printf(dev, "%s: setup interface failed!\n",
		    __func__);
		error = EIO;
		goto out;
	}
	INIT_DBG_DEV(dev, "Queue memory and interface setup");
	if (ixlv_assign_msix(sc) != 0) {
		device_printf(dev, "%s: allocating queue interrupts failed!\n",
		    __func__);
		error = ENXIO;
		goto out;
	}
	ixlv_init_taskqueue(sc);
	bzero(&sc->vsi.eth_stats, sizeof(struct i40e_eth_stats));
	ixlv_add_sysctls(sc);
	vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
	    ixlv_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
	vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
	    ixlv_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
	ixlv_enable_adminq_irq(hw);
	sc->init_state = IXLV_INIT_READY;
	ixl_vc_init_mgr(sc, &sc->vc_mgr);
	INIT_DBG_DEV(dev, "end");
	return (error);
out:
	ixlv_free_queues(vsi);
err_res_buf:
	free(sc->vf_res, M_DEVBUF);
err_aq:
	i40e_shutdown_adminq(hw);
err_pci_res:
	ixlv_free_pci_resources(sc);
err_early:
	mtx_destroy(&sc->mtx);
	ixlv_free_filters(sc);
	INIT_DBG_DEV(dev, "end: error %d", error);
	return (error);
}
static int ixlv_attach ( device_t dev ) { struct ixlv_sc * sc ; struct i40e_hw * hw ; struct ixl_vsi * vsi ; int error = 0 ; INIT_DBG_DEV ( dev , " " ) ; sc = device_get_softc ( dev ) ; sc -> dev = sc -> osdep . dev = dev ; hw = & sc -> hw ; vsi = & sc -> vsi ; vsi -> dev = dev ; ixlv_init_hw ( sc ) ; ixlv_init_filters ( sc ) ; mtx_init ( & sc -> mtx , device_get_nameunit ( dev ) , " " , MTX_DEF ) ; callout_init_mtx ( & sc -> timer , & sc -> mtx , 0 ) ; if ( ixlv_allocate_pci_resources ( sc ) ) { device_printf ( dev , " \n " , __func__ ) ; error = ENXIO ; goto err_early ; } INIT_DBG_DEV ( dev , " " ) ; error = i40e_set_mac_type ( hw ) ; if ( error ) { device_printf ( dev , " \n " , __func__ , error ) ; goto err_pci_res ; } error = ixlv_reset_complete ( hw ) ; if ( error ) { device_printf ( dev , " \n " , __func__ ) ; goto err_pci_res ; } INIT_DBG_DEV ( dev , " " ) ; error = ixlv_setup_vc ( sc ) ; if ( error ) { device_printf ( dev , " \n " , __func__ , error ) ; goto err_pci_res ; } INIT_DBG_DEV ( dev , " " ) ; error = ixlv_reset ( sc ) ; if ( error ) { device_printf ( dev , " \n " ) ; goto err_aq ; } INIT_DBG_DEV ( dev , " " ) ; error = ixlv_vf_config ( sc ) ; if ( error ) { device_printf ( dev , " \n " , error ) ; goto err_aq ; } device_printf ( dev , " \n " , sc -> vf_res -> num_vsis , sc -> vf_res -> num_queue_pairs , sc -> vf_res -> max_vectors , sc -> vf_res -> rss_key_size , sc -> vf_res -> rss_lut_size ) ; #ifdef IXL_DEBUG device_printf ( dev , " \n " , sc -> vf_res -> vf_offload_flags , IXLV_PRINTF_VF_OFFLOAD_FLAGS ) ; #endif for ( int i = 0 ; i < sc -> vf_res -> num_vsis ; i ++ ) { if ( sc -> vf_res -> vsi_res [ i ] . vsi_type == I40E_VSI_SRIOV ) sc -> vsi_res = & sc -> vf_res -> vsi_res [ i ] ; } if ( ! sc -> vsi_res ) { device_printf ( dev , " \n " , __func__ ) ; error = EIO ; goto err_res_buf ; } INIT_DBG_DEV ( dev , " " ) ; if ( ! ixlv_check_ether_addr ( hw -> mac . addr ) ) { u8 addr [ ETHER_ADDR_LEN ] ; arc4rand ( & addr , sizeof ( addr ) , 0 ) ; addr [ 0 ] &= 0xFE ; addr [ 0 ] |= 0x02 ; bcopy ( addr , hw -> mac . addr , sizeof ( addr ) ) ; } sc -> msix = ixlv_init_msix ( sc ) ; if ( sc -> msix == 0 ) { error = ENXIO ; goto err_res_buf ; } vsi -> id = sc -> vsi_res -> vsi_id ; vsi -> back = ( void * ) sc ; sc -> link_up = TRUE ; if ( ixlv_setup_queues ( sc ) != 0 ) { device_printf ( dev , " \n " , __func__ ) ; error = EIO ; goto out ; } if ( ixlv_setup_interface ( dev , sc ) != 0 ) { device_printf ( dev , " \n " , __func__ ) ; error = EIO ; goto out ; } INIT_DBG_DEV ( dev , " " ) ; if ( ixlv_assign_msix ( sc ) != 0 ) { device_printf ( dev , " \n " , __func__ ) ; error = ENXIO ; goto out ; } ixlv_init_taskqueue ( sc ) ; bzero ( & sc -> vsi . eth_stats , sizeof ( struct i40e_eth_stats ) ) ; ixlv_add_sysctls ( sc ) ; vsi -> vlan_attach = EVENTHANDLER_REGISTER ( vlan_config , ixlv_register_vlan , vsi , EVENTHANDLER_PRI_FIRST ) ; vsi -> vlan_detach = EVENTHANDLER_REGISTER ( vlan_unconfig , ixlv_unregister_vlan , vsi , EVENTHANDLER_PRI_FIRST ) ; ixlv_enable_adminq_irq ( hw ) ; sc -> init_state = IXLV_INIT_READY ; ixl_vc_init_mgr ( sc , & sc -> vc_mgr ) ; INIT_DBG_DEV ( dev , " " ) ; return ( error ) ; out : ixlv_free_queues ( vsi ) ; err_res_buf : free ( sc -> vf_res , M_DEVBUF ) ; err_aq : i40e_shutdown_adminq ( hw ) ; err_pci_res : ixlv_free_pci_resources ( sc ) ; err_early : mtx_destroy ( & sc -> mtx ) ; ixlv_free_filters ( sc ) ; INIT_DBG_DEV ( dev , " " , error ) ; return ( error ) ; }
Device initialization routine
  The attach entry point is called when the driver is being loaded.
Device initialization routine The attach entry point is called when the driver is being loaded .
/* Allocate, clear, and link in our primary soft structure */ /* Initialize hw struct */ /* Allocate filter lists */ /* Core Lock Init */ /* Set up the timer callout */ /* Do PCI setup - map BAR0, etc */ /* Need API version before sending reset message */ /* Ask for VF config from PF */ /* got VF config message back from PF, now we can parse it */ /* If no mac address was assigned just make a random one */ /* Now that the number of queues for this VF is known, set up interrupts */ /* We fail without MSIX support */ /* This allocates the memory and early settings */ /* Setup the stack interface */ /* Do queue interrupt setup */ /* Start AdminQ taskqueue */ /* Initialize stats */ /* Register for VLAN events */ /* We want AQ enabled early */ /* Set things up to run init */