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, 204*0acab8b3SDoug Ambrisko .isc_admin_intrcnt = 2, 2059c067b84SDoug Ambrisko .isc_vendor_info = enic_vendor_info_array, 2069c067b84SDoug Ambrisko .isc_driver_version = "1", 2079c067b84SDoug Ambrisko .isc_driver = &enic_iflib_driver, 208*0acab8b3SDoug Ambrisko .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ | IFLIB_SKIP_MSIX, 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 * 2339c067b84SDoug Ambrisko enic_register(device_t dev) 2349c067b84SDoug Ambrisko { 2359c067b84SDoug Ambrisko return (&enic_sctx_init); 2369c067b84SDoug Ambrisko } 2379c067b84SDoug Ambrisko 2389c067b84SDoug Ambrisko static int 239*0acab8b3SDoug Ambrisko enic_allocate_msix(struct enic_softc *softc) { 240*0acab8b3SDoug Ambrisko if_ctx_t ctx; 241*0acab8b3SDoug Ambrisko if_softc_ctx_t scctx; 242*0acab8b3SDoug Ambrisko if_shared_ctx_t sctx; 243*0acab8b3SDoug Ambrisko device_t dev; 244*0acab8b3SDoug Ambrisko cpuset_t cpus; 245*0acab8b3SDoug Ambrisko int queues, vectors, requested; 246*0acab8b3SDoug Ambrisko int err = 0; 247*0acab8b3SDoug Ambrisko 248*0acab8b3SDoug Ambrisko dev = softc->dev; 249*0acab8b3SDoug Ambrisko ctx = softc->ctx; 250*0acab8b3SDoug Ambrisko scctx = softc->scctx; 251*0acab8b3SDoug Ambrisko sctx = iflib_get_sctx(ctx); 252*0acab8b3SDoug Ambrisko 253*0acab8b3SDoug Ambrisko if (bus_get_cpus(dev, INTR_CPUS, sizeof(cpus), &cpus) != 0) { 254*0acab8b3SDoug Ambrisko device_printf(dev, "Unable to fetch CPU list\n"); 255*0acab8b3SDoug Ambrisko CPU_COPY(&all_cpus, &cpus); 256*0acab8b3SDoug Ambrisko } 257*0acab8b3SDoug Ambrisko 258*0acab8b3SDoug Ambrisko 259*0acab8b3SDoug Ambrisko queues = CPU_COUNT(&cpus); 260*0acab8b3SDoug Ambrisko queues = imin(queues, scctx->isc_nrxqsets); 261*0acab8b3SDoug Ambrisko queues = imin(queues, scctx->isc_ntxqsets); 262*0acab8b3SDoug Ambrisko requested = queues * 2 + sctx->isc_admin_intrcnt; 263*0acab8b3SDoug Ambrisko scctx->isc_nrxqsets = queues; 264*0acab8b3SDoug Ambrisko scctx->isc_ntxqsets = queues; 265*0acab8b3SDoug Ambrisko 266*0acab8b3SDoug Ambrisko vectors = requested; 267*0acab8b3SDoug Ambrisko if ((err = pci_alloc_msix(dev, &vectors)) != 0) { 268*0acab8b3SDoug Ambrisko device_printf(dev, 269*0acab8b3SDoug Ambrisko "failed to allocate %d MSI-X vectors, err: %d\n", requested, 270*0acab8b3SDoug Ambrisko err); 271*0acab8b3SDoug Ambrisko err = 1; 272*0acab8b3SDoug Ambrisko goto enic_allocate_msix_out; 273*0acab8b3SDoug Ambrisko } else { 274*0acab8b3SDoug Ambrisko if (vectors != requested) { 275*0acab8b3SDoug Ambrisko device_printf(dev, 276*0acab8b3SDoug Ambrisko "Unable to allocate sufficient MSI-X vectors " 277*0acab8b3SDoug Ambrisko "(got %d, need %d)\n", requested, vectors); 278*0acab8b3SDoug Ambrisko pci_release_msi(dev); 279*0acab8b3SDoug Ambrisko err = 1; 280*0acab8b3SDoug Ambrisko goto enic_allocate_msix_out; 281*0acab8b3SDoug Ambrisko } 282*0acab8b3SDoug Ambrisko } 283*0acab8b3SDoug Ambrisko 284*0acab8b3SDoug Ambrisko device_printf(dev, "Using MSI-X interrupts with %d vectors\n", 285*0acab8b3SDoug Ambrisko vectors); 286*0acab8b3SDoug Ambrisko 287*0acab8b3SDoug Ambrisko scctx->isc_intr = IFLIB_INTR_MSIX; 288*0acab8b3SDoug Ambrisko scctx->isc_vectors = vectors; 289*0acab8b3SDoug Ambrisko 290*0acab8b3SDoug Ambrisko enic_allocate_msix_out: 291*0acab8b3SDoug Ambrisko return (err); 292*0acab8b3SDoug Ambrisko 293*0acab8b3SDoug Ambrisko } 294*0acab8b3SDoug Ambrisko 295*0acab8b3SDoug Ambrisko static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = { 296*0acab8b3SDoug Ambrisko {0, 0}, /* 0 - 4 Gbps */ 297*0acab8b3SDoug Ambrisko {0, 3}, /* 4 - 10 Gbps */ 298*0acab8b3SDoug Ambrisko {3, 6}, /* 10 - 40 Gbps */ 299*0acab8b3SDoug Ambrisko }; 300*0acab8b3SDoug Ambrisko 301*0acab8b3SDoug Ambrisko static void enic_set_rx_coal_setting(struct enic *enic) 302*0acab8b3SDoug Ambrisko { 303*0acab8b3SDoug Ambrisko unsigned int speed; 304*0acab8b3SDoug Ambrisko int index = -1; 305*0acab8b3SDoug Ambrisko struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting; 306*0acab8b3SDoug Ambrisko 307*0acab8b3SDoug Ambrisko /* 1. Read the link speed from fw 308*0acab8b3SDoug Ambrisko * 2. Pick the default range for the speed 309*0acab8b3SDoug Ambrisko * 3. Update it in enic->rx_coalesce_setting 310*0acab8b3SDoug Ambrisko */ 311*0acab8b3SDoug Ambrisko speed = vnic_dev_port_speed(enic->vdev); 312*0acab8b3SDoug Ambrisko if (ENIC_LINK_SPEED_10G < speed) 313*0acab8b3SDoug Ambrisko index = ENIC_LINK_40G_INDEX; 314*0acab8b3SDoug Ambrisko else if (ENIC_LINK_SPEED_4G < speed) 315*0acab8b3SDoug Ambrisko index = ENIC_LINK_10G_INDEX; 316*0acab8b3SDoug Ambrisko else 317*0acab8b3SDoug Ambrisko index = ENIC_LINK_4G_INDEX; 318*0acab8b3SDoug Ambrisko 319*0acab8b3SDoug Ambrisko rx_coal->small_pkt_range_start = mod_range[index].small_pkt_range_start; 320*0acab8b3SDoug Ambrisko rx_coal->large_pkt_range_start = mod_range[index].large_pkt_range_start; 321*0acab8b3SDoug Ambrisko rx_coal->range_end = ENIC_RX_COALESCE_RANGE_END; 322*0acab8b3SDoug Ambrisko 323*0acab8b3SDoug Ambrisko /* Start with the value provided by UCSM */ 324*0acab8b3SDoug Ambrisko for (index = 0; index < enic->rq_count; index++) 325*0acab8b3SDoug Ambrisko enic->cq[index].cur_rx_coal_timeval = 326*0acab8b3SDoug Ambrisko enic->config.intr_timer_usec; 327*0acab8b3SDoug Ambrisko 328*0acab8b3SDoug Ambrisko rx_coal->use_adaptive_rx_coalesce = 1; 329*0acab8b3SDoug Ambrisko } 330*0acab8b3SDoug Ambrisko 331*0acab8b3SDoug Ambrisko static int 3329c067b84SDoug Ambrisko enic_attach_pre(if_ctx_t ctx) 3339c067b84SDoug Ambrisko { 3349c067b84SDoug Ambrisko if_softc_ctx_t scctx; 3359c067b84SDoug Ambrisko struct enic_softc *softc; 3369c067b84SDoug Ambrisko struct vnic_dev *vdev; 3379c067b84SDoug Ambrisko struct enic *enic; 3389c067b84SDoug Ambrisko device_t dev; 3399c067b84SDoug Ambrisko 3409c067b84SDoug Ambrisko int err = -1; 3419c067b84SDoug Ambrisko int rc = 0; 3429c067b84SDoug Ambrisko int i; 3439c067b84SDoug Ambrisko u64 a0 = 0, a1 = 0; 3449c067b84SDoug Ambrisko int wait = 1000; 3459c067b84SDoug Ambrisko struct vnic_stats *stats; 3469c067b84SDoug Ambrisko int ret; 3479c067b84SDoug Ambrisko 3489c067b84SDoug Ambrisko dev = iflib_get_dev(ctx); 3499c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 3509c067b84SDoug Ambrisko softc->dev = dev; 3519c067b84SDoug Ambrisko softc->ctx = ctx; 3529c067b84SDoug Ambrisko softc->sctx = iflib_get_sctx(ctx); 3539c067b84SDoug Ambrisko softc->scctx = iflib_get_softc_ctx(ctx); 3549c067b84SDoug Ambrisko softc->ifp = iflib_get_ifp(ctx); 3559c067b84SDoug Ambrisko softc->media = iflib_get_media(ctx); 3569c067b84SDoug Ambrisko softc->mta = malloc(sizeof(u8) * ETHER_ADDR_LEN * 3579c067b84SDoug Ambrisko ENIC_MAX_MULTICAST_ADDRESSES, M_DEVBUF, 3589c067b84SDoug Ambrisko M_NOWAIT | M_ZERO); 3599c067b84SDoug Ambrisko if (softc->mta == NULL) 3609c067b84SDoug Ambrisko return (ENOMEM); 3619c067b84SDoug Ambrisko scctx = softc->scctx; 3629c067b84SDoug Ambrisko 3639c067b84SDoug Ambrisko mtx_init(&softc->enic_lock, "ENIC Lock", NULL, MTX_DEF); 3649c067b84SDoug Ambrisko 3659c067b84SDoug Ambrisko pci_enable_busmaster(softc->dev); 3669c067b84SDoug Ambrisko if (enic_pci_mapping(softc)) 3679c067b84SDoug Ambrisko return (ENXIO); 3689c067b84SDoug Ambrisko 3699c067b84SDoug Ambrisko enic = &softc->enic; 3709c067b84SDoug Ambrisko enic->softc = softc; 3719c067b84SDoug Ambrisko vdev = &softc->vdev; 3729c067b84SDoug Ambrisko vdev->softc = softc; 3739c067b84SDoug Ambrisko enic->vdev = vdev; 3749c067b84SDoug Ambrisko vdev->priv = enic; 3759c067b84SDoug Ambrisko 3769c067b84SDoug Ambrisko ENIC_LOCK(softc); 3779c067b84SDoug Ambrisko vnic_dev_register(vdev, &softc->mem, 1); 3789c067b84SDoug Ambrisko enic->vdev = vdev; 379*0acab8b3SDoug Ambrisko vnic_dev_cmd_init(enic->vdev); 380*0acab8b3SDoug Ambrisko 3819c067b84SDoug Ambrisko vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0); 3829c067b84SDoug Ambrisko 3839c067b84SDoug Ambrisko vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); 3849c067b84SDoug Ambrisko vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait); 3859c067b84SDoug Ambrisko 3869c067b84SDoug Ambrisko bcopy((u_int8_t *) & a0, softc->mac_addr, ETHER_ADDR_LEN); 3879c067b84SDoug Ambrisko iflib_set_mac(ctx, softc->mac_addr); 3889c067b84SDoug Ambrisko 3899c067b84SDoug Ambrisko vnic_register_cbacks(enic->vdev, enic_alloc_consistent, 3909c067b84SDoug Ambrisko enic_free_consistent); 3919c067b84SDoug Ambrisko 3929c067b84SDoug Ambrisko /* 3939c067b84SDoug Ambrisko * Allocate the consistent memory for stats and counters upfront so 3949c067b84SDoug Ambrisko * both primary and secondary processes can access them. 3959c067b84SDoug Ambrisko */ 3969c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 3979c067b84SDoug Ambrisko err = vnic_dev_alloc_stats_mem(enic->vdev); 3989c067b84SDoug Ambrisko ENIC_LOCK(softc); 3999c067b84SDoug Ambrisko if (err) { 4009c067b84SDoug Ambrisko dev_err(enic, "Failed to allocate cmd memory, aborting\n"); 4019c067b84SDoug Ambrisko goto err_out_unregister; 4029c067b84SDoug Ambrisko } 4039c067b84SDoug Ambrisko vnic_dev_stats_clear(enic->vdev); 4049c067b84SDoug Ambrisko ret = vnic_dev_stats_dump(enic->vdev, &stats); 4059c067b84SDoug Ambrisko if (ret) { 4069c067b84SDoug Ambrisko dev_err(enic, "Error in getting stats\n"); 4079c067b84SDoug Ambrisko goto err_out_unregister; 4089c067b84SDoug Ambrisko } 4099c067b84SDoug Ambrisko err = vnic_dev_alloc_counter_mem(enic->vdev); 4109c067b84SDoug Ambrisko if (err) { 4119c067b84SDoug Ambrisko dev_err(enic, "Failed to allocate counter memory, aborting\n"); 4129c067b84SDoug Ambrisko goto err_out_unregister; 4139c067b84SDoug Ambrisko } 4149c067b84SDoug Ambrisko 4159c067b84SDoug Ambrisko /* Issue device open to get device in known state */ 4169c067b84SDoug Ambrisko err = enic_dev_open(enic); 4179c067b84SDoug Ambrisko if (err) { 4189c067b84SDoug Ambrisko dev_err(enic, "vNIC dev open failed, aborting\n"); 4199c067b84SDoug Ambrisko goto err_out_unregister; 4209c067b84SDoug Ambrisko } 4219c067b84SDoug Ambrisko 4229c067b84SDoug Ambrisko /* Set ingress vlan rewrite mode before vnic initialization */ 4239c067b84SDoug Ambrisko enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN; 424*0acab8b3SDoug Ambrisko enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN; 4259c067b84SDoug Ambrisko err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev, 4269c067b84SDoug Ambrisko enic->ig_vlan_rewrite_mode); 4279c067b84SDoug Ambrisko if (err) { 4289c067b84SDoug Ambrisko dev_err(enic, 4299c067b84SDoug Ambrisko "Failed to set ingress vlan rewrite mode, aborting.\n"); 4309c067b84SDoug Ambrisko goto err_out_dev_close; 4319c067b84SDoug Ambrisko } 4329c067b84SDoug Ambrisko 4339c067b84SDoug Ambrisko /* 4349c067b84SDoug Ambrisko * Issue device init to initialize the vnic-to-switch link. We'll 4359c067b84SDoug Ambrisko * start with carrier off and wait for link UP notification later to 4369c067b84SDoug Ambrisko * turn on carrier. We don't need to wait here for the 4379c067b84SDoug Ambrisko * vnic-to-switch link initialization to complete; link UP 4389c067b84SDoug Ambrisko * notification is the indication that the process is complete. 4399c067b84SDoug Ambrisko */ 4409c067b84SDoug Ambrisko 4419c067b84SDoug Ambrisko err = vnic_dev_init(enic->vdev, 0); 4429c067b84SDoug Ambrisko if (err) { 4439c067b84SDoug Ambrisko dev_err(enic, "vNIC dev init failed, aborting\n"); 4449c067b84SDoug Ambrisko goto err_out_dev_close; 4459c067b84SDoug Ambrisko } 4469c067b84SDoug Ambrisko 4479c067b84SDoug Ambrisko err = enic_dev_init(enic); 4489c067b84SDoug Ambrisko if (err) { 4499c067b84SDoug Ambrisko dev_err(enic, "Device initialization failed, aborting\n"); 4509c067b84SDoug Ambrisko goto err_out_dev_close; 4519c067b84SDoug Ambrisko } 4529c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 4539c067b84SDoug Ambrisko 4549c067b84SDoug Ambrisko enic->port_mtu = vnic_dev_mtu(enic->vdev); 4559c067b84SDoug Ambrisko 4569c067b84SDoug Ambrisko softc->scctx = iflib_get_softc_ctx(ctx); 4579c067b84SDoug Ambrisko scctx = softc->scctx; 4589c067b84SDoug Ambrisko scctx->isc_txrx = &enic_txrx; 459*0acab8b3SDoug Ambrisko scctx->isc_capabilities = scctx->isc_capenable = \ 460*0acab8b3SDoug Ambrisko IFCAP_HWCSUM; 4619c067b84SDoug Ambrisko scctx->isc_tx_csum_flags = 0; 462*0acab8b3SDoug Ambrisko if_setmtu(softc->ifp, enic->config.mtu); 4639c067b84SDoug Ambrisko scctx->isc_max_frame_size = enic->config.mtu + ETHER_HDR_LEN + \ 4649c067b84SDoug Ambrisko ETHER_CRC_LEN; 4659c067b84SDoug Ambrisko scctx->isc_nrxqsets_max = enic->conf_rq_count; 4669c067b84SDoug Ambrisko scctx->isc_ntxqsets_max = enic->conf_wq_count; 4679c067b84SDoug Ambrisko scctx->isc_nrxqsets = enic->conf_rq_count; 4689c067b84SDoug Ambrisko scctx->isc_ntxqsets = enic->conf_wq_count; 4699c067b84SDoug Ambrisko for (i = 0; i < enic->conf_wq_count; i++) { 4709c067b84SDoug Ambrisko scctx->isc_ntxd[i] = enic->config.wq_desc_count; 4719c067b84SDoug Ambrisko scctx->isc_txqsizes[i] = sizeof(struct cq_enet_wq_desc) 4729c067b84SDoug Ambrisko * scctx->isc_ntxd[i]; 4739c067b84SDoug Ambrisko scctx->isc_ntxd[i + enic->conf_wq_count] = 4749c067b84SDoug Ambrisko enic->config.wq_desc_count; 4759c067b84SDoug Ambrisko scctx->isc_txqsizes[i + enic->conf_wq_count] = 4769c067b84SDoug Ambrisko sizeof(struct cq_desc) * scctx->isc_ntxd[i + 4779c067b84SDoug Ambrisko enic->conf_wq_count]; 4789c067b84SDoug Ambrisko } 4799c067b84SDoug Ambrisko for (i = 0; i < enic->conf_rq_count; i++) { 4809c067b84SDoug Ambrisko scctx->isc_nrxd[i] = enic->config.rq_desc_count; 4819c067b84SDoug Ambrisko scctx->isc_rxqsizes[i] = sizeof(struct cq_enet_rq_desc) * 4829c067b84SDoug Ambrisko scctx->isc_nrxd[i]; 4839c067b84SDoug Ambrisko scctx->isc_nrxd[i + enic->conf_rq_count] = 4849c067b84SDoug Ambrisko enic->config.rq_desc_count; 4859c067b84SDoug Ambrisko scctx->isc_rxqsizes[i + enic->conf_rq_count] = sizeof(struct 4869c067b84SDoug Ambrisko cq_desc) * scctx->isc_nrxd[i + enic->conf_rq_count]; 4879c067b84SDoug Ambrisko } 4889c067b84SDoug Ambrisko scctx->isc_tx_nsegments = 31; 4899c067b84SDoug Ambrisko 4909c067b84SDoug Ambrisko scctx->isc_msix_bar = -1; 4919c067b84SDoug Ambrisko 4929c067b84SDoug Ambrisko ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); 4939c067b84SDoug Ambrisko ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0, NULL); 4949c067b84SDoug Ambrisko ifmedia_add(softc->media, IFM_ETHER | IFM_10_FL, 0, NULL); 4959c067b84SDoug Ambrisko 4969c067b84SDoug Ambrisko /* 4979c067b84SDoug Ambrisko * Allocate the CQ here since TX is called first before RX for now 4989c067b84SDoug Ambrisko * assume RX and TX are the same 4999c067b84SDoug Ambrisko */ 5009c067b84SDoug Ambrisko if (softc->enic.cq == NULL) 5019c067b84SDoug Ambrisko softc->enic.cq = malloc(sizeof(struct vnic_cq) * 5029c067b84SDoug Ambrisko softc->enic.wq_count + softc->enic.rq_count, M_DEVBUF, 5039c067b84SDoug Ambrisko M_NOWAIT | M_ZERO); 5049c067b84SDoug Ambrisko if (softc->enic.cq == NULL) 5059c067b84SDoug Ambrisko return (ENOMEM); 5069c067b84SDoug Ambrisko 5079c067b84SDoug Ambrisko softc->enic.cq->ntxqsets = softc->enic.wq_count + softc->enic.rq_count; 5089c067b84SDoug Ambrisko 5099c067b84SDoug Ambrisko /* 5109c067b84SDoug Ambrisko * Allocate the consistent memory for stats and counters upfront so 5119c067b84SDoug Ambrisko * both primary and secondary processes can access them. 5129c067b84SDoug Ambrisko */ 5139c067b84SDoug Ambrisko err = vnic_dev_alloc_stats_mem(enic->vdev); 5149c067b84SDoug Ambrisko if (err) { 5159c067b84SDoug Ambrisko dev_err(enic, "Failed to allocate cmd memory, aborting\n"); 516*0acab8b3SDoug Ambrisko goto err_out_dev_close; 517*0acab8b3SDoug Ambrisko } 518*0acab8b3SDoug Ambrisko 519*0acab8b3SDoug Ambrisko err = enic_allocate_msix(softc); 520*0acab8b3SDoug Ambrisko if (err) { 521*0acab8b3SDoug Ambrisko dev_err(enic, "Failed to allocate MSIX, aborting\n"); 522*0acab8b3SDoug Ambrisko goto err_out_dev_close; 5239c067b84SDoug Ambrisko } 5249c067b84SDoug Ambrisko 5259c067b84SDoug Ambrisko return (rc); 5269c067b84SDoug Ambrisko 5279c067b84SDoug Ambrisko err_out_dev_close: 5289c067b84SDoug Ambrisko vnic_dev_close(enic->vdev); 529*0acab8b3SDoug Ambrisko vnic_dev_deinit_devcmd2(enic->vdev); 5309c067b84SDoug Ambrisko err_out_unregister: 5319c067b84SDoug Ambrisko free(softc->vdev.devcmd, M_DEVBUF); 5329c067b84SDoug Ambrisko free(softc->enic.intr_queues, M_DEVBUF); 5339c067b84SDoug Ambrisko free(softc->enic.cq, M_DEVBUF); 5349c067b84SDoug Ambrisko free(softc->mta, M_DEVBUF); 5359c067b84SDoug Ambrisko rc = -1; 5369c067b84SDoug Ambrisko pci_disable_busmaster(softc->dev); 5379c067b84SDoug Ambrisko enic_pci_mapping_free(softc); 5389c067b84SDoug Ambrisko mtx_destroy(&softc->enic_lock); 5399c067b84SDoug Ambrisko return (rc); 5409c067b84SDoug Ambrisko } 5419c067b84SDoug Ambrisko 5429c067b84SDoug Ambrisko static int 5439c067b84SDoug Ambrisko enic_msix_intr_assign(if_ctx_t ctx, int msix) 5449c067b84SDoug Ambrisko { 5459c067b84SDoug Ambrisko struct enic_softc *softc; 5469c067b84SDoug Ambrisko struct enic *enic; 5479c067b84SDoug Ambrisko if_softc_ctx_t scctx; 5489c067b84SDoug Ambrisko 5499c067b84SDoug Ambrisko int error; 5509c067b84SDoug Ambrisko int i; 5519c067b84SDoug Ambrisko char irq_name[16]; 5529c067b84SDoug Ambrisko 5539c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 5549c067b84SDoug Ambrisko enic = &softc->enic; 5559c067b84SDoug Ambrisko scctx = softc->scctx; 5569c067b84SDoug Ambrisko 5579c067b84SDoug Ambrisko ENIC_LOCK(softc); 5589c067b84SDoug Ambrisko vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX); 5599c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 5609c067b84SDoug Ambrisko 5619c067b84SDoug Ambrisko enic->intr_queues = malloc(sizeof(*enic->intr_queues) * 5629c067b84SDoug Ambrisko enic->conf_intr_count, M_DEVBUF, M_NOWAIT | M_ZERO); 5639c067b84SDoug Ambrisko enic->intr = malloc(sizeof(*enic->intr) * msix, M_DEVBUF, M_NOWAIT 5649c067b84SDoug Ambrisko | M_ZERO); 5659c067b84SDoug Ambrisko for (i = 0; i < scctx->isc_nrxqsets; i++) { 5669c067b84SDoug Ambrisko snprintf(irq_name, sizeof(irq_name), "erxq%d:%d", i, 5679c067b84SDoug Ambrisko device_get_unit(softc->dev)); 5689c067b84SDoug Ambrisko 5699c067b84SDoug Ambrisko error = iflib_irq_alloc_generic(ctx, 5709c067b84SDoug Ambrisko &enic->intr_queues[i].intr_irq, i + 1, IFLIB_INTR_RX, 5719c067b84SDoug Ambrisko enic_rxq_intr, &enic->rq[i], i, irq_name); 5729c067b84SDoug Ambrisko if (error) { 5739c067b84SDoug Ambrisko device_printf(iflib_get_dev(ctx), 5749c067b84SDoug Ambrisko "Failed to register rxq %d interrupt handler\n", i); 5759c067b84SDoug Ambrisko return (error); 5769c067b84SDoug Ambrisko } 5779c067b84SDoug Ambrisko enic->intr[i].index = i; 5789c067b84SDoug Ambrisko enic->intr[i].vdev = enic->vdev; 5799c067b84SDoug Ambrisko ENIC_LOCK(softc); 5809c067b84SDoug Ambrisko enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev, 5819c067b84SDoug Ambrisko RES_TYPE_INTR_CTRL, i); 5829c067b84SDoug Ambrisko vnic_intr_mask(&enic->intr[i]); 5839c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 5849c067b84SDoug Ambrisko } 5859c067b84SDoug Ambrisko 5869c067b84SDoug Ambrisko for (i = scctx->isc_nrxqsets; i < scctx->isc_nrxqsets + scctx->isc_ntxqsets; i++) { 5879c067b84SDoug Ambrisko snprintf(irq_name, sizeof(irq_name), "etxq%d:%d", i - 5889c067b84SDoug Ambrisko scctx->isc_nrxqsets, device_get_unit(softc->dev)); 5899c067b84SDoug Ambrisko 590*0acab8b3SDoug Ambrisko iflib_softirq_alloc_generic(ctx, 591*0acab8b3SDoug Ambrisko &enic->intr_queues[i].intr_irq, IFLIB_INTR_TX, 592*0acab8b3SDoug Ambrisko &enic->wq[i - scctx->isc_nrxqsets], i - scctx->isc_nrxqsets, 593*0acab8b3SDoug Ambrisko irq_name); 5949c067b84SDoug Ambrisko 5959c067b84SDoug Ambrisko enic->intr[i].index = i; 5969c067b84SDoug Ambrisko enic->intr[i].vdev = enic->vdev; 5979c067b84SDoug Ambrisko ENIC_LOCK(softc); 5989c067b84SDoug Ambrisko enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev, 5999c067b84SDoug Ambrisko RES_TYPE_INTR_CTRL, i); 6009c067b84SDoug Ambrisko vnic_intr_mask(&enic->intr[i]); 6019c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 6029c067b84SDoug Ambrisko } 6039c067b84SDoug Ambrisko 6049c067b84SDoug Ambrisko i = scctx->isc_nrxqsets + scctx->isc_ntxqsets; 6059c067b84SDoug Ambrisko error = iflib_irq_alloc_generic(ctx, &softc->enic_event_intr_irq, 6069c067b84SDoug Ambrisko i + 1, IFLIB_INTR_ADMIN, enic_event_intr, softc, 0, "event"); 6079c067b84SDoug Ambrisko if (error) { 6089c067b84SDoug Ambrisko device_printf(iflib_get_dev(ctx), 6099c067b84SDoug Ambrisko "Failed to register event interrupt handler\n"); 6109c067b84SDoug Ambrisko return (error); 6119c067b84SDoug Ambrisko } 6129c067b84SDoug Ambrisko 6139c067b84SDoug Ambrisko enic->intr[i].index = i; 6149c067b84SDoug Ambrisko enic->intr[i].vdev = enic->vdev; 6159c067b84SDoug Ambrisko ENIC_LOCK(softc); 6169c067b84SDoug Ambrisko enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev, RES_TYPE_INTR_CTRL, 6179c067b84SDoug Ambrisko i); 6189c067b84SDoug Ambrisko vnic_intr_mask(&enic->intr[i]); 6199c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 6209c067b84SDoug Ambrisko 6219c067b84SDoug Ambrisko i++; 6229c067b84SDoug Ambrisko error = iflib_irq_alloc_generic(ctx, &softc->enic_err_intr_irq, 6239c067b84SDoug Ambrisko i + 1, IFLIB_INTR_ADMIN, enic_err_intr, softc, 0, "err"); 6249c067b84SDoug Ambrisko if (error) { 6259c067b84SDoug Ambrisko device_printf(iflib_get_dev(ctx), 6269c067b84SDoug Ambrisko "Failed to register event interrupt handler\n"); 6279c067b84SDoug Ambrisko return (error); 6289c067b84SDoug Ambrisko } 6299c067b84SDoug Ambrisko enic->intr[i].index = i; 6309c067b84SDoug Ambrisko enic->intr[i].vdev = enic->vdev; 6319c067b84SDoug Ambrisko ENIC_LOCK(softc); 6329c067b84SDoug Ambrisko enic->intr[i].ctrl = vnic_dev_get_res(enic->vdev, RES_TYPE_INTR_CTRL, 6339c067b84SDoug Ambrisko i); 6349c067b84SDoug Ambrisko vnic_intr_mask(&enic->intr[i]); 6359c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 6369c067b84SDoug Ambrisko 6379c067b84SDoug Ambrisko enic->intr_count = msix; 6389c067b84SDoug Ambrisko 6399c067b84SDoug Ambrisko return (0); 6409c067b84SDoug Ambrisko } 6419c067b84SDoug Ambrisko 6429c067b84SDoug Ambrisko static void 6439c067b84SDoug Ambrisko enic_free_irqs(struct enic_softc *softc) 6449c067b84SDoug Ambrisko { 6459c067b84SDoug Ambrisko if_softc_ctx_t scctx; 6469c067b84SDoug Ambrisko 6479c067b84SDoug Ambrisko struct enic *enic; 6489c067b84SDoug Ambrisko int i; 6499c067b84SDoug Ambrisko 6509c067b84SDoug Ambrisko scctx = softc->scctx; 6519c067b84SDoug Ambrisko enic = &softc->enic; 6529c067b84SDoug Ambrisko 6539c067b84SDoug Ambrisko for (i = 0; i < scctx->isc_nrxqsets + scctx->isc_ntxqsets; i++) { 6549c067b84SDoug Ambrisko iflib_irq_free(softc->ctx, &enic->intr_queues[i].intr_irq); 6559c067b84SDoug Ambrisko } 6569c067b84SDoug Ambrisko 6579c067b84SDoug Ambrisko iflib_irq_free(softc->ctx, &softc->enic_event_intr_irq); 6589c067b84SDoug Ambrisko iflib_irq_free(softc->ctx, &softc->enic_err_intr_irq); 6599c067b84SDoug Ambrisko free(enic->intr_queues, M_DEVBUF); 6609c067b84SDoug Ambrisko free(enic->intr, M_DEVBUF); 6619c067b84SDoug Ambrisko } 6629c067b84SDoug Ambrisko 6639c067b84SDoug Ambrisko static int 6649c067b84SDoug Ambrisko enic_attach_post(if_ctx_t ctx) 6659c067b84SDoug Ambrisko { 6669c067b84SDoug Ambrisko struct enic *enic; 6679c067b84SDoug Ambrisko struct enic_softc *softc; 6689c067b84SDoug Ambrisko int error = 0; 6699c067b84SDoug Ambrisko 6709c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 6719c067b84SDoug Ambrisko enic = &softc->enic; 6729c067b84SDoug Ambrisko 6739c067b84SDoug Ambrisko enic_setup_sysctl(softc); 6749c067b84SDoug Ambrisko 6759c067b84SDoug Ambrisko enic_init_vnic_resources(enic); 676*0acab8b3SDoug Ambrisko enic_set_rx_coal_setting(enic); 6779c067b84SDoug Ambrisko enic_setup_finish(enic); 6789c067b84SDoug Ambrisko 6799c067b84SDoug Ambrisko ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); 6809c067b84SDoug Ambrisko ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); 6819c067b84SDoug Ambrisko 6829c067b84SDoug Ambrisko return (error); 6839c067b84SDoug Ambrisko } 6849c067b84SDoug Ambrisko 6859c067b84SDoug Ambrisko static int 6869c067b84SDoug Ambrisko enic_detach(if_ctx_t ctx) 6879c067b84SDoug Ambrisko { 6889c067b84SDoug Ambrisko struct enic_softc *softc; 6899c067b84SDoug Ambrisko struct enic *enic; 6909c067b84SDoug Ambrisko 6919c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 6929c067b84SDoug Ambrisko enic = &softc->enic; 6939c067b84SDoug Ambrisko 6949c067b84SDoug Ambrisko vnic_dev_notify_unset(enic->vdev); 6959c067b84SDoug Ambrisko 6969c067b84SDoug Ambrisko enic_free_irqs(softc); 6979c067b84SDoug Ambrisko 6989c067b84SDoug Ambrisko ENIC_LOCK(softc); 699*0acab8b3SDoug Ambrisko vnic_dev_deinit(enic->vdev); 7009c067b84SDoug Ambrisko vnic_dev_close(enic->vdev); 701*0acab8b3SDoug Ambrisko vnic_dev_deinit_devcmd2(enic->vdev); 7029c067b84SDoug Ambrisko free(softc->vdev.devcmd, M_DEVBUF); 7039c067b84SDoug Ambrisko pci_disable_busmaster(softc->dev); 7049c067b84SDoug Ambrisko enic_pci_mapping_free(softc); 7059c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 7069c067b84SDoug Ambrisko 7079c067b84SDoug Ambrisko return 0; 7089c067b84SDoug Ambrisko } 7099c067b84SDoug Ambrisko 7109c067b84SDoug Ambrisko static int 7119c067b84SDoug Ambrisko enic_tx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs, 7129c067b84SDoug Ambrisko int ntxqs, int ntxqsets) 7139c067b84SDoug Ambrisko { 7149c067b84SDoug Ambrisko struct enic_softc *softc; 7159c067b84SDoug Ambrisko int q; 7169c067b84SDoug Ambrisko 7179c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 7189c067b84SDoug Ambrisko /* Allocate the array of transmit queues */ 7199c067b84SDoug Ambrisko softc->enic.wq = malloc(sizeof(struct vnic_wq) * 7209c067b84SDoug Ambrisko ntxqsets, M_DEVBUF, M_NOWAIT | M_ZERO); 7219c067b84SDoug Ambrisko if (softc->enic.wq == NULL) 7229c067b84SDoug Ambrisko return (ENOMEM); 7239c067b84SDoug Ambrisko 7249c067b84SDoug Ambrisko /* Initialize driver state for each transmit queue */ 7259c067b84SDoug Ambrisko 7269c067b84SDoug Ambrisko /* 7279c067b84SDoug Ambrisko * Allocate queue state that is shared with the device. This check 7289c067b84SDoug Ambrisko * and call is performed in both enic_tx_queues_alloc() and 7299c067b84SDoug Ambrisko * enic_rx_queues_alloc() so that we don't have to care which order 7309c067b84SDoug Ambrisko * iflib invokes those routines in. 7319c067b84SDoug Ambrisko */ 7329c067b84SDoug Ambrisko 7339c067b84SDoug Ambrisko /* Record descriptor ring vaddrs and paddrs */ 7349c067b84SDoug Ambrisko ENIC_LOCK(softc); 7359c067b84SDoug Ambrisko for (q = 0; q < ntxqsets; q++) { 7369c067b84SDoug Ambrisko struct vnic_wq *wq; 7379c067b84SDoug Ambrisko struct vnic_cq *cq; 7389c067b84SDoug Ambrisko unsigned int cq_wq; 7399c067b84SDoug Ambrisko 7409c067b84SDoug Ambrisko wq = &softc->enic.wq[q]; 7419c067b84SDoug Ambrisko cq_wq = enic_cq_wq(&softc->enic, q); 7429c067b84SDoug Ambrisko cq = &softc->enic.cq[cq_wq]; 7439c067b84SDoug Ambrisko 7449c067b84SDoug Ambrisko /* Completion ring */ 7459c067b84SDoug Ambrisko wq->vdev = softc->enic.vdev; 7469c067b84SDoug Ambrisko wq->index = q; 7479c067b84SDoug Ambrisko wq->ctrl = vnic_dev_get_res(softc->enic.vdev, RES_TYPE_WQ, 7489c067b84SDoug Ambrisko wq->index); 7499c067b84SDoug Ambrisko vnic_wq_disable(wq); 7509c067b84SDoug Ambrisko 7519c067b84SDoug Ambrisko wq->ring.desc_size = sizeof(struct wq_enet_desc); 7529c067b84SDoug Ambrisko wq->ring.desc_count = softc->scctx->isc_ntxd[q]; 7539c067b84SDoug Ambrisko wq->ring.desc_avail = wq->ring.desc_count - 1; 7549c067b84SDoug Ambrisko wq->ring.last_count = wq->ring.desc_count; 7559c067b84SDoug Ambrisko wq->head_idx = 0; 7569c067b84SDoug Ambrisko wq->tail_idx = 0; 7579c067b84SDoug Ambrisko 7589c067b84SDoug Ambrisko wq->ring.size = wq->ring.desc_count * wq->ring.desc_size; 7599c067b84SDoug Ambrisko wq->ring.descs = vaddrs[q * ntxqs + 0]; 7609c067b84SDoug Ambrisko wq->ring.base_addr = paddrs[q * ntxqs + 0]; 7619c067b84SDoug Ambrisko 7629c067b84SDoug Ambrisko /* Command ring */ 7639c067b84SDoug Ambrisko cq->vdev = softc->enic.vdev; 7649c067b84SDoug Ambrisko cq->index = cq_wq; 7659c067b84SDoug Ambrisko cq->ctrl = vnic_dev_get_res(softc->enic.vdev, 7669c067b84SDoug Ambrisko RES_TYPE_CQ, cq->index); 7679c067b84SDoug Ambrisko cq->ring.desc_size = sizeof(struct cq_enet_wq_desc); 7689c067b84SDoug Ambrisko cq->ring.desc_count = softc->scctx->isc_ntxd[q]; 7699c067b84SDoug Ambrisko cq->ring.desc_avail = cq->ring.desc_count - 1; 7709c067b84SDoug Ambrisko 7719c067b84SDoug Ambrisko cq->ring.size = cq->ring.desc_count * cq->ring.desc_size; 7729c067b84SDoug Ambrisko cq->ring.descs = vaddrs[q * ntxqs + 1]; 7739c067b84SDoug Ambrisko cq->ring.base_addr = paddrs[q * ntxqs + 1]; 7749c067b84SDoug Ambrisko 7759c067b84SDoug Ambrisko } 7769c067b84SDoug Ambrisko 7779c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 7789c067b84SDoug Ambrisko 7799c067b84SDoug Ambrisko return (0); 7809c067b84SDoug Ambrisko } 7819c067b84SDoug Ambrisko 7829c067b84SDoug Ambrisko 7839c067b84SDoug Ambrisko 7849c067b84SDoug Ambrisko static int 7859c067b84SDoug Ambrisko enic_rx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs, 7869c067b84SDoug Ambrisko int nrxqs, int nrxqsets) 7879c067b84SDoug Ambrisko { 7889c067b84SDoug Ambrisko struct enic_softc *softc; 7899c067b84SDoug Ambrisko int q; 7909c067b84SDoug Ambrisko 7919c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 7929c067b84SDoug Ambrisko /* Allocate the array of receive queues */ 7939c067b84SDoug Ambrisko softc->enic.rq = malloc(sizeof(struct vnic_rq) * nrxqsets, M_DEVBUF, 7949c067b84SDoug Ambrisko M_NOWAIT | M_ZERO); 7959c067b84SDoug Ambrisko if (softc->enic.rq == NULL) 7969c067b84SDoug Ambrisko return (ENOMEM); 7979c067b84SDoug Ambrisko 7989c067b84SDoug Ambrisko /* Initialize driver state for each receive queue */ 7999c067b84SDoug Ambrisko 8009c067b84SDoug Ambrisko /* 8019c067b84SDoug Ambrisko * Allocate queue state that is shared with the device. This check 8029c067b84SDoug Ambrisko * and call is performed in both enic_tx_queues_alloc() and 8039c067b84SDoug Ambrisko * enic_rx_queues_alloc() so that we don't have to care which order 8049c067b84SDoug Ambrisko * iflib invokes those routines in. 8059c067b84SDoug Ambrisko */ 8069c067b84SDoug Ambrisko 8079c067b84SDoug Ambrisko /* Record descriptor ring vaddrs and paddrs */ 8089c067b84SDoug Ambrisko ENIC_LOCK(softc); 8099c067b84SDoug Ambrisko for (q = 0; q < nrxqsets; q++) { 8109c067b84SDoug Ambrisko struct vnic_rq *rq; 8119c067b84SDoug Ambrisko struct vnic_cq *cq; 8129c067b84SDoug Ambrisko unsigned int cq_rq; 8139c067b84SDoug Ambrisko 8149c067b84SDoug Ambrisko rq = &softc->enic.rq[q]; 8159c067b84SDoug Ambrisko cq_rq = enic_cq_rq(&softc->enic, q); 8169c067b84SDoug Ambrisko cq = &softc->enic.cq[cq_rq]; 8179c067b84SDoug Ambrisko 8189c067b84SDoug Ambrisko /* Completion ring */ 8199c067b84SDoug Ambrisko cq->vdev = softc->enic.vdev; 8209c067b84SDoug Ambrisko cq->index = cq_rq; 8219c067b84SDoug Ambrisko cq->ctrl = vnic_dev_get_res(softc->enic.vdev, RES_TYPE_CQ, 8229c067b84SDoug Ambrisko cq->index); 8239c067b84SDoug Ambrisko cq->ring.desc_size = sizeof(struct cq_enet_wq_desc); 8249c067b84SDoug Ambrisko cq->ring.desc_count = softc->scctx->isc_nrxd[1]; 8259c067b84SDoug Ambrisko cq->ring.desc_avail = cq->ring.desc_count - 1; 8269c067b84SDoug Ambrisko 8279c067b84SDoug Ambrisko cq->ring.size = cq->ring.desc_count * cq->ring.desc_size; 8289c067b84SDoug Ambrisko cq->ring.descs = vaddrs[q * nrxqs + 0]; 8299c067b84SDoug Ambrisko cq->ring.base_addr = paddrs[q * nrxqs + 0]; 8309c067b84SDoug Ambrisko 8319c067b84SDoug Ambrisko /* Command ring(s) */ 8329c067b84SDoug Ambrisko rq->vdev = softc->enic.vdev; 8339c067b84SDoug Ambrisko 8349c067b84SDoug Ambrisko rq->index = q; 8359c067b84SDoug Ambrisko rq->ctrl = vnic_dev_get_res(softc->enic.vdev, 8369c067b84SDoug Ambrisko RES_TYPE_RQ, rq->index); 8379c067b84SDoug Ambrisko vnic_rq_disable(rq); 8389c067b84SDoug Ambrisko 8399c067b84SDoug Ambrisko rq->ring.desc_size = sizeof(struct rq_enet_desc); 8409c067b84SDoug Ambrisko rq->ring.desc_count = softc->scctx->isc_nrxd[0]; 8419c067b84SDoug Ambrisko rq->ring.desc_avail = rq->ring.desc_count - 1; 8429c067b84SDoug Ambrisko 8439c067b84SDoug Ambrisko rq->ring.size = rq->ring.desc_count * rq->ring.desc_size; 8449c067b84SDoug Ambrisko rq->ring.descs = vaddrs[q * nrxqs + 1]; 8459c067b84SDoug Ambrisko rq->ring.base_addr = paddrs[q * nrxqs + 1]; 8469c067b84SDoug Ambrisko rq->need_initial_post = true; 8479c067b84SDoug Ambrisko } 8489c067b84SDoug Ambrisko 8499c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 8509c067b84SDoug Ambrisko 8519c067b84SDoug Ambrisko return (0); 8529c067b84SDoug Ambrisko } 8539c067b84SDoug Ambrisko 8549c067b84SDoug Ambrisko static void 8559c067b84SDoug Ambrisko enic_queues_free(if_ctx_t ctx) 8569c067b84SDoug Ambrisko { 8579c067b84SDoug Ambrisko struct enic_softc *softc; 8589c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 8599c067b84SDoug Ambrisko 8609c067b84SDoug Ambrisko free(softc->enic.rq, M_DEVBUF); 8619c067b84SDoug Ambrisko free(softc->enic.wq, M_DEVBUF); 8629c067b84SDoug Ambrisko free(softc->enic.cq, M_DEVBUF); 8639c067b84SDoug Ambrisko } 8649c067b84SDoug Ambrisko 8659c067b84SDoug Ambrisko static int 8669c067b84SDoug Ambrisko enic_rxq_intr(void *rxq) 8679c067b84SDoug Ambrisko { 8689c067b84SDoug Ambrisko struct vnic_rq *rq; 869bbd354cbSDoug Ambrisko if_t ifp; 8709c067b84SDoug Ambrisko 8719c067b84SDoug Ambrisko rq = (struct vnic_rq *)rxq; 8729c067b84SDoug Ambrisko ifp = iflib_get_ifp(rq->vdev->softc->ctx); 873bbd354cbSDoug Ambrisko if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) 8749c067b84SDoug Ambrisko return (FILTER_HANDLED); 8759c067b84SDoug Ambrisko 8769c067b84SDoug Ambrisko return (FILTER_SCHEDULE_THREAD); 8779c067b84SDoug Ambrisko } 8789c067b84SDoug Ambrisko 8799c067b84SDoug Ambrisko static int 8809c067b84SDoug Ambrisko enic_event_intr(void *vsc) 8819c067b84SDoug Ambrisko { 8829c067b84SDoug Ambrisko struct enic_softc *softc; 8839c067b84SDoug Ambrisko struct enic *enic; 8849c067b84SDoug Ambrisko uint32_t mtu; 8859c067b84SDoug Ambrisko 8869c067b84SDoug Ambrisko softc = vsc; 8879c067b84SDoug Ambrisko enic = &softc->enic; 8889c067b84SDoug Ambrisko 8899c067b84SDoug Ambrisko mtu = vnic_dev_mtu(enic->vdev); 8909c067b84SDoug Ambrisko if (mtu && mtu != enic->port_mtu) { 8919c067b84SDoug Ambrisko enic->port_mtu = mtu; 8929c067b84SDoug Ambrisko } 8939c067b84SDoug Ambrisko 8949c067b84SDoug Ambrisko enic_link_status(softc); 8959c067b84SDoug Ambrisko 8969c067b84SDoug Ambrisko return (FILTER_HANDLED); 8979c067b84SDoug Ambrisko } 8989c067b84SDoug Ambrisko 8999c067b84SDoug Ambrisko static int 9009c067b84SDoug Ambrisko enic_err_intr(void *vsc) 9019c067b84SDoug Ambrisko { 9029c067b84SDoug Ambrisko struct enic_softc *softc; 9039c067b84SDoug Ambrisko 9049c067b84SDoug Ambrisko softc = vsc; 9059c067b84SDoug Ambrisko 9069c067b84SDoug Ambrisko enic_stop(softc->ctx); 9079c067b84SDoug Ambrisko enic_init(softc->ctx); 9089c067b84SDoug Ambrisko 9099c067b84SDoug Ambrisko return (FILTER_HANDLED); 9109c067b84SDoug Ambrisko } 9119c067b84SDoug Ambrisko 9129c067b84SDoug Ambrisko static void 9139c067b84SDoug Ambrisko enic_stop(if_ctx_t ctx) 9149c067b84SDoug Ambrisko { 9159c067b84SDoug Ambrisko struct enic_softc *softc; 9169c067b84SDoug Ambrisko struct enic *enic; 9179c067b84SDoug Ambrisko if_softc_ctx_t scctx; 9189c067b84SDoug Ambrisko unsigned int index; 919*0acab8b3SDoug Ambrisko struct vnic_wq *wq; 920*0acab8b3SDoug Ambrisko struct vnic_rq *rq; 921*0acab8b3SDoug Ambrisko struct vnic_cq *cq; 922*0acab8b3SDoug Ambrisko unsigned int cq_wq, cq_rq; 923*0acab8b3SDoug Ambrisko 9249c067b84SDoug Ambrisko 9259c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 9269c067b84SDoug Ambrisko scctx = softc->scctx; 9279c067b84SDoug Ambrisko enic = &softc->enic; 9289c067b84SDoug Ambrisko 9299c067b84SDoug Ambrisko if (softc->stopped) 9309c067b84SDoug Ambrisko return; 9319c067b84SDoug Ambrisko softc->link_active = 0; 9329c067b84SDoug Ambrisko softc->stopped = 1; 9339c067b84SDoug Ambrisko 934*0acab8b3SDoug Ambrisko enic_dev_disable(enic); 935*0acab8b3SDoug Ambrisko 9369c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_ntxqsets; index++) { 9379c067b84SDoug Ambrisko enic_stop_wq(enic, index); 9389c067b84SDoug Ambrisko vnic_wq_clean(&enic->wq[index]); 9399c067b84SDoug Ambrisko vnic_cq_clean(&enic->cq[enic_cq_rq(enic, index)]); 940*0acab8b3SDoug Ambrisko 941*0acab8b3SDoug Ambrisko wq = &softc->enic.wq[index]; 942*0acab8b3SDoug Ambrisko wq->ring.desc_avail = wq->ring.desc_count - 1; 943*0acab8b3SDoug Ambrisko wq->ring.last_count = wq->ring.desc_count; 944*0acab8b3SDoug Ambrisko wq->head_idx = 0; 945*0acab8b3SDoug Ambrisko wq->tail_idx = 0; 946*0acab8b3SDoug Ambrisko 947*0acab8b3SDoug Ambrisko cq_wq = enic_cq_wq(&softc->enic, index); 948*0acab8b3SDoug Ambrisko cq = &softc->enic.cq[cq_wq]; 949*0acab8b3SDoug Ambrisko cq->ring.desc_avail = cq->ring.desc_count - 1; 9509c067b84SDoug Ambrisko } 9519c067b84SDoug Ambrisko 9529c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_nrxqsets; index++) { 953*0acab8b3SDoug Ambrisko enic_stop_rq(enic, index); 9549c067b84SDoug Ambrisko vnic_rq_clean(&enic->rq[index]); 9559c067b84SDoug Ambrisko vnic_cq_clean(&enic->cq[enic_cq_wq(enic, index)]); 956*0acab8b3SDoug Ambrisko 957*0acab8b3SDoug Ambrisko rq = &softc->enic.rq[index]; 958*0acab8b3SDoug Ambrisko cq_rq = enic_cq_rq(&softc->enic, index); 959*0acab8b3SDoug Ambrisko cq = &softc->enic.cq[cq_rq]; 960*0acab8b3SDoug Ambrisko 961*0acab8b3SDoug Ambrisko cq->ring.desc_avail = cq->ring.desc_count - 1; 962*0acab8b3SDoug Ambrisko rq->ring.desc_avail = rq->ring.desc_count - 1; 963*0acab8b3SDoug Ambrisko rq->need_initial_post = true; 9649c067b84SDoug Ambrisko } 9659c067b84SDoug Ambrisko 9669c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_vectors; index++) { 9679c067b84SDoug Ambrisko vnic_intr_clean(&enic->intr[index]); 9689c067b84SDoug Ambrisko } 9699c067b84SDoug Ambrisko } 9709c067b84SDoug Ambrisko 9719c067b84SDoug Ambrisko static void 9729c067b84SDoug Ambrisko enic_init(if_ctx_t ctx) 9739c067b84SDoug Ambrisko { 9749c067b84SDoug Ambrisko struct enic_softc *softc; 9759c067b84SDoug Ambrisko struct enic *enic; 9769c067b84SDoug Ambrisko if_softc_ctx_t scctx; 9779c067b84SDoug Ambrisko unsigned int index; 9789c067b84SDoug Ambrisko 9799c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 9809c067b84SDoug Ambrisko scctx = softc->scctx; 9819c067b84SDoug Ambrisko enic = &softc->enic; 9829c067b84SDoug Ambrisko 983*0acab8b3SDoug Ambrisko 984*0acab8b3SDoug Ambrisko enic_init_vnic_resources(enic); 985*0acab8b3SDoug Ambrisko 9869c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_ntxqsets; index++) 9879c067b84SDoug Ambrisko enic_prep_wq_for_simple_tx(&softc->enic, index); 9889c067b84SDoug Ambrisko 9899c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_ntxqsets; index++) 9909c067b84SDoug Ambrisko enic_start_wq(enic, index); 9919c067b84SDoug Ambrisko 9929c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_nrxqsets; index++) 9939c067b84SDoug Ambrisko enic_start_rq(enic, index); 9949c067b84SDoug Ambrisko 9959c067b84SDoug Ambrisko /* Use the current MAC address. */ 996bbd354cbSDoug Ambrisko bcopy(if_getlladdr(softc->ifp), softc->lladdr, ETHER_ADDR_LEN); 9979c067b84SDoug Ambrisko enic_set_lladdr(softc); 9989c067b84SDoug Ambrisko 9999c067b84SDoug Ambrisko ENIC_LOCK(softc); 10009c067b84SDoug Ambrisko vnic_dev_enable_wait(enic->vdev); 10019c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 10029c067b84SDoug Ambrisko 1003*0acab8b3SDoug Ambrisko softc->stopped = 0; 1004*0acab8b3SDoug Ambrisko 10059c067b84SDoug Ambrisko enic_link_status(softc); 10069c067b84SDoug Ambrisko } 10079c067b84SDoug Ambrisko 10089c067b84SDoug Ambrisko static void 10099c067b84SDoug Ambrisko enic_del_mcast(struct enic_softc *softc) { 10109c067b84SDoug Ambrisko struct enic *enic; 10119c067b84SDoug Ambrisko int i; 10129c067b84SDoug Ambrisko 10139c067b84SDoug Ambrisko enic = &softc->enic; 10149c067b84SDoug Ambrisko for (i=0; i < softc->mc_count; i++) { 10159c067b84SDoug Ambrisko vnic_dev_del_addr(enic->vdev, &softc->mta[i * ETHER_ADDR_LEN]); 10169c067b84SDoug Ambrisko } 10179c067b84SDoug Ambrisko softc->multicast = 0; 10189c067b84SDoug Ambrisko softc->mc_count = 0; 10199c067b84SDoug Ambrisko } 10209c067b84SDoug Ambrisko 10219c067b84SDoug Ambrisko static void 10229c067b84SDoug Ambrisko enic_add_mcast(struct enic_softc *softc) { 10239c067b84SDoug Ambrisko struct enic *enic; 10249c067b84SDoug Ambrisko int i; 10259c067b84SDoug Ambrisko 10269c067b84SDoug Ambrisko enic = &softc->enic; 10279c067b84SDoug Ambrisko for (i=0; i < softc->mc_count; i++) { 10289c067b84SDoug Ambrisko vnic_dev_add_addr(enic->vdev, &softc->mta[i * ETHER_ADDR_LEN]); 10299c067b84SDoug Ambrisko } 10309c067b84SDoug Ambrisko softc->multicast = 1; 10319c067b84SDoug Ambrisko } 10329c067b84SDoug Ambrisko 10339c067b84SDoug Ambrisko static u_int 10349c067b84SDoug Ambrisko enic_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int idx) 10359c067b84SDoug Ambrisko { 10369c067b84SDoug Ambrisko uint8_t *mta = arg; 10379c067b84SDoug Ambrisko 10389c067b84SDoug Ambrisko if (idx == ENIC_MAX_MULTICAST_ADDRESSES) 10399c067b84SDoug Ambrisko return (0); 10409c067b84SDoug Ambrisko 10419c067b84SDoug Ambrisko bcopy(LLADDR(sdl), &mta[idx * ETHER_ADDR_LEN], ETHER_ADDR_LEN); 10429c067b84SDoug Ambrisko return (1); 10439c067b84SDoug Ambrisko } 10449c067b84SDoug Ambrisko 10459c067b84SDoug Ambrisko static void 10469c067b84SDoug Ambrisko enic_multi_set(if_ctx_t ctx) 10479c067b84SDoug Ambrisko { 1048bbd354cbSDoug Ambrisko if_t ifp; 10499c067b84SDoug Ambrisko struct enic_softc *softc; 10509c067b84SDoug Ambrisko u_int count; 10519c067b84SDoug Ambrisko 10529c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 10539c067b84SDoug Ambrisko ifp = iflib_get_ifp(ctx); 10549c067b84SDoug Ambrisko 10559c067b84SDoug Ambrisko ENIC_LOCK(softc); 10569c067b84SDoug Ambrisko enic_del_mcast(softc); 10579c067b84SDoug Ambrisko count = if_foreach_llmaddr(ifp, enic_copy_maddr, softc->mta); 10589c067b84SDoug Ambrisko softc->mc_count = count; 10599c067b84SDoug Ambrisko enic_add_mcast(softc); 10609c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 10619c067b84SDoug Ambrisko 1062bbd354cbSDoug Ambrisko if (if_getflags(ifp) & IFF_PROMISC) { 10639c067b84SDoug Ambrisko softc->promisc = 1; 10649c067b84SDoug Ambrisko } else { 10659c067b84SDoug Ambrisko softc->promisc = 0; 10669c067b84SDoug Ambrisko } 1067bbd354cbSDoug Ambrisko if (if_getflags(ifp) & IFF_ALLMULTI) { 10689c067b84SDoug Ambrisko softc->allmulti = 1; 10699c067b84SDoug Ambrisko } else { 10709c067b84SDoug Ambrisko softc->allmulti = 0; 10719c067b84SDoug Ambrisko } 10729c067b84SDoug Ambrisko enic_update_packet_filter(&softc->enic); 10739c067b84SDoug Ambrisko } 10749c067b84SDoug Ambrisko 10759c067b84SDoug Ambrisko static int 10769c067b84SDoug Ambrisko enic_mtu_set(if_ctx_t ctx, uint32_t mtu) 10779c067b84SDoug Ambrisko { 10789c067b84SDoug Ambrisko struct enic_softc *softc; 10799c067b84SDoug Ambrisko struct enic *enic; 10809c067b84SDoug Ambrisko if_softc_ctx_t scctx = iflib_get_softc_ctx(ctx); 10819c067b84SDoug Ambrisko 10829c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 10839c067b84SDoug Ambrisko enic = &softc->enic; 10849c067b84SDoug Ambrisko 1085*0acab8b3SDoug Ambrisko enic_stop(softc->ctx); 10869c067b84SDoug Ambrisko if (mtu > enic->port_mtu){ 10879c067b84SDoug Ambrisko return (EINVAL); 10889c067b84SDoug Ambrisko } 10899c067b84SDoug Ambrisko 10909c067b84SDoug Ambrisko enic->config.mtu = mtu; 10919c067b84SDoug Ambrisko scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 1092*0acab8b3SDoug Ambrisko enic_init(softc->ctx); 10939c067b84SDoug Ambrisko 10949c067b84SDoug Ambrisko return (0); 10959c067b84SDoug Ambrisko } 10969c067b84SDoug Ambrisko 10979c067b84SDoug Ambrisko static void 10989c067b84SDoug Ambrisko enic_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) 10999c067b84SDoug Ambrisko { 11009c067b84SDoug Ambrisko struct enic_softc *softc; 11019c067b84SDoug Ambrisko struct ifmedia_entry *next; 11029c067b84SDoug Ambrisko uint32_t speed; 11039c067b84SDoug Ambrisko uint64_t target_baudrate; 11049c067b84SDoug Ambrisko 11059c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 11069c067b84SDoug Ambrisko 11079c067b84SDoug Ambrisko ifmr->ifm_status = IFM_AVALID; 11089c067b84SDoug Ambrisko ifmr->ifm_active = IFM_ETHER; 11099c067b84SDoug Ambrisko 11109c067b84SDoug Ambrisko if (enic_link_is_up(softc) != 0) { 11119c067b84SDoug Ambrisko ENIC_LOCK(softc); 11129c067b84SDoug Ambrisko speed = vnic_dev_port_speed(&softc->vdev); 11139c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 11149c067b84SDoug Ambrisko target_baudrate = 1000ull * speed; 11159c067b84SDoug Ambrisko LIST_FOREACH(next, &(iflib_get_media(ctx)->ifm_list), ifm_list) { 11169c067b84SDoug Ambrisko if (ifmedia_baudrate(next->ifm_media) == target_baudrate) { 11179c067b84SDoug Ambrisko ifmr->ifm_active |= next->ifm_media; 11189c067b84SDoug Ambrisko } 11199c067b84SDoug Ambrisko } 11209c067b84SDoug Ambrisko 11219c067b84SDoug Ambrisko ifmr->ifm_status |= IFM_ACTIVE; 11229c067b84SDoug Ambrisko ifmr->ifm_active |= IFM_AUTO; 11239c067b84SDoug Ambrisko } else 11249c067b84SDoug Ambrisko ifmr->ifm_active |= IFM_NONE; 11259c067b84SDoug Ambrisko } 11269c067b84SDoug Ambrisko 11279c067b84SDoug Ambrisko static int 11289c067b84SDoug Ambrisko enic_media_change(if_ctx_t ctx) 11299c067b84SDoug Ambrisko { 11309c067b84SDoug Ambrisko return (ENODEV); 11319c067b84SDoug Ambrisko } 11329c067b84SDoug Ambrisko 11339c067b84SDoug Ambrisko static int 11349c067b84SDoug Ambrisko enic_promisc_set(if_ctx_t ctx, int flags) 11359c067b84SDoug Ambrisko { 1136bbd354cbSDoug Ambrisko if_t ifp; 11379c067b84SDoug Ambrisko struct enic_softc *softc; 11389c067b84SDoug Ambrisko 11399c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 11409c067b84SDoug Ambrisko ifp = iflib_get_ifp(ctx); 11419c067b84SDoug Ambrisko 1142bbd354cbSDoug Ambrisko if (if_getflags(ifp) & IFF_PROMISC) { 11439c067b84SDoug Ambrisko softc->promisc = 1; 11449c067b84SDoug Ambrisko } else { 11459c067b84SDoug Ambrisko softc->promisc = 0; 11469c067b84SDoug Ambrisko } 1147bbd354cbSDoug Ambrisko if (if_getflags(ifp) & IFF_ALLMULTI) { 11489c067b84SDoug Ambrisko softc->allmulti = 1; 11499c067b84SDoug Ambrisko } else { 11509c067b84SDoug Ambrisko softc->allmulti = 0; 11519c067b84SDoug Ambrisko } 11529c067b84SDoug Ambrisko enic_update_packet_filter(&softc->enic); 11539c067b84SDoug Ambrisko 11549c067b84SDoug Ambrisko return (0); 11559c067b84SDoug Ambrisko } 11569c067b84SDoug Ambrisko 11579c067b84SDoug Ambrisko static uint64_t 11589c067b84SDoug Ambrisko enic_get_counter(if_ctx_t ctx, ift_counter cnt) { 11599c067b84SDoug Ambrisko if_t ifp = iflib_get_ifp(ctx); 11609c067b84SDoug Ambrisko 11619c067b84SDoug Ambrisko if (cnt < IFCOUNTERS) 11629c067b84SDoug Ambrisko return if_get_counter_default(ifp, cnt); 11639c067b84SDoug Ambrisko 11649c067b84SDoug Ambrisko return (0); 11659c067b84SDoug Ambrisko } 11669c067b84SDoug Ambrisko 11679c067b84SDoug Ambrisko static void 11689c067b84SDoug Ambrisko enic_update_admin_status(if_ctx_t ctx) 11699c067b84SDoug Ambrisko { 11709c067b84SDoug Ambrisko struct enic_softc *softc; 11719c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 11729c067b84SDoug Ambrisko 11739c067b84SDoug Ambrisko enic_link_status(softc); 11749c067b84SDoug Ambrisko } 11759c067b84SDoug Ambrisko 11769c067b84SDoug Ambrisko static void 11779c067b84SDoug Ambrisko enic_txq_timer(if_ctx_t ctx, uint16_t qid) 11789c067b84SDoug Ambrisko { 11799c067b84SDoug Ambrisko 11809c067b84SDoug Ambrisko struct enic_softc *softc; 11819c067b84SDoug Ambrisko struct enic *enic; 11829c067b84SDoug Ambrisko struct vnic_stats *stats; 11839c067b84SDoug Ambrisko int ret; 11849c067b84SDoug Ambrisko 11859c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 11869c067b84SDoug Ambrisko enic = &softc->enic; 11879c067b84SDoug Ambrisko 11889c067b84SDoug Ambrisko ENIC_LOCK(softc); 11899c067b84SDoug Ambrisko ret = vnic_dev_stats_dump(enic->vdev, &stats); 11909c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 11919c067b84SDoug Ambrisko if (ret) { 11929c067b84SDoug Ambrisko dev_err(enic, "Error in getting stats\n"); 11939c067b84SDoug Ambrisko } 11949c067b84SDoug Ambrisko } 11959c067b84SDoug Ambrisko 11969c067b84SDoug Ambrisko static int 11979c067b84SDoug Ambrisko enic_link_is_up(struct enic_softc *softc) 11989c067b84SDoug Ambrisko { 11999c067b84SDoug Ambrisko return (vnic_dev_link_status(&softc->vdev) == 1); 12009c067b84SDoug Ambrisko } 12019c067b84SDoug Ambrisko 12029c067b84SDoug Ambrisko static void 12039c067b84SDoug Ambrisko enic_link_status(struct enic_softc *softc) 12049c067b84SDoug Ambrisko { 12059c067b84SDoug Ambrisko if_ctx_t ctx; 12069c067b84SDoug Ambrisko uint64_t speed; 12079c067b84SDoug Ambrisko int link; 12089c067b84SDoug Ambrisko 12099c067b84SDoug Ambrisko ctx = softc->ctx; 12109c067b84SDoug Ambrisko link = enic_link_is_up(softc); 12119c067b84SDoug Ambrisko speed = IF_Gbps(10); 12129c067b84SDoug Ambrisko 12139c067b84SDoug Ambrisko ENIC_LOCK(softc); 12149c067b84SDoug Ambrisko speed = vnic_dev_port_speed(&softc->vdev); 12159c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 12169c067b84SDoug Ambrisko 12179c067b84SDoug Ambrisko if (link != 0 && softc->link_active == 0) { 12189c067b84SDoug Ambrisko softc->link_active = 1; 12199c067b84SDoug Ambrisko iflib_link_state_change(ctx, LINK_STATE_UP, speed); 12209c067b84SDoug Ambrisko } else if (link == 0 && softc->link_active != 0) { 12219c067b84SDoug Ambrisko softc->link_active = 0; 12229c067b84SDoug Ambrisko iflib_link_state_change(ctx, LINK_STATE_DOWN, speed); 12239c067b84SDoug Ambrisko } 12249c067b84SDoug Ambrisko } 12259c067b84SDoug Ambrisko 12269c067b84SDoug Ambrisko static void 12279c067b84SDoug Ambrisko enic_set_lladdr(struct enic_softc *softc) 12289c067b84SDoug Ambrisko { 12299c067b84SDoug Ambrisko struct enic *enic; 12309c067b84SDoug Ambrisko enic = &softc->enic; 12319c067b84SDoug Ambrisko 12329c067b84SDoug Ambrisko ENIC_LOCK(softc); 12339c067b84SDoug Ambrisko vnic_dev_add_addr(enic->vdev, softc->lladdr); 12349c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 12359c067b84SDoug Ambrisko } 12369c067b84SDoug Ambrisko 12379c067b84SDoug Ambrisko 12389c067b84SDoug Ambrisko static void 12399c067b84SDoug Ambrisko enic_setup_txq_sysctl(struct vnic_wq *wq, int i, struct sysctl_ctx_list *ctx, 12409c067b84SDoug Ambrisko struct sysctl_oid_list *child) 12419c067b84SDoug Ambrisko { 12429c067b84SDoug Ambrisko struct sysctl_oid *txsnode; 12439c067b84SDoug Ambrisko struct sysctl_oid_list *txslist; 12449c067b84SDoug Ambrisko struct vnic_stats *stats = wq[i].vdev->stats; 12459c067b84SDoug Ambrisko 12469c067b84SDoug Ambrisko txsnode = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hstats", 12479c067b84SDoug Ambrisko CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Host Statistics"); 12489c067b84SDoug Ambrisko txslist = SYSCTL_CHILDREN(txsnode); 12499c067b84SDoug Ambrisko 12509c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_frames_ok", CTLFLAG_RD, 12519c067b84SDoug Ambrisko &stats->tx.tx_frames_ok, "TX Frames OK"); 12529c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_unicast_frames_ok", CTLFLAG_RD, 12539c067b84SDoug Ambrisko &stats->tx.tx_unicast_frames_ok, "TX unicast frames OK"); 12549c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_multicast_frames_ok", CTLFLAG_RD, 12559c067b84SDoug Ambrisko &stats->tx.tx_multicast_frames_ok, "TX multicast framse OK"); 12569c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_broadcast_frames_ok", CTLFLAG_RD, 12579c067b84SDoug Ambrisko &stats->tx.tx_broadcast_frames_ok, "TX Broadcast frames OK"); 12589c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_bytes_ok", CTLFLAG_RD, 12599c067b84SDoug Ambrisko &stats->tx.tx_bytes_ok, "TX bytes OK "); 12609c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_unicast_bytes_ok", CTLFLAG_RD, 12619c067b84SDoug Ambrisko &stats->tx.tx_unicast_bytes_ok, "TX unicast bytes OK"); 12629c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_multicast_bytes_ok", CTLFLAG_RD, 12639c067b84SDoug Ambrisko &stats->tx.tx_multicast_bytes_ok, "TX multicast bytes OK"); 12649c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_broadcast_bytes_ok", CTLFLAG_RD, 12659c067b84SDoug Ambrisko &stats->tx.tx_broadcast_bytes_ok, "TX broadcast bytes OK"); 12669c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_drops", CTLFLAG_RD, 12679c067b84SDoug Ambrisko &stats->tx.tx_drops, "TX drops"); 12689c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_errors", CTLFLAG_RD, 12699c067b84SDoug Ambrisko &stats->tx.tx_errors, "TX errors"); 12709c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, txslist, OID_AUTO, "tx_tso", CTLFLAG_RD, 12719c067b84SDoug Ambrisko &stats->tx.tx_tso, "TX TSO"); 12729c067b84SDoug Ambrisko } 12739c067b84SDoug Ambrisko 12749c067b84SDoug Ambrisko static void 12759c067b84SDoug Ambrisko enic_setup_rxq_sysctl(struct vnic_rq *rq, int i, struct sysctl_ctx_list *ctx, 12769c067b84SDoug Ambrisko struct sysctl_oid_list *child) 12779c067b84SDoug Ambrisko { 12789c067b84SDoug Ambrisko struct sysctl_oid *rxsnode; 12799c067b84SDoug Ambrisko struct sysctl_oid_list *rxslist; 12809c067b84SDoug Ambrisko struct vnic_stats *stats = rq[i].vdev->stats; 12819c067b84SDoug Ambrisko 12829c067b84SDoug Ambrisko rxsnode = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hstats", 12839c067b84SDoug Ambrisko CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Host Statistics"); 12849c067b84SDoug Ambrisko rxslist = SYSCTL_CHILDREN(rxsnode); 12859c067b84SDoug Ambrisko 12869c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_ok", CTLFLAG_RD, 12879c067b84SDoug Ambrisko &stats->rx.rx_frames_ok, "RX Frames OK"); 12889c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_total", CTLFLAG_RD, 12899c067b84SDoug Ambrisko &stats->rx.rx_frames_total, "RX frames total"); 12909c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_unicast_frames_ok", CTLFLAG_RD, 12919c067b84SDoug Ambrisko &stats->rx.rx_unicast_frames_ok, "RX unicast frames ok"); 12929c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_multicast_frames_ok", CTLFLAG_RD, 12939c067b84SDoug Ambrisko &stats->rx.rx_multicast_frames_ok, "RX multicast Frames ok"); 12949c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_broadcast_frames_ok", CTLFLAG_RD, 12959c067b84SDoug Ambrisko &stats->rx.rx_broadcast_frames_ok, "RX broadcast frames ok"); 12969c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_bytes_ok", CTLFLAG_RD, 12979c067b84SDoug Ambrisko &stats->rx.rx_bytes_ok, "RX bytes ok"); 12989c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_unicast_bytes_ok", CTLFLAG_RD, 12999c067b84SDoug Ambrisko &stats->rx.rx_unicast_bytes_ok, "RX unicast bytes ok"); 13009c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_multicast_bytes_ok", CTLFLAG_RD, 13019c067b84SDoug Ambrisko &stats->rx.rx_multicast_bytes_ok, "RX multicast bytes ok"); 13029c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_broadcast_bytes_ok", CTLFLAG_RD, 13039c067b84SDoug Ambrisko &stats->rx.rx_broadcast_bytes_ok, "RX broadcast bytes ok"); 13049c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_drop", CTLFLAG_RD, 13059c067b84SDoug Ambrisko &stats->rx.rx_drop, "RX drop"); 13069c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_errors", CTLFLAG_RD, 13079c067b84SDoug Ambrisko &stats->rx.rx_errors, "RX errors"); 13089c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_rss", CTLFLAG_RD, 13099c067b84SDoug Ambrisko &stats->rx.rx_rss, "RX rss"); 13109c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_crc_errors", CTLFLAG_RD, 13119c067b84SDoug Ambrisko &stats->rx.rx_crc_errors, "RX crc errors"); 13129c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_64", CTLFLAG_RD, 13139c067b84SDoug Ambrisko &stats->rx.rx_frames_64, "RX frames 64"); 13149c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_127", CTLFLAG_RD, 13159c067b84SDoug Ambrisko &stats->rx.rx_frames_127, "RX frames 127"); 13169c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_255", CTLFLAG_RD, 13179c067b84SDoug Ambrisko &stats->rx.rx_frames_255, "RX frames 255"); 13189c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_511", CTLFLAG_RD, 13199c067b84SDoug Ambrisko &stats->rx.rx_frames_511, "RX frames 511"); 13209c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_1023", CTLFLAG_RD, 13219c067b84SDoug Ambrisko &stats->rx.rx_frames_1023, "RX frames 1023"); 13229c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_1518", CTLFLAG_RD, 13239c067b84SDoug Ambrisko &stats->rx.rx_frames_1518, "RX frames 1518"); 13249c067b84SDoug Ambrisko SYSCTL_ADD_UQUAD(ctx, rxslist, OID_AUTO, "rx_frames_to_max", CTLFLAG_RD, 13259c067b84SDoug Ambrisko &stats->rx.rx_frames_to_max, "RX frames to max"); 13269c067b84SDoug Ambrisko } 13279c067b84SDoug Ambrisko 13289c067b84SDoug Ambrisko static void 13299c067b84SDoug Ambrisko enic_setup_queue_sysctl(struct enic_softc *softc, struct sysctl_ctx_list *ctx, 13309c067b84SDoug Ambrisko struct sysctl_oid_list *child) 13319c067b84SDoug Ambrisko { 13329c067b84SDoug Ambrisko enic_setup_txq_sysctl(softc->enic.wq, 0, ctx, child); 13339c067b84SDoug Ambrisko enic_setup_rxq_sysctl(softc->enic.rq, 0, ctx, child); 13349c067b84SDoug Ambrisko } 13359c067b84SDoug Ambrisko 13369c067b84SDoug Ambrisko static void 13379c067b84SDoug Ambrisko enic_setup_sysctl(struct enic_softc *softc) 13389c067b84SDoug Ambrisko { 13399c067b84SDoug Ambrisko device_t dev; 13409c067b84SDoug Ambrisko struct sysctl_ctx_list *ctx; 13419c067b84SDoug Ambrisko struct sysctl_oid *tree; 13429c067b84SDoug Ambrisko struct sysctl_oid_list *child; 13439c067b84SDoug Ambrisko 13449c067b84SDoug Ambrisko dev = softc->dev; 13459c067b84SDoug Ambrisko ctx = device_get_sysctl_ctx(dev); 13469c067b84SDoug Ambrisko tree = device_get_sysctl_tree(dev); 13479c067b84SDoug Ambrisko child = SYSCTL_CHILDREN(tree); 13489c067b84SDoug Ambrisko 13499c067b84SDoug Ambrisko enic_setup_queue_sysctl(softc, ctx, child); 13509c067b84SDoug Ambrisko } 13519c067b84SDoug Ambrisko 13529c067b84SDoug Ambrisko static void 13539c067b84SDoug Ambrisko enic_enable_intr(struct enic_softc *softc, int irq) 13549c067b84SDoug Ambrisko { 13559c067b84SDoug Ambrisko struct enic *enic = &softc->enic; 13569c067b84SDoug Ambrisko 13579c067b84SDoug Ambrisko vnic_intr_unmask(&enic->intr[irq]); 13589c067b84SDoug Ambrisko vnic_intr_return_all_credits(&enic->intr[irq]); 13599c067b84SDoug Ambrisko } 13609c067b84SDoug Ambrisko 13619c067b84SDoug Ambrisko static void 13629c067b84SDoug Ambrisko enic_disable_intr(struct enic_softc *softc, int irq) 13639c067b84SDoug Ambrisko { 13649c067b84SDoug Ambrisko struct enic *enic = &softc->enic; 13659c067b84SDoug Ambrisko 13669c067b84SDoug Ambrisko vnic_intr_mask(&enic->intr[irq]); 13679c067b84SDoug Ambrisko vnic_intr_masked(&enic->intr[irq]); /* flush write */ 13689c067b84SDoug Ambrisko } 13699c067b84SDoug Ambrisko 13709c067b84SDoug Ambrisko static int 13719c067b84SDoug Ambrisko enic_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 13729c067b84SDoug Ambrisko { 13739c067b84SDoug Ambrisko struct enic_softc *softc; 13749c067b84SDoug Ambrisko if_softc_ctx_t scctx; 13759c067b84SDoug Ambrisko 13769c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 13779c067b84SDoug Ambrisko scctx = softc->scctx; 13789c067b84SDoug Ambrisko 13799c067b84SDoug Ambrisko enic_enable_intr(softc, qid + scctx->isc_nrxqsets); 13809c067b84SDoug Ambrisko 13819c067b84SDoug Ambrisko return 0; 13829c067b84SDoug Ambrisko } 13839c067b84SDoug Ambrisko 13849c067b84SDoug Ambrisko static int 13859c067b84SDoug Ambrisko enic_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 13869c067b84SDoug Ambrisko { 13879c067b84SDoug Ambrisko struct enic_softc *softc; 13889c067b84SDoug Ambrisko 13899c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 13909c067b84SDoug Ambrisko enic_enable_intr(softc, qid); 13919c067b84SDoug Ambrisko 13929c067b84SDoug Ambrisko return 0; 13939c067b84SDoug Ambrisko } 13949c067b84SDoug Ambrisko 13959c067b84SDoug Ambrisko static void 13969c067b84SDoug Ambrisko enic_intr_enable_all(if_ctx_t ctx) 13979c067b84SDoug Ambrisko { 13989c067b84SDoug Ambrisko struct enic_softc *softc; 13999c067b84SDoug Ambrisko if_softc_ctx_t scctx; 14009c067b84SDoug Ambrisko int i; 14019c067b84SDoug Ambrisko 14029c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 14039c067b84SDoug Ambrisko scctx = softc->scctx; 14049c067b84SDoug Ambrisko 14059c067b84SDoug Ambrisko for (i = 0; i < scctx->isc_vectors; i++) { 14069c067b84SDoug Ambrisko enic_enable_intr(softc, i); 14079c067b84SDoug Ambrisko } 14089c067b84SDoug Ambrisko } 14099c067b84SDoug Ambrisko 14109c067b84SDoug Ambrisko static void 14119c067b84SDoug Ambrisko enic_intr_disable_all(if_ctx_t ctx) 14129c067b84SDoug Ambrisko { 14139c067b84SDoug Ambrisko struct enic_softc *softc; 14149c067b84SDoug Ambrisko if_softc_ctx_t scctx; 14159c067b84SDoug Ambrisko int i; 14169c067b84SDoug Ambrisko 14179c067b84SDoug Ambrisko softc = iflib_get_softc(ctx); 14189c067b84SDoug Ambrisko scctx = softc->scctx; 14199c067b84SDoug Ambrisko /* 14209c067b84SDoug Ambrisko * iflib may invoke this routine before enic_attach_post() has run, 14219c067b84SDoug Ambrisko * which is before the top level shared data area is initialized and 14229c067b84SDoug Ambrisko * the device made aware of it. 14239c067b84SDoug Ambrisko */ 14249c067b84SDoug Ambrisko 14259c067b84SDoug Ambrisko for (i = 0; i < scctx->isc_vectors; i++) { 14269c067b84SDoug Ambrisko enic_disable_intr(softc, i); 14279c067b84SDoug Ambrisko } 14289c067b84SDoug Ambrisko } 14299c067b84SDoug Ambrisko 14309c067b84SDoug Ambrisko static int 14319c067b84SDoug Ambrisko enic_dev_open(struct enic *enic) 14329c067b84SDoug Ambrisko { 14339c067b84SDoug Ambrisko int err; 14349c067b84SDoug Ambrisko int flags = CMD_OPENF_IG_DESCCACHE; 14359c067b84SDoug Ambrisko 14369c067b84SDoug Ambrisko err = enic_dev_wait(enic->vdev, vnic_dev_open, 14379c067b84SDoug Ambrisko vnic_dev_open_done, flags); 14389c067b84SDoug Ambrisko if (err) 14399c067b84SDoug Ambrisko dev_err(enic_get_dev(enic), 14409c067b84SDoug Ambrisko "vNIC device open failed, err %d\n", err); 14419c067b84SDoug Ambrisko 14429c067b84SDoug Ambrisko return err; 14439c067b84SDoug Ambrisko } 14449c067b84SDoug Ambrisko 14459c067b84SDoug Ambrisko static int 14469c067b84SDoug Ambrisko enic_dev_init(struct enic *enic) 14479c067b84SDoug Ambrisko { 14489c067b84SDoug Ambrisko int err; 14499c067b84SDoug Ambrisko 14509c067b84SDoug Ambrisko vnic_dev_intr_coal_timer_info_default(enic->vdev); 14519c067b84SDoug Ambrisko 14529c067b84SDoug Ambrisko /* 14539c067b84SDoug Ambrisko * Get vNIC configuration 14549c067b84SDoug Ambrisko */ 14559c067b84SDoug Ambrisko err = enic_get_vnic_config(enic); 14569c067b84SDoug Ambrisko if (err) { 14579c067b84SDoug Ambrisko dev_err(dev, "Get vNIC configuration failed, aborting\n"); 14589c067b84SDoug Ambrisko return err; 14599c067b84SDoug Ambrisko } 14609c067b84SDoug Ambrisko 14619c067b84SDoug Ambrisko /* Get available resource counts */ 14629c067b84SDoug Ambrisko enic_get_res_counts(enic); 14639c067b84SDoug Ambrisko 14649c067b84SDoug Ambrisko /* Queue counts may be zeros. rte_zmalloc returns NULL in that case. */ 14659c067b84SDoug Ambrisko enic->intr_queues = malloc(sizeof(*enic->intr_queues) * 14669c067b84SDoug Ambrisko enic->conf_intr_count, M_DEVBUF, M_NOWAIT | M_ZERO); 14679c067b84SDoug Ambrisko 14689c067b84SDoug Ambrisko vnic_dev_set_reset_flag(enic->vdev, 0); 14699c067b84SDoug Ambrisko enic->max_flow_counter = -1; 14709c067b84SDoug Ambrisko 14719c067b84SDoug Ambrisko /* set up link status checking */ 14729c067b84SDoug Ambrisko vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */ 14739c067b84SDoug Ambrisko 14749c067b84SDoug Ambrisko enic->overlay_offload = false; 14759c067b84SDoug Ambrisko if (enic->disable_overlay && enic->vxlan) { 14769c067b84SDoug Ambrisko /* 14779c067b84SDoug Ambrisko * Explicitly disable overlay offload as the setting is 14789c067b84SDoug Ambrisko * sticky, and resetting vNIC does not disable it. 14799c067b84SDoug Ambrisko */ 14809c067b84SDoug Ambrisko if (vnic_dev_overlay_offload_ctrl(enic->vdev, 14819c067b84SDoug Ambrisko OVERLAY_FEATURE_VXLAN, OVERLAY_OFFLOAD_DISABLE)) { 14829c067b84SDoug Ambrisko dev_err(enic, "failed to disable overlay offload\n"); 14839c067b84SDoug Ambrisko } else { 14849c067b84SDoug Ambrisko dev_info(enic, "Overlay offload is disabled\n"); 14859c067b84SDoug Ambrisko } 14869c067b84SDoug Ambrisko } 14879c067b84SDoug Ambrisko if (!enic->disable_overlay && enic->vxlan && 14889c067b84SDoug Ambrisko /* 'VXLAN feature' enables VXLAN, NVGRE, and GENEVE. */ 14899c067b84SDoug Ambrisko vnic_dev_overlay_offload_ctrl(enic->vdev, 14909c067b84SDoug Ambrisko OVERLAY_FEATURE_VXLAN, OVERLAY_OFFLOAD_ENABLE) == 0) { 14919c067b84SDoug Ambrisko enic->overlay_offload = true; 14929c067b84SDoug Ambrisko enic->vxlan_port = ENIC_DEFAULT_VXLAN_PORT; 14939c067b84SDoug Ambrisko dev_info(enic, "Overlay offload is enabled\n"); 14949c067b84SDoug Ambrisko /* 14959c067b84SDoug Ambrisko * Reset the vxlan port to the default, as the NIC firmware 14969c067b84SDoug Ambrisko * does not reset it automatically and keeps the old setting. 14979c067b84SDoug Ambrisko */ 14989c067b84SDoug Ambrisko if (vnic_dev_overlay_offload_cfg(enic->vdev, 14999c067b84SDoug Ambrisko OVERLAY_CFG_VXLAN_PORT_UPDATE, ENIC_DEFAULT_VXLAN_PORT)) { 15009c067b84SDoug Ambrisko dev_err(enic, "failed to update vxlan port\n"); 1501*0acab8b3SDoug Ambrisko return (EINVAL); 15029c067b84SDoug Ambrisko } 15039c067b84SDoug Ambrisko } 15049c067b84SDoug Ambrisko return 0; 15059c067b84SDoug Ambrisko } 15069c067b84SDoug Ambrisko 15079c067b84SDoug Ambrisko static void * 15089c067b84SDoug Ambrisko enic_alloc_consistent(void *priv, size_t size, bus_addr_t * dma_handle, 15099c067b84SDoug Ambrisko struct iflib_dma_info *res, u8 * name) 15109c067b84SDoug Ambrisko { 15119c067b84SDoug Ambrisko void *vaddr; 15129c067b84SDoug Ambrisko *dma_handle = 0; 15139c067b84SDoug Ambrisko struct enic *enic = (struct enic *)priv; 15149c067b84SDoug Ambrisko int rz; 15159c067b84SDoug Ambrisko 15169c067b84SDoug Ambrisko rz = iflib_dma_alloc(enic->softc->ctx, size, res, BUS_DMA_NOWAIT); 15179c067b84SDoug Ambrisko if (rz) { 15189c067b84SDoug Ambrisko pr_err("%s : Failed to allocate memory requested for %s\n", 15199c067b84SDoug Ambrisko __func__, name); 15209c067b84SDoug Ambrisko return NULL; 15219c067b84SDoug Ambrisko } 15229c067b84SDoug Ambrisko 15239c067b84SDoug Ambrisko vaddr = res->idi_vaddr; 15249c067b84SDoug Ambrisko *dma_handle = res->idi_paddr; 15259c067b84SDoug Ambrisko 15269c067b84SDoug Ambrisko return vaddr; 15279c067b84SDoug Ambrisko } 15289c067b84SDoug Ambrisko 15299c067b84SDoug Ambrisko static void 15309c067b84SDoug Ambrisko enic_free_consistent(void *priv, size_t size, void *vaddr, 15319c067b84SDoug Ambrisko bus_addr_t dma_handle, struct iflib_dma_info *res) 15329c067b84SDoug Ambrisko { 15339c067b84SDoug Ambrisko iflib_dma_free(res); 15349c067b84SDoug Ambrisko } 15359c067b84SDoug Ambrisko 15369c067b84SDoug Ambrisko static int 15379c067b84SDoug Ambrisko enic_pci_mapping(struct enic_softc *softc) 15389c067b84SDoug Ambrisko { 15399c067b84SDoug Ambrisko int rc; 15409c067b84SDoug Ambrisko 15419c067b84SDoug Ambrisko rc = enic_map_bar(softc, &softc->mem, 0, true); 15429c067b84SDoug Ambrisko if (rc) 15439c067b84SDoug Ambrisko return rc; 15449c067b84SDoug Ambrisko 15459c067b84SDoug Ambrisko rc = enic_map_bar(softc, &softc->io, 2, false); 15469c067b84SDoug Ambrisko 15479c067b84SDoug Ambrisko return rc; 15489c067b84SDoug Ambrisko } 15499c067b84SDoug Ambrisko 15509c067b84SDoug Ambrisko static void 15519c067b84SDoug Ambrisko enic_pci_mapping_free(struct enic_softc *softc) 15529c067b84SDoug Ambrisko { 15539c067b84SDoug Ambrisko if (softc->mem.res != NULL) 15549c067b84SDoug Ambrisko bus_release_resource(softc->dev, SYS_RES_MEMORY, 15559c067b84SDoug Ambrisko softc->mem.rid, softc->mem.res); 15569c067b84SDoug Ambrisko softc->mem.res = NULL; 15579c067b84SDoug Ambrisko 15589c067b84SDoug Ambrisko if (softc->io.res != NULL) 15599c067b84SDoug Ambrisko bus_release_resource(softc->dev, SYS_RES_MEMORY, 15609c067b84SDoug Ambrisko softc->io.rid, softc->io.res); 15619c067b84SDoug Ambrisko softc->io.res = NULL; 15629c067b84SDoug Ambrisko } 15639c067b84SDoug Ambrisko 15649c067b84SDoug Ambrisko static int 15659c067b84SDoug Ambrisko enic_dev_wait(struct vnic_dev *vdev, int (*start) (struct vnic_dev *, int), 15669c067b84SDoug Ambrisko int (*finished) (struct vnic_dev *, int *), int arg) 15679c067b84SDoug Ambrisko { 15689c067b84SDoug Ambrisko int done; 15699c067b84SDoug Ambrisko int err; 15709c067b84SDoug Ambrisko int i; 15719c067b84SDoug Ambrisko 15729c067b84SDoug Ambrisko err = start(vdev, arg); 15739c067b84SDoug Ambrisko if (err) 15749c067b84SDoug Ambrisko return err; 15759c067b84SDoug Ambrisko 15769c067b84SDoug Ambrisko /* Wait for func to complete...2 seconds max */ 15779c067b84SDoug Ambrisko for (i = 0; i < 2000; i++) { 15789c067b84SDoug Ambrisko err = finished(vdev, &done); 15799c067b84SDoug Ambrisko if (err) 15809c067b84SDoug Ambrisko return err; 15819c067b84SDoug Ambrisko if (done) 15829c067b84SDoug Ambrisko return 0; 15839c067b84SDoug Ambrisko usleep(1000); 15849c067b84SDoug Ambrisko } 1585*0acab8b3SDoug Ambrisko return (ETIMEDOUT); 15869c067b84SDoug Ambrisko } 15879c067b84SDoug Ambrisko 15889c067b84SDoug Ambrisko static int 15899c067b84SDoug Ambrisko enic_map_bar(struct enic_softc *softc, struct enic_bar_info *bar, int bar_num, 15909c067b84SDoug Ambrisko bool shareable) 15919c067b84SDoug Ambrisko { 15929c067b84SDoug Ambrisko uint32_t flag; 15939c067b84SDoug Ambrisko 15949c067b84SDoug Ambrisko if (bar->res != NULL) { 15959c067b84SDoug Ambrisko device_printf(softc->dev, "Bar %d already mapped\n", bar_num); 1596*0acab8b3SDoug Ambrisko return (EDOOFUS); 15979c067b84SDoug Ambrisko } 15989c067b84SDoug Ambrisko 15999c067b84SDoug Ambrisko bar->rid = PCIR_BAR(bar_num); 16009c067b84SDoug Ambrisko flag = RF_ACTIVE; 16019c067b84SDoug Ambrisko if (shareable) 16029c067b84SDoug Ambrisko flag |= RF_SHAREABLE; 16039c067b84SDoug Ambrisko 16049c067b84SDoug Ambrisko if ((bar->res = bus_alloc_resource_any(softc->dev, 16059c067b84SDoug Ambrisko SYS_RES_MEMORY, &bar->rid, flag)) == NULL) { 16069c067b84SDoug Ambrisko device_printf(softc->dev, 16079c067b84SDoug Ambrisko "PCI BAR%d mapping failure\n", bar_num); 16089c067b84SDoug Ambrisko return (ENXIO); 16099c067b84SDoug Ambrisko } 16109c067b84SDoug Ambrisko bar->tag = rman_get_bustag(bar->res); 16119c067b84SDoug Ambrisko bar->handle = rman_get_bushandle(bar->res); 16129c067b84SDoug Ambrisko bar->size = rman_get_size(bar->res); 16139c067b84SDoug Ambrisko 16149c067b84SDoug Ambrisko return 0; 16159c067b84SDoug Ambrisko } 16169c067b84SDoug Ambrisko 16179c067b84SDoug Ambrisko void 16189c067b84SDoug Ambrisko enic_init_vnic_resources(struct enic *enic) 16199c067b84SDoug Ambrisko { 16209c067b84SDoug Ambrisko unsigned int error_interrupt_enable = 1; 16219c067b84SDoug Ambrisko unsigned int error_interrupt_offset = 0; 16229c067b84SDoug Ambrisko unsigned int rxq_interrupt_enable = 0; 16239c067b84SDoug Ambrisko unsigned int rxq_interrupt_offset = ENICPMD_RXQ_INTR_OFFSET; 16249c067b84SDoug Ambrisko unsigned int txq_interrupt_enable = 0; 1625*0acab8b3SDoug Ambrisko unsigned int txq_interrupt_offset; 16269c067b84SDoug Ambrisko unsigned int index = 0; 16279c067b84SDoug Ambrisko unsigned int cq_idx; 16289c067b84SDoug Ambrisko if_softc_ctx_t scctx; 16299c067b84SDoug Ambrisko 16309c067b84SDoug Ambrisko scctx = enic->softc->scctx; 16319c067b84SDoug Ambrisko 16329c067b84SDoug Ambrisko rxq_interrupt_enable = 1; 1633*0acab8b3SDoug Ambrisko txq_interrupt_enable = 0; 16349c067b84SDoug Ambrisko 16359c067b84SDoug Ambrisko rxq_interrupt_offset = 0; 1636*0acab8b3SDoug Ambrisko txq_interrupt_offset = scctx->isc_nrxqsets; 16379c067b84SDoug Ambrisko 16389c067b84SDoug Ambrisko for (index = 0; index < enic->intr_count; index++) { 16399c067b84SDoug Ambrisko vnic_intr_alloc(enic->vdev, &enic->intr[index], index); 16409c067b84SDoug Ambrisko } 16419c067b84SDoug Ambrisko 16429c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_nrxqsets; index++) { 16439c067b84SDoug Ambrisko cq_idx = enic_cq_rq(enic, index); 16449c067b84SDoug Ambrisko 16459c067b84SDoug Ambrisko vnic_rq_clean(&enic->rq[index]); 16469c067b84SDoug Ambrisko vnic_rq_init(&enic->rq[index], cq_idx, error_interrupt_enable, 16479c067b84SDoug Ambrisko error_interrupt_offset); 16489c067b84SDoug Ambrisko 16499c067b84SDoug Ambrisko vnic_cq_clean(&enic->cq[cq_idx]); 16509c067b84SDoug Ambrisko vnic_cq_init(&enic->cq[cq_idx], 16519c067b84SDoug Ambrisko 0 /* flow_control_enable */ , 16529c067b84SDoug Ambrisko 1 /* color_enable */ , 16539c067b84SDoug Ambrisko 0 /* cq_head */ , 16549c067b84SDoug Ambrisko 0 /* cq_tail */ , 16559c067b84SDoug Ambrisko 1 /* cq_tail_color */ , 16569c067b84SDoug Ambrisko rxq_interrupt_enable, 16579c067b84SDoug Ambrisko 1 /* cq_entry_enable */ , 16589c067b84SDoug Ambrisko 0 /* cq_message_enable */ , 16599c067b84SDoug Ambrisko rxq_interrupt_offset, 16609c067b84SDoug Ambrisko 0 /* cq_message_addr */ ); 16619c067b84SDoug Ambrisko if (rxq_interrupt_enable) 16629c067b84SDoug Ambrisko rxq_interrupt_offset++; 16639c067b84SDoug Ambrisko } 16649c067b84SDoug Ambrisko 16659c067b84SDoug Ambrisko for (index = 0; index < scctx->isc_ntxqsets; index++) { 16669c067b84SDoug Ambrisko cq_idx = enic_cq_wq(enic, index); 16679c067b84SDoug Ambrisko vnic_wq_clean(&enic->wq[index]); 16689c067b84SDoug Ambrisko vnic_wq_init(&enic->wq[index], cq_idx, error_interrupt_enable, 16699c067b84SDoug Ambrisko error_interrupt_offset); 16709c067b84SDoug Ambrisko /* Compute unsupported ol flags for enic_prep_pkts() */ 16719c067b84SDoug Ambrisko enic->wq[index].tx_offload_notsup_mask = 0; 16729c067b84SDoug Ambrisko 16739c067b84SDoug Ambrisko vnic_cq_clean(&enic->cq[cq_idx]); 16749c067b84SDoug Ambrisko vnic_cq_init(&enic->cq[cq_idx], 16759c067b84SDoug Ambrisko 0 /* flow_control_enable */ , 16769c067b84SDoug Ambrisko 1 /* color_enable */ , 16779c067b84SDoug Ambrisko 0 /* cq_head */ , 16789c067b84SDoug Ambrisko 0 /* cq_tail */ , 16799c067b84SDoug Ambrisko 1 /* cq_tail_color */ , 16809c067b84SDoug Ambrisko txq_interrupt_enable, 16819c067b84SDoug Ambrisko 1, 16829c067b84SDoug Ambrisko 0, 16839c067b84SDoug Ambrisko txq_interrupt_offset, 16849c067b84SDoug Ambrisko 0 /* (u64)enic->wq[index].cqmsg_rz->iova */ ); 16859c067b84SDoug Ambrisko 16869c067b84SDoug Ambrisko } 16879c067b84SDoug Ambrisko 16889c067b84SDoug Ambrisko for (index = 0; index < enic->intr_count; index++) { 16899c067b84SDoug Ambrisko vnic_intr_init(&enic->intr[index], 125, 16909c067b84SDoug Ambrisko enic->config.intr_timer_type, /* mask_on_assertion */ 1); 16919c067b84SDoug Ambrisko } 16929c067b84SDoug Ambrisko } 16939c067b84SDoug Ambrisko 16949c067b84SDoug Ambrisko static void 16959c067b84SDoug Ambrisko enic_update_packet_filter(struct enic *enic) 16969c067b84SDoug Ambrisko { 16979c067b84SDoug Ambrisko struct enic_softc *softc = enic->softc; 16989c067b84SDoug Ambrisko 16999c067b84SDoug Ambrisko ENIC_LOCK(softc); 17009c067b84SDoug Ambrisko vnic_dev_packet_filter(enic->vdev, 17019c067b84SDoug Ambrisko softc->directed, 17029c067b84SDoug Ambrisko softc->multicast, 17039c067b84SDoug Ambrisko softc->broadcast, 17049c067b84SDoug Ambrisko softc->promisc, 17059c067b84SDoug Ambrisko softc->allmulti); 17069c067b84SDoug Ambrisko ENIC_UNLOCK(softc); 17079c067b84SDoug Ambrisko } 17089c067b84SDoug Ambrisko 1709fe6c4e21SKevin Bowling static bool 1710*0acab8b3SDoug Ambrisko enic_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event) 1711fe6c4e21SKevin Bowling { 1712fe6c4e21SKevin Bowling switch (event) { 1713fe6c4e21SKevin Bowling case IFLIB_RESTART_VLAN_CONFIG: 1714fe6c4e21SKevin Bowling default: 1715fe6c4e21SKevin Bowling return (false); 1716fe6c4e21SKevin Bowling } 1717fe6c4e21SKevin Bowling } 1718fe6c4e21SKevin Bowling 17199c067b84SDoug Ambrisko int 17209c067b84SDoug Ambrisko enic_setup_finish(struct enic *enic) 17219c067b84SDoug Ambrisko { 17229c067b84SDoug Ambrisko struct enic_softc *softc = enic->softc; 17239c067b84SDoug Ambrisko 17249c067b84SDoug Ambrisko /* Default conf */ 17259c067b84SDoug Ambrisko softc->directed = 1; 17269c067b84SDoug Ambrisko softc->multicast = 0; 17279c067b84SDoug Ambrisko softc->broadcast = 1; 17289c067b84SDoug Ambrisko softc->promisc = 0; 1729f830db48Srilysh softc->allmulti = 1; 17309c067b84SDoug Ambrisko enic_update_packet_filter(enic); 17319c067b84SDoug Ambrisko 17329c067b84SDoug Ambrisko return 0; 17339c067b84SDoug Ambrisko } 1734