xref: /freebsd/sys/dev/enic/if_enic.c (revision f830db48c131064bfb534efff92e37653d6f05c4)
19c067b84SDoug Ambrisko /* SPDX-License-Identifier: BSD-3-Clause
29c067b84SDoug Ambrisko  * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
39c067b84SDoug Ambrisko  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
49c067b84SDoug Ambrisko  */
59c067b84SDoug Ambrisko 
69c067b84SDoug Ambrisko #include "opt_rss.h"
79c067b84SDoug Ambrisko 
89c067b84SDoug Ambrisko #include <sys/param.h>
99c067b84SDoug Ambrisko #include <sys/systm.h>
109c067b84SDoug Ambrisko #include <sys/kernel.h>
119c067b84SDoug Ambrisko #include <sys/endian.h>
129c067b84SDoug Ambrisko #include <sys/sockio.h>
139c067b84SDoug Ambrisko #include <sys/mbuf.h>
149c067b84SDoug Ambrisko #include <sys/malloc.h>
159c067b84SDoug Ambrisko #include <sys/module.h>
169c067b84SDoug Ambrisko #include <sys/socket.h>
179c067b84SDoug Ambrisko #include <sys/sysctl.h>
189c067b84SDoug Ambrisko #include <sys/smp.h>
199c067b84SDoug Ambrisko #include <vm/vm.h>
209c067b84SDoug Ambrisko #include <vm/pmap.h>
219c067b84SDoug Ambrisko 
229c067b84SDoug Ambrisko #include <net/ethernet.h>
239c067b84SDoug Ambrisko #include <net/if.h>
249c067b84SDoug Ambrisko #include <net/if_var.h>
259c067b84SDoug Ambrisko #include <net/if_arp.h>
269c067b84SDoug Ambrisko #include <net/if_dl.h>
279c067b84SDoug Ambrisko #include <net/if_types.h>
289c067b84SDoug Ambrisko #include <net/if_media.h>
299c067b84SDoug Ambrisko #include <net/if_vlan_var.h>
309c067b84SDoug Ambrisko #include <net/iflib.h>
319c067b84SDoug Ambrisko #ifdef RSS
329c067b84SDoug Ambrisko #include <net/rss_config.h>
339c067b84SDoug Ambrisko #endif
349c067b84SDoug Ambrisko 
359c067b84SDoug Ambrisko #include <netinet/in_systm.h>
369c067b84SDoug Ambrisko #include <netinet/in.h>
379c067b84SDoug Ambrisko #include <netinet/ip.h>
389c067b84SDoug Ambrisko #include <netinet/ip6.h>
399c067b84SDoug Ambrisko #include <netinet6/ip6_var.h>
409c067b84SDoug Ambrisko #include <netinet/udp.h>
419c067b84SDoug Ambrisko #include <netinet/tcp.h>
429c067b84SDoug Ambrisko 
439c067b84SDoug Ambrisko #include <machine/bus.h>
449c067b84SDoug Ambrisko #include <machine/resource.h>
459c067b84SDoug Ambrisko #include <sys/bus.h>
469c067b84SDoug Ambrisko #include <sys/rman.h>
479c067b84SDoug Ambrisko 
489c067b84SDoug Ambrisko #include <dev/pci/pcireg.h>
499c067b84SDoug Ambrisko #include <dev/pci/pcivar.h>
509c067b84SDoug Ambrisko 
519c067b84SDoug Ambrisko #include "ifdi_if.h"
529c067b84SDoug Ambrisko #include "enic.h"
539c067b84SDoug Ambrisko 
549c067b84SDoug Ambrisko #include "opt_inet.h"
559c067b84SDoug Ambrisko #include "opt_inet6.h"
569c067b84SDoug Ambrisko 
579c067b84SDoug Ambrisko static SYSCTL_NODE(_hw, OID_AUTO, enic, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
589c067b84SDoug Ambrisko     "ENIC");
599c067b84SDoug Ambrisko 
6051e23514SMarius Strobl static const pci_vendor_info_t enic_vendor_info_array[] =
619c067b84SDoug Ambrisko {
629c067b84SDoug Ambrisko 	PVID(CISCO_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET,
639c067b84SDoug Ambrisko 	     DRV_DESCRIPTION),
649c067b84SDoug Ambrisko 		PVID(CISCO_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF,
659c067b84SDoug Ambrisko 		     DRV_DESCRIPTION " VF"),
669c067b84SDoug Ambrisko 	/* required last entry */
679c067b84SDoug Ambrisko 
689c067b84SDoug Ambrisko 		PVID_END
699c067b84SDoug Ambrisko };
709c067b84SDoug Ambrisko 
719c067b84SDoug Ambrisko static void *enic_register(device_t);
729c067b84SDoug Ambrisko static int enic_attach_pre(if_ctx_t);
739c067b84SDoug Ambrisko static int enic_msix_intr_assign(if_ctx_t, int);
749c067b84SDoug Ambrisko 
759c067b84SDoug Ambrisko static int enic_attach_post(if_ctx_t);
769c067b84SDoug Ambrisko static int enic_detach(if_ctx_t);
779c067b84SDoug Ambrisko 
789c067b84SDoug Ambrisko static int enic_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int);
799c067b84SDoug Ambrisko static int enic_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int);
809c067b84SDoug Ambrisko static void enic_queues_free(if_ctx_t);
819c067b84SDoug Ambrisko static int enic_rxq_intr(void *);
829c067b84SDoug Ambrisko static int enic_event_intr(void *);
839c067b84SDoug Ambrisko static int enic_err_intr(void *);
849c067b84SDoug Ambrisko static void enic_stop(if_ctx_t);
859c067b84SDoug Ambrisko static void enic_init(if_ctx_t);
869c067b84SDoug Ambrisko static void enic_multi_set(if_ctx_t);
879c067b84SDoug Ambrisko static int enic_mtu_set(if_ctx_t, uint32_t);
889c067b84SDoug Ambrisko static void enic_media_status(if_ctx_t, struct ifmediareq *);
899c067b84SDoug Ambrisko static int enic_media_change(if_ctx_t);
909c067b84SDoug Ambrisko static int enic_promisc_set(if_ctx_t, int);
919c067b84SDoug Ambrisko static uint64_t enic_get_counter(if_ctx_t, ift_counter);
929c067b84SDoug Ambrisko static void enic_update_admin_status(if_ctx_t);
939c067b84SDoug Ambrisko static void enic_txq_timer(if_ctx_t, uint16_t);
949c067b84SDoug Ambrisko static int enic_link_is_up(struct enic_softc *);
959c067b84SDoug Ambrisko static void enic_link_status(struct enic_softc *);
969c067b84SDoug Ambrisko static void enic_set_lladdr(struct enic_softc *);
979c067b84SDoug Ambrisko static void enic_setup_txq_sysctl(struct vnic_wq *, int, struct sysctl_ctx_list *,
989c067b84SDoug Ambrisko     struct sysctl_oid_list *);
999c067b84SDoug Ambrisko static void enic_setup_rxq_sysctl(struct vnic_rq *, int,  struct sysctl_ctx_list *,
1009c067b84SDoug Ambrisko     struct sysctl_oid_list *);
1019c067b84SDoug Ambrisko static void enic_setup_sysctl(struct enic_softc *);
1029c067b84SDoug Ambrisko static int enic_tx_queue_intr_enable(if_ctx_t, uint16_t);
1039c067b84SDoug Ambrisko static int enic_rx_queue_intr_enable(if_ctx_t, uint16_t);
1049c067b84SDoug Ambrisko static void enic_enable_intr(struct enic_softc *, int);
1059c067b84SDoug Ambrisko static void enic_disable_intr(struct enic_softc *, int);
1069c067b84SDoug Ambrisko static void enic_intr_enable_all(if_ctx_t);
1079c067b84SDoug Ambrisko static void enic_intr_disable_all(if_ctx_t);
1089c067b84SDoug Ambrisko static int enic_dev_open(struct enic *);
1099c067b84SDoug Ambrisko static int enic_dev_init(struct enic *);
1109c067b84SDoug Ambrisko static void *enic_alloc_consistent(void *, size_t, bus_addr_t *,
1119c067b84SDoug Ambrisko     struct iflib_dma_info *, u8 *);
1129c067b84SDoug Ambrisko static void enic_free_consistent(void *, size_t, void *, bus_addr_t,
1139c067b84SDoug Ambrisko     struct iflib_dma_info *);
1149c067b84SDoug Ambrisko static int enic_pci_mapping(struct enic_softc *);
1159c067b84SDoug Ambrisko static void enic_pci_mapping_free(struct enic_softc *);
1169c067b84SDoug Ambrisko static int enic_dev_wait(struct vnic_dev *, int (*) (struct vnic_dev *, int),
1179c067b84SDoug Ambrisko     int (*) (struct vnic_dev *, int *), int arg);
1189c067b84SDoug Ambrisko static int enic_map_bar(struct enic_softc *, struct enic_bar_info *, int, bool);
1199c067b84SDoug Ambrisko static void enic_update_packet_filter(struct enic *enic);
120fe6c4e21SKevin Bowling static bool enic_if_needs_restart(if_ctx_t, enum iflib_restart_event);
1219c067b84SDoug Ambrisko 
1229c067b84SDoug Ambrisko typedef enum {
1239c067b84SDoug Ambrisko 	ENIC_BARRIER_RD,
1249c067b84SDoug Ambrisko 	ENIC_BARRIER_WR,
1259c067b84SDoug Ambrisko 	ENIC_BARRIER_RDWR,
1269c067b84SDoug Ambrisko } enic_barrier_t;
1279c067b84SDoug Ambrisko 
1289c067b84SDoug Ambrisko static device_method_t enic_methods[] = {
1299c067b84SDoug Ambrisko 	/* Device interface */
1309c067b84SDoug Ambrisko 	DEVMETHOD(device_register, enic_register),
1319c067b84SDoug Ambrisko 	DEVMETHOD(device_probe, iflib_device_probe),
1329c067b84SDoug Ambrisko 	DEVMETHOD(device_attach, iflib_device_attach),
1339c067b84SDoug Ambrisko 	DEVMETHOD(device_detach, iflib_device_detach),
1349c067b84SDoug Ambrisko 	DEVMETHOD(device_shutdown, iflib_device_shutdown),
1359c067b84SDoug Ambrisko 	DEVMETHOD(device_suspend, iflib_device_suspend),
1369c067b84SDoug Ambrisko 	DEVMETHOD(device_resume, iflib_device_resume),
1379c067b84SDoug Ambrisko 	DEVMETHOD_END
1389c067b84SDoug Ambrisko };
1399c067b84SDoug Ambrisko 
1409c067b84SDoug Ambrisko static driver_t enic_driver = {
1419c067b84SDoug Ambrisko 	"enic", enic_methods, sizeof(struct enic_softc)
1429c067b84SDoug Ambrisko };
1439c067b84SDoug Ambrisko 
1449c067b84SDoug Ambrisko DRIVER_MODULE(enic, pci, enic_driver, 0, 0);
1459c067b84SDoug Ambrisko IFLIB_PNP_INFO(pci, enic, enic_vendor_info_array);
1469c067b84SDoug Ambrisko MODULE_VERSION(enic, 2);
1479c067b84SDoug Ambrisko 
1489c067b84SDoug Ambrisko MODULE_DEPEND(enic, pci, 1, 1, 1);
1499c067b84SDoug Ambrisko MODULE_DEPEND(enic, ether, 1, 1, 1);
1509c067b84SDoug Ambrisko MODULE_DEPEND(enic, iflib, 1, 1, 1);
1519c067b84SDoug Ambrisko 
1529c067b84SDoug Ambrisko static device_method_t enic_iflib_methods[] = {
1539c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_tx_queues_alloc, enic_tx_queues_alloc),
1549c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_rx_queues_alloc, enic_rx_queues_alloc),
1559c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_queues_free, enic_queues_free),
1569c067b84SDoug Ambrisko 
1579c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_attach_pre, enic_attach_pre),
1589c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_attach_post, enic_attach_post),
1599c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_detach, enic_detach),
1609c067b84SDoug Ambrisko 
1619c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_init, enic_init),
1629c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_stop, enic_stop),
1639c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_multi_set, enic_multi_set),
1649c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_mtu_set, enic_mtu_set),
1659c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_media_status, enic_media_status),
1669c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_media_change, enic_media_change),
1679c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_promisc_set, enic_promisc_set),
1689c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_get_counter, enic_get_counter),
1699c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_update_admin_status, enic_update_admin_status),
1709c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_timer, enic_txq_timer),
1719c067b84SDoug Ambrisko 
1729c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_tx_queue_intr_enable, enic_tx_queue_intr_enable),
1739c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_rx_queue_intr_enable, enic_rx_queue_intr_enable),
1749c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_intr_enable, enic_intr_enable_all),
1759c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_intr_disable, enic_intr_disable_all),
1769c067b84SDoug Ambrisko 	DEVMETHOD(ifdi_msix_intr_assign, enic_msix_intr_assign),
1779c067b84SDoug Ambrisko 
178fe6c4e21SKevin Bowling 	DEVMETHOD(ifdi_needs_restart, enic_if_needs_restart),
179fe6c4e21SKevin Bowling 
1809c067b84SDoug Ambrisko 	DEVMETHOD_END
1819c067b84SDoug Ambrisko };
1829c067b84SDoug Ambrisko 
1839c067b84SDoug Ambrisko static driver_t enic_iflib_driver = {
1849c067b84SDoug Ambrisko 	"enic", enic_iflib_methods, sizeof(struct enic_softc)
1859c067b84SDoug Ambrisko };
1869c067b84SDoug Ambrisko 
1879c067b84SDoug Ambrisko extern struct if_txrx enic_txrx;
1889c067b84SDoug Ambrisko 
1899c067b84SDoug Ambrisko static struct if_shared_ctx enic_sctx_init = {
1909c067b84SDoug Ambrisko 	.isc_magic = IFLIB_MAGIC,
1919c067b84SDoug Ambrisko 	.isc_q_align = 512,
1929c067b84SDoug Ambrisko 
1939c067b84SDoug Ambrisko 	.isc_tx_maxsize = ENIC_TX_MAX_PKT_SIZE,
1949c067b84SDoug Ambrisko 	.isc_tx_maxsegsize = PAGE_SIZE,
1959c067b84SDoug Ambrisko 
1969c067b84SDoug Ambrisko 	/*
1979c067b84SDoug Ambrisko 	 * These values are used to configure the busdma tag used for receive
1989c067b84SDoug Ambrisko 	 * descriptors.  Each receive descriptor only points to one buffer.
1999c067b84SDoug Ambrisko 	 */
2009c067b84SDoug Ambrisko 	.isc_rx_maxsize = ENIC_DEFAULT_RX_MAX_PKT_SIZE,	/* One buf per
2019c067b84SDoug Ambrisko 							 * descriptor */
2029c067b84SDoug Ambrisko 	.isc_rx_nsegments = 1,	/* One mapping per descriptor */
2039c067b84SDoug Ambrisko 	.isc_rx_maxsegsize = ENIC_DEFAULT_RX_MAX_PKT_SIZE,
2049c067b84SDoug Ambrisko 	.isc_admin_intrcnt = 3,
2059c067b84SDoug Ambrisko 	.isc_vendor_info = enic_vendor_info_array,
2069c067b84SDoug Ambrisko 	.isc_driver_version = "1",
2079c067b84SDoug Ambrisko 	.isc_driver = &enic_iflib_driver,
2089c067b84SDoug Ambrisko 	.isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ,
2099c067b84SDoug Ambrisko 
2109c067b84SDoug Ambrisko 	/*
2119c067b84SDoug Ambrisko 	 * Number of receive queues per receive queue set, with associated
2129c067b84SDoug Ambrisko 	 * descriptor settings for each.
2139c067b84SDoug Ambrisko 	 */
2149c067b84SDoug Ambrisko 
2159c067b84SDoug Ambrisko 	.isc_nrxqs = 2,
2169c067b84SDoug Ambrisko 	.isc_nfl = 1,		/* one free list for each receive command
2179c067b84SDoug Ambrisko 				 * queue */
2189c067b84SDoug Ambrisko 	.isc_nrxd_min = {16, 16},
2199c067b84SDoug Ambrisko 	.isc_nrxd_max = {2048, 2048},
2209c067b84SDoug Ambrisko 	.isc_nrxd_default = {64, 64},
2219c067b84SDoug Ambrisko 
2229c067b84SDoug Ambrisko 	/*
2239c067b84SDoug Ambrisko 	 * Number of transmit queues per transmit queue set, with associated
2249c067b84SDoug Ambrisko 	 * descriptor settings for each.
2259c067b84SDoug Ambrisko 	 */
2269c067b84SDoug Ambrisko 	.isc_ntxqs = 2,
2279c067b84SDoug Ambrisko 	.isc_ntxd_min = {16, 16},
2289c067b84SDoug Ambrisko 	.isc_ntxd_max = {2048, 2048},
2299c067b84SDoug Ambrisko 	.isc_ntxd_default = {64, 64},
2309c067b84SDoug Ambrisko };
2319c067b84SDoug Ambrisko 
2329c067b84SDoug Ambrisko static void *
enic_register(device_t dev)2339c067b84SDoug Ambrisko enic_register(device_t dev)
2349c067b84SDoug Ambrisko {
2359c067b84SDoug Ambrisko 	return (&enic_sctx_init);
2369c067b84SDoug Ambrisko }
2379c067b84SDoug Ambrisko 
2389c067b84SDoug Ambrisko static int
enic_attach_pre(if_ctx_t ctx)2399c067b84SDoug Ambrisko enic_attach_pre(if_ctx_t ctx)
2409c067b84SDoug Ambrisko {
2419c067b84SDoug Ambrisko 	if_softc_ctx_t	scctx;
2429c067b84SDoug Ambrisko 	struct enic_softc *softc;
2439c067b84SDoug Ambrisko 	struct vnic_dev *vdev;
2449c067b84SDoug Ambrisko 	struct enic *enic;
2459c067b84SDoug Ambrisko 	device_t dev;
2469c067b84SDoug Ambrisko 
2479c067b84SDoug Ambrisko 	int err = -1;
2489c067b84SDoug Ambrisko 	int rc = 0;
2499c067b84SDoug Ambrisko 	int i;
2509c067b84SDoug Ambrisko 	u64 a0 = 0, a1 = 0;
2519c067b84SDoug Ambrisko 	int wait = 1000;
2529c067b84SDoug Ambrisko 	struct vnic_stats *stats;
2539c067b84SDoug Ambrisko 	int ret;
2549c067b84SDoug Ambrisko 
2559c067b84SDoug Ambrisko 	dev = iflib_get_dev(ctx);
2569c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
2579c067b84SDoug Ambrisko 	softc->dev = dev;
2589c067b84SDoug Ambrisko 	softc->ctx = ctx;
2599c067b84SDoug Ambrisko 	softc->sctx = iflib_get_sctx(ctx);
2609c067b84SDoug Ambrisko 	softc->scctx = iflib_get_softc_ctx(ctx);
2619c067b84SDoug Ambrisko 	softc->ifp = iflib_get_ifp(ctx);
2629c067b84SDoug Ambrisko 	softc->media = iflib_get_media(ctx);
2639c067b84SDoug Ambrisko 	softc->mta = malloc(sizeof(u8) * ETHER_ADDR_LEN *
2649c067b84SDoug Ambrisko 		ENIC_MAX_MULTICAST_ADDRESSES, M_DEVBUF,
2659c067b84SDoug Ambrisko 		     M_NOWAIT | M_ZERO);
2669c067b84SDoug Ambrisko 	if (softc->mta == NULL)
2679c067b84SDoug Ambrisko 		return (ENOMEM);
2689c067b84SDoug Ambrisko 	scctx = softc->scctx;
2699c067b84SDoug Ambrisko 
2709c067b84SDoug Ambrisko 	mtx_init(&softc->enic_lock, "ENIC Lock", NULL, MTX_DEF);
2719c067b84SDoug Ambrisko 
2729c067b84SDoug Ambrisko 	pci_enable_busmaster(softc->dev);
2739c067b84SDoug Ambrisko 	if (enic_pci_mapping(softc))
2749c067b84SDoug Ambrisko 		return (ENXIO);
2759c067b84SDoug Ambrisko 
2769c067b84SDoug Ambrisko 	enic = &softc->enic;
2779c067b84SDoug Ambrisko 	enic->softc = softc;
2789c067b84SDoug Ambrisko 	vdev = &softc->vdev;
2799c067b84SDoug Ambrisko 	vdev->softc = softc;
2809c067b84SDoug Ambrisko 	enic->vdev = vdev;
2819c067b84SDoug Ambrisko 	vdev->priv = enic;
2829c067b84SDoug Ambrisko 
2839c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
2849c067b84SDoug Ambrisko 	vnic_dev_register(vdev, &softc->mem, 1);
2859c067b84SDoug Ambrisko 	enic->vdev = vdev;
2869c067b84SDoug Ambrisko 	vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
2879c067b84SDoug Ambrisko 
2889c067b84SDoug Ambrisko 	vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
2899c067b84SDoug Ambrisko 	vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
2909c067b84SDoug Ambrisko 
2919c067b84SDoug Ambrisko 	bcopy((u_int8_t *) & a0, softc->mac_addr, ETHER_ADDR_LEN);
2929c067b84SDoug Ambrisko 	iflib_set_mac(ctx, softc->mac_addr);
2939c067b84SDoug Ambrisko 
2949c067b84SDoug Ambrisko 	vnic_register_cbacks(enic->vdev, enic_alloc_consistent,
2959c067b84SDoug Ambrisko 	    enic_free_consistent);
2969c067b84SDoug Ambrisko 
2979c067b84SDoug Ambrisko 	/*
2989c067b84SDoug Ambrisko 	 * Allocate the consistent memory for stats and counters upfront so
2999c067b84SDoug Ambrisko 	 * both primary and secondary processes can access them.
3009c067b84SDoug Ambrisko 	 */
3019c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
3029c067b84SDoug Ambrisko 	err = vnic_dev_alloc_stats_mem(enic->vdev);
3039c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
3049c067b84SDoug Ambrisko 	if (err) {
3059c067b84SDoug Ambrisko 		dev_err(enic, "Failed to allocate cmd memory, aborting\n");
3069c067b84SDoug Ambrisko 		goto err_out_unregister;
3079c067b84SDoug Ambrisko 	}
3089c067b84SDoug Ambrisko 	vnic_dev_stats_clear(enic->vdev);
3099c067b84SDoug Ambrisko 	ret = vnic_dev_stats_dump(enic->vdev, &stats);
3109c067b84SDoug Ambrisko 	if (ret) {
3119c067b84SDoug Ambrisko 		dev_err(enic, "Error in getting stats\n");
3129c067b84SDoug Ambrisko 		goto err_out_unregister;
3139c067b84SDoug Ambrisko 	}
3149c067b84SDoug Ambrisko 	err = vnic_dev_alloc_counter_mem(enic->vdev);
3159c067b84SDoug Ambrisko 	if (err) {
3169c067b84SDoug Ambrisko 		dev_err(enic, "Failed to allocate counter memory, aborting\n");
3179c067b84SDoug Ambrisko 		goto err_out_unregister;
3189c067b84SDoug Ambrisko 	}
3199c067b84SDoug Ambrisko 
3209c067b84SDoug Ambrisko 	/* Issue device open to get device in known state */
3219c067b84SDoug Ambrisko 	err = enic_dev_open(enic);
3229c067b84SDoug Ambrisko 	if (err) {
3239c067b84SDoug Ambrisko 		dev_err(enic, "vNIC dev open failed, aborting\n");
3249c067b84SDoug Ambrisko 		goto err_out_unregister;
3259c067b84SDoug Ambrisko 	}
3269c067b84SDoug Ambrisko 
3279c067b84SDoug Ambrisko 	/* Set ingress vlan rewrite mode before vnic initialization */
3289c067b84SDoug Ambrisko 	enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN;
3299c067b84SDoug Ambrisko 	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
3309c067b84SDoug Ambrisko 						enic->ig_vlan_rewrite_mode);
3319c067b84SDoug Ambrisko 	if (err) {
3329c067b84SDoug Ambrisko 		dev_err(enic,
3339c067b84SDoug Ambrisko 		    "Failed to set ingress vlan rewrite mode, aborting.\n");
3349c067b84SDoug Ambrisko 		goto err_out_dev_close;
3359c067b84SDoug Ambrisko 	}
3369c067b84SDoug Ambrisko 
3379c067b84SDoug Ambrisko 	/*
3389c067b84SDoug Ambrisko 	 * Issue device init to initialize the vnic-to-switch link. We'll
3399c067b84SDoug Ambrisko 	 * start with carrier off and wait for link UP notification later to
3409c067b84SDoug Ambrisko 	 * turn on carrier.  We don't need to wait here for the
3419c067b84SDoug Ambrisko 	 * vnic-to-switch link initialization to complete; link UP
3429c067b84SDoug Ambrisko 	 * notification is the indication that the process is complete.
3439c067b84SDoug Ambrisko 	 */
3449c067b84SDoug Ambrisko 
3459c067b84SDoug Ambrisko 	err = vnic_dev_init(enic->vdev, 0);
3469c067b84SDoug Ambrisko 	if (err) {
3479c067b84SDoug Ambrisko 		dev_err(enic, "vNIC dev init failed, aborting\n");
3489c067b84SDoug Ambrisko 		goto err_out_dev_close;
3499c067b84SDoug Ambrisko 	}
3509c067b84SDoug Ambrisko 
3519c067b84SDoug Ambrisko 	err = enic_dev_init(enic);
3529c067b84SDoug Ambrisko 	if (err) {
3539c067b84SDoug Ambrisko 		dev_err(enic, "Device initialization failed, aborting\n");
3549c067b84SDoug Ambrisko 		goto err_out_dev_close;
3559c067b84SDoug Ambrisko 	}
3569c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
3579c067b84SDoug Ambrisko 
3589c067b84SDoug Ambrisko 	enic->port_mtu = vnic_dev_mtu(enic->vdev);
3599c067b84SDoug Ambrisko 
3609c067b84SDoug Ambrisko 	softc->scctx = iflib_get_softc_ctx(ctx);
3619c067b84SDoug Ambrisko 	scctx = softc->scctx;
3629c067b84SDoug Ambrisko 	scctx->isc_txrx = &enic_txrx;
3639c067b84SDoug Ambrisko 	scctx->isc_capabilities = scctx->isc_capenable = 0;
3649c067b84SDoug Ambrisko 	scctx->isc_tx_csum_flags = 0;
3659c067b84SDoug Ambrisko 	scctx->isc_max_frame_size = enic->config.mtu + ETHER_HDR_LEN + \
3669c067b84SDoug Ambrisko 		ETHER_CRC_LEN;
3679c067b84SDoug Ambrisko 	scctx->isc_nrxqsets_max = enic->conf_rq_count;
3689c067b84SDoug Ambrisko 	scctx->isc_ntxqsets_max = enic->conf_wq_count;
3699c067b84SDoug Ambrisko 	scctx->isc_nrxqsets = enic->conf_rq_count;
3709c067b84SDoug Ambrisko 	scctx->isc_ntxqsets = enic->conf_wq_count;
3719c067b84SDoug Ambrisko 	for (i = 0; i < enic->conf_wq_count; i++) {
3729c067b84SDoug Ambrisko 		scctx->isc_ntxd[i] = enic->config.wq_desc_count;
3739c067b84SDoug Ambrisko 		scctx->isc_txqsizes[i] = sizeof(struct cq_enet_wq_desc)
3749c067b84SDoug Ambrisko 			* scctx->isc_ntxd[i];
3759c067b84SDoug Ambrisko 		scctx->isc_ntxd[i + enic->conf_wq_count] =
3769c067b84SDoug Ambrisko 		    enic->config.wq_desc_count;
3779c067b84SDoug Ambrisko 		scctx->isc_txqsizes[i + enic->conf_wq_count] =
3789c067b84SDoug Ambrisko 		    sizeof(struct cq_desc) * scctx->isc_ntxd[i +
3799c067b84SDoug Ambrisko 		    enic->conf_wq_count];
3809c067b84SDoug Ambrisko 	}
3819c067b84SDoug Ambrisko 	for (i = 0; i < enic->conf_rq_count; i++) {
3829c067b84SDoug Ambrisko 		scctx->isc_nrxd[i] = enic->config.rq_desc_count;
3839c067b84SDoug Ambrisko 		scctx->isc_rxqsizes[i] = sizeof(struct cq_enet_rq_desc) *
3849c067b84SDoug Ambrisko 		    scctx->isc_nrxd[i];
3859c067b84SDoug Ambrisko 		scctx->isc_nrxd[i + enic->conf_rq_count] =
3869c067b84SDoug Ambrisko 		    enic->config.rq_desc_count;
3879c067b84SDoug Ambrisko 		scctx->isc_rxqsizes[i + enic->conf_rq_count] = sizeof(struct
3889c067b84SDoug Ambrisko 		    cq_desc) * scctx->isc_nrxd[i + enic->conf_rq_count];
3899c067b84SDoug Ambrisko 	}
3909c067b84SDoug Ambrisko 	scctx->isc_tx_nsegments = 31;
3919c067b84SDoug Ambrisko 
3929c067b84SDoug Ambrisko 	scctx->isc_vectors = enic->conf_cq_count;
3939c067b84SDoug Ambrisko 	scctx->isc_msix_bar = -1;
3949c067b84SDoug Ambrisko 
3959c067b84SDoug Ambrisko 	ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
3969c067b84SDoug Ambrisko 	ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
3979c067b84SDoug Ambrisko 	ifmedia_add(softc->media, IFM_ETHER | IFM_10_FL, 0, NULL);
3989c067b84SDoug Ambrisko 
3999c067b84SDoug Ambrisko 	/*
4009c067b84SDoug Ambrisko 	 * Allocate the CQ here since TX is called first before RX for now
4019c067b84SDoug Ambrisko 	 * assume RX and TX are the same
4029c067b84SDoug Ambrisko 	 */
4039c067b84SDoug Ambrisko 	if (softc->enic.cq == NULL)
4049c067b84SDoug Ambrisko 		softc->enic.cq = malloc(sizeof(struct vnic_cq) *
4059c067b84SDoug Ambrisko 		     softc->enic.wq_count + softc->enic.rq_count, M_DEVBUF,
4069c067b84SDoug Ambrisko 		     M_NOWAIT | M_ZERO);
4079c067b84SDoug Ambrisko 	if (softc->enic.cq == NULL)
4089c067b84SDoug Ambrisko 		return (ENOMEM);
4099c067b84SDoug Ambrisko 
4109c067b84SDoug Ambrisko 	softc->enic.cq->ntxqsets = softc->enic.wq_count + softc->enic.rq_count;
4119c067b84SDoug Ambrisko 
4129c067b84SDoug Ambrisko 	/*
4139c067b84SDoug Ambrisko 	 * Allocate the consistent memory for stats and counters upfront so
4149c067b84SDoug Ambrisko 	 * both primary and secondary processes can access them.
4159c067b84SDoug Ambrisko 	 */
4169c067b84SDoug Ambrisko 	err = vnic_dev_alloc_stats_mem(enic->vdev);
4179c067b84SDoug Ambrisko 	if (err) {
4189c067b84SDoug Ambrisko 		dev_err(enic, "Failed to allocate cmd memory, aborting\n");
4199c067b84SDoug Ambrisko 	}
4209c067b84SDoug Ambrisko 
4219c067b84SDoug Ambrisko 	return (rc);
4229c067b84SDoug Ambrisko 
4239c067b84SDoug Ambrisko err_out_dev_close:
4249c067b84SDoug Ambrisko 	vnic_dev_close(enic->vdev);
4259c067b84SDoug Ambrisko err_out_unregister:
4269c067b84SDoug Ambrisko 	free(softc->vdev.devcmd, M_DEVBUF);
4279c067b84SDoug Ambrisko 	free(softc->enic.intr_queues, M_DEVBUF);
4289c067b84SDoug Ambrisko 	free(softc->enic.cq, M_DEVBUF);
4299c067b84SDoug Ambrisko 	free(softc->mta, M_DEVBUF);
4309c067b84SDoug Ambrisko 	rc = -1;
4319c067b84SDoug Ambrisko 	pci_disable_busmaster(softc->dev);
4329c067b84SDoug Ambrisko 	enic_pci_mapping_free(softc);
4339c067b84SDoug Ambrisko 	mtx_destroy(&softc->enic_lock);
4349c067b84SDoug Ambrisko 	return (rc);
4359c067b84SDoug Ambrisko }
4369c067b84SDoug Ambrisko 
4379c067b84SDoug Ambrisko static int
enic_msix_intr_assign(if_ctx_t ctx,int msix)4389c067b84SDoug Ambrisko enic_msix_intr_assign(if_ctx_t ctx, int msix)
4399c067b84SDoug Ambrisko {
4409c067b84SDoug Ambrisko 	struct enic_softc *softc;
4419c067b84SDoug Ambrisko 	struct enic *enic;
4429c067b84SDoug Ambrisko 	if_softc_ctx_t scctx;
4439c067b84SDoug Ambrisko 
4449c067b84SDoug Ambrisko 	int error;
4459c067b84SDoug Ambrisko 	int i;
4469c067b84SDoug Ambrisko 	char irq_name[16];
4479c067b84SDoug Ambrisko 
4489c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
4499c067b84SDoug Ambrisko 	enic = &softc->enic;
4509c067b84SDoug Ambrisko 	scctx = softc->scctx;
4519c067b84SDoug Ambrisko 
4529c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
4539c067b84SDoug Ambrisko 	vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX);
4549c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
4559c067b84SDoug Ambrisko 
4569c067b84SDoug Ambrisko 	enic->intr_queues = malloc(sizeof(*enic->intr_queues) *
4579c067b84SDoug Ambrisko 	    enic->conf_intr_count, M_DEVBUF, M_NOWAIT | M_ZERO);
4589c067b84SDoug Ambrisko 	enic->intr = malloc(sizeof(*enic->intr) * msix, M_DEVBUF, M_NOWAIT
4599c067b84SDoug Ambrisko 	    | M_ZERO);
4609c067b84SDoug Ambrisko 	for (i = 0; i < scctx->isc_nrxqsets; i++) {
4619c067b84SDoug Ambrisko 		snprintf(irq_name, sizeof(irq_name), "erxq%d:%d", i,
4629c067b84SDoug Ambrisko 		    device_get_unit(softc->dev));
4639c067b84SDoug Ambrisko 
4649c067b84SDoug Ambrisko 		error = iflib_irq_alloc_generic(ctx,
4659c067b84SDoug Ambrisko 		    &enic->intr_queues[i].intr_irq, i + 1, IFLIB_INTR_RX,
4669c067b84SDoug Ambrisko 		    enic_rxq_intr, &enic->rq[i], i, irq_name);
4679c067b84SDoug Ambrisko 		if (error) {
4689c067b84SDoug Ambrisko 			device_printf(iflib_get_dev(ctx),
4699c067b84SDoug Ambrisko 			    "Failed to register rxq %d interrupt handler\n", i);
4709c067b84SDoug Ambrisko 			return (error);
4719c067b84SDoug Ambrisko 		}
4729c067b84SDoug Ambrisko 		enic->intr[i].index = i;
4739c067b84SDoug Ambrisko 		enic->intr[i].vdev = enic->vdev;
4749c067b84SDoug Ambrisko 		ENIC_LOCK(softc);
4759c067b84SDoug Ambrisko 		enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev,
4769c067b84SDoug Ambrisko 		    RES_TYPE_INTR_CTRL, i);
4779c067b84SDoug Ambrisko 		vnic_intr_mask(&enic->intr[i]);
4789c067b84SDoug Ambrisko 		ENIC_UNLOCK(softc);
4799c067b84SDoug Ambrisko 	}
4809c067b84SDoug Ambrisko 
4819c067b84SDoug Ambrisko 	for (i = scctx->isc_nrxqsets; i < scctx->isc_nrxqsets + scctx->isc_ntxqsets; i++) {
4829c067b84SDoug Ambrisko 		snprintf(irq_name, sizeof(irq_name), "etxq%d:%d", i -
4839c067b84SDoug Ambrisko 		    scctx->isc_nrxqsets, device_get_unit(softc->dev));
4849c067b84SDoug Ambrisko 
4859c067b84SDoug Ambrisko 
4869c067b84SDoug Ambrisko 		iflib_softirq_alloc_generic(ctx, &enic->intr_queues[i].intr_irq, IFLIB_INTR_TX, &enic->wq[i - scctx->isc_nrxqsets], i - scctx->isc_nrxqsets, irq_name);
4879c067b84SDoug Ambrisko 
4889c067b84SDoug Ambrisko 
4899c067b84SDoug Ambrisko 		enic->intr[i].index = i;
4909c067b84SDoug Ambrisko 		enic->intr[i].vdev = enic->vdev;
4919c067b84SDoug Ambrisko 		ENIC_LOCK(softc);
4929c067b84SDoug Ambrisko 		enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev,
4939c067b84SDoug Ambrisko 		    RES_TYPE_INTR_CTRL, i);
4949c067b84SDoug Ambrisko 		vnic_intr_mask(&enic->intr[i]);
4959c067b84SDoug Ambrisko 		ENIC_UNLOCK(softc);
4969c067b84SDoug Ambrisko 	}
4979c067b84SDoug Ambrisko 
4989c067b84SDoug Ambrisko 	i = scctx->isc_nrxqsets + scctx->isc_ntxqsets;
4999c067b84SDoug Ambrisko 	error = iflib_irq_alloc_generic(ctx, &softc->enic_event_intr_irq,
5009c067b84SDoug Ambrisko 		 i + 1, IFLIB_INTR_ADMIN, enic_event_intr, softc, 0, "event");
5019c067b84SDoug Ambrisko 	if (error) {
5029c067b84SDoug Ambrisko 		device_printf(iflib_get_dev(ctx),
5039c067b84SDoug Ambrisko 		    "Failed to register event interrupt handler\n");
5049c067b84SDoug Ambrisko 		return (error);
5059c067b84SDoug Ambrisko 	}
5069c067b84SDoug Ambrisko 
5079c067b84SDoug Ambrisko 	enic->intr[i].index = i;
5089c067b84SDoug Ambrisko 	enic->intr[i].vdev = enic->vdev;
5099c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
5109c067b84SDoug Ambrisko 	enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev, RES_TYPE_INTR_CTRL,
5119c067b84SDoug Ambrisko 	    i);
5129c067b84SDoug Ambrisko 	vnic_intr_mask(&enic->intr[i]);
5139c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
5149c067b84SDoug Ambrisko 
5159c067b84SDoug Ambrisko 	i++;
5169c067b84SDoug Ambrisko 	error = iflib_irq_alloc_generic(ctx, &softc->enic_err_intr_irq,
5179c067b84SDoug Ambrisko 		   i + 1, IFLIB_INTR_ADMIN, enic_err_intr, softc, 0, "err");
5189c067b84SDoug Ambrisko 	if (error) {
5199c067b84SDoug Ambrisko 		device_printf(iflib_get_dev(ctx),
5209c067b84SDoug Ambrisko 		    "Failed to register event interrupt handler\n");
5219c067b84SDoug Ambrisko 		return (error);
5229c067b84SDoug Ambrisko 	}
5239c067b84SDoug Ambrisko 	enic->intr[i].index = i;
5249c067b84SDoug Ambrisko 	enic->intr[i].vdev = enic->vdev;
5259c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
5269c067b84SDoug Ambrisko 	enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev, RES_TYPE_INTR_CTRL,
5279c067b84SDoug Ambrisko 	    i);
5289c067b84SDoug Ambrisko 	vnic_intr_mask(&enic->intr[i]);
5299c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
5309c067b84SDoug Ambrisko 
5319c067b84SDoug Ambrisko 	enic->intr_count = msix;
5329c067b84SDoug Ambrisko 
5339c067b84SDoug Ambrisko 	return (0);
5349c067b84SDoug Ambrisko }
5359c067b84SDoug Ambrisko 
5369c067b84SDoug Ambrisko static void
enic_free_irqs(struct enic_softc * softc)5379c067b84SDoug Ambrisko enic_free_irqs(struct enic_softc *softc)
5389c067b84SDoug Ambrisko {
5399c067b84SDoug Ambrisko 	if_softc_ctx_t	scctx;
5409c067b84SDoug Ambrisko 
5419c067b84SDoug Ambrisko 	struct enic    *enic;
5429c067b84SDoug Ambrisko 	int		i;
5439c067b84SDoug Ambrisko 
5449c067b84SDoug Ambrisko 	scctx = softc->scctx;
5459c067b84SDoug Ambrisko 	enic = &softc->enic;
5469c067b84SDoug Ambrisko 
5479c067b84SDoug Ambrisko 	for (i = 0; i < scctx->isc_nrxqsets + scctx->isc_ntxqsets; i++) {
5489c067b84SDoug Ambrisko 		iflib_irq_free(softc->ctx, &enic->intr_queues[i].intr_irq);
5499c067b84SDoug Ambrisko 	}
5509c067b84SDoug Ambrisko 
5519c067b84SDoug Ambrisko 	iflib_irq_free(softc->ctx, &softc->enic_event_intr_irq);
5529c067b84SDoug Ambrisko 	iflib_irq_free(softc->ctx, &softc->enic_err_intr_irq);
5539c067b84SDoug Ambrisko 	free(enic->intr_queues, M_DEVBUF);
5549c067b84SDoug Ambrisko 	free(enic->intr, M_DEVBUF);
5559c067b84SDoug Ambrisko }
5569c067b84SDoug Ambrisko 
5579c067b84SDoug Ambrisko static int
enic_attach_post(if_ctx_t ctx)5589c067b84SDoug Ambrisko enic_attach_post(if_ctx_t ctx)
5599c067b84SDoug Ambrisko {
5609c067b84SDoug Ambrisko 	struct enic *enic;
5619c067b84SDoug Ambrisko 	struct enic_softc *softc;
5629c067b84SDoug Ambrisko 	int error = 0;
5639c067b84SDoug Ambrisko 
5649c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
5659c067b84SDoug Ambrisko 	enic = &softc->enic;
5669c067b84SDoug Ambrisko 
5679c067b84SDoug Ambrisko 	enic_setup_sysctl(softc);
5689c067b84SDoug Ambrisko 
5699c067b84SDoug Ambrisko 	enic_init_vnic_resources(enic);
5709c067b84SDoug Ambrisko 	enic_setup_finish(enic);
5719c067b84SDoug Ambrisko 
5729c067b84SDoug Ambrisko 	ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
5739c067b84SDoug Ambrisko 	ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO);
5749c067b84SDoug Ambrisko 
5759c067b84SDoug Ambrisko 	return (error);
5769c067b84SDoug Ambrisko }
5779c067b84SDoug Ambrisko 
5789c067b84SDoug Ambrisko static int
enic_detach(if_ctx_t ctx)5799c067b84SDoug Ambrisko enic_detach(if_ctx_t ctx)
5809c067b84SDoug Ambrisko {
5819c067b84SDoug Ambrisko 	struct enic_softc *softc;
5829c067b84SDoug Ambrisko 	struct enic *enic;
5839c067b84SDoug Ambrisko 
5849c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
5859c067b84SDoug Ambrisko 	enic = &softc->enic;
5869c067b84SDoug Ambrisko 
5879c067b84SDoug Ambrisko 	vnic_dev_notify_unset(enic->vdev);
5889c067b84SDoug Ambrisko 
5899c067b84SDoug Ambrisko 	enic_free_irqs(softc);
5909c067b84SDoug Ambrisko 
5919c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
5929c067b84SDoug Ambrisko 	vnic_dev_close(enic->vdev);
5939c067b84SDoug Ambrisko 	free(softc->vdev.devcmd, M_DEVBUF);
5949c067b84SDoug Ambrisko 	pci_disable_busmaster(softc->dev);
5959c067b84SDoug Ambrisko 	enic_pci_mapping_free(softc);
5969c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
5979c067b84SDoug Ambrisko 
5989c067b84SDoug Ambrisko 	return 0;
5999c067b84SDoug Ambrisko }
6009c067b84SDoug Ambrisko 
6019c067b84SDoug Ambrisko static int
enic_tx_queues_alloc(if_ctx_t ctx,caddr_t * vaddrs,uint64_t * paddrs,int ntxqs,int ntxqsets)6029c067b84SDoug Ambrisko enic_tx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
6039c067b84SDoug Ambrisko 		     int ntxqs, int ntxqsets)
6049c067b84SDoug Ambrisko {
6059c067b84SDoug Ambrisko 	struct enic_softc *softc;
6069c067b84SDoug Ambrisko 	int q;
6079c067b84SDoug Ambrisko 
6089c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
6099c067b84SDoug Ambrisko 	/* Allocate the array of transmit queues */
6109c067b84SDoug Ambrisko 	softc->enic.wq = malloc(sizeof(struct vnic_wq) *
6119c067b84SDoug Ambrisko 				ntxqsets, M_DEVBUF, M_NOWAIT | M_ZERO);
6129c067b84SDoug Ambrisko 	if (softc->enic.wq == NULL)
6139c067b84SDoug Ambrisko 		return (ENOMEM);
6149c067b84SDoug Ambrisko 
6159c067b84SDoug Ambrisko 	/* Initialize driver state for each transmit queue */
6169c067b84SDoug Ambrisko 
6179c067b84SDoug Ambrisko 	/*
6189c067b84SDoug Ambrisko 	 * Allocate queue state that is shared with the device.  This check
6199c067b84SDoug Ambrisko 	 * and call is performed in both enic_tx_queues_alloc() and
6209c067b84SDoug Ambrisko 	 * enic_rx_queues_alloc() so that we don't have to care which order
6219c067b84SDoug Ambrisko 	 * iflib invokes those routines in.
6229c067b84SDoug Ambrisko 	 */
6239c067b84SDoug Ambrisko 
6249c067b84SDoug Ambrisko 	/* Record descriptor ring vaddrs and paddrs */
6259c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
6269c067b84SDoug Ambrisko 	for (q = 0; q < ntxqsets; q++) {
6279c067b84SDoug Ambrisko 		struct vnic_wq *wq;
6289c067b84SDoug Ambrisko 		struct vnic_cq *cq;
6299c067b84SDoug Ambrisko 		unsigned int	cq_wq;
6309c067b84SDoug Ambrisko 
6319c067b84SDoug Ambrisko 		wq = &softc->enic.wq[q];
6329c067b84SDoug Ambrisko 		cq_wq = enic_cq_wq(&softc->enic, q);
6339c067b84SDoug Ambrisko 		cq = &softc->enic.cq[cq_wq];
6349c067b84SDoug Ambrisko 
6359c067b84SDoug Ambrisko 		/* Completion ring */
6369c067b84SDoug Ambrisko 		wq->vdev = softc->enic.vdev;
6379c067b84SDoug Ambrisko 		wq->index = q;
6389c067b84SDoug Ambrisko 		wq->ctrl = vnic_dev_get_res(softc->enic.vdev, RES_TYPE_WQ,
6399c067b84SDoug Ambrisko 		    wq->index);
6409c067b84SDoug Ambrisko 		vnic_wq_disable(wq);
6419c067b84SDoug Ambrisko 
6429c067b84SDoug Ambrisko 		wq->ring.desc_size = sizeof(struct wq_enet_desc);
6439c067b84SDoug Ambrisko 		wq->ring.desc_count = softc->scctx->isc_ntxd[q];
6449c067b84SDoug Ambrisko 		wq->ring.desc_avail = wq->ring.desc_count - 1;
6459c067b84SDoug Ambrisko 		wq->ring.last_count = wq->ring.desc_count;
6469c067b84SDoug Ambrisko 		wq->head_idx = 0;
6479c067b84SDoug Ambrisko 		wq->tail_idx = 0;
6489c067b84SDoug Ambrisko 
6499c067b84SDoug Ambrisko 		wq->ring.size = wq->ring.desc_count * wq->ring.desc_size;
6509c067b84SDoug Ambrisko 		wq->ring.descs = vaddrs[q * ntxqs + 0];
6519c067b84SDoug Ambrisko 		wq->ring.base_addr = paddrs[q * ntxqs + 0];
6529c067b84SDoug Ambrisko 
6539c067b84SDoug Ambrisko 		/* Command ring */
6549c067b84SDoug Ambrisko 		cq->vdev = softc->enic.vdev;
6559c067b84SDoug Ambrisko 		cq->index = cq_wq;
6569c067b84SDoug Ambrisko 		cq->ctrl = vnic_dev_get_res(softc->enic.vdev,
6579c067b84SDoug Ambrisko 					    RES_TYPE_CQ, cq->index);
6589c067b84SDoug Ambrisko 		cq->ring.desc_size = sizeof(struct cq_enet_wq_desc);
6599c067b84SDoug Ambrisko 		cq->ring.desc_count = softc->scctx->isc_ntxd[q];
6609c067b84SDoug Ambrisko 		cq->ring.desc_avail = cq->ring.desc_count - 1;
6619c067b84SDoug Ambrisko 
6629c067b84SDoug Ambrisko 		cq->ring.size = cq->ring.desc_count * cq->ring.desc_size;
6639c067b84SDoug Ambrisko 		cq->ring.descs = vaddrs[q * ntxqs + 1];
6649c067b84SDoug Ambrisko 		cq->ring.base_addr = paddrs[q * ntxqs + 1];
6659c067b84SDoug Ambrisko 
6669c067b84SDoug Ambrisko 	}
6679c067b84SDoug Ambrisko 
6689c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
6699c067b84SDoug Ambrisko 
6709c067b84SDoug Ambrisko 	return (0);
6719c067b84SDoug Ambrisko }
6729c067b84SDoug Ambrisko 
6739c067b84SDoug Ambrisko 
6749c067b84SDoug Ambrisko 
6759c067b84SDoug Ambrisko static int
enic_rx_queues_alloc(if_ctx_t ctx,caddr_t * vaddrs,uint64_t * paddrs,int nrxqs,int nrxqsets)6769c067b84SDoug Ambrisko enic_rx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
6779c067b84SDoug Ambrisko 		     int nrxqs, int nrxqsets)
6789c067b84SDoug Ambrisko {
6799c067b84SDoug Ambrisko 	struct enic_softc *softc;
6809c067b84SDoug Ambrisko 	int q;
6819c067b84SDoug Ambrisko 
6829c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
6839c067b84SDoug Ambrisko 	/* Allocate the array of receive queues */
6849c067b84SDoug Ambrisko 	softc->enic.rq = malloc(sizeof(struct vnic_rq) * nrxqsets, M_DEVBUF,
6859c067b84SDoug Ambrisko 	    M_NOWAIT | M_ZERO);
6869c067b84SDoug Ambrisko 	if (softc->enic.rq == NULL)
6879c067b84SDoug Ambrisko 		return (ENOMEM);
6889c067b84SDoug Ambrisko 
6899c067b84SDoug Ambrisko 	/* Initialize driver state for each receive queue */
6909c067b84SDoug Ambrisko 
6919c067b84SDoug Ambrisko 	/*
6929c067b84SDoug Ambrisko 	 * Allocate queue state that is shared with the device.  This check
6939c067b84SDoug Ambrisko 	 * and call is performed in both enic_tx_queues_alloc() and
6949c067b84SDoug Ambrisko 	 * enic_rx_queues_alloc() so that we don't have to care which order
6959c067b84SDoug Ambrisko 	 * iflib invokes those routines in.
6969c067b84SDoug Ambrisko 	 */
6979c067b84SDoug Ambrisko 
6989c067b84SDoug Ambrisko 	/* Record descriptor ring vaddrs and paddrs */
6999c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
7009c067b84SDoug Ambrisko 	for (q = 0; q < nrxqsets; q++) {
7019c067b84SDoug Ambrisko 		struct vnic_rq *rq;
7029c067b84SDoug Ambrisko 		struct vnic_cq *cq;
7039c067b84SDoug Ambrisko 		unsigned int	cq_rq;
7049c067b84SDoug Ambrisko 
7059c067b84SDoug Ambrisko 		rq = &softc->enic.rq[q];
7069c067b84SDoug Ambrisko 		cq_rq = enic_cq_rq(&softc->enic, q);
7079c067b84SDoug Ambrisko 		cq = &softc->enic.cq[cq_rq];
7089c067b84SDoug Ambrisko 
7099c067b84SDoug Ambrisko 		/* Completion ring */
7109c067b84SDoug Ambrisko 		cq->vdev = softc->enic.vdev;
7119c067b84SDoug Ambrisko 		cq->index = cq_rq;
7129c067b84SDoug Ambrisko 		cq->ctrl = vnic_dev_get_res(softc->enic.vdev, RES_TYPE_CQ,
7139c067b84SDoug Ambrisko 		    cq->index);
7149c067b84SDoug Ambrisko 		cq->ring.desc_size = sizeof(struct cq_enet_wq_desc);
7159c067b84SDoug Ambrisko 		cq->ring.desc_count = softc->scctx->isc_nrxd[1];
7169c067b84SDoug Ambrisko 		cq->ring.desc_avail = cq->ring.desc_count - 1;
7179c067b84SDoug Ambrisko 
7189c067b84SDoug Ambrisko 		cq->ring.size = cq->ring.desc_count * cq->ring.desc_size;
7199c067b84SDoug Ambrisko 		cq->ring.descs = vaddrs[q * nrxqs + 0];
7209c067b84SDoug Ambrisko 		cq->ring.base_addr = paddrs[q * nrxqs + 0];
7219c067b84SDoug Ambrisko 
7229c067b84SDoug Ambrisko 		/* Command ring(s) */
7239c067b84SDoug Ambrisko 		rq->vdev = softc->enic.vdev;
7249c067b84SDoug Ambrisko 
7259c067b84SDoug Ambrisko 		rq->index = q;
7269c067b84SDoug Ambrisko 		rq->ctrl = vnic_dev_get_res(softc->enic.vdev,
7279c067b84SDoug Ambrisko 					    RES_TYPE_RQ, rq->index);
7289c067b84SDoug Ambrisko 		vnic_rq_disable(rq);
7299c067b84SDoug Ambrisko 
7309c067b84SDoug Ambrisko 		rq->ring.desc_size = sizeof(struct rq_enet_desc);
7319c067b84SDoug Ambrisko 		rq->ring.desc_count = softc->scctx->isc_nrxd[0];
7329c067b84SDoug Ambrisko 		rq->ring.desc_avail = rq->ring.desc_count - 1;
7339c067b84SDoug Ambrisko 
7349c067b84SDoug Ambrisko 		rq->ring.size = rq->ring.desc_count * rq->ring.desc_size;
7359c067b84SDoug Ambrisko 		rq->ring.descs = vaddrs[q * nrxqs + 1];
7369c067b84SDoug Ambrisko 		rq->ring.base_addr = paddrs[q * nrxqs + 1];
7379c067b84SDoug Ambrisko 		rq->need_initial_post = true;
7389c067b84SDoug Ambrisko 	}
7399c067b84SDoug Ambrisko 
7409c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
7419c067b84SDoug Ambrisko 
7429c067b84SDoug Ambrisko 	return (0);
7439c067b84SDoug Ambrisko }
7449c067b84SDoug Ambrisko 
7459c067b84SDoug Ambrisko static void
enic_queues_free(if_ctx_t ctx)7469c067b84SDoug Ambrisko enic_queues_free(if_ctx_t ctx)
7479c067b84SDoug Ambrisko {
7489c067b84SDoug Ambrisko 	struct enic_softc *softc;
7499c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
7509c067b84SDoug Ambrisko 
7519c067b84SDoug Ambrisko 	free(softc->enic.rq, M_DEVBUF);
7529c067b84SDoug Ambrisko 	free(softc->enic.wq, M_DEVBUF);
7539c067b84SDoug Ambrisko 	free(softc->enic.cq, M_DEVBUF);
7549c067b84SDoug Ambrisko }
7559c067b84SDoug Ambrisko 
7569c067b84SDoug Ambrisko static int
enic_rxq_intr(void * rxq)7579c067b84SDoug Ambrisko enic_rxq_intr(void *rxq)
7589c067b84SDoug Ambrisko {
7599c067b84SDoug Ambrisko 	struct vnic_rq *rq;
760bbd354cbSDoug Ambrisko 	if_t ifp;
7619c067b84SDoug Ambrisko 
7629c067b84SDoug Ambrisko 	rq = (struct vnic_rq *)rxq;
7639c067b84SDoug Ambrisko 	ifp = iflib_get_ifp(rq->vdev->softc->ctx);
764bbd354cbSDoug Ambrisko 	if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
7659c067b84SDoug Ambrisko 		return (FILTER_HANDLED);
7669c067b84SDoug Ambrisko 
7679c067b84SDoug Ambrisko 	return (FILTER_SCHEDULE_THREAD);
7689c067b84SDoug Ambrisko }
7699c067b84SDoug Ambrisko 
7709c067b84SDoug Ambrisko static int
enic_event_intr(void * vsc)7719c067b84SDoug Ambrisko enic_event_intr(void *vsc)
7729c067b84SDoug Ambrisko {
7739c067b84SDoug Ambrisko 	struct enic_softc *softc;
7749c067b84SDoug Ambrisko 	struct enic    *enic;
7759c067b84SDoug Ambrisko 	uint32_t mtu;
7769c067b84SDoug Ambrisko 
7779c067b84SDoug Ambrisko 	softc = vsc;
7789c067b84SDoug Ambrisko 	enic = &softc->enic;
7799c067b84SDoug Ambrisko 
7809c067b84SDoug Ambrisko 	mtu = vnic_dev_mtu(enic->vdev);
7819c067b84SDoug Ambrisko 	if (mtu && mtu != enic->port_mtu) {
7829c067b84SDoug Ambrisko 		enic->port_mtu = mtu;
7839c067b84SDoug Ambrisko 	}
7849c067b84SDoug Ambrisko 
7859c067b84SDoug Ambrisko 	enic_link_status(softc);
7869c067b84SDoug Ambrisko 
7879c067b84SDoug Ambrisko 	return (FILTER_HANDLED);
7889c067b84SDoug Ambrisko }
7899c067b84SDoug Ambrisko 
7909c067b84SDoug Ambrisko static int
enic_err_intr(void * vsc)7919c067b84SDoug Ambrisko enic_err_intr(void *vsc)
7929c067b84SDoug Ambrisko {
7939c067b84SDoug Ambrisko 	struct enic_softc *softc;
7949c067b84SDoug Ambrisko 
7959c067b84SDoug Ambrisko 	softc = vsc;
7969c067b84SDoug Ambrisko 
7979c067b84SDoug Ambrisko 	enic_stop(softc->ctx);
7989c067b84SDoug Ambrisko 	enic_init(softc->ctx);
7999c067b84SDoug Ambrisko 
8009c067b84SDoug Ambrisko 	return (FILTER_HANDLED);
8019c067b84SDoug Ambrisko }
8029c067b84SDoug Ambrisko 
8039c067b84SDoug Ambrisko static void
enic_stop(if_ctx_t ctx)8049c067b84SDoug Ambrisko enic_stop(if_ctx_t ctx)
8059c067b84SDoug Ambrisko {
8069c067b84SDoug Ambrisko 	struct enic_softc *softc;
8079c067b84SDoug Ambrisko 	struct enic    *enic;
8089c067b84SDoug Ambrisko 	if_softc_ctx_t	scctx;
8099c067b84SDoug Ambrisko 	unsigned int	index;
8109c067b84SDoug Ambrisko 
8119c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
8129c067b84SDoug Ambrisko 	scctx = softc->scctx;
8139c067b84SDoug Ambrisko 	enic = &softc->enic;
8149c067b84SDoug Ambrisko 
8159c067b84SDoug Ambrisko 	if (softc->stopped)
8169c067b84SDoug Ambrisko 		return;
8179c067b84SDoug Ambrisko 	softc->link_active = 0;
8189c067b84SDoug Ambrisko 	softc->stopped = 1;
8199c067b84SDoug Ambrisko 
8209c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_ntxqsets; index++) {
8219c067b84SDoug Ambrisko 		enic_stop_wq(enic, index);
8229c067b84SDoug Ambrisko 		vnic_wq_clean(&enic->wq[index]);
8239c067b84SDoug Ambrisko 		vnic_cq_clean(&enic->cq[enic_cq_rq(enic, index)]);
8249c067b84SDoug Ambrisko 	}
8259c067b84SDoug Ambrisko 
8269c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_nrxqsets; index++) {
8279c067b84SDoug Ambrisko 		vnic_rq_clean(&enic->rq[index]);
8289c067b84SDoug Ambrisko 		vnic_cq_clean(&enic->cq[enic_cq_wq(enic, index)]);
8299c067b84SDoug Ambrisko 	}
8309c067b84SDoug Ambrisko 
8319c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_vectors; index++) {
8329c067b84SDoug Ambrisko 		vnic_intr_clean(&enic->intr[index]);
8339c067b84SDoug Ambrisko 	}
8349c067b84SDoug Ambrisko }
8359c067b84SDoug Ambrisko 
8369c067b84SDoug Ambrisko static void
enic_init(if_ctx_t ctx)8379c067b84SDoug Ambrisko enic_init(if_ctx_t ctx)
8389c067b84SDoug Ambrisko {
8399c067b84SDoug Ambrisko 	struct enic_softc *softc;
8409c067b84SDoug Ambrisko 	struct enic *enic;
8419c067b84SDoug Ambrisko 	if_softc_ctx_t scctx;
8429c067b84SDoug Ambrisko 	unsigned int index;
8439c067b84SDoug Ambrisko 
8449c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
8459c067b84SDoug Ambrisko 	scctx = softc->scctx;
8469c067b84SDoug Ambrisko 	enic = &softc->enic;
8479c067b84SDoug Ambrisko 
8489c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_ntxqsets; index++)
8499c067b84SDoug Ambrisko 		enic_prep_wq_for_simple_tx(&softc->enic, index);
8509c067b84SDoug Ambrisko 
8519c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_ntxqsets; index++)
8529c067b84SDoug Ambrisko 		enic_start_wq(enic, index);
8539c067b84SDoug Ambrisko 
8549c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_nrxqsets; index++)
8559c067b84SDoug Ambrisko 		enic_start_rq(enic, index);
8569c067b84SDoug Ambrisko 
8579c067b84SDoug Ambrisko 	/* Use the current MAC address. */
858bbd354cbSDoug Ambrisko 	bcopy(if_getlladdr(softc->ifp), softc->lladdr, ETHER_ADDR_LEN);
8599c067b84SDoug Ambrisko 	enic_set_lladdr(softc);
8609c067b84SDoug Ambrisko 
8619c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
8629c067b84SDoug Ambrisko 	vnic_dev_enable_wait(enic->vdev);
8639c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
8649c067b84SDoug Ambrisko 
8659c067b84SDoug Ambrisko 	enic_link_status(softc);
8669c067b84SDoug Ambrisko }
8679c067b84SDoug Ambrisko 
8689c067b84SDoug Ambrisko static void
enic_del_mcast(struct enic_softc * softc)8699c067b84SDoug Ambrisko enic_del_mcast(struct enic_softc *softc) {
8709c067b84SDoug Ambrisko 	struct enic *enic;
8719c067b84SDoug Ambrisko 	int i;
8729c067b84SDoug Ambrisko 
8739c067b84SDoug Ambrisko 	enic = &softc->enic;
8749c067b84SDoug Ambrisko 	for (i=0; i < softc->mc_count; i++) {
8759c067b84SDoug Ambrisko 		vnic_dev_del_addr(enic->vdev, &softc->mta[i * ETHER_ADDR_LEN]);
8769c067b84SDoug Ambrisko 	}
8779c067b84SDoug Ambrisko 	softc->multicast = 0;
8789c067b84SDoug Ambrisko 	softc->mc_count = 0;
8799c067b84SDoug Ambrisko }
8809c067b84SDoug Ambrisko 
8819c067b84SDoug Ambrisko static void
enic_add_mcast(struct enic_softc * softc)8829c067b84SDoug Ambrisko enic_add_mcast(struct enic_softc *softc) {
8839c067b84SDoug Ambrisko 	struct enic *enic;
8849c067b84SDoug Ambrisko 	int i;
8859c067b84SDoug Ambrisko 
8869c067b84SDoug Ambrisko 	enic = &softc->enic;
8879c067b84SDoug Ambrisko 	for (i=0; i < softc->mc_count; i++) {
8889c067b84SDoug Ambrisko 		vnic_dev_add_addr(enic->vdev, &softc->mta[i * ETHER_ADDR_LEN]);
8899c067b84SDoug Ambrisko 	}
8909c067b84SDoug Ambrisko 	softc->multicast = 1;
8919c067b84SDoug Ambrisko }
8929c067b84SDoug Ambrisko 
8939c067b84SDoug Ambrisko static u_int
enic_copy_maddr(void * arg,struct sockaddr_dl * sdl,u_int idx)8949c067b84SDoug Ambrisko enic_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int idx)
8959c067b84SDoug Ambrisko {
8969c067b84SDoug Ambrisko 	uint8_t *mta = arg;
8979c067b84SDoug Ambrisko 
8989c067b84SDoug Ambrisko 	if (idx == ENIC_MAX_MULTICAST_ADDRESSES)
8999c067b84SDoug Ambrisko 		return (0);
9009c067b84SDoug Ambrisko 
9019c067b84SDoug Ambrisko 	bcopy(LLADDR(sdl), &mta[idx * ETHER_ADDR_LEN], ETHER_ADDR_LEN);
9029c067b84SDoug Ambrisko 	return (1);
9039c067b84SDoug Ambrisko }
9049c067b84SDoug Ambrisko 
9059c067b84SDoug Ambrisko static void
enic_multi_set(if_ctx_t ctx)9069c067b84SDoug Ambrisko enic_multi_set(if_ctx_t ctx)
9079c067b84SDoug Ambrisko {
908bbd354cbSDoug Ambrisko 	if_t ifp;
9099c067b84SDoug Ambrisko 	struct enic_softc *softc;
9109c067b84SDoug Ambrisko 	u_int count;
9119c067b84SDoug Ambrisko 
9129c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
9139c067b84SDoug Ambrisko 	ifp = iflib_get_ifp(ctx);
9149c067b84SDoug Ambrisko 
9159c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
9169c067b84SDoug Ambrisko 	enic_del_mcast(softc);
9179c067b84SDoug Ambrisko 	count = if_foreach_llmaddr(ifp, enic_copy_maddr, softc->mta);
9189c067b84SDoug Ambrisko 	softc->mc_count = count;
9199c067b84SDoug Ambrisko 	enic_add_mcast(softc);
9209c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
9219c067b84SDoug Ambrisko 
922bbd354cbSDoug Ambrisko 	if (if_getflags(ifp) & IFF_PROMISC) {
9239c067b84SDoug Ambrisko 		softc->promisc = 1;
9249c067b84SDoug Ambrisko 	} else {
9259c067b84SDoug Ambrisko 		softc->promisc = 0;
9269c067b84SDoug Ambrisko 	}
927bbd354cbSDoug Ambrisko 	if (if_getflags(ifp) & IFF_ALLMULTI) {
9289c067b84SDoug Ambrisko 		softc->allmulti = 1;
9299c067b84SDoug Ambrisko 	} else {
9309c067b84SDoug Ambrisko 		softc->allmulti = 0;
9319c067b84SDoug Ambrisko 	}
9329c067b84SDoug Ambrisko 	enic_update_packet_filter(&softc->enic);
9339c067b84SDoug Ambrisko }
9349c067b84SDoug Ambrisko 
9359c067b84SDoug Ambrisko static int
enic_mtu_set(if_ctx_t ctx,uint32_t mtu)9369c067b84SDoug Ambrisko enic_mtu_set(if_ctx_t ctx, uint32_t mtu)
9379c067b84SDoug Ambrisko {
9389c067b84SDoug Ambrisko 	struct enic_softc *softc;
9399c067b84SDoug Ambrisko 	struct enic *enic;
9409c067b84SDoug Ambrisko 	if_softc_ctx_t scctx = iflib_get_softc_ctx(ctx);
9419c067b84SDoug Ambrisko 
9429c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
9439c067b84SDoug Ambrisko 	enic = &softc->enic;
9449c067b84SDoug Ambrisko 
9459c067b84SDoug Ambrisko 	if (mtu > enic->port_mtu){
9469c067b84SDoug Ambrisko 		return (EINVAL);
9479c067b84SDoug Ambrisko 	}
9489c067b84SDoug Ambrisko 
9499c067b84SDoug Ambrisko 	enic->config.mtu = mtu;
9509c067b84SDoug Ambrisko 	scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
9519c067b84SDoug Ambrisko 
9529c067b84SDoug Ambrisko 	return (0);
9539c067b84SDoug Ambrisko }
9549c067b84SDoug Ambrisko 
9559c067b84SDoug Ambrisko static void
enic_media_status(if_ctx_t ctx,struct ifmediareq * ifmr)9569c067b84SDoug Ambrisko enic_media_status(if_ctx_t ctx, struct ifmediareq *ifmr)
9579c067b84SDoug Ambrisko {
9589c067b84SDoug Ambrisko 	struct enic_softc *softc;
9599c067b84SDoug Ambrisko 	struct ifmedia_entry *next;
9609c067b84SDoug Ambrisko 	uint32_t speed;
9619c067b84SDoug Ambrisko 	uint64_t target_baudrate;
9629c067b84SDoug Ambrisko 
9639c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
9649c067b84SDoug Ambrisko 
9659c067b84SDoug Ambrisko 	ifmr->ifm_status = IFM_AVALID;
9669c067b84SDoug Ambrisko 	ifmr->ifm_active = IFM_ETHER;
9679c067b84SDoug Ambrisko 
9689c067b84SDoug Ambrisko 	if (enic_link_is_up(softc) != 0) {
9699c067b84SDoug Ambrisko 		ENIC_LOCK(softc);
9709c067b84SDoug Ambrisko 		speed = vnic_dev_port_speed(&softc->vdev);
9719c067b84SDoug Ambrisko 		ENIC_UNLOCK(softc);
9729c067b84SDoug Ambrisko 		target_baudrate = 1000ull * speed;
9739c067b84SDoug Ambrisko 		LIST_FOREACH(next, &(iflib_get_media(ctx)->ifm_list), ifm_list) {
9749c067b84SDoug Ambrisko 			if (ifmedia_baudrate(next->ifm_media) == target_baudrate) {
9759c067b84SDoug Ambrisko 				ifmr->ifm_active |= next->ifm_media;
9769c067b84SDoug Ambrisko 			}
9779c067b84SDoug Ambrisko 		}
9789c067b84SDoug Ambrisko 
9799c067b84SDoug Ambrisko 		ifmr->ifm_status |= IFM_ACTIVE;
9809c067b84SDoug Ambrisko 		ifmr->ifm_active |= IFM_AUTO;
9819c067b84SDoug Ambrisko 	} else
9829c067b84SDoug Ambrisko 		ifmr->ifm_active |= IFM_NONE;
9839c067b84SDoug Ambrisko }
9849c067b84SDoug Ambrisko 
9859c067b84SDoug Ambrisko static int
enic_media_change(if_ctx_t ctx)9869c067b84SDoug Ambrisko enic_media_change(if_ctx_t ctx)
9879c067b84SDoug Ambrisko {
9889c067b84SDoug Ambrisko 	return (ENODEV);
9899c067b84SDoug Ambrisko }
9909c067b84SDoug Ambrisko 
9919c067b84SDoug Ambrisko static int
enic_promisc_set(if_ctx_t ctx,int flags)9929c067b84SDoug Ambrisko enic_promisc_set(if_ctx_t ctx, int flags)
9939c067b84SDoug Ambrisko {
994bbd354cbSDoug Ambrisko 	if_t ifp;
9959c067b84SDoug Ambrisko 	struct enic_softc *softc;
9969c067b84SDoug Ambrisko 
9979c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
9989c067b84SDoug Ambrisko 	ifp = iflib_get_ifp(ctx);
9999c067b84SDoug Ambrisko 
1000bbd354cbSDoug Ambrisko 	if (if_getflags(ifp) & IFF_PROMISC) {
10019c067b84SDoug Ambrisko 		softc->promisc = 1;
10029c067b84SDoug Ambrisko 	} else {
10039c067b84SDoug Ambrisko 		softc->promisc = 0;
10049c067b84SDoug Ambrisko 	}
1005bbd354cbSDoug Ambrisko 	if (if_getflags(ifp) & IFF_ALLMULTI) {
10069c067b84SDoug Ambrisko 		softc->allmulti = 1;
10079c067b84SDoug Ambrisko 	} else {
10089c067b84SDoug Ambrisko 		softc->allmulti = 0;
10099c067b84SDoug Ambrisko 	}
10109c067b84SDoug Ambrisko 	enic_update_packet_filter(&softc->enic);
10119c067b84SDoug Ambrisko 
10129c067b84SDoug Ambrisko 	return (0);
10139c067b84SDoug Ambrisko }
10149c067b84SDoug Ambrisko 
10159c067b84SDoug Ambrisko static uint64_t
enic_get_counter(if_ctx_t ctx,ift_counter cnt)10169c067b84SDoug Ambrisko enic_get_counter(if_ctx_t ctx, ift_counter cnt) {
10179c067b84SDoug Ambrisko 	if_t ifp = iflib_get_ifp(ctx);
10189c067b84SDoug Ambrisko 
10199c067b84SDoug Ambrisko 	if (cnt < IFCOUNTERS)
10209c067b84SDoug Ambrisko 		return if_get_counter_default(ifp, cnt);
10219c067b84SDoug Ambrisko 
10229c067b84SDoug Ambrisko 	return (0);
10239c067b84SDoug Ambrisko }
10249c067b84SDoug Ambrisko 
10259c067b84SDoug Ambrisko static void
enic_update_admin_status(if_ctx_t ctx)10269c067b84SDoug Ambrisko enic_update_admin_status(if_ctx_t ctx)
10279c067b84SDoug Ambrisko {
10289c067b84SDoug Ambrisko 	struct enic_softc *softc;
10299c067b84SDoug Ambrisko 
10309c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
10319c067b84SDoug Ambrisko 
10329c067b84SDoug Ambrisko 	enic_link_status(softc);
10339c067b84SDoug Ambrisko }
10349c067b84SDoug Ambrisko 
10359c067b84SDoug Ambrisko static void
enic_txq_timer(if_ctx_t ctx,uint16_t qid)10369c067b84SDoug Ambrisko enic_txq_timer(if_ctx_t ctx, uint16_t qid)
10379c067b84SDoug Ambrisko {
10389c067b84SDoug Ambrisko 
10399c067b84SDoug Ambrisko 	struct enic_softc *softc;
10409c067b84SDoug Ambrisko 	struct enic *enic;
10419c067b84SDoug Ambrisko 	struct vnic_stats *stats;
10429c067b84SDoug Ambrisko 	int ret;
10439c067b84SDoug Ambrisko 
10449c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
10459c067b84SDoug Ambrisko 	enic = &softc->enic;
10469c067b84SDoug Ambrisko 
10479c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
10489c067b84SDoug Ambrisko 	ret = vnic_dev_stats_dump(enic->vdev, &stats);
10499c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
10509c067b84SDoug Ambrisko 	if (ret) {
10519c067b84SDoug Ambrisko 		dev_err(enic, "Error in getting stats\n");
10529c067b84SDoug Ambrisko 	}
10539c067b84SDoug Ambrisko }
10549c067b84SDoug Ambrisko 
10559c067b84SDoug Ambrisko static int
enic_link_is_up(struct enic_softc * softc)10569c067b84SDoug Ambrisko enic_link_is_up(struct enic_softc *softc)
10579c067b84SDoug Ambrisko {
10589c067b84SDoug Ambrisko 	return (vnic_dev_link_status(&softc->vdev) == 1);
10599c067b84SDoug Ambrisko }
10609c067b84SDoug Ambrisko 
10619c067b84SDoug Ambrisko static void
enic_link_status(struct enic_softc * softc)10629c067b84SDoug Ambrisko enic_link_status(struct enic_softc *softc)
10639c067b84SDoug Ambrisko {
10649c067b84SDoug Ambrisko 	if_ctx_t ctx;
10659c067b84SDoug Ambrisko 	uint64_t speed;
10669c067b84SDoug Ambrisko 	int link;
10679c067b84SDoug Ambrisko 
10689c067b84SDoug Ambrisko 	ctx = softc->ctx;
10699c067b84SDoug Ambrisko 	link = enic_link_is_up(softc);
10709c067b84SDoug Ambrisko 	speed = IF_Gbps(10);
10719c067b84SDoug Ambrisko 
10729c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
10739c067b84SDoug Ambrisko 	speed = vnic_dev_port_speed(&softc->vdev);
10749c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
10759c067b84SDoug Ambrisko 
10769c067b84SDoug Ambrisko 	if (link != 0 && softc->link_active == 0) {
10779c067b84SDoug Ambrisko 		softc->link_active = 1;
10789c067b84SDoug Ambrisko 		iflib_link_state_change(ctx, LINK_STATE_UP, speed);
10799c067b84SDoug Ambrisko 	} else if (link == 0 && softc->link_active != 0) {
10809c067b84SDoug Ambrisko 		softc->link_active = 0;
10819c067b84SDoug Ambrisko 		iflib_link_state_change(ctx, LINK_STATE_DOWN, speed);
10829c067b84SDoug Ambrisko 	}
10839c067b84SDoug Ambrisko }
10849c067b84SDoug Ambrisko 
10859c067b84SDoug Ambrisko static void
enic_set_lladdr(struct enic_softc * softc)10869c067b84SDoug Ambrisko enic_set_lladdr(struct enic_softc *softc)
10879c067b84SDoug Ambrisko {
10889c067b84SDoug Ambrisko 	struct enic *enic;
10899c067b84SDoug Ambrisko 	enic = &softc->enic;
10909c067b84SDoug Ambrisko 
10919c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
10929c067b84SDoug Ambrisko 	vnic_dev_add_addr(enic->vdev, softc->lladdr);
10939c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
10949c067b84SDoug Ambrisko }
10959c067b84SDoug Ambrisko 
10969c067b84SDoug Ambrisko 
10979c067b84SDoug Ambrisko static void
enic_setup_txq_sysctl(struct vnic_wq * wq,int i,struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child)10989c067b84SDoug Ambrisko enic_setup_txq_sysctl(struct vnic_wq *wq, int i, struct sysctl_ctx_list *ctx,
10999c067b84SDoug Ambrisko     struct sysctl_oid_list *child)
11009c067b84SDoug Ambrisko {
11019c067b84SDoug Ambrisko 	struct sysctl_oid *txsnode;
11029c067b84SDoug Ambrisko 	struct sysctl_oid_list *txslist;
11039c067b84SDoug Ambrisko 	struct vnic_stats *stats = wq[i].vdev->stats;
11049c067b84SDoug Ambrisko 
11059c067b84SDoug Ambrisko 	txsnode = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hstats",
11069c067b84SDoug Ambrisko 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Host Statistics");
11079c067b84SDoug Ambrisko 	txslist = SYSCTL_CHILDREN(txsnode);
11089c067b84SDoug Ambrisko 
11099c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_frames_ok", CTLFLAG_RD,
11109c067b84SDoug Ambrisko 	   &stats->tx.tx_frames_ok, "TX Frames OK");
11119c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_unicast_frames_ok", CTLFLAG_RD,
11129c067b84SDoug Ambrisko 	   &stats->tx.tx_unicast_frames_ok, "TX unicast frames OK");
11139c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_multicast_frames_ok", CTLFLAG_RD,
11149c067b84SDoug Ambrisko 	    &stats->tx.tx_multicast_frames_ok, "TX multicast framse OK");
11159c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_broadcast_frames_ok", CTLFLAG_RD,
11169c067b84SDoug Ambrisko 	    &stats->tx.tx_broadcast_frames_ok, "TX Broadcast frames OK");
11179c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_bytes_ok", CTLFLAG_RD,
11189c067b84SDoug Ambrisko 	    &stats->tx.tx_bytes_ok, "TX bytes OK ");
11199c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_unicast_bytes_ok", CTLFLAG_RD,
11209c067b84SDoug Ambrisko 	    &stats->tx.tx_unicast_bytes_ok, "TX unicast bytes OK");
11219c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_multicast_bytes_ok", CTLFLAG_RD,
11229c067b84SDoug Ambrisko 	    &stats->tx.tx_multicast_bytes_ok, "TX multicast bytes OK");
11239c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_broadcast_bytes_ok", CTLFLAG_RD,
11249c067b84SDoug Ambrisko 	    &stats->tx.tx_broadcast_bytes_ok, "TX broadcast bytes OK");
11259c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_drops", CTLFLAG_RD,
11269c067b84SDoug Ambrisko 	    &stats->tx.tx_drops, "TX drops");
11279c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_errors", CTLFLAG_RD,
11289c067b84SDoug Ambrisko 	    &stats->tx.tx_errors, "TX errors");
11299c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_tso", CTLFLAG_RD,
11309c067b84SDoug Ambrisko 	    &stats->tx.tx_tso, "TX TSO");
11319c067b84SDoug Ambrisko }
11329c067b84SDoug Ambrisko 
11339c067b84SDoug Ambrisko static void
enic_setup_rxq_sysctl(struct vnic_rq * rq,int i,struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child)11349c067b84SDoug Ambrisko enic_setup_rxq_sysctl(struct vnic_rq *rq, int i, struct sysctl_ctx_list *ctx,
11359c067b84SDoug Ambrisko     struct sysctl_oid_list *child)
11369c067b84SDoug Ambrisko {
11379c067b84SDoug Ambrisko 	struct sysctl_oid *rxsnode;
11389c067b84SDoug Ambrisko 	struct sysctl_oid_list *rxslist;
11399c067b84SDoug Ambrisko 	struct vnic_stats *stats = rq[i].vdev->stats;
11409c067b84SDoug Ambrisko 
11419c067b84SDoug Ambrisko 	rxsnode = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hstats",
11429c067b84SDoug Ambrisko 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Host Statistics");
11439c067b84SDoug Ambrisko 	rxslist = SYSCTL_CHILDREN(rxsnode);
11449c067b84SDoug Ambrisko 
11459c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_ok", CTLFLAG_RD,
11469c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_ok, "RX Frames OK");
11479c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_total", CTLFLAG_RD,
11489c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_total, "RX frames total");
11499c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_unicast_frames_ok", CTLFLAG_RD,
11509c067b84SDoug Ambrisko 	    &stats->rx.rx_unicast_frames_ok, "RX unicast frames ok");
11519c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_multicast_frames_ok", CTLFLAG_RD,
11529c067b84SDoug Ambrisko 	    &stats->rx.rx_multicast_frames_ok, "RX multicast Frames ok");
11539c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_broadcast_frames_ok", CTLFLAG_RD,
11549c067b84SDoug Ambrisko 	    &stats->rx.rx_broadcast_frames_ok, "RX broadcast frames ok");
11559c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_bytes_ok", CTLFLAG_RD,
11569c067b84SDoug Ambrisko 	    &stats->rx.rx_bytes_ok, "RX bytes ok");
11579c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_unicast_bytes_ok", CTLFLAG_RD,
11589c067b84SDoug Ambrisko 	    &stats->rx.rx_unicast_bytes_ok, "RX unicast bytes ok");
11599c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_multicast_bytes_ok", CTLFLAG_RD,
11609c067b84SDoug Ambrisko 	    &stats->rx.rx_multicast_bytes_ok, "RX multicast bytes ok");
11619c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_broadcast_bytes_ok", CTLFLAG_RD,
11629c067b84SDoug Ambrisko 	    &stats->rx.rx_broadcast_bytes_ok, "RX broadcast bytes ok");
11639c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_drop", CTLFLAG_RD,
11649c067b84SDoug Ambrisko 	    &stats->rx.rx_drop, "RX drop");
11659c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_errors", CTLFLAG_RD,
11669c067b84SDoug Ambrisko 	    &stats->rx.rx_errors, "RX errors");
11679c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_rss", CTLFLAG_RD,
11689c067b84SDoug Ambrisko 	    &stats->rx.rx_rss, "RX rss");
11699c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_crc_errors", CTLFLAG_RD,
11709c067b84SDoug Ambrisko 	    &stats->rx.rx_crc_errors, "RX crc errors");
11719c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_64", CTLFLAG_RD,
11729c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_64, "RX frames 64");
11739c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_127", CTLFLAG_RD,
11749c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_127, "RX frames 127");
11759c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_255", CTLFLAG_RD,
11769c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_255, "RX frames 255");
11779c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_511", CTLFLAG_RD,
11789c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_511, "RX frames 511");
11799c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_1023", CTLFLAG_RD,
11809c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_1023, "RX frames 1023");
11819c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_1518", CTLFLAG_RD,
11829c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_1518, "RX frames 1518");
11839c067b84SDoug Ambrisko 	SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_to_max", CTLFLAG_RD,
11849c067b84SDoug Ambrisko 	    &stats->rx.rx_frames_to_max, "RX frames to max");
11859c067b84SDoug Ambrisko }
11869c067b84SDoug Ambrisko 
11879c067b84SDoug Ambrisko static void
enic_setup_queue_sysctl(struct enic_softc * softc,struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child)11889c067b84SDoug Ambrisko enic_setup_queue_sysctl(struct enic_softc *softc, struct sysctl_ctx_list *ctx,
11899c067b84SDoug Ambrisko     struct sysctl_oid_list *child)
11909c067b84SDoug Ambrisko {
11919c067b84SDoug Ambrisko 	enic_setup_txq_sysctl(softc->enic.wq, 0, ctx, child);
11929c067b84SDoug Ambrisko 	enic_setup_rxq_sysctl(softc->enic.rq, 0, ctx, child);
11939c067b84SDoug Ambrisko }
11949c067b84SDoug Ambrisko 
11959c067b84SDoug Ambrisko static void
enic_setup_sysctl(struct enic_softc * softc)11969c067b84SDoug Ambrisko enic_setup_sysctl(struct enic_softc *softc)
11979c067b84SDoug Ambrisko {
11989c067b84SDoug Ambrisko 	device_t dev;
11999c067b84SDoug Ambrisko 	struct sysctl_ctx_list *ctx;
12009c067b84SDoug Ambrisko 	struct sysctl_oid *tree;
12019c067b84SDoug Ambrisko 	struct sysctl_oid_list *child;
12029c067b84SDoug Ambrisko 
12039c067b84SDoug Ambrisko 	dev = softc->dev;
12049c067b84SDoug Ambrisko 	ctx = device_get_sysctl_ctx(dev);
12059c067b84SDoug Ambrisko 	tree = device_get_sysctl_tree(dev);
12069c067b84SDoug Ambrisko 	child = SYSCTL_CHILDREN(tree);
12079c067b84SDoug Ambrisko 
12089c067b84SDoug Ambrisko 	enic_setup_queue_sysctl(softc, ctx, child);
12099c067b84SDoug Ambrisko }
12109c067b84SDoug Ambrisko 
12119c067b84SDoug Ambrisko static void
enic_enable_intr(struct enic_softc * softc,int irq)12129c067b84SDoug Ambrisko enic_enable_intr(struct enic_softc *softc, int irq)
12139c067b84SDoug Ambrisko {
12149c067b84SDoug Ambrisko 	struct enic *enic = &softc->enic;
12159c067b84SDoug Ambrisko 
12169c067b84SDoug Ambrisko 	vnic_intr_unmask(&enic->intr[irq]);
12179c067b84SDoug Ambrisko 	vnic_intr_return_all_credits(&enic->intr[irq]);
12189c067b84SDoug Ambrisko }
12199c067b84SDoug Ambrisko 
12209c067b84SDoug Ambrisko static void
enic_disable_intr(struct enic_softc * softc,int irq)12219c067b84SDoug Ambrisko enic_disable_intr(struct enic_softc *softc, int irq)
12229c067b84SDoug Ambrisko {
12239c067b84SDoug Ambrisko 	struct enic *enic = &softc->enic;
12249c067b84SDoug Ambrisko 
12259c067b84SDoug Ambrisko 	vnic_intr_mask(&enic->intr[irq]);
12269c067b84SDoug Ambrisko 	vnic_intr_masked(&enic->intr[irq]);	/* flush write */
12279c067b84SDoug Ambrisko }
12289c067b84SDoug Ambrisko 
12299c067b84SDoug Ambrisko static int
enic_tx_queue_intr_enable(if_ctx_t ctx,uint16_t qid)12309c067b84SDoug Ambrisko enic_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid)
12319c067b84SDoug Ambrisko {
12329c067b84SDoug Ambrisko 	struct enic_softc *softc;
12339c067b84SDoug Ambrisko 	if_softc_ctx_t scctx;
12349c067b84SDoug Ambrisko 
12359c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
12369c067b84SDoug Ambrisko 	scctx = softc->scctx;
12379c067b84SDoug Ambrisko 
12389c067b84SDoug Ambrisko 	enic_enable_intr(softc, qid + scctx->isc_nrxqsets);
12399c067b84SDoug Ambrisko 
12409c067b84SDoug Ambrisko 	return 0;
12419c067b84SDoug Ambrisko }
12429c067b84SDoug Ambrisko 
12439c067b84SDoug Ambrisko static int
enic_rx_queue_intr_enable(if_ctx_t ctx,uint16_t qid)12449c067b84SDoug Ambrisko enic_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid)
12459c067b84SDoug Ambrisko {
12469c067b84SDoug Ambrisko 	struct enic_softc *softc;
12479c067b84SDoug Ambrisko 
12489c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
12499c067b84SDoug Ambrisko 	enic_enable_intr(softc, qid);
12509c067b84SDoug Ambrisko 
12519c067b84SDoug Ambrisko 	return 0;
12529c067b84SDoug Ambrisko }
12539c067b84SDoug Ambrisko 
12549c067b84SDoug Ambrisko static void
enic_intr_enable_all(if_ctx_t ctx)12559c067b84SDoug Ambrisko enic_intr_enable_all(if_ctx_t ctx)
12569c067b84SDoug Ambrisko {
12579c067b84SDoug Ambrisko 	struct enic_softc *softc;
12589c067b84SDoug Ambrisko 	if_softc_ctx_t scctx;
12599c067b84SDoug Ambrisko 	int i;
12609c067b84SDoug Ambrisko 
12619c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
12629c067b84SDoug Ambrisko 	scctx = softc->scctx;
12639c067b84SDoug Ambrisko 
12649c067b84SDoug Ambrisko 	for (i = 0; i < scctx->isc_vectors; i++) {
12659c067b84SDoug Ambrisko 		enic_enable_intr(softc, i);
12669c067b84SDoug Ambrisko 	}
12679c067b84SDoug Ambrisko }
12689c067b84SDoug Ambrisko 
12699c067b84SDoug Ambrisko static void
enic_intr_disable_all(if_ctx_t ctx)12709c067b84SDoug Ambrisko enic_intr_disable_all(if_ctx_t ctx)
12719c067b84SDoug Ambrisko {
12729c067b84SDoug Ambrisko 	struct enic_softc *softc;
12739c067b84SDoug Ambrisko 	if_softc_ctx_t scctx;
12749c067b84SDoug Ambrisko 	int i;
12759c067b84SDoug Ambrisko 
12769c067b84SDoug Ambrisko 	softc = iflib_get_softc(ctx);
12779c067b84SDoug Ambrisko 	scctx = softc->scctx;
12789c067b84SDoug Ambrisko 	/*
12799c067b84SDoug Ambrisko 	 * iflib may invoke this routine before enic_attach_post() has run,
12809c067b84SDoug Ambrisko 	 * which is before the top level shared data area is initialized and
12819c067b84SDoug Ambrisko 	 * the device made aware of it.
12829c067b84SDoug Ambrisko 	 */
12839c067b84SDoug Ambrisko 
12849c067b84SDoug Ambrisko 	for (i = 0; i < scctx->isc_vectors; i++) {
12859c067b84SDoug Ambrisko 		enic_disable_intr(softc, i);
12869c067b84SDoug Ambrisko 	}
12879c067b84SDoug Ambrisko }
12889c067b84SDoug Ambrisko 
12899c067b84SDoug Ambrisko static int
enic_dev_open(struct enic * enic)12909c067b84SDoug Ambrisko enic_dev_open(struct enic *enic)
12919c067b84SDoug Ambrisko {
12929c067b84SDoug Ambrisko 	int err;
12939c067b84SDoug Ambrisko 	int flags = CMD_OPENF_IG_DESCCACHE;
12949c067b84SDoug Ambrisko 
12959c067b84SDoug Ambrisko 	err = enic_dev_wait(enic->vdev, vnic_dev_open,
12969c067b84SDoug Ambrisko 			    vnic_dev_open_done, flags);
12979c067b84SDoug Ambrisko 	if (err)
12989c067b84SDoug Ambrisko 		dev_err(enic_get_dev(enic),
12999c067b84SDoug Ambrisko 			"vNIC device open failed, err %d\n", err);
13009c067b84SDoug Ambrisko 
13019c067b84SDoug Ambrisko 	return err;
13029c067b84SDoug Ambrisko }
13039c067b84SDoug Ambrisko 
13049c067b84SDoug Ambrisko static int
enic_dev_init(struct enic * enic)13059c067b84SDoug Ambrisko enic_dev_init(struct enic *enic)
13069c067b84SDoug Ambrisko {
13079c067b84SDoug Ambrisko 	int err;
13089c067b84SDoug Ambrisko 
13099c067b84SDoug Ambrisko 	vnic_dev_intr_coal_timer_info_default(enic->vdev);
13109c067b84SDoug Ambrisko 
13119c067b84SDoug Ambrisko 	/*
13129c067b84SDoug Ambrisko 	 * Get vNIC configuration
13139c067b84SDoug Ambrisko 	 */
13149c067b84SDoug Ambrisko 	err = enic_get_vnic_config(enic);
13159c067b84SDoug Ambrisko 	if (err) {
13169c067b84SDoug Ambrisko 		dev_err(dev, "Get vNIC configuration failed, aborting\n");
13179c067b84SDoug Ambrisko 		return err;
13189c067b84SDoug Ambrisko 	}
13199c067b84SDoug Ambrisko 
13209c067b84SDoug Ambrisko 	/* Get available resource counts */
13219c067b84SDoug Ambrisko 	enic_get_res_counts(enic);
13229c067b84SDoug Ambrisko 
13239c067b84SDoug Ambrisko 	/* Queue counts may be zeros. rte_zmalloc returns NULL in that case. */
13249c067b84SDoug Ambrisko 	enic->intr_queues = malloc(sizeof(*enic->intr_queues) *
13259c067b84SDoug Ambrisko 	    enic->conf_intr_count, M_DEVBUF, M_NOWAIT | M_ZERO);
13269c067b84SDoug Ambrisko 
13279c067b84SDoug Ambrisko 	vnic_dev_set_reset_flag(enic->vdev, 0);
13289c067b84SDoug Ambrisko 	enic->max_flow_counter = -1;
13299c067b84SDoug Ambrisko 
13309c067b84SDoug Ambrisko 	/* set up link status checking */
13319c067b84SDoug Ambrisko 	vnic_dev_notify_set(enic->vdev, -1);	/* No Intr for notify */
13329c067b84SDoug Ambrisko 
13339c067b84SDoug Ambrisko 	enic->overlay_offload = false;
13349c067b84SDoug Ambrisko 	if (enic->disable_overlay && enic->vxlan) {
13359c067b84SDoug Ambrisko 		/*
13369c067b84SDoug Ambrisko 		 * Explicitly disable overlay offload as the setting is
13379c067b84SDoug Ambrisko 		 * sticky, and resetting vNIC does not disable it.
13389c067b84SDoug Ambrisko 		 */
13399c067b84SDoug Ambrisko 		if (vnic_dev_overlay_offload_ctrl(enic->vdev,
13409c067b84SDoug Ambrisko 		    OVERLAY_FEATURE_VXLAN, OVERLAY_OFFLOAD_DISABLE)) {
13419c067b84SDoug Ambrisko 			dev_err(enic, "failed to disable overlay offload\n");
13429c067b84SDoug Ambrisko 		} else {
13439c067b84SDoug Ambrisko 			dev_info(enic, "Overlay offload is disabled\n");
13449c067b84SDoug Ambrisko 		}
13459c067b84SDoug Ambrisko 	}
13469c067b84SDoug Ambrisko 	if (!enic->disable_overlay && enic->vxlan &&
13479c067b84SDoug Ambrisko 	/* 'VXLAN feature' enables VXLAN, NVGRE, and GENEVE. */
13489c067b84SDoug Ambrisko 	    vnic_dev_overlay_offload_ctrl(enic->vdev,
13499c067b84SDoug Ambrisko 	    OVERLAY_FEATURE_VXLAN, OVERLAY_OFFLOAD_ENABLE) == 0) {
13509c067b84SDoug Ambrisko 		enic->overlay_offload = true;
13519c067b84SDoug Ambrisko 		enic->vxlan_port = ENIC_DEFAULT_VXLAN_PORT;
13529c067b84SDoug Ambrisko 		dev_info(enic, "Overlay offload is enabled\n");
13539c067b84SDoug Ambrisko 		/*
13549c067b84SDoug Ambrisko 		 * Reset the vxlan port to the default, as the NIC firmware
13559c067b84SDoug Ambrisko 		 * does not reset it automatically and keeps the old setting.
13569c067b84SDoug Ambrisko 		 */
13579c067b84SDoug Ambrisko 		if (vnic_dev_overlay_offload_cfg(enic->vdev,
13589c067b84SDoug Ambrisko 		   OVERLAY_CFG_VXLAN_PORT_UPDATE, ENIC_DEFAULT_VXLAN_PORT)) {
13599c067b84SDoug Ambrisko 			dev_err(enic, "failed to update vxlan port\n");
13609c067b84SDoug Ambrisko 			return -EINVAL;
13619c067b84SDoug Ambrisko 		}
13629c067b84SDoug Ambrisko 	}
13639c067b84SDoug Ambrisko 	return 0;
13649c067b84SDoug Ambrisko }
13659c067b84SDoug Ambrisko 
13669c067b84SDoug Ambrisko static void    *
enic_alloc_consistent(void * priv,size_t size,bus_addr_t * dma_handle,struct iflib_dma_info * res,u8 * name)13679c067b84SDoug Ambrisko enic_alloc_consistent(void *priv, size_t size, bus_addr_t * dma_handle,
13689c067b84SDoug Ambrisko     struct iflib_dma_info *res, u8 * name)
13699c067b84SDoug Ambrisko {
13709c067b84SDoug Ambrisko 	void	       *vaddr;
13719c067b84SDoug Ambrisko 	*dma_handle = 0;
13729c067b84SDoug Ambrisko 	struct enic    *enic = (struct enic *)priv;
13739c067b84SDoug Ambrisko 	int		rz;
13749c067b84SDoug Ambrisko 
13759c067b84SDoug Ambrisko 	rz = iflib_dma_alloc(enic->softc->ctx, size, res, BUS_DMA_NOWAIT);
13769c067b84SDoug Ambrisko 	if (rz) {
13779c067b84SDoug Ambrisko 		pr_err("%s : Failed to allocate memory requested for %s\n",
13789c067b84SDoug Ambrisko 		    __func__, name);
13799c067b84SDoug Ambrisko 		return NULL;
13809c067b84SDoug Ambrisko 	}
13819c067b84SDoug Ambrisko 
13829c067b84SDoug Ambrisko 	vaddr = res->idi_vaddr;
13839c067b84SDoug Ambrisko 	*dma_handle = res->idi_paddr;
13849c067b84SDoug Ambrisko 
13859c067b84SDoug Ambrisko 	return vaddr;
13869c067b84SDoug Ambrisko }
13879c067b84SDoug Ambrisko 
13889c067b84SDoug Ambrisko static void
enic_free_consistent(void * priv,size_t size,void * vaddr,bus_addr_t dma_handle,struct iflib_dma_info * res)13899c067b84SDoug Ambrisko enic_free_consistent(void *priv, size_t size, void *vaddr,
13909c067b84SDoug Ambrisko     bus_addr_t dma_handle, struct iflib_dma_info *res)
13919c067b84SDoug Ambrisko {
13929c067b84SDoug Ambrisko 	iflib_dma_free(res);
13939c067b84SDoug Ambrisko }
13949c067b84SDoug Ambrisko 
13959c067b84SDoug Ambrisko static int
enic_pci_mapping(struct enic_softc * softc)13969c067b84SDoug Ambrisko enic_pci_mapping(struct enic_softc *softc)
13979c067b84SDoug Ambrisko {
13989c067b84SDoug Ambrisko 	int rc;
13999c067b84SDoug Ambrisko 
14009c067b84SDoug Ambrisko 	rc = enic_map_bar(softc, &softc->mem, 0, true);
14019c067b84SDoug Ambrisko 	if (rc)
14029c067b84SDoug Ambrisko 		return rc;
14039c067b84SDoug Ambrisko 
14049c067b84SDoug Ambrisko 	rc = enic_map_bar(softc, &softc->io, 2, false);
14059c067b84SDoug Ambrisko 
14069c067b84SDoug Ambrisko 	return rc;
14079c067b84SDoug Ambrisko }
14089c067b84SDoug Ambrisko 
14099c067b84SDoug Ambrisko static void
enic_pci_mapping_free(struct enic_softc * softc)14109c067b84SDoug Ambrisko enic_pci_mapping_free(struct enic_softc *softc)
14119c067b84SDoug Ambrisko {
14129c067b84SDoug Ambrisko 	if (softc->mem.res != NULL)
14139c067b84SDoug Ambrisko 		bus_release_resource(softc->dev, SYS_RES_MEMORY,
14149c067b84SDoug Ambrisko 				     softc->mem.rid, softc->mem.res);
14159c067b84SDoug Ambrisko 	softc->mem.res = NULL;
14169c067b84SDoug Ambrisko 
14179c067b84SDoug Ambrisko 	if (softc->io.res != NULL)
14189c067b84SDoug Ambrisko 		bus_release_resource(softc->dev, SYS_RES_MEMORY,
14199c067b84SDoug Ambrisko 				     softc->io.rid, softc->io.res);
14209c067b84SDoug Ambrisko 	softc->io.res = NULL;
14219c067b84SDoug Ambrisko }
14229c067b84SDoug Ambrisko 
14239c067b84SDoug Ambrisko static int
enic_dev_wait(struct vnic_dev * vdev,int (* start)(struct vnic_dev *,int),int (* finished)(struct vnic_dev *,int *),int arg)14249c067b84SDoug Ambrisko enic_dev_wait(struct vnic_dev *vdev, int (*start) (struct vnic_dev *, int),
14259c067b84SDoug Ambrisko     int (*finished) (struct vnic_dev *, int *), int arg)
14269c067b84SDoug Ambrisko {
14279c067b84SDoug Ambrisko 	int done;
14289c067b84SDoug Ambrisko 	int err;
14299c067b84SDoug Ambrisko 	int i;
14309c067b84SDoug Ambrisko 
14319c067b84SDoug Ambrisko 	err = start(vdev, arg);
14329c067b84SDoug Ambrisko 	if (err)
14339c067b84SDoug Ambrisko 		return err;
14349c067b84SDoug Ambrisko 
14359c067b84SDoug Ambrisko 	/* Wait for func to complete...2 seconds max */
14369c067b84SDoug Ambrisko 	for (i = 0; i < 2000; i++) {
14379c067b84SDoug Ambrisko 		err = finished(vdev, &done);
14389c067b84SDoug Ambrisko 		if (err)
14399c067b84SDoug Ambrisko 			return err;
14409c067b84SDoug Ambrisko 		if (done)
14419c067b84SDoug Ambrisko 			return 0;
14429c067b84SDoug Ambrisko 		usleep(1000);
14439c067b84SDoug Ambrisko 	}
14449c067b84SDoug Ambrisko 	return -ETIMEDOUT;
14459c067b84SDoug Ambrisko }
14469c067b84SDoug Ambrisko 
14479c067b84SDoug Ambrisko static int
enic_map_bar(struct enic_softc * softc,struct enic_bar_info * bar,int bar_num,bool shareable)14489c067b84SDoug Ambrisko enic_map_bar(struct enic_softc *softc, struct enic_bar_info *bar, int bar_num,
14499c067b84SDoug Ambrisko     bool shareable)
14509c067b84SDoug Ambrisko {
14519c067b84SDoug Ambrisko 	uint32_t flag;
14529c067b84SDoug Ambrisko 
14539c067b84SDoug Ambrisko 	if (bar->res != NULL) {
14549c067b84SDoug Ambrisko 		device_printf(softc->dev, "Bar %d already mapped\n", bar_num);
14559c067b84SDoug Ambrisko 		return EDOOFUS;
14569c067b84SDoug Ambrisko 	}
14579c067b84SDoug Ambrisko 
14589c067b84SDoug Ambrisko 	bar->rid = PCIR_BAR(bar_num);
14599c067b84SDoug Ambrisko 	flag = RF_ACTIVE;
14609c067b84SDoug Ambrisko 	if (shareable)
14619c067b84SDoug Ambrisko 		flag |= RF_SHAREABLE;
14629c067b84SDoug Ambrisko 
14639c067b84SDoug Ambrisko 	if ((bar->res = bus_alloc_resource_any(softc->dev,
14649c067b84SDoug Ambrisko 	   SYS_RES_MEMORY, &bar->rid, flag)) == NULL) {
14659c067b84SDoug Ambrisko 		device_printf(softc->dev,
14669c067b84SDoug Ambrisko 			      "PCI BAR%d mapping failure\n", bar_num);
14679c067b84SDoug Ambrisko 		return (ENXIO);
14689c067b84SDoug Ambrisko 	}
14699c067b84SDoug Ambrisko 	bar->tag = rman_get_bustag(bar->res);
14709c067b84SDoug Ambrisko 	bar->handle = rman_get_bushandle(bar->res);
14719c067b84SDoug Ambrisko 	bar->size = rman_get_size(bar->res);
14729c067b84SDoug Ambrisko 
14739c067b84SDoug Ambrisko 	return 0;
14749c067b84SDoug Ambrisko }
14759c067b84SDoug Ambrisko 
14769c067b84SDoug Ambrisko void
enic_init_vnic_resources(struct enic * enic)14779c067b84SDoug Ambrisko enic_init_vnic_resources(struct enic *enic)
14789c067b84SDoug Ambrisko {
14799c067b84SDoug Ambrisko 	unsigned int error_interrupt_enable = 1;
14809c067b84SDoug Ambrisko 	unsigned int error_interrupt_offset = 0;
14819c067b84SDoug Ambrisko 	unsigned int rxq_interrupt_enable = 0;
14829c067b84SDoug Ambrisko 	unsigned int rxq_interrupt_offset = ENICPMD_RXQ_INTR_OFFSET;
14839c067b84SDoug Ambrisko 	unsigned int txq_interrupt_enable = 0;
14849c067b84SDoug Ambrisko 	unsigned int txq_interrupt_offset = ENICPMD_RXQ_INTR_OFFSET;
14859c067b84SDoug Ambrisko 	unsigned int index = 0;
14869c067b84SDoug Ambrisko 	unsigned int cq_idx;
14879c067b84SDoug Ambrisko 	if_softc_ctx_t scctx;
14889c067b84SDoug Ambrisko 
14899c067b84SDoug Ambrisko 	scctx = enic->softc->scctx;
14909c067b84SDoug Ambrisko 
14919c067b84SDoug Ambrisko 
14929c067b84SDoug Ambrisko 	rxq_interrupt_enable = 1;
14939c067b84SDoug Ambrisko 	txq_interrupt_enable = 1;
14949c067b84SDoug Ambrisko 
14959c067b84SDoug Ambrisko 	rxq_interrupt_offset = 0;
14969c067b84SDoug Ambrisko 	txq_interrupt_offset = enic->intr_count - 2;
14979c067b84SDoug Ambrisko 	txq_interrupt_offset = 1;
14989c067b84SDoug Ambrisko 
14999c067b84SDoug Ambrisko 	for (index = 0; index < enic->intr_count; index++) {
15009c067b84SDoug Ambrisko 		vnic_intr_alloc(enic->vdev, &enic->intr[index], index);
15019c067b84SDoug Ambrisko 	}
15029c067b84SDoug Ambrisko 
15039c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_nrxqsets; index++) {
15049c067b84SDoug Ambrisko 		cq_idx = enic_cq_rq(enic, index);
15059c067b84SDoug Ambrisko 
15069c067b84SDoug Ambrisko 		vnic_rq_clean(&enic->rq[index]);
15079c067b84SDoug Ambrisko 		vnic_rq_init(&enic->rq[index], cq_idx, error_interrupt_enable,
15089c067b84SDoug Ambrisko 		    error_interrupt_offset);
15099c067b84SDoug Ambrisko 
15109c067b84SDoug Ambrisko 		vnic_cq_clean(&enic->cq[cq_idx]);
15119c067b84SDoug Ambrisko 		vnic_cq_init(&enic->cq[cq_idx],
15129c067b84SDoug Ambrisko 		    0 /* flow_control_enable */ ,
15139c067b84SDoug Ambrisko 		    1 /* color_enable */ ,
15149c067b84SDoug Ambrisko 		    0 /* cq_head */ ,
15159c067b84SDoug Ambrisko 		    0 /* cq_tail */ ,
15169c067b84SDoug Ambrisko 		    1 /* cq_tail_color */ ,
15179c067b84SDoug Ambrisko 		    rxq_interrupt_enable,
15189c067b84SDoug Ambrisko 		    1 /* cq_entry_enable */ ,
15199c067b84SDoug Ambrisko 		    0 /* cq_message_enable */ ,
15209c067b84SDoug Ambrisko 		    rxq_interrupt_offset,
15219c067b84SDoug Ambrisko 		    0 /* cq_message_addr */ );
15229c067b84SDoug Ambrisko 		if (rxq_interrupt_enable)
15239c067b84SDoug Ambrisko 			rxq_interrupt_offset++;
15249c067b84SDoug Ambrisko 	}
15259c067b84SDoug Ambrisko 
15269c067b84SDoug Ambrisko 	for (index = 0; index < scctx->isc_ntxqsets; index++) {
15279c067b84SDoug Ambrisko 		cq_idx = enic_cq_wq(enic, index);
15289c067b84SDoug Ambrisko 		vnic_wq_clean(&enic->wq[index]);
15299c067b84SDoug Ambrisko 		vnic_wq_init(&enic->wq[index], cq_idx, error_interrupt_enable,
15309c067b84SDoug Ambrisko 		    error_interrupt_offset);
15319c067b84SDoug Ambrisko 		/* Compute unsupported ol flags for enic_prep_pkts() */
15329c067b84SDoug Ambrisko 		enic->wq[index].tx_offload_notsup_mask = 0;
15339c067b84SDoug Ambrisko 
15349c067b84SDoug Ambrisko 		vnic_cq_clean(&enic->cq[cq_idx]);
15359c067b84SDoug Ambrisko 		vnic_cq_init(&enic->cq[cq_idx],
15369c067b84SDoug Ambrisko 		   0 /* flow_control_enable */ ,
15379c067b84SDoug Ambrisko 		   1 /* color_enable */ ,
15389c067b84SDoug Ambrisko 		   0 /* cq_head */ ,
15399c067b84SDoug Ambrisko 		   0 /* cq_tail */ ,
15409c067b84SDoug Ambrisko 		   1 /* cq_tail_color */ ,
15419c067b84SDoug Ambrisko 		   txq_interrupt_enable,
15429c067b84SDoug Ambrisko 		   1,
15439c067b84SDoug Ambrisko 		   0,
15449c067b84SDoug Ambrisko 		   txq_interrupt_offset,
15459c067b84SDoug Ambrisko 		   0 /* (u64)enic->wq[index].cqmsg_rz->iova */ );
15469c067b84SDoug Ambrisko 
15479c067b84SDoug Ambrisko 	}
15489c067b84SDoug Ambrisko 
15499c067b84SDoug Ambrisko 	for (index = 0; index < enic->intr_count; index++) {
15509c067b84SDoug Ambrisko 		vnic_intr_init(&enic->intr[index], 125,
15519c067b84SDoug Ambrisko 		    enic->config.intr_timer_type, /* mask_on_assertion */ 1);
15529c067b84SDoug Ambrisko 	}
15539c067b84SDoug Ambrisko }
15549c067b84SDoug Ambrisko 
15559c067b84SDoug Ambrisko static void
enic_update_packet_filter(struct enic * enic)15569c067b84SDoug Ambrisko enic_update_packet_filter(struct enic *enic)
15579c067b84SDoug Ambrisko {
15589c067b84SDoug Ambrisko 	struct enic_softc *softc = enic->softc;
15599c067b84SDoug Ambrisko 
15609c067b84SDoug Ambrisko 	ENIC_LOCK(softc);
15619c067b84SDoug Ambrisko 	vnic_dev_packet_filter(enic->vdev,
15629c067b84SDoug Ambrisko 	    softc->directed,
15639c067b84SDoug Ambrisko 	    softc->multicast,
15649c067b84SDoug Ambrisko 	    softc->broadcast,
15659c067b84SDoug Ambrisko 	    softc->promisc,
15669c067b84SDoug Ambrisko 	    softc->allmulti);
15679c067b84SDoug Ambrisko 	ENIC_UNLOCK(softc);
15689c067b84SDoug Ambrisko }
15699c067b84SDoug Ambrisko 
1570fe6c4e21SKevin Bowling static bool
enic_if_needs_restart(if_ctx_t ctx __unused,enum iflib_restart_event event)1571fe6c4e21SKevin Bowling enic_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event)
1572fe6c4e21SKevin Bowling {
1573fe6c4e21SKevin Bowling 	switch (event) {
1574fe6c4e21SKevin Bowling 	case IFLIB_RESTART_VLAN_CONFIG:
1575fe6c4e21SKevin Bowling 	default:
1576fe6c4e21SKevin Bowling 		return (false);
1577fe6c4e21SKevin Bowling 	}
1578fe6c4e21SKevin Bowling }
1579fe6c4e21SKevin Bowling 
15809c067b84SDoug Ambrisko int
enic_setup_finish(struct enic * enic)15819c067b84SDoug Ambrisko enic_setup_finish(struct enic *enic)
15829c067b84SDoug Ambrisko {
15839c067b84SDoug Ambrisko 	struct enic_softc *softc = enic->softc;
15849c067b84SDoug Ambrisko 
15859c067b84SDoug Ambrisko 	/* Default conf */
15869c067b84SDoug Ambrisko 	softc->directed = 1;
15879c067b84SDoug Ambrisko 	softc->multicast = 0;
15889c067b84SDoug Ambrisko 	softc->broadcast = 1;
15899c067b84SDoug Ambrisko 	softc->promisc = 0;
1590*f830db48Srilysh 	softc->allmulti = 1;
15919c067b84SDoug Ambrisko 	enic_update_packet_filter(enic);
15929c067b84SDoug Ambrisko 
15939c067b84SDoug Ambrisko 	return 0;
15949c067b84SDoug Ambrisko }
1595