1*60b8dadeSjan /* $OpenBSD: if_ixl.c,v 1.102 2024/10/30 18:02:45 jan Exp $ */ 2ccb96312Sdlg 3ccb96312Sdlg /* 4ccb96312Sdlg * Copyright (c) 2013-2015, Intel Corporation 5ccb96312Sdlg * All rights reserved. 6ccb96312Sdlg 7ccb96312Sdlg * Redistribution and use in source and binary forms, with or without 8ccb96312Sdlg * modification, are permitted provided that the following conditions are met: 9ccb96312Sdlg * 10ccb96312Sdlg * 1. Redistributions of source code must retain the above copyright notice, 11ccb96312Sdlg * this list of conditions and the following disclaimer. 12ccb96312Sdlg * 13ccb96312Sdlg * 2. Redistributions in binary form must reproduce the above copyright 14ccb96312Sdlg * notice, this list of conditions and the following disclaimer in the 15ccb96312Sdlg * documentation and/or other materials provided with the distribution. 16ccb96312Sdlg * 17ccb96312Sdlg * 3. Neither the name of the Intel Corporation nor the names of its 18ccb96312Sdlg * contributors may be used to endorse or promote products derived from 19ccb96312Sdlg * this software without specific prior written permission. 20ccb96312Sdlg * 21ccb96312Sdlg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22ccb96312Sdlg * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23ccb96312Sdlg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24ccb96312Sdlg * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25ccb96312Sdlg * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26ccb96312Sdlg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27ccb96312Sdlg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28ccb96312Sdlg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29ccb96312Sdlg * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30ccb96312Sdlg * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31ccb96312Sdlg * POSSIBILITY OF SUCH DAMAGE. 32ccb96312Sdlg */ 33ccb96312Sdlg 34ccb96312Sdlg /* 35ccb96312Sdlg * Copyright (c) 2016,2017 David Gwynne <dlg@openbsd.org> 36ccb96312Sdlg * 37ccb96312Sdlg * Permission to use, copy, modify, and distribute this software for any 38ccb96312Sdlg * purpose with or without fee is hereby granted, provided that the above 39ccb96312Sdlg * copyright notice and this permission notice appear in all copies. 40ccb96312Sdlg * 41ccb96312Sdlg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 42ccb96312Sdlg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 43ccb96312Sdlg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 44ccb96312Sdlg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 45ccb96312Sdlg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 46ccb96312Sdlg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 47ccb96312Sdlg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 48ccb96312Sdlg */ 49ccb96312Sdlg 50ccb96312Sdlg #include "bpfilter.h" 512ee1fcb3Sdlg #include "kstat.h" 52*60b8dadeSjan #include "vlan.h" 53ccb96312Sdlg 54ccb96312Sdlg #include <sys/param.h> 55ccb96312Sdlg #include <sys/systm.h> 56b661852cSdlg #include <sys/proc.h> 57ccb96312Sdlg #include <sys/sockio.h> 58ccb96312Sdlg #include <sys/mbuf.h> 59ccb96312Sdlg #include <sys/socket.h> 60ccb96312Sdlg #include <sys/device.h> 61ccb96312Sdlg #include <sys/pool.h> 62ccb96312Sdlg #include <sys/queue.h> 63ccb96312Sdlg #include <sys/timeout.h> 64ccb96312Sdlg #include <sys/task.h> 65d3ac7020Sdlg #include <sys/syslog.h> 66e01adc04Sdlg #include <sys/intrmap.h> 67ccb96312Sdlg 68ccb96312Sdlg #include <machine/bus.h> 69ccb96312Sdlg #include <machine/intr.h> 70ccb96312Sdlg 71ccb96312Sdlg #include <net/if.h> 72ccb96312Sdlg #include <net/if_media.h> 73f77c9c95Sjan #include <net/route.h> 74819ac441Sdlg #include <net/toeplitz.h> 75ccb96312Sdlg 76ccb96312Sdlg #if NBPFILTER > 0 77ccb96312Sdlg #include <net/bpf.h> 78ccb96312Sdlg #endif 79ccb96312Sdlg 802ee1fcb3Sdlg #if NKSTAT > 0 812ee1fcb3Sdlg #include <sys/kstat.h> 822ee1fcb3Sdlg #endif 832ee1fcb3Sdlg 84ccb96312Sdlg #include <netinet/in.h> 8538ec96dbSjan #include <netinet/if_ether.h> 8604206048Sdlg #include <netinet/tcp.h> 87f77c9c95Sjan #include <netinet/tcp_timer.h> 88f77c9c95Sjan #include <netinet/tcp_var.h> 8904206048Sdlg #include <netinet/udp.h> 90ccb96312Sdlg 91ccb96312Sdlg #include <dev/pci/pcireg.h> 92ccb96312Sdlg #include <dev/pci/pcivar.h> 93ccb96312Sdlg #include <dev/pci/pcidevs.h> 94ccb96312Sdlg 9512b3627cSjmatthew #ifdef __sparc64__ 9612b3627cSjmatthew #include <dev/ofw/openfirm.h> 9712b3627cSjmatthew #endif 9812b3627cSjmatthew 99e01adc04Sdlg #ifndef CACHE_LINE_SIZE 100e01adc04Sdlg #define CACHE_LINE_SIZE 64 101e01adc04Sdlg #endif 102e01adc04Sdlg 103e01adc04Sdlg #define IXL_MAX_VECTORS 8 /* XXX this is pretty arbitrary */ 104e01adc04Sdlg 105ccb96312Sdlg #define I40E_MASK(mask, shift) ((mask) << (shift)) 106ccb96312Sdlg #define I40E_PF_RESET_WAIT_COUNT 200 107ccb96312Sdlg #define I40E_AQ_LARGE_BUF 512 108ccb96312Sdlg 109ccb96312Sdlg /* bitfields for Tx queue mapping in QTX_CTL */ 110ccb96312Sdlg #define I40E_QTX_CTL_VF_QUEUE 0x0 111ccb96312Sdlg #define I40E_QTX_CTL_VM_QUEUE 0x1 112ccb96312Sdlg #define I40E_QTX_CTL_PF_QUEUE 0x2 113ccb96312Sdlg 114eb1b42e4Sdlg #define I40E_QUEUE_TYPE_EOL 0x7ff 115eb1b42e4Sdlg #define I40E_INTR_NOTX_QUEUE 0 116eb1b42e4Sdlg 117eb1b42e4Sdlg #define I40E_QUEUE_TYPE_RX 0x0 118eb1b42e4Sdlg #define I40E_QUEUE_TYPE_TX 0x1 119eb1b42e4Sdlg #define I40E_QUEUE_TYPE_PE_CEQ 0x2 120eb1b42e4Sdlg #define I40E_QUEUE_TYPE_UNKNOWN 0x3 121eb1b42e4Sdlg 122eb1b42e4Sdlg #define I40E_ITR_INDEX_RX 0x0 123eb1b42e4Sdlg #define I40E_ITR_INDEX_TX 0x1 124eb1b42e4Sdlg #define I40E_ITR_INDEX_OTHER 0x2 125eb1b42e4Sdlg #define I40E_ITR_INDEX_NONE 0x3 126eb1b42e4Sdlg 127ccb96312Sdlg #include <dev/pci/if_ixlreg.h> 128ccb96312Sdlg 129eb1b42e4Sdlg #define I40E_INTR_NOTX_QUEUE 0 130eb1b42e4Sdlg #define I40E_INTR_NOTX_INTR 0 131eb1b42e4Sdlg #define I40E_INTR_NOTX_RX_QUEUE 0 132eb1b42e4Sdlg #define I40E_INTR_NOTX_TX_QUEUE 1 133eb1b42e4Sdlg #define I40E_INTR_NOTX_RX_MASK I40E_PFINT_ICR0_QUEUE_0_MASK 134eb1b42e4Sdlg #define I40E_INTR_NOTX_TX_MASK I40E_PFINT_ICR0_QUEUE_1_MASK 135eb1b42e4Sdlg 136ccb96312Sdlg struct ixl_aq_desc { 137ccb96312Sdlg uint16_t iaq_flags; 138ccb96312Sdlg #define IXL_AQ_DD (1U << 0) 139ccb96312Sdlg #define IXL_AQ_CMP (1U << 1) 140ccb96312Sdlg #define IXL_AQ_ERR (1U << 2) 141ccb96312Sdlg #define IXL_AQ_VFE (1U << 3) 142ccb96312Sdlg #define IXL_AQ_LB (1U << 9) 143ccb96312Sdlg #define IXL_AQ_RD (1U << 10) 144ccb96312Sdlg #define IXL_AQ_VFC (1U << 11) 145ccb96312Sdlg #define IXL_AQ_BUF (1U << 12) 146ccb96312Sdlg #define IXL_AQ_SI (1U << 13) 147ccb96312Sdlg #define IXL_AQ_EI (1U << 14) 148ccb96312Sdlg #define IXL_AQ_FE (1U << 15) 149ccb96312Sdlg 150ccb96312Sdlg #define IXL_AQ_FLAGS_FMT "\020" "\020FE" "\017EI" "\016SI" "\015BUF" \ 151ccb96312Sdlg "\014VFC" "\013DB" "\012LB" "\004VFE" \ 152ccb96312Sdlg "\003ERR" "\002CMP" "\001DD" 153ccb96312Sdlg 154ccb96312Sdlg uint16_t iaq_opcode; 155ccb96312Sdlg 156ccb96312Sdlg uint16_t iaq_datalen; 157ccb96312Sdlg uint16_t iaq_retval; 158ccb96312Sdlg 159ccb96312Sdlg uint64_t iaq_cookie; 160ccb96312Sdlg 161ccb96312Sdlg uint32_t iaq_param[4]; 162ccb96312Sdlg /* iaq_data_hi iaq_param[2] */ 163ccb96312Sdlg /* iaq_data_lo iaq_param[3] */ 1647e7a8c99Sdlg } __packed __aligned(8); 165ccb96312Sdlg 166ccb96312Sdlg /* aq commands */ 167ccb96312Sdlg #define IXL_AQ_OP_GET_VERSION 0x0001 168ccb96312Sdlg #define IXL_AQ_OP_DRIVER_VERSION 0x0002 169ccb96312Sdlg #define IXL_AQ_OP_QUEUE_SHUTDOWN 0x0003 170ccb96312Sdlg #define IXL_AQ_OP_SET_PF_CONTEXT 0x0004 171ccb96312Sdlg #define IXL_AQ_OP_GET_AQ_ERR_REASON 0x0005 172ccb96312Sdlg #define IXL_AQ_OP_REQUEST_RESOURCE 0x0008 173ccb96312Sdlg #define IXL_AQ_OP_RELEASE_RESOURCE 0x0009 174ccb96312Sdlg #define IXL_AQ_OP_LIST_FUNC_CAP 0x000a 175ccb96312Sdlg #define IXL_AQ_OP_LIST_DEV_CAP 0x000b 176ccb96312Sdlg #define IXL_AQ_OP_MAC_ADDRESS_READ 0x0107 177ccb96312Sdlg #define IXL_AQ_OP_CLEAR_PXE_MODE 0x0110 178ccb96312Sdlg #define IXL_AQ_OP_SWITCH_GET_CONFIG 0x0200 179819ac441Sdlg #define IXL_AQ_OP_RX_CTL_READ 0x0206 180819ac441Sdlg #define IXL_AQ_OP_RX_CTL_WRITE 0x0207 181ccb96312Sdlg #define IXL_AQ_OP_ADD_VSI 0x0210 182ccb96312Sdlg #define IXL_AQ_OP_UPD_VSI_PARAMS 0x0211 183ccb96312Sdlg #define IXL_AQ_OP_GET_VSI_PARAMS 0x0212 184ccb96312Sdlg #define IXL_AQ_OP_ADD_VEB 0x0230 185ccb96312Sdlg #define IXL_AQ_OP_UPD_VEB_PARAMS 0x0231 186ccb96312Sdlg #define IXL_AQ_OP_GET_VEB_PARAMS 0x0232 1872bb8400cSjmatthew #define IXL_AQ_OP_ADD_MACVLAN 0x0250 1882bb8400cSjmatthew #define IXL_AQ_OP_REMOVE_MACVLAN 0x0251 189ccb96312Sdlg #define IXL_AQ_OP_SET_VSI_PROMISC 0x0254 190ccb96312Sdlg #define IXL_AQ_OP_PHY_GET_ABILITIES 0x0600 191ccb96312Sdlg #define IXL_AQ_OP_PHY_SET_CONFIG 0x0601 192ccb96312Sdlg #define IXL_AQ_OP_PHY_SET_MAC_CONFIG 0x0603 193ccb96312Sdlg #define IXL_AQ_OP_PHY_RESTART_AN 0x0605 194ccb96312Sdlg #define IXL_AQ_OP_PHY_LINK_STATUS 0x0607 195ccb96312Sdlg #define IXL_AQ_OP_PHY_SET_EVENT_MASK 0x0613 1964eec9beaSdlg #define IXL_AQ_OP_PHY_SET_REGISTER 0x0628 1974eec9beaSdlg #define IXL_AQ_OP_PHY_GET_REGISTER 0x0629 198ccb96312Sdlg #define IXL_AQ_OP_LLDP_GET_MIB 0x0a00 199ccb96312Sdlg #define IXL_AQ_OP_LLDP_MIB_CHG_EV 0x0a01 200ccb96312Sdlg #define IXL_AQ_OP_LLDP_ADD_TLV 0x0a02 201ccb96312Sdlg #define IXL_AQ_OP_LLDP_UPD_TLV 0x0a03 202ccb96312Sdlg #define IXL_AQ_OP_LLDP_DEL_TLV 0x0a04 203ccb96312Sdlg #define IXL_AQ_OP_LLDP_STOP_AGENT 0x0a05 204ccb96312Sdlg #define IXL_AQ_OP_LLDP_START_AGENT 0x0a06 205ccb96312Sdlg #define IXL_AQ_OP_LLDP_GET_CEE_DCBX 0x0a07 206ccb96312Sdlg #define IXL_AQ_OP_LLDP_SPECIFIC_AGENT 0x0a09 207e0731eceSdlg #define IXL_AQ_OP_SET_RSS_KEY 0x0b02 /* 722 only */ 208e0731eceSdlg #define IXL_AQ_OP_SET_RSS_LUT 0x0b03 /* 722 only */ 209e0731eceSdlg #define IXL_AQ_OP_GET_RSS_KEY 0x0b04 /* 722 only */ 210e0731eceSdlg #define IXL_AQ_OP_GET_RSS_LUT 0x0b05 /* 722 only */ 211ccb96312Sdlg 212ccb96312Sdlg struct ixl_aq_mac_addresses { 213ccb96312Sdlg uint8_t pf_lan[ETHER_ADDR_LEN]; 214ccb96312Sdlg uint8_t pf_san[ETHER_ADDR_LEN]; 215ccb96312Sdlg uint8_t port[ETHER_ADDR_LEN]; 216ccb96312Sdlg uint8_t pf_wol[ETHER_ADDR_LEN]; 217ccb96312Sdlg } __packed; 218ccb96312Sdlg 219ccb96312Sdlg #define IXL_AQ_MAC_PF_LAN_VALID (1U << 4) 220ccb96312Sdlg #define IXL_AQ_MAC_PF_SAN_VALID (1U << 5) 221ccb96312Sdlg #define IXL_AQ_MAC_PORT_VALID (1U << 6) 222ccb96312Sdlg #define IXL_AQ_MAC_PF_WOL_VALID (1U << 7) 223ccb96312Sdlg 224ccb96312Sdlg struct ixl_aq_capability { 225ccb96312Sdlg uint16_t cap_id; 226ccb96312Sdlg #define IXL_AQ_CAP_SWITCH_MODE 0x0001 227ccb96312Sdlg #define IXL_AQ_CAP_MNG_MODE 0x0002 228ccb96312Sdlg #define IXL_AQ_CAP_NPAR_ACTIVE 0x0003 229ccb96312Sdlg #define IXL_AQ_CAP_OS2BMC_CAP 0x0004 230ccb96312Sdlg #define IXL_AQ_CAP_FUNCTIONS_VALID 0x0005 231ccb96312Sdlg #define IXL_AQ_CAP_ALTERNATE_RAM 0x0006 232ccb96312Sdlg #define IXL_AQ_CAP_WOL_AND_PROXY 0x0008 233ccb96312Sdlg #define IXL_AQ_CAP_SRIOV 0x0012 234ccb96312Sdlg #define IXL_AQ_CAP_VF 0x0013 235ccb96312Sdlg #define IXL_AQ_CAP_VMDQ 0x0014 236ccb96312Sdlg #define IXL_AQ_CAP_8021QBG 0x0015 237ccb96312Sdlg #define IXL_AQ_CAP_8021QBR 0x0016 238ccb96312Sdlg #define IXL_AQ_CAP_VSI 0x0017 239ccb96312Sdlg #define IXL_AQ_CAP_DCB 0x0018 240ccb96312Sdlg #define IXL_AQ_CAP_FCOE 0x0021 241ccb96312Sdlg #define IXL_AQ_CAP_ISCSI 0x0022 242ccb96312Sdlg #define IXL_AQ_CAP_RSS 0x0040 243ccb96312Sdlg #define IXL_AQ_CAP_RXQ 0x0041 244ccb96312Sdlg #define IXL_AQ_CAP_TXQ 0x0042 245ccb96312Sdlg #define IXL_AQ_CAP_MSIX 0x0043 246ccb96312Sdlg #define IXL_AQ_CAP_VF_MSIX 0x0044 247ccb96312Sdlg #define IXL_AQ_CAP_FLOW_DIRECTOR 0x0045 248ccb96312Sdlg #define IXL_AQ_CAP_1588 0x0046 249ccb96312Sdlg #define IXL_AQ_CAP_IWARP 0x0051 250ccb96312Sdlg #define IXL_AQ_CAP_LED 0x0061 251ccb96312Sdlg #define IXL_AQ_CAP_SDP 0x0062 252ccb96312Sdlg #define IXL_AQ_CAP_MDIO 0x0063 253ccb96312Sdlg #define IXL_AQ_CAP_WSR_PROT 0x0064 254ccb96312Sdlg #define IXL_AQ_CAP_NVM_MGMT 0x0080 255ccb96312Sdlg #define IXL_AQ_CAP_FLEX10 0x00F1 256ccb96312Sdlg #define IXL_AQ_CAP_CEM 0x00F2 257ccb96312Sdlg uint8_t major_rev; 258ccb96312Sdlg uint8_t minor_rev; 259ccb96312Sdlg uint32_t number; 260ccb96312Sdlg uint32_t logical_id; 261ccb96312Sdlg uint32_t phys_id; 262ccb96312Sdlg uint8_t _reserved[16]; 263ccb96312Sdlg } __packed __aligned(4); 264ccb96312Sdlg 265ccb96312Sdlg #define IXL_LLDP_SHUTDOWN 0x1 266ccb96312Sdlg 267ccb96312Sdlg struct ixl_aq_switch_config { 268ccb96312Sdlg uint16_t num_reported; 269ccb96312Sdlg uint16_t num_total; 270ccb96312Sdlg uint8_t _reserved[12]; 271ccb96312Sdlg } __packed __aligned(4); 272ccb96312Sdlg 273ccb96312Sdlg struct ixl_aq_switch_config_element { 274ccb96312Sdlg uint8_t type; 275ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_MAC 1 276ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_PF 2 277ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_VF 3 278ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_EMP 4 279ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_BMC 5 280ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_PV 16 281ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_VEB 17 282ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_PA 18 283ccb96312Sdlg #define IXL_AQ_SW_ELEM_TYPE_VSI 19 284ccb96312Sdlg uint8_t revision; 285ccb96312Sdlg #define IXL_AQ_SW_ELEM_REV_1 1 286ccb96312Sdlg uint16_t seid; 287ccb96312Sdlg 288ccb96312Sdlg uint16_t uplink_seid; 289ccb96312Sdlg uint16_t downlink_seid; 290ccb96312Sdlg 291ccb96312Sdlg uint8_t _reserved[3]; 292ccb96312Sdlg uint8_t connection_type; 293ccb96312Sdlg #define IXL_AQ_CONN_TYPE_REGULAR 0x1 294ccb96312Sdlg #define IXL_AQ_CONN_TYPE_DEFAULT 0x2 295ccb96312Sdlg #define IXL_AQ_CONN_TYPE_CASCADED 0x3 296ccb96312Sdlg 297ccb96312Sdlg uint16_t scheduler_id; 298ccb96312Sdlg uint16_t element_info; 299ccb96312Sdlg } __packed __aligned(4); 300ccb96312Sdlg 301ccb96312Sdlg #define IXL_PHY_TYPE_SGMII 0x00 302ccb96312Sdlg #define IXL_PHY_TYPE_1000BASE_KX 0x01 303ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_KX4 0x02 304ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_KR 0x03 305ccb96312Sdlg #define IXL_PHY_TYPE_40GBASE_KR4 0x04 306ccb96312Sdlg #define IXL_PHY_TYPE_XAUI 0x05 307ccb96312Sdlg #define IXL_PHY_TYPE_XFI 0x06 308ccb96312Sdlg #define IXL_PHY_TYPE_SFI 0x07 309ccb96312Sdlg #define IXL_PHY_TYPE_XLAUI 0x08 310ccb96312Sdlg #define IXL_PHY_TYPE_XLPPI 0x09 311ccb96312Sdlg #define IXL_PHY_TYPE_40GBASE_CR4_CU 0x0a 312ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_CR1_CU 0x0b 313ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_AOC 0x0c 314ccb96312Sdlg #define IXL_PHY_TYPE_40GBASE_AOC 0x0d 315ccb96312Sdlg #define IXL_PHY_TYPE_100BASE_TX 0x11 316ccb96312Sdlg #define IXL_PHY_TYPE_1000BASE_T 0x12 317ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_T 0x13 318ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_SR 0x14 319ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_LR 0x15 320ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_SFPP_CU 0x16 321ccb96312Sdlg #define IXL_PHY_TYPE_10GBASE_CR1 0x17 322ccb96312Sdlg #define IXL_PHY_TYPE_40GBASE_CR4 0x18 323ccb96312Sdlg #define IXL_PHY_TYPE_40GBASE_SR4 0x19 324ccb96312Sdlg #define IXL_PHY_TYPE_40GBASE_LR4 0x1a 325ccb96312Sdlg #define IXL_PHY_TYPE_1000BASE_SX 0x1b 326ccb96312Sdlg #define IXL_PHY_TYPE_1000BASE_LX 0x1c 327ccb96312Sdlg #define IXL_PHY_TYPE_1000BASE_T_OPTICAL 0x1d 328ccb96312Sdlg #define IXL_PHY_TYPE_20GBASE_KR2 0x1e 329ccb96312Sdlg 330ccb96312Sdlg #define IXL_PHY_TYPE_25GBASE_KR 0x1f 331ccb96312Sdlg #define IXL_PHY_TYPE_25GBASE_CR 0x20 332ccb96312Sdlg #define IXL_PHY_TYPE_25GBASE_SR 0x21 333ccb96312Sdlg #define IXL_PHY_TYPE_25GBASE_LR 0x22 334ccb96312Sdlg #define IXL_PHY_TYPE_25GBASE_AOC 0x23 335ccb96312Sdlg #define IXL_PHY_TYPE_25GBASE_ACC 0x24 336ccb96312Sdlg 337ccb96312Sdlg struct ixl_aq_module_desc { 338ccb96312Sdlg uint8_t oui[3]; 339ccb96312Sdlg uint8_t _reserved1; 340ccb96312Sdlg uint8_t part_number[16]; 341ccb96312Sdlg uint8_t revision[4]; 342ccb96312Sdlg uint8_t _reserved2[8]; 343ccb96312Sdlg } __packed __aligned(4); 344ccb96312Sdlg 345ccb96312Sdlg struct ixl_aq_phy_abilities { 346ccb96312Sdlg uint32_t phy_type; 347ccb96312Sdlg 348ccb96312Sdlg uint8_t link_speed; 349185ef768Syasuoka #define IXL_AQ_PHY_LINK_SPEED_100MB (1 << 1) 350185ef768Syasuoka #define IXL_AQ_PHY_LINK_SPEED_1000MB (1 << 2) 351185ef768Syasuoka #define IXL_AQ_PHY_LINK_SPEED_10GB (1 << 3) 352185ef768Syasuoka #define IXL_AQ_PHY_LINK_SPEED_40GB (1 << 4) 353185ef768Syasuoka #define IXL_AQ_PHY_LINK_SPEED_20GB (1 << 5) 354185ef768Syasuoka #define IXL_AQ_PHY_LINK_SPEED_25GB (1 << 6) 355ccb96312Sdlg uint8_t abilities; 356ccb96312Sdlg uint16_t eee_capability; 357ccb96312Sdlg 358ccb96312Sdlg uint32_t eeer_val; 359ccb96312Sdlg 360ccb96312Sdlg uint8_t d3_lpan; 361ccb96312Sdlg uint8_t phy_type_ext; 362ccb96312Sdlg #define IXL_AQ_PHY_TYPE_EXT_25G_KR 0x01 363ccb96312Sdlg #define IXL_AQ_PHY_TYPE_EXT_25G_CR 0x02 364ccb96312Sdlg #define IXL_AQ_PHY_TYPE_EXT_25G_SR 0x04 365ccb96312Sdlg #define IXL_AQ_PHY_TYPE_EXT_25G_LR 0x08 366ccb96312Sdlg uint8_t fec_cfg_curr_mod_ext_info; 367ccb96312Sdlg #define IXL_AQ_ENABLE_FEC_KR 0x01 368ccb96312Sdlg #define IXL_AQ_ENABLE_FEC_RS 0x02 369ccb96312Sdlg #define IXL_AQ_REQUEST_FEC_KR 0x04 370ccb96312Sdlg #define IXL_AQ_REQUEST_FEC_RS 0x08 371ccb96312Sdlg #define IXL_AQ_ENABLE_FEC_AUTO 0x10 372ccb96312Sdlg #define IXL_AQ_MODULE_TYPE_EXT_MASK 0xe0 373ccb96312Sdlg #define IXL_AQ_MODULE_TYPE_EXT_SHIFT 5 374ccb96312Sdlg uint8_t ext_comp_code; 375ccb96312Sdlg 376ccb96312Sdlg uint8_t phy_id[4]; 377ccb96312Sdlg 378ccb96312Sdlg uint8_t module_type[3]; 37925fbbcc0Sdlg #define IXL_SFF8024_ID_SFP 0x03 38025fbbcc0Sdlg #define IXL_SFF8024_ID_QSFP 0x0c 38125fbbcc0Sdlg #define IXL_SFF8024_ID_QSFP_PLUS 0x0d 38225fbbcc0Sdlg #define IXL_SFF8024_ID_QSFP28 0x11 383ccb96312Sdlg uint8_t qualified_module_count; 384ccb96312Sdlg #define IXL_AQ_PHY_MAX_QMS 16 385ccb96312Sdlg struct ixl_aq_module_desc 386ccb96312Sdlg qualified_module[IXL_AQ_PHY_MAX_QMS]; 387ccb96312Sdlg } __packed __aligned(4); 388ccb96312Sdlg 3897f4b2a0fSjmatthew struct ixl_aq_link_param { 3907f4b2a0fSjmatthew uint8_t notify; 3917f4b2a0fSjmatthew #define IXL_AQ_LINK_NOTIFY 0x03 3927f4b2a0fSjmatthew uint8_t _reserved1; 3937f4b2a0fSjmatthew uint8_t phy; 3947f4b2a0fSjmatthew uint8_t speed; 3957f4b2a0fSjmatthew uint8_t status; 3967f4b2a0fSjmatthew uint8_t _reserved2[11]; 3977f4b2a0fSjmatthew } __packed __aligned(4); 3987f4b2a0fSjmatthew 399ccb96312Sdlg struct ixl_aq_vsi_param { 400ccb96312Sdlg uint16_t uplink_seid; 401ccb96312Sdlg uint8_t connect_type; 402ccb96312Sdlg #define IXL_AQ_VSI_CONN_TYPE_NORMAL (0x1) 403ccb96312Sdlg #define IXL_AQ_VSI_CONN_TYPE_DEFAULT (0x2) 404ccb96312Sdlg #define IXL_AQ_VSI_CONN_TYPE_CASCADED (0x3) 405ccb96312Sdlg uint8_t _reserved1; 406ccb96312Sdlg 407ccb96312Sdlg uint8_t vf_id; 408ccb96312Sdlg uint8_t _reserved2; 409ccb96312Sdlg uint16_t vsi_flags; 410ccb96312Sdlg #define IXL_AQ_VSI_TYPE_SHIFT 0x0 411ccb96312Sdlg #define IXL_AQ_VSI_TYPE_MASK (0x3 << IXL_AQ_VSI_TYPE_SHIFT) 412ccb96312Sdlg #define IXL_AQ_VSI_TYPE_VF 0x0 413ccb96312Sdlg #define IXL_AQ_VSI_TYPE_VMDQ2 0x1 414ccb96312Sdlg #define IXL_AQ_VSI_TYPE_PF 0x2 415ccb96312Sdlg #define IXL_AQ_VSI_TYPE_EMP_MNG 0x3 416ccb96312Sdlg #define IXL_AQ_VSI_FLAG_CASCADED_PV 0x4 417ccb96312Sdlg 418ccb96312Sdlg uint32_t addr_hi; 419ccb96312Sdlg uint32_t addr_lo; 420ccb96312Sdlg } __packed __aligned(16); 421ccb96312Sdlg 4222bb8400cSjmatthew struct ixl_aq_add_macvlan { 4232bb8400cSjmatthew uint16_t num_addrs; 4242bb8400cSjmatthew uint16_t seid0; 4252bb8400cSjmatthew uint16_t seid1; 4262bb8400cSjmatthew uint16_t seid2; 4272bb8400cSjmatthew uint32_t addr_hi; 4282bb8400cSjmatthew uint32_t addr_lo; 4292bb8400cSjmatthew } __packed __aligned(16); 4302bb8400cSjmatthew 4312bb8400cSjmatthew struct ixl_aq_add_macvlan_elem { 4322bb8400cSjmatthew uint8_t macaddr[6]; 4332bb8400cSjmatthew uint16_t vlan; 4342bb8400cSjmatthew uint16_t flags; 4352bb8400cSjmatthew #define IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH 0x0001 4362bb8400cSjmatthew #define IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN 0x0004 4372bb8400cSjmatthew uint16_t queue; 4382bb8400cSjmatthew uint32_t _reserved; 4392bb8400cSjmatthew } __packed __aligned(16); 4402bb8400cSjmatthew 4412bb8400cSjmatthew struct ixl_aq_remove_macvlan { 4422bb8400cSjmatthew uint16_t num_addrs; 4432bb8400cSjmatthew uint16_t seid0; 4442bb8400cSjmatthew uint16_t seid1; 4452bb8400cSjmatthew uint16_t seid2; 4462bb8400cSjmatthew uint32_t addr_hi; 4472bb8400cSjmatthew uint32_t addr_lo; 4482bb8400cSjmatthew } __packed __aligned(16); 4492bb8400cSjmatthew 4502bb8400cSjmatthew struct ixl_aq_remove_macvlan_elem { 4512bb8400cSjmatthew uint8_t macaddr[6]; 4522bb8400cSjmatthew uint16_t vlan; 4532bb8400cSjmatthew uint8_t flags; 4542bb8400cSjmatthew #define IXL_AQ_OP_REMOVE_MACVLAN_PERFECT_MATCH 0x0001 4552bb8400cSjmatthew #define IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN 0x0008 4562bb8400cSjmatthew uint8_t _reserved[7]; 4572bb8400cSjmatthew } __packed __aligned(16); 4582bb8400cSjmatthew 459ccb96312Sdlg struct ixl_aq_vsi_reply { 460ccb96312Sdlg uint16_t seid; 461ccb96312Sdlg uint16_t vsi_number; 462ccb96312Sdlg 463ccb96312Sdlg uint16_t vsis_used; 464ccb96312Sdlg uint16_t vsis_free; 465ccb96312Sdlg 466ccb96312Sdlg uint32_t addr_hi; 467ccb96312Sdlg uint32_t addr_lo; 468ccb96312Sdlg } __packed __aligned(16); 469ccb96312Sdlg 470ccb96312Sdlg struct ixl_aq_vsi_data { 471ccb96312Sdlg /* first 96 byte are written by SW */ 472ccb96312Sdlg uint16_t valid_sections; 473ccb96312Sdlg #define IXL_AQ_VSI_VALID_SWITCH (1 << 0) 474ccb96312Sdlg #define IXL_AQ_VSI_VALID_SECURITY (1 << 1) 475ccb96312Sdlg #define IXL_AQ_VSI_VALID_VLAN (1 << 2) 476ccb96312Sdlg #define IXL_AQ_VSI_VALID_CAS_PV (1 << 3) 477ccb96312Sdlg #define IXL_AQ_VSI_VALID_INGRESS_UP (1 << 4) 478ccb96312Sdlg #define IXL_AQ_VSI_VALID_EGRESS_UP (1 << 5) 479ccb96312Sdlg #define IXL_AQ_VSI_VALID_QUEUE_MAP (1 << 6) 480ccb96312Sdlg #define IXL_AQ_VSI_VALID_QUEUE_OPT (1 << 7) 481ccb96312Sdlg #define IXL_AQ_VSI_VALID_OUTER_UP (1 << 8) 482ccb96312Sdlg #define IXL_AQ_VSI_VALID_SCHED (1 << 9) 483ccb96312Sdlg /* switch section */ 484ccb96312Sdlg uint16_t switch_id; 485ccb96312Sdlg #define IXL_AQ_VSI_SWITCH_ID_SHIFT 0 486ccb96312Sdlg #define IXL_AQ_VSI_SWITCH_ID_MASK (0xfff << IXL_AQ_VSI_SWITCH_ID_SHIFT) 487ccb96312Sdlg #define IXL_AQ_VSI_SWITCH_NOT_STAG (1 << 12) 488ccb96312Sdlg #define IXL_AQ_VSI_SWITCH_LOCAL_LB (1 << 14) 489ccb96312Sdlg 490ccb96312Sdlg uint8_t _reserved1[2]; 491ccb96312Sdlg /* security section */ 492ccb96312Sdlg uint8_t sec_flags; 493ccb96312Sdlg #define IXL_AQ_VSI_SEC_ALLOW_DEST_OVRD (1 << 0) 494ccb96312Sdlg #define IXL_AQ_VSI_SEC_ENABLE_VLAN_CHK (1 << 1) 495ccb96312Sdlg #define IXL_AQ_VSI_SEC_ENABLE_MAC_CHK (1 << 2) 496ccb96312Sdlg uint8_t _reserved2; 497ccb96312Sdlg 498ccb96312Sdlg /* vlan section */ 499ccb96312Sdlg uint16_t pvid; 500ccb96312Sdlg uint16_t fcoe_pvid; 501ccb96312Sdlg 502ccb96312Sdlg uint8_t port_vlan_flags; 503ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_MODE_SHIFT 0 504ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_MODE_MASK (0x3 << IXL_AQ_VSI_PVLAN_MODE_SHIFT) 505ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_MODE_TAGGED (0x1 << IXL_AQ_VSI_PVLAN_MODE_SHIFT) 506ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_MODE_UNTAGGED (0x2 << IXL_AQ_VSI_PVLAN_MODE_SHIFT) 507ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_MODE_ALL (0x3 << IXL_AQ_VSI_PVLAN_MODE_SHIFT) 508ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_INSERT_PVID (0x4 << IXL_AQ_VSI_PVLAN_MODE_SHIFT) 509ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_EMOD_SHIFT 0x3 510ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_EMOD_MASK (0x3 << IXL_AQ_VSI_PVLAN_EMOD_SHIFT) 511ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_EMOD_STR_BOTH (0x0 << IXL_AQ_VSI_PVLAN_EMOD_SHIFT) 512ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_EMOD_STR_UP (0x1 << IXL_AQ_VSI_PVLAN_EMOD_SHIFT) 513ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_EMOD_STR (0x2 << IXL_AQ_VSI_PVLAN_EMOD_SHIFT) 514ccb96312Sdlg #define IXL_AQ_VSI_PVLAN_EMOD_NOTHING (0x3 << IXL_AQ_VSI_PVLAN_EMOD_SHIFT) 515ccb96312Sdlg uint8_t _reserved3[3]; 516ccb96312Sdlg 517ccb96312Sdlg /* ingress egress up section */ 518ccb96312Sdlg uint32_t ingress_table; 519ccb96312Sdlg #define IXL_AQ_VSI_UP_SHIFT(_up) ((_up) * 3) 520ccb96312Sdlg #define IXL_AQ_VSI_UP_MASK(_up) (0x7 << (IXL_AQ_VSI_UP_SHIFT(_up)) 521ccb96312Sdlg uint32_t egress_table; 522ccb96312Sdlg 523ccb96312Sdlg /* cascaded pv section */ 524ccb96312Sdlg uint16_t cas_pv_tag; 525ccb96312Sdlg uint8_t cas_pv_flags; 526ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_TAGX_SHIFT 0 527ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_TAGX_MASK (0x3 << IXL_AQ_VSI_CAS_PV_TAGX_SHIFT) 528ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_TAGX_LEAVE (0x0 << IXL_AQ_VSI_CAS_PV_TAGX_SHIFT) 529ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_TAGX_REMOVE (0x1 << IXL_AQ_VSI_CAS_PV_TAGX_SHIFT) 530ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_TAGX_COPY (0x2 << IXL_AQ_VSI_CAS_PV_TAGX_SHIFT) 531ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_INSERT_TAG (1 << 4) 532ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_ETAG_PRUNE (1 << 5) 533ccb96312Sdlg #define IXL_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG \ 534ccb96312Sdlg (1 << 6) 535ccb96312Sdlg uint8_t _reserved4; 536ccb96312Sdlg 537ccb96312Sdlg /* queue mapping section */ 538ccb96312Sdlg uint16_t mapping_flags; 539ccb96312Sdlg #define IXL_AQ_VSI_QUE_MAP_MASK 0x1 540ccb96312Sdlg #define IXL_AQ_VSI_QUE_MAP_CONTIG 0x0 541ccb96312Sdlg #define IXL_AQ_VSI_QUE_MAP_NONCONTIG 0x1 542ccb96312Sdlg uint16_t queue_mapping[16]; 543ccb96312Sdlg #define IXL_AQ_VSI_QUEUE_SHIFT 0x0 544ccb96312Sdlg #define IXL_AQ_VSI_QUEUE_MASK (0x7ff << IXL_AQ_VSI_QUEUE_SHIFT) 545ccb96312Sdlg uint16_t tc_mapping[8]; 546ccb96312Sdlg #define IXL_AQ_VSI_TC_Q_OFFSET_SHIFT 0 547ccb96312Sdlg #define IXL_AQ_VSI_TC_Q_OFFSET_MASK (0x1ff << IXL_AQ_VSI_TC_Q_OFFSET_SHIFT) 548ccb96312Sdlg #define IXL_AQ_VSI_TC_Q_NUMBER_SHIFT 9 549ccb96312Sdlg #define IXL_AQ_VSI_TC_Q_NUMBER_MASK (0x7 << IXL_AQ_VSI_TC_Q_NUMBER_SHIFT) 550ccb96312Sdlg 551ccb96312Sdlg /* queueing option section */ 552ccb96312Sdlg uint8_t queueing_opt_flags; 553ccb96312Sdlg #define IXL_AQ_VSI_QUE_OPT_MCAST_UDP_EN (1 << 2) 554ccb96312Sdlg #define IXL_AQ_VSI_QUE_OPT_UCAST_UDP_EN (1 << 3) 555ccb96312Sdlg #define IXL_AQ_VSI_QUE_OPT_TCP_EN (1 << 4) 556ccb96312Sdlg #define IXL_AQ_VSI_QUE_OPT_FCOE_EN (1 << 5) 557ccb96312Sdlg #define IXL_AQ_VSI_QUE_OPT_RSS_LUT_PF 0 558ccb96312Sdlg #define IXL_AQ_VSI_QUE_OPT_RSS_LUT_VSI (1 << 6) 559ccb96312Sdlg uint8_t _reserved5[3]; 560ccb96312Sdlg 561ccb96312Sdlg /* scheduler section */ 562ccb96312Sdlg uint8_t up_enable_bits; 563ccb96312Sdlg uint8_t _reserved6; 564ccb96312Sdlg 565ccb96312Sdlg /* outer up section */ 566ccb96312Sdlg uint32_t outer_up_table; /* same as ingress/egress tables */ 567ccb96312Sdlg uint8_t _reserved7[8]; 568ccb96312Sdlg 569ccb96312Sdlg /* last 32 bytes are written by FW */ 570ccb96312Sdlg uint16_t qs_handle[8]; 571ccb96312Sdlg #define IXL_AQ_VSI_QS_HANDLE_INVALID 0xffff 572ccb96312Sdlg uint16_t stat_counter_idx; 573ccb96312Sdlg uint16_t sched_id; 574ccb96312Sdlg 575ccb96312Sdlg uint8_t _reserved8[12]; 576ccb96312Sdlg } __packed __aligned(8); 577ccb96312Sdlg 578ccb96312Sdlg CTASSERT(sizeof(struct ixl_aq_vsi_data) == 128); 579ccb96312Sdlg 580ccb96312Sdlg struct ixl_aq_vsi_promisc_param { 581ccb96312Sdlg uint16_t flags; 582ccb96312Sdlg uint16_t valid_flags; 583ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_FLAG_UCAST (1 << 0) 584ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_FLAG_MCAST (1 << 1) 585ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_FLAG_BCAST (1 << 2) 586ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_FLAG_DFLT (1 << 3) 587ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_FLAG_VLAN (1 << 4) 588ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_FLAG_RXONLY (1 << 15) 589ccb96312Sdlg 590ccb96312Sdlg uint16_t seid; 591ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_SEID_VALID (1 << 15) 592ccb96312Sdlg uint16_t vlan; 593ccb96312Sdlg #define IXL_AQ_VSI_PROMISC_VLAN_VALID (1 << 15) 594ccb96312Sdlg uint32_t reserved[2]; 595ccb96312Sdlg } __packed __aligned(8); 596ccb96312Sdlg 597ccb96312Sdlg struct ixl_aq_veb_param { 598ccb96312Sdlg uint16_t uplink_seid; 599ccb96312Sdlg uint16_t downlink_seid; 600ccb96312Sdlg uint16_t veb_flags; 601ccb96312Sdlg #define IXL_AQ_ADD_VEB_FLOATING (1 << 0) 602ccb96312Sdlg #define IXL_AQ_ADD_VEB_PORT_TYPE_SHIFT 1 603ccb96312Sdlg #define IXL_AQ_ADD_VEB_PORT_TYPE_MASK (0x3 << IXL_AQ_ADD_VEB_PORT_TYPE_SHIFT) 604ccb96312Sdlg #define IXL_AQ_ADD_VEB_PORT_TYPE_DEFAULT \ 605ccb96312Sdlg (0x2 << IXL_AQ_ADD_VEB_PORT_TYPE_SHIFT) 606ccb96312Sdlg #define IXL_AQ_ADD_VEB_PORT_TYPE_DATA (0x4 << IXL_AQ_ADD_VEB_PORT_TYPE_SHIFT) 607ccb96312Sdlg #define IXL_AQ_ADD_VEB_ENABLE_L2_FILTER (1 << 3) /* deprecated */ 608ccb96312Sdlg #define IXL_AQ_ADD_VEB_DISABLE_STATS (1 << 4) 609ccb96312Sdlg uint8_t enable_tcs; 610ccb96312Sdlg uint8_t _reserved[9]; 611ccb96312Sdlg } __packed __aligned(16); 612ccb96312Sdlg 613ccb96312Sdlg struct ixl_aq_veb_reply { 614ccb96312Sdlg uint16_t _reserved1; 615ccb96312Sdlg uint16_t _reserved2; 616ccb96312Sdlg uint16_t _reserved3; 617ccb96312Sdlg uint16_t switch_seid; 618ccb96312Sdlg uint16_t veb_seid; 619ccb96312Sdlg #define IXL_AQ_VEB_ERR_FLAG_NO_VEB (1 << 0) 620ccb96312Sdlg #define IXL_AQ_VEB_ERR_FLAG_NO_SCHED (1 << 1) 621ccb96312Sdlg #define IXL_AQ_VEB_ERR_FLAG_NO_COUNTER (1 << 2) 622ccb96312Sdlg #define IXL_AQ_VEB_ERR_FLAG_NO_ENTRY (1 << 3); 623ccb96312Sdlg uint16_t statistic_index; 624ccb96312Sdlg uint16_t vebs_used; 625ccb96312Sdlg uint16_t vebs_free; 626ccb96312Sdlg } __packed __aligned(16); 627ccb96312Sdlg 628ccb96312Sdlg /* GET PHY ABILITIES param[0] */ 629ccb96312Sdlg #define IXL_AQ_PHY_REPORT_QUAL (1 << 0) 630ccb96312Sdlg #define IXL_AQ_PHY_REPORT_INIT (1 << 1) 631ccb96312Sdlg 6324eec9beaSdlg struct ixl_aq_phy_reg_access { 6334eec9beaSdlg uint8_t phy_iface; 6344eec9beaSdlg #define IXL_AQ_PHY_IF_INTERNAL 0 6354eec9beaSdlg #define IXL_AQ_PHY_IF_EXTERNAL 1 6364eec9beaSdlg #define IXL_AQ_PHY_IF_MODULE 2 6374eec9beaSdlg uint8_t dev_addr; 63825fbbcc0Sdlg uint16_t recall; 63925fbbcc0Sdlg #define IXL_AQ_PHY_QSFP_DEV_ADDR 0 64025fbbcc0Sdlg #define IXL_AQ_PHY_QSFP_LAST 1 6414eec9beaSdlg uint32_t reg; 6424eec9beaSdlg uint32_t val; 6434eec9beaSdlg uint32_t _reserved2; 6444eec9beaSdlg } __packed __aligned(16); 6454eec9beaSdlg 646ccb96312Sdlg /* RESTART_AN param[0] */ 647ccb96312Sdlg #define IXL_AQ_PHY_RESTART_AN (1 << 1) 648ccb96312Sdlg #define IXL_AQ_PHY_LINK_ENABLE (1 << 2) 649ccb96312Sdlg 650ccb96312Sdlg struct ixl_aq_link_status { /* this occupies the iaq_param space */ 651ccb96312Sdlg uint16_t command_flags; /* only field set on command */ 652ccb96312Sdlg #define IXL_AQ_LSE_MASK 0x3 653ccb96312Sdlg #define IXL_AQ_LSE_NOP 0x0 654ccb96312Sdlg #define IXL_AQ_LSE_DISABLE 0x2 655ccb96312Sdlg #define IXL_AQ_LSE_ENABLE 0x3 656ccb96312Sdlg #define IXL_AQ_LSE_IS_ENABLED 0x1 /* only set in response */ 657ccb96312Sdlg uint8_t phy_type; 658ccb96312Sdlg uint8_t link_speed; 659a4742ff3Sdlg #define IXL_AQ_LINK_SPEED_1GB (1 << 2) 660a4742ff3Sdlg #define IXL_AQ_LINK_SPEED_10GB (1 << 3) 661a4742ff3Sdlg #define IXL_AQ_LINK_SPEED_40GB (1 << 4) 662a4742ff3Sdlg #define IXL_AQ_LINK_SPEED_25GB (1 << 6) 663ccb96312Sdlg uint8_t link_info; 664ccb96312Sdlg #define IXL_AQ_LINK_UP_FUNCTION 0x01 665ccb96312Sdlg #define IXL_AQ_LINK_FAULT 0x02 666ccb96312Sdlg #define IXL_AQ_LINK_FAULT_TX 0x04 667ccb96312Sdlg #define IXL_AQ_LINK_FAULT_RX 0x08 668ccb96312Sdlg #define IXL_AQ_LINK_FAULT_REMOTE 0x10 669ccb96312Sdlg #define IXL_AQ_LINK_UP_PORT 0x20 670ccb96312Sdlg #define IXL_AQ_MEDIA_AVAILABLE 0x40 671ccb96312Sdlg #define IXL_AQ_SIGNAL_DETECT 0x80 672ccb96312Sdlg uint8_t an_info; 673ccb96312Sdlg #define IXL_AQ_AN_COMPLETED 0x01 674ccb96312Sdlg #define IXL_AQ_LP_AN_ABILITY 0x02 675ccb96312Sdlg #define IXL_AQ_PD_FAULT 0x04 676ccb96312Sdlg #define IXL_AQ_FEC_EN 0x08 677ccb96312Sdlg #define IXL_AQ_PHY_LOW_POWER 0x10 678ccb96312Sdlg #define IXL_AQ_LINK_PAUSE_TX 0x20 679ccb96312Sdlg #define IXL_AQ_LINK_PAUSE_RX 0x40 680ccb96312Sdlg #define IXL_AQ_QUALIFIED_MODULE 0x80 681ccb96312Sdlg 682ccb96312Sdlg uint8_t ext_info; 683ccb96312Sdlg #define IXL_AQ_LINK_PHY_TEMP_ALARM 0x01 684ccb96312Sdlg #define IXL_AQ_LINK_XCESSIVE_ERRORS 0x02 685ccb96312Sdlg #define IXL_AQ_LINK_TX_SHIFT 0x02 686ccb96312Sdlg #define IXL_AQ_LINK_TX_MASK (0x03 << IXL_AQ_LINK_TX_SHIFT) 687ccb96312Sdlg #define IXL_AQ_LINK_TX_ACTIVE 0x00 688ccb96312Sdlg #define IXL_AQ_LINK_TX_DRAINED 0x01 689ccb96312Sdlg #define IXL_AQ_LINK_TX_FLUSHED 0x03 690ccb96312Sdlg #define IXL_AQ_LINK_FORCED_40G 0x10 691ccb96312Sdlg /* 25G Error Codes */ 692ccb96312Sdlg #define IXL_AQ_25G_NO_ERR 0X00 693ccb96312Sdlg #define IXL_AQ_25G_NOT_PRESENT 0X01 694ccb96312Sdlg #define IXL_AQ_25G_NVM_CRC_ERR 0X02 695ccb96312Sdlg #define IXL_AQ_25G_SBUS_UCODE_ERR 0X03 696ccb96312Sdlg #define IXL_AQ_25G_SERDES_UCODE_ERR 0X04 697ccb96312Sdlg #define IXL_AQ_25G_NIMB_UCODE_ERR 0X05 698ccb96312Sdlg uint8_t loopback; 699ccb96312Sdlg uint16_t max_frame_size; 700ccb96312Sdlg 701ccb96312Sdlg uint8_t config; 702ccb96312Sdlg #define IXL_AQ_CONFIG_FEC_KR_ENA 0x01 703ccb96312Sdlg #define IXL_AQ_CONFIG_FEC_RS_ENA 0x02 704ccb96312Sdlg #define IXL_AQ_CONFIG_CRC_ENA 0x04 705ccb96312Sdlg #define IXL_AQ_CONFIG_PACING_MASK 0x78 706ccb96312Sdlg uint8_t power_desc; 707ccb96312Sdlg #define IXL_AQ_LINK_POWER_CLASS_1 0x00 708ccb96312Sdlg #define IXL_AQ_LINK_POWER_CLASS_2 0x01 709ccb96312Sdlg #define IXL_AQ_LINK_POWER_CLASS_3 0x02 710ccb96312Sdlg #define IXL_AQ_LINK_POWER_CLASS_4 0x03 711ccb96312Sdlg #define IXL_AQ_PWR_CLASS_MASK 0x03 712ccb96312Sdlg 713ccb96312Sdlg uint8_t reserved[4]; 714ccb96312Sdlg } __packed __aligned(4); 715ccb96312Sdlg /* event mask command flags for param[2] */ 716ccb96312Sdlg #define IXL_AQ_PHY_EV_MASK 0x3ff 717ccb96312Sdlg #define IXL_AQ_PHY_EV_LINK_UPDOWN (1 << 1) 718ccb96312Sdlg #define IXL_AQ_PHY_EV_MEDIA_NA (1 << 2) 719ccb96312Sdlg #define IXL_AQ_PHY_EV_LINK_FAULT (1 << 3) 720ccb96312Sdlg #define IXL_AQ_PHY_EV_PHY_TEMP_ALARM (1 << 4) 721ccb96312Sdlg #define IXL_AQ_PHY_EV_EXCESS_ERRORS (1 << 5) 722ccb96312Sdlg #define IXL_AQ_PHY_EV_SIGNAL_DETECT (1 << 6) 723ccb96312Sdlg #define IXL_AQ_PHY_EV_AN_COMPLETED (1 << 7) 724ccb96312Sdlg #define IXL_AQ_PHY_EV_MODULE_QUAL_FAIL (1 << 8) 725ccb96312Sdlg #define IXL_AQ_PHY_EV_PORT_TX_SUSPENDED (1 << 9) 726ccb96312Sdlg 727e0731eceSdlg struct ixl_aq_rss_lut { /* 722 */ 728e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_VSI_VALID (1 << 15) 729e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_VSI_ID_SHIFT 0 730e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_VSI_ID_MASK \ 731e0731eceSdlg (0x3FF << IXL_AQ_SET_RSS_LUT_VSI_ID_SHIFT) 732e0731eceSdlg 733e0731eceSdlg uint16_t vsi_number; 734e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_TABLE_TYPE_SHIFT 0 735e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_TABLE_TYPE_MASK \ 736e0731eceSdlg (0x1 << IXL_AQ_SET_RSS_LUT_TABLE_TYPE_SHIFT) 737e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_TABLE_TYPE_VSI 0 738e0731eceSdlg #define IXL_AQ_SET_RSS_LUT_TABLE_TYPE_PF 1 739e0731eceSdlg uint16_t flags; 740e0731eceSdlg uint8_t _reserved[4]; 741e0731eceSdlg uint32_t addr_hi; 742e0731eceSdlg uint32_t addr_lo; 743e0731eceSdlg } __packed __aligned(16); 744e0731eceSdlg 745e0731eceSdlg struct ixl_aq_get_set_rss_key { /* 722 */ 746e0731eceSdlg #define IXL_AQ_SET_RSS_KEY_VSI_VALID (1 << 15) 747e0731eceSdlg #define IXL_AQ_SET_RSS_KEY_VSI_ID_SHIFT 0 748e0731eceSdlg #define IXL_AQ_SET_RSS_KEY_VSI_ID_MASK \ 749e0731eceSdlg (0x3FF << IXL_AQ_SET_RSS_KEY_VSI_ID_SHIFT) 750e0731eceSdlg uint16_t vsi_number; 751e0731eceSdlg uint8_t _reserved[6]; 752e0731eceSdlg uint32_t addr_hi; 753e0731eceSdlg uint32_t addr_lo; 754e0731eceSdlg } __packed __aligned(16); 755e0731eceSdlg 756ccb96312Sdlg /* aq response codes */ 757ccb96312Sdlg #define IXL_AQ_RC_OK 0 /* success */ 758ccb96312Sdlg #define IXL_AQ_RC_EPERM 1 /* Operation not permitted */ 759ccb96312Sdlg #define IXL_AQ_RC_ENOENT 2 /* No such element */ 760ccb96312Sdlg #define IXL_AQ_RC_ESRCH 3 /* Bad opcode */ 761ccb96312Sdlg #define IXL_AQ_RC_EINTR 4 /* operation interrupted */ 762ccb96312Sdlg #define IXL_AQ_RC_EIO 5 /* I/O error */ 763ccb96312Sdlg #define IXL_AQ_RC_ENXIO 6 /* No such resource */ 764ccb96312Sdlg #define IXL_AQ_RC_E2BIG 7 /* Arg too long */ 765ccb96312Sdlg #define IXL_AQ_RC_EAGAIN 8 /* Try again */ 766ccb96312Sdlg #define IXL_AQ_RC_ENOMEM 9 /* Out of memory */ 767ccb96312Sdlg #define IXL_AQ_RC_EACCES 10 /* Permission denied */ 768ccb96312Sdlg #define IXL_AQ_RC_EFAULT 11 /* Bad address */ 769ccb96312Sdlg #define IXL_AQ_RC_EBUSY 12 /* Device or resource busy */ 770ccb96312Sdlg #define IXL_AQ_RC_EEXIST 13 /* object already exists */ 771ccb96312Sdlg #define IXL_AQ_RC_EINVAL 14 /* invalid argument */ 772ccb96312Sdlg #define IXL_AQ_RC_ENOTTY 15 /* not a typewriter */ 773ccb96312Sdlg #define IXL_AQ_RC_ENOSPC 16 /* No space or alloc failure */ 774ccb96312Sdlg #define IXL_AQ_RC_ENOSYS 17 /* function not implemented */ 775ccb96312Sdlg #define IXL_AQ_RC_ERANGE 18 /* parameter out of range */ 776ccb96312Sdlg #define IXL_AQ_RC_EFLUSHED 19 /* cmd flushed due to prev error */ 777ccb96312Sdlg #define IXL_AQ_RC_BAD_ADDR 20 /* contains a bad pointer */ 778ccb96312Sdlg #define IXL_AQ_RC_EMODE 21 /* not allowed in current mode */ 779ccb96312Sdlg #define IXL_AQ_RC_EFBIG 22 /* file too large */ 780ccb96312Sdlg 781ccb96312Sdlg struct ixl_tx_desc { 782ccb96312Sdlg uint64_t addr; 783ccb96312Sdlg uint64_t cmd; 784ccb96312Sdlg #define IXL_TX_DESC_DTYPE_SHIFT 0 785ccb96312Sdlg #define IXL_TX_DESC_DTYPE_MASK (0xfULL << IXL_TX_DESC_DTYPE_SHIFT) 786ccb96312Sdlg #define IXL_TX_DESC_DTYPE_DATA (0x0ULL << IXL_TX_DESC_DTYPE_SHIFT) 787ccb96312Sdlg #define IXL_TX_DESC_DTYPE_NOP (0x1ULL << IXL_TX_DESC_DTYPE_SHIFT) 788ccb96312Sdlg #define IXL_TX_DESC_DTYPE_CONTEXT (0x1ULL << IXL_TX_DESC_DTYPE_SHIFT) 789ccb96312Sdlg #define IXL_TX_DESC_DTYPE_FCOE_CTX (0x2ULL << IXL_TX_DESC_DTYPE_SHIFT) 790ccb96312Sdlg #define IXL_TX_DESC_DTYPE_FD (0x8ULL << IXL_TX_DESC_DTYPE_SHIFT) 791ccb96312Sdlg #define IXL_TX_DESC_DTYPE_DDP_CTX (0x9ULL << IXL_TX_DESC_DTYPE_SHIFT) 792ccb96312Sdlg #define IXL_TX_DESC_DTYPE_FLEX_DATA (0xbULL << IXL_TX_DESC_DTYPE_SHIFT) 793ccb96312Sdlg #define IXL_TX_DESC_DTYPE_FLEX_CTX_1 (0xcULL << IXL_TX_DESC_DTYPE_SHIFT) 794ccb96312Sdlg #define IXL_TX_DESC_DTYPE_FLEX_CTX_2 (0xdULL << IXL_TX_DESC_DTYPE_SHIFT) 795ccb96312Sdlg #define IXL_TX_DESC_DTYPE_DONE (0xfULL << IXL_TX_DESC_DTYPE_SHIFT) 796ccb96312Sdlg 797ccb96312Sdlg #define IXL_TX_DESC_CMD_SHIFT 4 798ccb96312Sdlg #define IXL_TX_DESC_CMD_MASK (0x3ffULL << IXL_TX_DESC_CMD_SHIFT) 799ccb96312Sdlg #define IXL_TX_DESC_CMD_EOP (0x001 << IXL_TX_DESC_CMD_SHIFT) 800ccb96312Sdlg #define IXL_TX_DESC_CMD_RS (0x002 << IXL_TX_DESC_CMD_SHIFT) 801ccb96312Sdlg #define IXL_TX_DESC_CMD_ICRC (0x004 << IXL_TX_DESC_CMD_SHIFT) 802ccb96312Sdlg #define IXL_TX_DESC_CMD_IL2TAG1 (0x008 << IXL_TX_DESC_CMD_SHIFT) 803ccb96312Sdlg #define IXL_TX_DESC_CMD_DUMMY (0x010 << IXL_TX_DESC_CMD_SHIFT) 804ccb96312Sdlg #define IXL_TX_DESC_CMD_IIPT_MASK (0x060 << IXL_TX_DESC_CMD_SHIFT) 805ccb96312Sdlg #define IXL_TX_DESC_CMD_IIPT_NONIP (0x000 << IXL_TX_DESC_CMD_SHIFT) 806ccb96312Sdlg #define IXL_TX_DESC_CMD_IIPT_IPV6 (0x020 << IXL_TX_DESC_CMD_SHIFT) 807ccb96312Sdlg #define IXL_TX_DESC_CMD_IIPT_IPV4 (0x040 << IXL_TX_DESC_CMD_SHIFT) 808ccb96312Sdlg #define IXL_TX_DESC_CMD_IIPT_IPV4_CSUM (0x060 << IXL_TX_DESC_CMD_SHIFT) 809ccb96312Sdlg #define IXL_TX_DESC_CMD_FCOET (0x080 << IXL_TX_DESC_CMD_SHIFT) 810ccb96312Sdlg #define IXL_TX_DESC_CMD_L4T_EOFT_MASK (0x300 << IXL_TX_DESC_CMD_SHIFT) 811ccb96312Sdlg #define IXL_TX_DESC_CMD_L4T_EOFT_UNK (0x000 << IXL_TX_DESC_CMD_SHIFT) 812ccb96312Sdlg #define IXL_TX_DESC_CMD_L4T_EOFT_TCP (0x100 << IXL_TX_DESC_CMD_SHIFT) 813ccb96312Sdlg #define IXL_TX_DESC_CMD_L4T_EOFT_SCTP (0x200 << IXL_TX_DESC_CMD_SHIFT) 814ccb96312Sdlg #define IXL_TX_DESC_CMD_L4T_EOFT_UDP (0x300 << IXL_TX_DESC_CMD_SHIFT) 815ccb96312Sdlg 816ccb96312Sdlg #define IXL_TX_DESC_MACLEN_SHIFT 16 817ccb96312Sdlg #define IXL_TX_DESC_MACLEN_MASK (0x7fULL << IXL_TX_DESC_MACLEN_SHIFT) 818ccb96312Sdlg #define IXL_TX_DESC_IPLEN_SHIFT 23 819ccb96312Sdlg #define IXL_TX_DESC_IPLEN_MASK (0x7fULL << IXL_TX_DESC_IPLEN_SHIFT) 820ccb96312Sdlg #define IXL_TX_DESC_L4LEN_SHIFT 30 821ccb96312Sdlg #define IXL_TX_DESC_L4LEN_MASK (0xfULL << IXL_TX_DESC_L4LEN_SHIFT) 822ccb96312Sdlg #define IXL_TX_DESC_FCLEN_SHIFT 30 823ccb96312Sdlg #define IXL_TX_DESC_FCLEN_MASK (0xfULL << IXL_TX_DESC_FCLEN_SHIFT) 824ccb96312Sdlg 825ccb96312Sdlg #define IXL_TX_DESC_BSIZE_SHIFT 34 826ccb96312Sdlg #define IXL_TX_DESC_BSIZE_MAX 0x3fffULL 827ccb96312Sdlg #define IXL_TX_DESC_BSIZE_MASK \ 828ccb96312Sdlg (IXL_TX_DESC_BSIZE_MAX << IXL_TX_DESC_BSIZE_SHIFT) 829983d220cSdlg 830f77c9c95Sjan #define IXL_TX_CTX_DESC_CMD_TSO 0x10 831f77c9c95Sjan #define IXL_TX_CTX_DESC_TLEN_SHIFT 30 832f77c9c95Sjan #define IXL_TX_CTX_DESC_MSS_SHIFT 50 833f77c9c95Sjan 834983d220cSdlg #define IXL_TX_DESC_L2TAG1_SHIFT 48 835ccb96312Sdlg } __packed __aligned(16); 836ccb96312Sdlg 837ccb96312Sdlg struct ixl_rx_rd_desc_16 { 838ccb96312Sdlg uint64_t paddr; /* packet addr */ 839ccb96312Sdlg uint64_t haddr; /* header addr */ 840ccb96312Sdlg } __packed __aligned(16); 841ccb96312Sdlg 842ccb96312Sdlg struct ixl_rx_rd_desc_32 { 843ccb96312Sdlg uint64_t paddr; /* packet addr */ 844ccb96312Sdlg uint64_t haddr; /* header addr */ 845ccb96312Sdlg uint64_t _reserved1; 846ccb96312Sdlg uint64_t _reserved2; 847ccb96312Sdlg } __packed __aligned(16); 848ccb96312Sdlg 849ccb96312Sdlg struct ixl_rx_wb_desc_16 { 850555fd15dSdlg uint16_t _reserved1; 851555fd15dSdlg uint16_t l2tag1; 8526850335aSdlg uint32_t filter_status; 853ccb96312Sdlg uint64_t qword1; 854ccb96312Sdlg #define IXL_RX_DESC_DD (1 << 0) 855ccb96312Sdlg #define IXL_RX_DESC_EOP (1 << 1) 856ccb96312Sdlg #define IXL_RX_DESC_L2TAG1P (1 << 2) 857ccb96312Sdlg #define IXL_RX_DESC_L3L4P (1 << 3) 858ccb96312Sdlg #define IXL_RX_DESC_CRCP (1 << 4) 859ccb96312Sdlg #define IXL_RX_DESC_TSYNINDX_SHIFT 5 /* TSYNINDX */ 860ccb96312Sdlg #define IXL_RX_DESC_TSYNINDX_MASK (7 << IXL_RX_DESC_TSYNINDX_SHIFT) 861ccb96312Sdlg #define IXL_RX_DESC_UMB_SHIFT 9 862ccb96312Sdlg #define IXL_RX_DESC_UMB_MASK (0x3 << IXL_RX_DESC_UMB_SHIFT) 863ccb96312Sdlg #define IXL_RX_DESC_UMB_UCAST (0x0 << IXL_RX_DESC_UMB_SHIFT) 864ccb96312Sdlg #define IXL_RX_DESC_UMB_MCAST (0x1 << IXL_RX_DESC_UMB_SHIFT) 865ccb96312Sdlg #define IXL_RX_DESC_UMB_BCAST (0x2 << IXL_RX_DESC_UMB_SHIFT) 866ccb96312Sdlg #define IXL_RX_DESC_UMB_MIRROR (0x3 << IXL_RX_DESC_UMB_SHIFT) 867ccb96312Sdlg #define IXL_RX_DESC_FLM (1 << 11) 868ccb96312Sdlg #define IXL_RX_DESC_FLTSTAT_SHIFT 12 869ccb96312Sdlg #define IXL_RX_DESC_FLTSTAT_MASK (0x3 << IXL_RX_DESC_FLTSTAT_SHIFT) 870ccb96312Sdlg #define IXL_RX_DESC_FLTSTAT_NODATA (0x0 << IXL_RX_DESC_FLTSTAT_SHIFT) 871ccb96312Sdlg #define IXL_RX_DESC_FLTSTAT_FDFILTID (0x1 << IXL_RX_DESC_FLTSTAT_SHIFT) 872ccb96312Sdlg #define IXL_RX_DESC_FLTSTAT_RSS (0x3 << IXL_RX_DESC_FLTSTAT_SHIFT) 873ccb96312Sdlg #define IXL_RX_DESC_LPBK (1 << 14) 874ccb96312Sdlg #define IXL_RX_DESC_IPV6EXTADD (1 << 15) 875ccb96312Sdlg #define IXL_RX_DESC_INT_UDP_0 (1 << 18) 876ccb96312Sdlg 877ccb96312Sdlg #define IXL_RX_DESC_RXE (1 << 19) 878ccb96312Sdlg #define IXL_RX_DESC_HBO (1 << 21) 879ccb96312Sdlg #define IXL_RX_DESC_IPE (1 << 22) 880ccb96312Sdlg #define IXL_RX_DESC_L4E (1 << 23) 881ccb96312Sdlg #define IXL_RX_DESC_EIPE (1 << 24) 882ccb96312Sdlg #define IXL_RX_DESC_OVERSIZE (1 << 25) 883ccb96312Sdlg 884ccb96312Sdlg #define IXL_RX_DESC_PTYPE_SHIFT 30 885ccb96312Sdlg #define IXL_RX_DESC_PTYPE_MASK (0xffULL << IXL_RX_DESC_PTYPE_SHIFT) 886ccb96312Sdlg 887ccb96312Sdlg #define IXL_RX_DESC_PLEN_SHIFT 38 888ccb96312Sdlg #define IXL_RX_DESC_PLEN_MASK (0x3fffULL << IXL_RX_DESC_PLEN_SHIFT) 889ccb96312Sdlg #define IXL_RX_DESC_HLEN_SHIFT 42 890ccb96312Sdlg #define IXL_RX_DESC_HLEN_MASK (0x7ffULL << IXL_RX_DESC_HLEN_SHIFT) 891ccb96312Sdlg } __packed __aligned(16); 892ccb96312Sdlg 893ccb96312Sdlg struct ixl_rx_wb_desc_32 { 894ccb96312Sdlg uint64_t qword0; 895ccb96312Sdlg uint64_t qword1; 896ccb96312Sdlg uint64_t qword2; 897ccb96312Sdlg uint64_t qword3; 898ccb96312Sdlg } __packed __aligned(16); 899ccb96312Sdlg 90076ade4a7Sbluhm #define IXL_TX_PKT_DESCS 8 901ccb96312Sdlg #define IXL_TX_QUEUE_ALIGN 128 902ccb96312Sdlg #define IXL_RX_QUEUE_ALIGN 128 903ccb96312Sdlg 904bf059df2Sjmatthew #define IXL_HARDMTU 9712 /* 9726 - ETHER_HDR_LEN */ 905f77c9c95Sjan #define IXL_TSO_SIZE ((255 * 1024) - 1) 906f77c9c95Sjan #define IXL_MAX_DMA_SEG_SIZE ((16 * 1024) - 1) 907f77c9c95Sjan 908f77c9c95Sjan /* 909936f91c6Sjan * Our TCP/IP Stack is unable handle packets greater than MAXMCLBYTES. 910936f91c6Sjan * This interface is unable handle packets greater than IXL_TSO_SIZE. 911f77c9c95Sjan */ 912f77c9c95Sjan CTASSERT(MAXMCLBYTES < IXL_TSO_SIZE); 913ccb96312Sdlg 914ccb96312Sdlg #define IXL_PCIREG PCI_MAPREG_START 915ccb96312Sdlg 916ccb96312Sdlg #define IXL_ITR0 0x0 917ccb96312Sdlg #define IXL_ITR1 0x1 918ccb96312Sdlg #define IXL_ITR2 0x2 919ccb96312Sdlg #define IXL_NOITR 0x2 920ccb96312Sdlg 921ccb96312Sdlg #define IXL_AQ_NUM 256 922ccb96312Sdlg #define IXL_AQ_MASK (IXL_AQ_NUM - 1) 923ccb96312Sdlg #define IXL_AQ_ALIGN 64 /* lol */ 924ccb96312Sdlg #define IXL_AQ_BUFLEN 4096 925ccb96312Sdlg 926e0731eceSdlg /* Packet Classifier Types for filters */ 927e0731eceSdlg /* bits 0-28 are reserved for future use */ 928e0731eceSdlg #define IXL_PCT_NONF_IPV4_UDP_UCAST (1ULL << 29) /* 722 */ 929e0731eceSdlg #define IXL_PCT_NONF_IPV4_UDP_MCAST (1ULL << 30) /* 722 */ 930e0731eceSdlg #define IXL_PCT_NONF_IPV4_UDP (1ULL << 31) 931e0731eceSdlg #define IXL_PCT_NONF_IPV4_TCP_SYN_NOACK (1ULL << 32) /* 722 */ 932e0731eceSdlg #define IXL_PCT_NONF_IPV4_TCP (1ULL << 33) 933e0731eceSdlg #define IXL_PCT_NONF_IPV4_SCTP (1ULL << 34) 934e0731eceSdlg #define IXL_PCT_NONF_IPV4_OTHER (1ULL << 35) 935e0731eceSdlg #define IXL_PCT_FRAG_IPV4 (1ULL << 36) 936e0731eceSdlg /* bits 37-38 are reserved for future use */ 937e0731eceSdlg #define IXL_PCT_NONF_IPV6_UDP_UCAST (1ULL << 39) /* 722 */ 938e0731eceSdlg #define IXL_PCT_NONF_IPV6_UDP_MCAST (1ULL << 40) /* 722 */ 939e0731eceSdlg #define IXL_PCT_NONF_IPV6_UDP (1ULL << 41) 940e0731eceSdlg #define IXL_PCT_NONF_IPV6_TCP_SYN_NOACK (1ULL << 42) /* 722 */ 941e0731eceSdlg #define IXL_PCT_NONF_IPV6_TCP (1ULL << 43) 942e0731eceSdlg #define IXL_PCT_NONF_IPV6_SCTP (1ULL << 44) 943e0731eceSdlg #define IXL_PCT_NONF_IPV6_OTHER (1ULL << 45) 944e0731eceSdlg #define IXL_PCT_FRAG_IPV6 (1ULL << 46) 945e0731eceSdlg /* bit 47 is reserved for future use */ 946e0731eceSdlg #define IXL_PCT_FCOE_OX (1ULL << 48) 947e0731eceSdlg #define IXL_PCT_FCOE_RX (1ULL << 49) 948e0731eceSdlg #define IXL_PCT_FCOE_OTHER (1ULL << 50) 949e0731eceSdlg /* bits 51-62 are reserved for future use */ 950e0731eceSdlg #define IXL_PCT_L2_PAYLOAD (1ULL << 63) 951e0731eceSdlg 9528d616574Sdlg #define IXL_RSS_HENA_BASE_DEFAULT \ 9538d616574Sdlg IXL_PCT_NONF_IPV4_UDP | \ 9548d616574Sdlg IXL_PCT_NONF_IPV4_TCP | \ 9558d616574Sdlg IXL_PCT_NONF_IPV4_SCTP | \ 9568d616574Sdlg IXL_PCT_NONF_IPV4_OTHER | \ 9578d616574Sdlg IXL_PCT_FRAG_IPV4 | \ 9588d616574Sdlg IXL_PCT_NONF_IPV6_UDP | \ 9598d616574Sdlg IXL_PCT_NONF_IPV6_TCP | \ 9608d616574Sdlg IXL_PCT_NONF_IPV6_SCTP | \ 9618d616574Sdlg IXL_PCT_NONF_IPV6_OTHER | \ 9628d616574Sdlg IXL_PCT_FRAG_IPV6 | \ 9638d616574Sdlg IXL_PCT_L2_PAYLOAD 9648d616574Sdlg 9658d616574Sdlg #define IXL_RSS_HENA_BASE_710 IXL_RSS_HENA_BASE_DEFAULT 9668d616574Sdlg #define IXL_RSS_HENA_BASE_722 IXL_RSS_HENA_BASE_DEFAULT | \ 9678d616574Sdlg IXL_PCT_NONF_IPV4_UDP_UCAST | \ 9688d616574Sdlg IXL_PCT_NONF_IPV4_UDP_MCAST | \ 9698d616574Sdlg IXL_PCT_NONF_IPV6_UDP_UCAST | \ 9708d616574Sdlg IXL_PCT_NONF_IPV6_UDP_MCAST | \ 9718d616574Sdlg IXL_PCT_NONF_IPV4_TCP_SYN_NOACK | \ 9728d616574Sdlg IXL_PCT_NONF_IPV6_TCP_SYN_NOACK 9738d616574Sdlg 974ccb96312Sdlg #define IXL_HMC_ROUNDUP 512 975ccb96312Sdlg #define IXL_HMC_PGSIZE 4096 976ccb96312Sdlg #define IXL_HMC_DVASZ sizeof(uint64_t) 977ccb96312Sdlg #define IXL_HMC_PGS (IXL_HMC_PGSIZE / IXL_HMC_DVASZ) 978ccb96312Sdlg #define IXL_HMC_L2SZ (IXL_HMC_PGSIZE * IXL_HMC_PGS) 979ccb96312Sdlg #define IXL_HMC_PDVALID 1ULL 980ccb96312Sdlg 981ccb96312Sdlg struct ixl_aq_regs { 982ccb96312Sdlg bus_size_t atq_tail; 983ccb96312Sdlg bus_size_t atq_head; 984ccb96312Sdlg bus_size_t atq_len; 985ccb96312Sdlg bus_size_t atq_bal; 986ccb96312Sdlg bus_size_t atq_bah; 987ccb96312Sdlg 988ccb96312Sdlg bus_size_t arq_tail; 989ccb96312Sdlg bus_size_t arq_head; 990ccb96312Sdlg bus_size_t arq_len; 991ccb96312Sdlg bus_size_t arq_bal; 992ccb96312Sdlg bus_size_t arq_bah; 993ccb96312Sdlg 994ccb96312Sdlg uint32_t atq_len_enable; 995ccb96312Sdlg uint32_t atq_tail_mask; 996ccb96312Sdlg uint32_t atq_head_mask; 997ccb96312Sdlg 998ccb96312Sdlg uint32_t arq_len_enable; 999ccb96312Sdlg uint32_t arq_tail_mask; 1000ccb96312Sdlg uint32_t arq_head_mask; 1001ccb96312Sdlg }; 1002ccb96312Sdlg 1003ccb96312Sdlg struct ixl_phy_type { 1004ccb96312Sdlg uint64_t phy_type; 1005ccb96312Sdlg uint64_t ifm_type; 1006ccb96312Sdlg }; 1007ccb96312Sdlg 1008ccb96312Sdlg struct ixl_speed_type { 1009ccb96312Sdlg uint8_t dev_speed; 1010ccb96312Sdlg uint64_t net_speed; 1011ccb96312Sdlg }; 1012ccb96312Sdlg 1013ccb96312Sdlg struct ixl_aq_buf { 1014ccb96312Sdlg SIMPLEQ_ENTRY(ixl_aq_buf) 1015ccb96312Sdlg aqb_entry; 1016ccb96312Sdlg void *aqb_data; 1017ccb96312Sdlg bus_dmamap_t aqb_map; 1018ccb96312Sdlg }; 1019ccb96312Sdlg SIMPLEQ_HEAD(ixl_aq_bufs, ixl_aq_buf); 1020ccb96312Sdlg 1021ccb96312Sdlg struct ixl_dmamem { 1022ccb96312Sdlg bus_dmamap_t ixm_map; 1023ccb96312Sdlg bus_dma_segment_t ixm_seg; 1024ccb96312Sdlg int ixm_nsegs; 1025ccb96312Sdlg size_t ixm_size; 1026ccb96312Sdlg caddr_t ixm_kva; 1027ccb96312Sdlg }; 1028ccb96312Sdlg #define IXL_DMA_MAP(_ixm) ((_ixm)->ixm_map) 1029ccb96312Sdlg #define IXL_DMA_DVA(_ixm) ((_ixm)->ixm_map->dm_segs[0].ds_addr) 1030ccb96312Sdlg #define IXL_DMA_KVA(_ixm) ((void *)(_ixm)->ixm_kva) 1031ccb96312Sdlg #define IXL_DMA_LEN(_ixm) ((_ixm)->ixm_size) 1032ccb96312Sdlg 1033ccb96312Sdlg struct ixl_hmc_entry { 1034ccb96312Sdlg uint64_t hmc_base; 1035ccb96312Sdlg uint32_t hmc_count; 1036ccb96312Sdlg uint32_t hmc_size; 1037ccb96312Sdlg }; 1038ccb96312Sdlg 1039ccb96312Sdlg #define IXL_HMC_LAN_TX 0 1040ccb96312Sdlg #define IXL_HMC_LAN_RX 1 1041ccb96312Sdlg #define IXL_HMC_FCOE_CTX 2 1042ccb96312Sdlg #define IXL_HMC_FCOE_FILTER 3 1043ccb96312Sdlg #define IXL_HMC_COUNT 4 1044ccb96312Sdlg 1045ccb96312Sdlg struct ixl_hmc_pack { 1046ccb96312Sdlg uint16_t offset; 1047ccb96312Sdlg uint16_t width; 1048ccb96312Sdlg uint16_t lsb; 1049ccb96312Sdlg }; 1050ccb96312Sdlg 1051ccb96312Sdlg /* 1052ccb96312Sdlg * these hmc objects have weird sizes and alignments, so these are abstract 1053ccb96312Sdlg * representations of them that are nice for c to populate. 1054ccb96312Sdlg * 1055ccb96312Sdlg * the packing code relies on little-endian values being stored in the fields, 1056ccb96312Sdlg * no high bits in the fields being set, and the fields must be packed in the 1057ccb96312Sdlg * same order as they are in the ctx structure. 1058ccb96312Sdlg */ 1059ccb96312Sdlg 1060ccb96312Sdlg struct ixl_hmc_rxq { 1061ccb96312Sdlg uint16_t head; 1062ccb96312Sdlg uint8_t cpuid; 1063ccb96312Sdlg uint64_t base; 1064ccb96312Sdlg #define IXL_HMC_RXQ_BASE_UNIT 128 1065ccb96312Sdlg uint16_t qlen; 1066ccb96312Sdlg uint16_t dbuff; 1067ccb96312Sdlg #define IXL_HMC_RXQ_DBUFF_UNIT 128 1068ccb96312Sdlg uint8_t hbuff; 1069ccb96312Sdlg #define IXL_HMC_RXQ_HBUFF_UNIT 64 1070ccb96312Sdlg uint8_t dtype; 1071ccb96312Sdlg #define IXL_HMC_RXQ_DTYPE_NOSPLIT 0x0 1072ccb96312Sdlg #define IXL_HMC_RXQ_DTYPE_HSPLIT 0x1 1073ccb96312Sdlg #define IXL_HMC_RXQ_DTYPE_SPLIT_ALWAYS 0x2 1074ccb96312Sdlg uint8_t dsize; 1075ccb96312Sdlg #define IXL_HMC_RXQ_DSIZE_16 0 1076ccb96312Sdlg #define IXL_HMC_RXQ_DSIZE_32 1 1077ccb96312Sdlg uint8_t crcstrip; 1078ccb96312Sdlg uint8_t fc_ena; 1079555fd15dSdlg uint8_t l2tsel; 1080555fd15dSdlg #define IXL_HMC_RXQ_L2TSEL_2ND_TAG_TO_L2TAG1 \ 1081555fd15dSdlg 0 1082555fd15dSdlg #define IXL_HMC_RXQ_L2TSEL_1ST_TAG_TO_L2TAG1 \ 1083555fd15dSdlg 1 1084ccb96312Sdlg uint8_t hsplit_0; 1085ccb96312Sdlg uint8_t hsplit_1; 1086ccb96312Sdlg uint8_t showiv; 1087ccb96312Sdlg uint16_t rxmax; 1088ccb96312Sdlg uint8_t tphrdesc_ena; 1089ccb96312Sdlg uint8_t tphwdesc_ena; 1090ccb96312Sdlg uint8_t tphdata_ena; 1091ccb96312Sdlg uint8_t tphhead_ena; 1092ccb96312Sdlg uint8_t lrxqthresh; 1093ccb96312Sdlg uint8_t prefena; 1094ccb96312Sdlg }; 1095ccb96312Sdlg 1096ccb96312Sdlg static const struct ixl_hmc_pack ixl_hmc_pack_rxq[] = { 1097ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, head), 13, 0 }, 1098ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, cpuid), 8, 13 }, 1099ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, base), 57, 32 }, 1100ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, qlen), 13, 89 }, 1101ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, dbuff), 7, 102 }, 1102ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, hbuff), 5, 109 }, 1103ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, dtype), 2, 114 }, 1104ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, dsize), 1, 116 }, 1105ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, crcstrip), 1, 117 }, 1106ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, fc_ena), 1, 118 }, 1107555fd15dSdlg { offsetof(struct ixl_hmc_rxq, l2tsel), 1, 119 }, 1108ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, hsplit_0), 4, 120 }, 1109ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, hsplit_1), 2, 124 }, 1110ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, showiv), 1, 127 }, 1111ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, rxmax), 14, 174 }, 1112ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, tphrdesc_ena), 1, 193 }, 1113ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, tphwdesc_ena), 1, 194 }, 1114ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, tphdata_ena), 1, 195 }, 1115ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, tphhead_ena), 1, 196 }, 1116ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, lrxqthresh), 3, 198 }, 1117ccb96312Sdlg { offsetof(struct ixl_hmc_rxq, prefena), 1, 201 }, 1118ccb96312Sdlg }; 1119ccb96312Sdlg 1120ccb96312Sdlg #define IXL_HMC_RXQ_MINSIZE (201 + 1) 1121ccb96312Sdlg 1122ccb96312Sdlg struct ixl_hmc_txq { 1123ccb96312Sdlg uint16_t head; 1124ccb96312Sdlg uint8_t new_context; 1125ccb96312Sdlg uint64_t base; 1126ccb96312Sdlg #define IXL_HMC_TXQ_BASE_UNIT 128 1127ccb96312Sdlg uint8_t fc_ena; 1128ccb96312Sdlg uint8_t timesync_ena; 1129ccb96312Sdlg uint8_t fd_ena; 1130ccb96312Sdlg uint8_t alt_vlan_ena; 1131ccb96312Sdlg uint16_t thead_wb; 1132ccb96312Sdlg uint8_t cpuid; 1133ccb96312Sdlg uint8_t head_wb_ena; 1134ccb96312Sdlg #define IXL_HMC_TXQ_DESC_WB 0 1135ccb96312Sdlg #define IXL_HMC_TXQ_HEAD_WB 1 1136ccb96312Sdlg uint16_t qlen; 1137ccb96312Sdlg uint8_t tphrdesc_ena; 1138ccb96312Sdlg uint8_t tphrpacket_ena; 1139ccb96312Sdlg uint8_t tphwdesc_ena; 1140ccb96312Sdlg uint64_t head_wb_addr; 1141ccb96312Sdlg uint32_t crc; 1142ccb96312Sdlg uint16_t rdylist; 1143ccb96312Sdlg uint8_t rdylist_act; 1144ccb96312Sdlg }; 1145ccb96312Sdlg 1146ccb96312Sdlg static const struct ixl_hmc_pack ixl_hmc_pack_txq[] = { 1147ccb96312Sdlg { offsetof(struct ixl_hmc_txq, head), 13, 0 }, 1148ccb96312Sdlg { offsetof(struct ixl_hmc_txq, new_context), 1, 30 }, 1149ccb96312Sdlg { offsetof(struct ixl_hmc_txq, base), 57, 32 }, 1150ccb96312Sdlg { offsetof(struct ixl_hmc_txq, fc_ena), 1, 89 }, 1151ccb96312Sdlg { offsetof(struct ixl_hmc_txq, timesync_ena), 1, 90 }, 1152ccb96312Sdlg { offsetof(struct ixl_hmc_txq, fd_ena), 1, 91 }, 1153ccb96312Sdlg { offsetof(struct ixl_hmc_txq, alt_vlan_ena), 1, 92 }, 1154ccb96312Sdlg { offsetof(struct ixl_hmc_txq, cpuid), 8, 96 }, 1155ccb96312Sdlg /* line 1 */ 1156ccb96312Sdlg { offsetof(struct ixl_hmc_txq, thead_wb), 13, 0 + 128 }, 1157ccb96312Sdlg { offsetof(struct ixl_hmc_txq, head_wb_ena), 1, 32 + 128 }, 1158ccb96312Sdlg { offsetof(struct ixl_hmc_txq, qlen), 13, 33 + 128 }, 1159ccb96312Sdlg { offsetof(struct ixl_hmc_txq, tphrdesc_ena), 1, 46 + 128 }, 1160ccb96312Sdlg { offsetof(struct ixl_hmc_txq, tphrpacket_ena), 1, 47 + 128 }, 1161ccb96312Sdlg { offsetof(struct ixl_hmc_txq, tphwdesc_ena), 1, 48 + 128 }, 1162ccb96312Sdlg { offsetof(struct ixl_hmc_txq, head_wb_addr), 64, 64 + 128 }, 1163ccb96312Sdlg /* line 7 */ 1164ccb96312Sdlg { offsetof(struct ixl_hmc_txq, crc), 32, 0 + (7*128) }, 1165ccb96312Sdlg { offsetof(struct ixl_hmc_txq, rdylist), 10, 84 + (7*128) }, 1166ccb96312Sdlg { offsetof(struct ixl_hmc_txq, rdylist_act), 1, 94 + (7*128) }, 1167ccb96312Sdlg }; 1168ccb96312Sdlg 1169ccb96312Sdlg #define IXL_HMC_TXQ_MINSIZE (94 + (7*128) + 1) 1170ccb96312Sdlg 1171819ac441Sdlg struct ixl_rss_key { 1172819ac441Sdlg uint32_t key[13]; 1173819ac441Sdlg }; 1174819ac441Sdlg 1175819ac441Sdlg struct ixl_rss_lut_128 { 1176819ac441Sdlg uint32_t entries[128 / sizeof(uint32_t)]; 1177819ac441Sdlg }; 1178819ac441Sdlg 1179819ac441Sdlg struct ixl_rss_lut_512 { 1180819ac441Sdlg uint32_t entries[512 / sizeof(uint32_t)]; 1181819ac441Sdlg }; 1182819ac441Sdlg 1183819ac441Sdlg /* driver structures */ 1184819ac441Sdlg 1185e01adc04Sdlg struct ixl_vector; 1186819ac441Sdlg struct ixl_chip; 1187e01adc04Sdlg 1188ccb96312Sdlg struct ixl_tx_map { 1189ccb96312Sdlg struct mbuf *txm_m; 1190ccb96312Sdlg bus_dmamap_t txm_map; 1191ccb96312Sdlg unsigned int txm_eop; 1192ccb96312Sdlg }; 1193ccb96312Sdlg 1194ccb96312Sdlg struct ixl_tx_ring { 1195e01adc04Sdlg struct ixl_softc *txr_sc; 1196e01adc04Sdlg struct ixl_vector *txr_vector; 1197e01adc04Sdlg struct ifqueue *txr_ifq; 1198e01adc04Sdlg 1199ccb96312Sdlg unsigned int txr_prod; 1200ccb96312Sdlg unsigned int txr_cons; 1201ccb96312Sdlg 1202ccb96312Sdlg struct ixl_tx_map *txr_maps; 1203ccb96312Sdlg struct ixl_dmamem txr_mem; 1204ccb96312Sdlg 1205ccb96312Sdlg bus_size_t txr_tail; 1206ccb96312Sdlg unsigned int txr_qid; 1207e01adc04Sdlg } __aligned(CACHE_LINE_SIZE); 1208ccb96312Sdlg 1209ccb96312Sdlg struct ixl_rx_map { 1210ccb96312Sdlg struct mbuf *rxm_m; 1211ccb96312Sdlg bus_dmamap_t rxm_map; 1212ccb96312Sdlg }; 1213ccb96312Sdlg 1214ccb96312Sdlg struct ixl_rx_ring { 1215ccb96312Sdlg struct ixl_softc *rxr_sc; 1216e01adc04Sdlg struct ixl_vector *rxr_vector; 1217e01adc04Sdlg struct ifiqueue *rxr_ifiq; 121800cd24f1Sdlg 1219ccb96312Sdlg struct if_rxring rxr_acct; 1220ccb96312Sdlg struct timeout rxr_refill; 1221ccb96312Sdlg 1222ccb96312Sdlg unsigned int rxr_prod; 1223ccb96312Sdlg unsigned int rxr_cons; 1224ccb96312Sdlg 1225ccb96312Sdlg struct ixl_rx_map *rxr_maps; 1226ccb96312Sdlg struct ixl_dmamem rxr_mem; 1227ccb96312Sdlg 1228ccb96312Sdlg struct mbuf *rxr_m_head; 1229ccb96312Sdlg struct mbuf **rxr_m_tail; 1230ccb96312Sdlg 1231ccb96312Sdlg bus_size_t rxr_tail; 1232ccb96312Sdlg unsigned int rxr_qid; 1233e01adc04Sdlg } __aligned(CACHE_LINE_SIZE); 1234ccb96312Sdlg 123510e66d97Sjmatthew struct ixl_atq { 123610e66d97Sjmatthew struct ixl_aq_desc iatq_desc; 123710e66d97Sjmatthew void *iatq_arg; 123810e66d97Sjmatthew void (*iatq_fn)(struct ixl_softc *, void *); 123910e66d97Sjmatthew }; 124010e66d97Sjmatthew SIMPLEQ_HEAD(ixl_atq_list, ixl_atq); 124110e66d97Sjmatthew 1242e01adc04Sdlg struct ixl_vector { 1243e01adc04Sdlg struct ixl_softc *iv_sc; 1244e01adc04Sdlg struct ixl_rx_ring *iv_rxr; 1245e01adc04Sdlg struct ixl_tx_ring *iv_txr; 1246e01adc04Sdlg int iv_qid; 1247e01adc04Sdlg void *iv_ihc; 1248e01adc04Sdlg char iv_name[16]; 1249e01adc04Sdlg } __aligned(CACHE_LINE_SIZE); 12509b0c6e1eSjmatthew 1251ccb96312Sdlg struct ixl_softc { 1252ccb96312Sdlg struct device sc_dev; 1253819ac441Sdlg const struct ixl_chip *sc_chip; 1254ccb96312Sdlg struct arpcom sc_ac; 1255ccb96312Sdlg struct ifmedia sc_media; 1256ccb96312Sdlg uint64_t sc_media_status; 1257ccb96312Sdlg uint64_t sc_media_active; 1258ccb96312Sdlg 1259ccb96312Sdlg pci_chipset_tag_t sc_pc; 1260ccb96312Sdlg pci_intr_handle_t sc_ih; 1261ccb96312Sdlg void *sc_ihc; 1262ccb96312Sdlg pcitag_t sc_tag; 1263ccb96312Sdlg 1264ccb96312Sdlg bus_dma_tag_t sc_dmat; 1265ccb96312Sdlg bus_space_tag_t sc_memt; 1266ccb96312Sdlg bus_space_handle_t sc_memh; 1267ccb96312Sdlg bus_size_t sc_mems; 1268ccb96312Sdlg 1269f5777d33Sdlg uint16_t sc_api_major; 1270f5777d33Sdlg uint16_t sc_api_minor; 1271ccb96312Sdlg uint8_t sc_pf_id; 1272ccb96312Sdlg uint16_t sc_uplink_seid; /* le */ 1273ccb96312Sdlg uint16_t sc_downlink_seid; /* le */ 1274ccb96312Sdlg uint16_t sc_veb_seid; /* le */ 1275ccb96312Sdlg uint16_t sc_vsi_number; /* le */ 1276ccb96312Sdlg uint16_t sc_seid; 1277eb1b42e4Sdlg unsigned int sc_base_queue; 12782ee1fcb3Sdlg unsigned int sc_port; 1279ccb96312Sdlg 12802bb8400cSjmatthew struct ixl_dmamem sc_scratch; 1281ccb96312Sdlg 1282ccb96312Sdlg const struct ixl_aq_regs * 1283ccb96312Sdlg sc_aq_regs; 1284ccb96312Sdlg 1285ccb96312Sdlg struct ixl_dmamem sc_atq; 1286ccb96312Sdlg unsigned int sc_atq_prod; 1287ccb96312Sdlg unsigned int sc_atq_cons; 1288ccb96312Sdlg 128995f940dfSjan struct mutex sc_atq_mtx; 1290ccb96312Sdlg struct ixl_dmamem sc_arq; 1291ccb96312Sdlg struct task sc_arq_task; 1292ccb96312Sdlg struct ixl_aq_bufs sc_arq_idle; 1293ccb96312Sdlg struct ixl_aq_bufs sc_arq_live; 1294ccb96312Sdlg struct if_rxring sc_arq_ring; 1295ccb96312Sdlg unsigned int sc_arq_prod; 1296ccb96312Sdlg unsigned int sc_arq_cons; 1297ccb96312Sdlg 12988014a50bSdlg struct mutex sc_link_state_mtx; 129910e66d97Sjmatthew struct task sc_link_state_task; 130010e66d97Sjmatthew struct ixl_atq sc_link_state_atq; 130110e66d97Sjmatthew 1302eb1b42e4Sdlg struct ixl_dmamem sc_hmc_sd; 1303eb1b42e4Sdlg struct ixl_dmamem sc_hmc_pd; 1304ccb96312Sdlg struct ixl_hmc_entry sc_hmc_entries[IXL_HMC_COUNT]; 1305ccb96312Sdlg 1306ccb96312Sdlg unsigned int sc_tx_ring_ndescs; 1307ccb96312Sdlg unsigned int sc_rx_ring_ndescs; 1308eb1b42e4Sdlg unsigned int sc_nqueues; /* 1 << sc_nqueues */ 1309d3ac7020Sdlg 1310e01adc04Sdlg struct intrmap *sc_intrmap; 1311e01adc04Sdlg struct ixl_vector *sc_vectors; 1312e01adc04Sdlg 1313d3ac7020Sdlg struct rwlock sc_cfg_lock; 1314d3ac7020Sdlg unsigned int sc_dead; 13154eec9beaSdlg 131656319b45Sjmatthew uint8_t sc_enaddr[ETHER_ADDR_LEN]; 13172ee1fcb3Sdlg 13182ee1fcb3Sdlg #if NKSTAT > 0 13192ee1fcb3Sdlg struct mutex sc_kstat_mtx; 13202ee1fcb3Sdlg struct timeout sc_kstat_tmo; 13212ee1fcb3Sdlg struct kstat *sc_port_kstat; 13222ee1fcb3Sdlg struct kstat *sc_vsi_kstat; 13232ee1fcb3Sdlg #endif 1324ccb96312Sdlg }; 1325ccb96312Sdlg #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname) 1326ccb96312Sdlg 1327ccb96312Sdlg #define delaymsec(_ms) delay(1000 * (_ms)) 1328ccb96312Sdlg 1329ccb96312Sdlg static void ixl_clear_hw(struct ixl_softc *); 1330ccb96312Sdlg static int ixl_pf_reset(struct ixl_softc *); 1331ccb96312Sdlg 1332ccb96312Sdlg static int ixl_dmamem_alloc(struct ixl_softc *, struct ixl_dmamem *, 1333ccb96312Sdlg bus_size_t, u_int); 1334ccb96312Sdlg static void ixl_dmamem_free(struct ixl_softc *, struct ixl_dmamem *); 1335ccb96312Sdlg 1336ccb96312Sdlg static int ixl_arq_fill(struct ixl_softc *); 1337ccb96312Sdlg static void ixl_arq_unfill(struct ixl_softc *); 1338ccb96312Sdlg 1339ccb96312Sdlg static int ixl_atq_poll(struct ixl_softc *, struct ixl_aq_desc *, 1340ccb96312Sdlg unsigned int); 1341ccb96312Sdlg static void ixl_atq_set(struct ixl_atq *, 1342ccb96312Sdlg void (*)(struct ixl_softc *, void *), void *); 1343ccb96312Sdlg static void ixl_atq_post(struct ixl_softc *, struct ixl_atq *); 1344ccb96312Sdlg static void ixl_atq_done(struct ixl_softc *); 1345ccb96312Sdlg static void ixl_atq_exec(struct ixl_softc *, struct ixl_atq *, 1346ccb96312Sdlg const char *); 1347ccb96312Sdlg static int ixl_get_version(struct ixl_softc *); 1348ccb96312Sdlg static int ixl_pxe_clear(struct ixl_softc *); 1349ccb96312Sdlg static int ixl_lldp_shut(struct ixl_softc *); 1350ccb96312Sdlg static int ixl_get_mac(struct ixl_softc *); 1351ccb96312Sdlg static int ixl_get_switch_config(struct ixl_softc *); 1352ccb96312Sdlg static int ixl_phy_mask_ints(struct ixl_softc *); 135325fbbcc0Sdlg static int ixl_get_phy_types(struct ixl_softc *, uint64_t *); 1354ccb96312Sdlg static int ixl_restart_an(struct ixl_softc *); 1355ccb96312Sdlg static int ixl_hmc(struct ixl_softc *); 1356eb1b42e4Sdlg static void ixl_hmc_free(struct ixl_softc *); 1357ccb96312Sdlg static int ixl_get_vsi(struct ixl_softc *); 1358ccb96312Sdlg static int ixl_set_vsi(struct ixl_softc *); 1359ccb96312Sdlg static int ixl_get_link_status(struct ixl_softc *); 1360ccb96312Sdlg static int ixl_set_link_status(struct ixl_softc *, 1361ccb96312Sdlg const struct ixl_aq_desc *); 13622bb8400cSjmatthew static int ixl_add_macvlan(struct ixl_softc *, uint8_t *, uint16_t, 13632bb8400cSjmatthew uint16_t); 13642bb8400cSjmatthew static int ixl_remove_macvlan(struct ixl_softc *, uint8_t *, uint16_t, 13652bb8400cSjmatthew uint16_t); 136610e66d97Sjmatthew static void ixl_link_state_update(void *); 1367ccb96312Sdlg static void ixl_arq(void *); 1368ccb96312Sdlg static void ixl_hmc_pack(void *, const void *, 1369ccb96312Sdlg const struct ixl_hmc_pack *, unsigned int); 1370ccb96312Sdlg 13714eec9beaSdlg static int ixl_get_sffpage(struct ixl_softc *, struct if_sffpage *); 13724eec9beaSdlg static int ixl_sff_get_byte(struct ixl_softc *, uint8_t, uint32_t, 13734eec9beaSdlg uint8_t *); 13744eec9beaSdlg static int ixl_sff_set_byte(struct ixl_softc *, uint8_t, uint32_t, 13754eec9beaSdlg uint8_t); 13764eec9beaSdlg 1377ccb96312Sdlg static int ixl_match(struct device *, void *, void *); 1378ccb96312Sdlg static void ixl_attach(struct device *, struct device *, void *); 1379ccb96312Sdlg 1380ccb96312Sdlg static void ixl_media_add(struct ixl_softc *, uint64_t); 1381ccb96312Sdlg static int ixl_media_change(struct ifnet *); 1382ccb96312Sdlg static void ixl_media_status(struct ifnet *, struct ifmediareq *); 1383ccb96312Sdlg static void ixl_watchdog(struct ifnet *); 1384ccb96312Sdlg static int ixl_ioctl(struct ifnet *, u_long, caddr_t); 1385ccb96312Sdlg static void ixl_start(struct ifqueue *); 13869b0c6e1eSjmatthew static int ixl_intr0(void *); 1387e01adc04Sdlg static int ixl_intr_vector(void *); 1388ccb96312Sdlg static int ixl_up(struct ixl_softc *); 1389ccb96312Sdlg static int ixl_down(struct ixl_softc *); 1390ccb96312Sdlg static int ixl_iff(struct ixl_softc *); 1391ccb96312Sdlg 1392ccb96312Sdlg static struct ixl_tx_ring * 1393ccb96312Sdlg ixl_txr_alloc(struct ixl_softc *, unsigned int); 1394eb1b42e4Sdlg static void ixl_txr_qdis(struct ixl_softc *, struct ixl_tx_ring *, int); 1395ccb96312Sdlg static void ixl_txr_config(struct ixl_softc *, struct ixl_tx_ring *); 1396eb1b42e4Sdlg static int ixl_txr_enabled(struct ixl_softc *, struct ixl_tx_ring *); 1397eb1b42e4Sdlg static int ixl_txr_disabled(struct ixl_softc *, struct ixl_tx_ring *); 1398ccb96312Sdlg static void ixl_txr_unconfig(struct ixl_softc *, struct ixl_tx_ring *); 1399ccb96312Sdlg static void ixl_txr_clean(struct ixl_softc *, struct ixl_tx_ring *); 1400ccb96312Sdlg static void ixl_txr_free(struct ixl_softc *, struct ixl_tx_ring *); 1401e01adc04Sdlg static int ixl_txeof(struct ixl_softc *, struct ixl_tx_ring *); 1402ccb96312Sdlg 1403ccb96312Sdlg static struct ixl_rx_ring * 1404ccb96312Sdlg ixl_rxr_alloc(struct ixl_softc *, unsigned int); 1405ccb96312Sdlg static void ixl_rxr_config(struct ixl_softc *, struct ixl_rx_ring *); 1406eb1b42e4Sdlg static int ixl_rxr_enabled(struct ixl_softc *, struct ixl_rx_ring *); 1407eb1b42e4Sdlg static int ixl_rxr_disabled(struct ixl_softc *, struct ixl_rx_ring *); 1408ccb96312Sdlg static void ixl_rxr_unconfig(struct ixl_softc *, struct ixl_rx_ring *); 1409ccb96312Sdlg static void ixl_rxr_clean(struct ixl_softc *, struct ixl_rx_ring *); 1410ccb96312Sdlg static void ixl_rxr_free(struct ixl_softc *, struct ixl_rx_ring *); 1411e01adc04Sdlg static int ixl_rxeof(struct ixl_softc *, struct ixl_rx_ring *); 1412ccb96312Sdlg static void ixl_rxfill(struct ixl_softc *, struct ixl_rx_ring *); 1413ccb96312Sdlg static void ixl_rxrefill(void *); 141496438522Sjmatthew static int ixl_rxrinfo(struct ixl_softc *, struct if_rxrinfo *); 141589760ddfSbluhm static void ixl_rx_checksum(struct mbuf *, uint64_t); 1416ccb96312Sdlg 14172ee1fcb3Sdlg #if NKSTAT > 0 14182ee1fcb3Sdlg static void ixl_kstat_attach(struct ixl_softc *); 14192ee1fcb3Sdlg #endif 14202ee1fcb3Sdlg 1421ccb96312Sdlg struct cfdriver ixl_cd = { 1422ccb96312Sdlg NULL, 1423ccb96312Sdlg "ixl", 1424ccb96312Sdlg DV_IFNET, 1425ccb96312Sdlg }; 1426ccb96312Sdlg 14278d2c75e4Smpi const struct cfattach ixl_ca = { 1428ccb96312Sdlg sizeof(struct ixl_softc), 1429ccb96312Sdlg ixl_match, 1430ccb96312Sdlg ixl_attach, 1431ccb96312Sdlg }; 1432ccb96312Sdlg 1433ccb96312Sdlg static const struct ixl_phy_type ixl_phy_type_map[] = { 1434ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_SGMII, IFM_1000_SGMII }, 1435ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_1000BASE_KX, IFM_1000_KX }, 1436ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_KX4, IFM_10G_KX4 }, 1437ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_KR, IFM_10G_KR }, 1438ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_40GBASE_KR4, IFM_40G_KR4 }, 1439ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_XAUI | 1440ccb96312Sdlg 1ULL << IXL_PHY_TYPE_XFI, IFM_10G_CX4 }, 1441ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_SFI, IFM_10G_SFI }, 1442ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_XLAUI | 1443ccb96312Sdlg 1ULL << IXL_PHY_TYPE_XLPPI, IFM_40G_XLPPI }, 1444ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_40GBASE_CR4_CU | 1445ccb96312Sdlg 1ULL << IXL_PHY_TYPE_40GBASE_CR4, IFM_40G_CR4 }, 1446ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_CR1_CU | 1447ccb96312Sdlg 1ULL << IXL_PHY_TYPE_10GBASE_CR1, IFM_10G_CR1 }, 1448ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_AOC, IFM_10G_AOC }, 1449ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_40GBASE_AOC, IFM_40G_AOC }, 1450ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_100BASE_TX, IFM_100_TX }, 1451ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_1000BASE_T_OPTICAL | 1452ccb96312Sdlg 1ULL << IXL_PHY_TYPE_1000BASE_T, IFM_1000_T }, 1453ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_T, IFM_10G_T }, 1454ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_SR, IFM_10G_SR }, 1455ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_LR, IFM_10G_LR }, 1456ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_10GBASE_SFPP_CU, IFM_10G_SFP_CU }, 1457ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_40GBASE_SR4, IFM_40G_SR4 }, 1458ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_40GBASE_LR4, IFM_40G_LR4 }, 1459ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_1000BASE_SX, IFM_1000_SX }, 1460ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_1000BASE_LX, IFM_1000_LX }, 1461ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_20GBASE_KR2, IFM_20G_KR2 }, 1462ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_25GBASE_KR, IFM_25G_KR }, 1463ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_25GBASE_CR, IFM_25G_CR }, 1464ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_25GBASE_SR, IFM_25G_SR }, 1465ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_25GBASE_LR, IFM_25G_LR }, 1466ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_25GBASE_AOC, IFM_25G_AOC }, 1467ccb96312Sdlg { 1ULL << IXL_PHY_TYPE_25GBASE_ACC, IFM_25G_CR }, 1468ccb96312Sdlg }; 1469ccb96312Sdlg 1470ccb96312Sdlg static const struct ixl_speed_type ixl_speed_type_map[] = { 1471a4742ff3Sdlg { IXL_AQ_LINK_SPEED_40GB, IF_Gbps(40) }, 1472a4742ff3Sdlg { IXL_AQ_LINK_SPEED_25GB, IF_Gbps(25) }, 1473a4742ff3Sdlg { IXL_AQ_LINK_SPEED_10GB, IF_Gbps(10) }, 1474a4742ff3Sdlg { IXL_AQ_LINK_SPEED_1GB, IF_Gbps(1) }, 1475ccb96312Sdlg }; 1476ccb96312Sdlg 1477ccb96312Sdlg static const struct ixl_aq_regs ixl_pf_aq_regs = { 1478ccb96312Sdlg .atq_tail = I40E_PF_ATQT, 1479ccb96312Sdlg .atq_tail_mask = I40E_PF_ATQT_ATQT_MASK, 1480ccb96312Sdlg .atq_head = I40E_PF_ATQH, 1481ccb96312Sdlg .atq_head_mask = I40E_PF_ATQH_ATQH_MASK, 1482ccb96312Sdlg .atq_len = I40E_PF_ATQLEN, 1483ccb96312Sdlg .atq_bal = I40E_PF_ATQBAL, 1484ccb96312Sdlg .atq_bah = I40E_PF_ATQBAH, 1485ccb96312Sdlg .atq_len_enable = I40E_PF_ATQLEN_ATQENABLE_MASK, 1486ccb96312Sdlg 1487ccb96312Sdlg .arq_tail = I40E_PF_ARQT, 1488ccb96312Sdlg .arq_tail_mask = I40E_PF_ARQT_ARQT_MASK, 1489ccb96312Sdlg .arq_head = I40E_PF_ARQH, 1490ccb96312Sdlg .arq_head_mask = I40E_PF_ARQH_ARQH_MASK, 1491ccb96312Sdlg .arq_len = I40E_PF_ARQLEN, 1492ccb96312Sdlg .arq_bal = I40E_PF_ARQBAL, 1493ccb96312Sdlg .arq_bah = I40E_PF_ARQBAH, 1494ccb96312Sdlg .arq_len_enable = I40E_PF_ARQLEN_ARQENABLE_MASK, 1495ccb96312Sdlg }; 1496ccb96312Sdlg 1497ccb96312Sdlg #define ixl_rd(_s, _r) \ 1498ccb96312Sdlg bus_space_read_4((_s)->sc_memt, (_s)->sc_memh, (_r)) 1499ccb96312Sdlg #define ixl_wr(_s, _r, _v) \ 1500ccb96312Sdlg bus_space_write_4((_s)->sc_memt, (_s)->sc_memh, (_r), (_v)) 1501ccb96312Sdlg #define ixl_barrier(_s, _r, _l, _o) \ 1502ccb96312Sdlg bus_space_barrier((_s)->sc_memt, (_s)->sc_memh, (_r), (_l), (_o)) 1503ccb96312Sdlg #define ixl_intr_enable(_s) \ 1504ccb96312Sdlg ixl_wr((_s), I40E_PFINT_DYN_CTL0, I40E_PFINT_DYN_CTL0_INTENA_MASK | \ 1505ccb96312Sdlg I40E_PFINT_DYN_CTL0_CLEARPBA_MASK | \ 1506ccb96312Sdlg (IXL_NOITR << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)) 1507ccb96312Sdlg 1508eb1b42e4Sdlg #define ixl_nqueues(_sc) (1 << (_sc)->sc_nqueues) 1509eb1b42e4Sdlg 1510ccb96312Sdlg #ifdef __LP64__ 1511ccb96312Sdlg #define ixl_dmamem_hi(_ixm) (uint32_t)(IXL_DMA_DVA(_ixm) >> 32) 1512ccb96312Sdlg #else 1513ccb96312Sdlg #define ixl_dmamem_hi(_ixm) 0 1514ccb96312Sdlg #endif 1515ccb96312Sdlg 1516ccb96312Sdlg #define ixl_dmamem_lo(_ixm) (uint32_t)IXL_DMA_DVA(_ixm) 1517ccb96312Sdlg 1518ccb96312Sdlg static inline void 1519ccb96312Sdlg ixl_aq_dva(struct ixl_aq_desc *iaq, bus_addr_t addr) 1520ccb96312Sdlg { 1521ccb96312Sdlg #ifdef __LP64__ 1522ccb96312Sdlg htolem32(&iaq->iaq_param[2], addr >> 32); 1523ccb96312Sdlg #else 1524ccb96312Sdlg iaq->iaq_param[2] = htole32(0); 1525ccb96312Sdlg #endif 1526ccb96312Sdlg htolem32(&iaq->iaq_param[3], addr); 1527ccb96312Sdlg } 1528ccb96312Sdlg 1529ccb96312Sdlg #if _BYTE_ORDER == _BIG_ENDIAN 1530ccb96312Sdlg #define HTOLE16(_x) (uint16_t)(((_x) & 0xff) << 8 | ((_x) & 0xff00) >> 8) 1531ccb96312Sdlg #else 1532ccb96312Sdlg #define HTOLE16(_x) (_x) 1533ccb96312Sdlg #endif 1534ccb96312Sdlg 15354eec9beaSdlg static struct rwlock ixl_sff_lock = RWLOCK_INITIALIZER("ixlsff"); 15364eec9beaSdlg 1537819ac441Sdlg /* deal with differences between chips */ 1538819ac441Sdlg 1539db742a36Sdlg struct ixl_chip { 15408d616574Sdlg uint64_t ic_rss_hena; 1541819ac441Sdlg uint32_t (*ic_rd_ctl)(struct ixl_softc *, uint32_t); 1542819ac441Sdlg void (*ic_wr_ctl)(struct ixl_softc *, uint32_t, 1543819ac441Sdlg uint32_t); 1544819ac441Sdlg 1545819ac441Sdlg int (*ic_set_rss_key)(struct ixl_softc *, 1546819ac441Sdlg const struct ixl_rss_key *); 1547819ac441Sdlg int (*ic_set_rss_lut)(struct ixl_softc *, 1548819ac441Sdlg const struct ixl_rss_lut_128 *); 1549ccb96312Sdlg }; 1550ccb96312Sdlg 1551819ac441Sdlg static inline uint64_t 1552819ac441Sdlg ixl_rss_hena(struct ixl_softc *sc) 1553819ac441Sdlg { 1554819ac441Sdlg return (sc->sc_chip->ic_rss_hena); 1555819ac441Sdlg } 1556819ac441Sdlg 1557819ac441Sdlg static inline uint32_t 1558819ac441Sdlg ixl_rd_ctl(struct ixl_softc *sc, uint32_t r) 1559819ac441Sdlg { 1560819ac441Sdlg return ((*sc->sc_chip->ic_rd_ctl)(sc, r)); 1561819ac441Sdlg } 1562819ac441Sdlg 1563819ac441Sdlg static inline void 1564819ac441Sdlg ixl_wr_ctl(struct ixl_softc *sc, uint32_t r, uint32_t v) 1565819ac441Sdlg { 1566819ac441Sdlg (*sc->sc_chip->ic_wr_ctl)(sc, r, v); 1567819ac441Sdlg } 1568819ac441Sdlg 1569819ac441Sdlg static inline int 1570819ac441Sdlg ixl_set_rss_key(struct ixl_softc *sc, const struct ixl_rss_key *rsskey) 1571819ac441Sdlg { 1572819ac441Sdlg return ((*sc->sc_chip->ic_set_rss_key)(sc, rsskey)); 1573819ac441Sdlg } 1574819ac441Sdlg 1575819ac441Sdlg static inline int 1576819ac441Sdlg ixl_set_rss_lut(struct ixl_softc *sc, const struct ixl_rss_lut_128 *lut) 1577819ac441Sdlg { 1578819ac441Sdlg return ((*sc->sc_chip->ic_set_rss_lut)(sc, lut)); 1579819ac441Sdlg } 1580819ac441Sdlg 1581819ac441Sdlg /* 710 chip specifics */ 1582819ac441Sdlg 1583819ac441Sdlg static uint32_t ixl_710_rd_ctl(struct ixl_softc *, uint32_t); 1584819ac441Sdlg static void ixl_710_wr_ctl(struct ixl_softc *, uint32_t, uint32_t); 1585819ac441Sdlg static int ixl_710_set_rss_key(struct ixl_softc *, 1586819ac441Sdlg const struct ixl_rss_key *); 1587819ac441Sdlg static int ixl_710_set_rss_lut(struct ixl_softc *, 1588819ac441Sdlg const struct ixl_rss_lut_128 *); 1589819ac441Sdlg 1590db742a36Sdlg static const struct ixl_chip ixl_710 = { 15918d616574Sdlg .ic_rss_hena = IXL_RSS_HENA_BASE_710, 1592819ac441Sdlg .ic_rd_ctl = ixl_710_rd_ctl, 1593819ac441Sdlg .ic_wr_ctl = ixl_710_wr_ctl, 1594819ac441Sdlg .ic_set_rss_key = ixl_710_set_rss_key, 1595819ac441Sdlg .ic_set_rss_lut = ixl_710_set_rss_lut, 1596db742a36Sdlg }; 1597db742a36Sdlg 1598819ac441Sdlg /* 722 chip specifics */ 1599819ac441Sdlg 1600819ac441Sdlg static uint32_t ixl_722_rd_ctl(struct ixl_softc *, uint32_t); 1601819ac441Sdlg static void ixl_722_wr_ctl(struct ixl_softc *, uint32_t, uint32_t); 1602819ac441Sdlg static int ixl_722_set_rss_key(struct ixl_softc *, 1603819ac441Sdlg const struct ixl_rss_key *); 1604819ac441Sdlg static int ixl_722_set_rss_lut(struct ixl_softc *, 1605819ac441Sdlg const struct ixl_rss_lut_128 *); 1606819ac441Sdlg 1607db742a36Sdlg static const struct ixl_chip ixl_722 = { 16088d616574Sdlg .ic_rss_hena = IXL_RSS_HENA_BASE_722, 1609819ac441Sdlg .ic_rd_ctl = ixl_722_rd_ctl, 1610819ac441Sdlg .ic_wr_ctl = ixl_722_wr_ctl, 1611819ac441Sdlg .ic_set_rss_key = ixl_722_set_rss_key, 1612819ac441Sdlg .ic_set_rss_lut = ixl_722_set_rss_lut, 1613db742a36Sdlg }; 1614db742a36Sdlg 1615f5777d33Sdlg /* 1616f5777d33Sdlg * 710 chips using an older firmware/API use the same ctl ops as 1617f5777d33Sdlg * 722 chips. or 722 chips use the same ctl ops as 710 chips in early 1618f5777d33Sdlg * firmware/API versions? 1619f5777d33Sdlg */ 1620f5777d33Sdlg 1621f5777d33Sdlg static const struct ixl_chip ixl_710_decrepit = { 1622f5777d33Sdlg .ic_rss_hena = IXL_RSS_HENA_BASE_710, 1623f5777d33Sdlg .ic_rd_ctl = ixl_722_rd_ctl, 1624f5777d33Sdlg .ic_wr_ctl = ixl_722_wr_ctl, 1625f5777d33Sdlg .ic_set_rss_key = ixl_710_set_rss_key, 1626f5777d33Sdlg .ic_set_rss_lut = ixl_710_set_rss_lut, 1627f5777d33Sdlg }; 1628f5777d33Sdlg 1629819ac441Sdlg /* driver code */ 1630819ac441Sdlg 1631db742a36Sdlg struct ixl_device { 1632db742a36Sdlg const struct ixl_chip *id_chip; 1633db742a36Sdlg pci_vendor_id_t id_vid; 1634db742a36Sdlg pci_product_id_t id_pid; 1635db742a36Sdlg }; 1636db742a36Sdlg 1637db742a36Sdlg static const struct ixl_device ixl_devices[] = { 1638db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_10G_SFP }, 1639c85bea54Sjan { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_10G_SFP_2 }, 1640db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XL710_40G_BP }, 1641db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_10G_BP, }, 1642db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XL710_QSFP_1 }, 1643db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XL710_QSFP_2 }, 1644db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_10G_QSFP }, 1645db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_10G_BASET }, 1646db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XL710_20G_BP_1 }, 1647db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XL710_20G_BP_2 }, 1648db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_T4_10G }, 1649db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XXV710_25G_BP }, 1650db742a36Sdlg { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_XXV710_25G_SFP28, }, 1651ae527cb3Sjan { &ixl_710, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X710_10G_T, }, 1652db742a36Sdlg { &ixl_722, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X722_10G_KX }, 1653db742a36Sdlg { &ixl_722, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X722_10G_QSFP }, 1654db742a36Sdlg { &ixl_722, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X722_10G_SFP_1 }, 1655db742a36Sdlg { &ixl_722, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X722_1G }, 1656db742a36Sdlg { &ixl_722, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X722_10G_T }, 1657db742a36Sdlg { &ixl_722, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X722_10G_SFP_2 }, 1658db742a36Sdlg }; 1659db742a36Sdlg 1660db742a36Sdlg static const struct ixl_device * 1661db742a36Sdlg ixl_device_lookup(struct pci_attach_args *pa) 1662db742a36Sdlg { 1663db742a36Sdlg pci_vendor_id_t vid = PCI_VENDOR(pa->pa_id); 1664db742a36Sdlg pci_product_id_t pid = PCI_PRODUCT(pa->pa_id); 1665db742a36Sdlg const struct ixl_device *id; 1666db742a36Sdlg unsigned int i; 1667db742a36Sdlg 1668db742a36Sdlg for (i = 0; i < nitems(ixl_devices); i++) { 1669db742a36Sdlg id = &ixl_devices[i]; 1670db742a36Sdlg if (id->id_vid == vid && id->id_pid == pid) 1671db742a36Sdlg return (id); 1672db742a36Sdlg } 1673db742a36Sdlg 1674db742a36Sdlg return (NULL); 1675db742a36Sdlg } 1676db742a36Sdlg 1677ccb96312Sdlg static int 1678ccb96312Sdlg ixl_match(struct device *parent, void *match, void *aux) 1679ccb96312Sdlg { 1680db742a36Sdlg return (ixl_device_lookup(aux) != NULL); 1681ccb96312Sdlg } 1682ccb96312Sdlg 1683ccb96312Sdlg void 1684ccb96312Sdlg ixl_attach(struct device *parent, struct device *self, void *aux) 1685ccb96312Sdlg { 1686ccb96312Sdlg struct ixl_softc *sc = (struct ixl_softc *)self; 1687ccb96312Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 1688ccb96312Sdlg struct pci_attach_args *pa = aux; 1689ccb96312Sdlg pcireg_t memtype; 1690ccb96312Sdlg uint32_t port, ari, func; 1691ccb96312Sdlg uint64_t phy_types = 0; 1692e01adc04Sdlg unsigned int nqueues, i; 1693ccb96312Sdlg int tries; 1694ccb96312Sdlg 1695d3ac7020Sdlg rw_init(&sc->sc_cfg_lock, "ixlcfg"); 1696d3ac7020Sdlg 1697819ac441Sdlg sc->sc_chip = ixl_device_lookup(pa)->id_chip; 1698ccb96312Sdlg sc->sc_pc = pa->pa_pc; 1699ccb96312Sdlg sc->sc_tag = pa->pa_tag; 1700ccb96312Sdlg sc->sc_dmat = pa->pa_dmat; 170101fa8758Sjmatthew sc->sc_aq_regs = &ixl_pf_aq_regs; 1702ccb96312Sdlg 1703eb1b42e4Sdlg sc->sc_nqueues = 0; /* 1 << 0 is 1 queue */ 1704ccb96312Sdlg sc->sc_tx_ring_ndescs = 1024; 1705ccb96312Sdlg sc->sc_rx_ring_ndescs = 1024; 1706ccb96312Sdlg 1707ccb96312Sdlg memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, IXL_PCIREG); 170853ad6b53Sjmatthew if (pci_mapreg_map(pa, IXL_PCIREG, memtype, 0, 1709ccb96312Sdlg &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems, 0)) { 1710ccb96312Sdlg printf(": unable to map registers\n"); 1711ccb96312Sdlg return; 1712ccb96312Sdlg } 1713ccb96312Sdlg 1714eb1b42e4Sdlg sc->sc_base_queue = (ixl_rd(sc, I40E_PFLAN_QALLOC) & 1715eb1b42e4Sdlg I40E_PFLAN_QALLOC_FIRSTQ_MASK) >> 1716eb1b42e4Sdlg I40E_PFLAN_QALLOC_FIRSTQ_SHIFT; 1717eb1b42e4Sdlg 1718ccb96312Sdlg ixl_clear_hw(sc); 1719ccb96312Sdlg if (ixl_pf_reset(sc) == -1) { 1720ccb96312Sdlg /* error printed by ixl_pf_reset */ 1721ccb96312Sdlg goto unmap; 1722ccb96312Sdlg } 1723ccb96312Sdlg 1724ccb96312Sdlg port = ixl_rd(sc, I40E_PFGEN_PORTNUM); 1725ccb96312Sdlg port &= I40E_PFGEN_PORTNUM_PORT_NUM_MASK; 1726ccb96312Sdlg port >>= I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT; 17272ee1fcb3Sdlg sc->sc_port = port; 1728ccb96312Sdlg printf(": port %u", port); 1729ccb96312Sdlg 1730ccb96312Sdlg ari = ixl_rd(sc, I40E_GLPCI_CAPSUP); 1731ccb96312Sdlg ari &= I40E_GLPCI_CAPSUP_ARI_EN_MASK; 1732ccb96312Sdlg ari >>= I40E_GLPCI_CAPSUP_ARI_EN_SHIFT; 1733ccb96312Sdlg 1734ccb96312Sdlg func = ixl_rd(sc, I40E_PF_FUNC_RID); 1735ccb96312Sdlg sc->sc_pf_id = func & (ari ? 0xff : 0x7); 1736ccb96312Sdlg 1737ccb96312Sdlg /* initialise the adminq */ 1738ccb96312Sdlg 173995f940dfSjan mtx_init(&sc->sc_atq_mtx, IPL_NET); 174095f940dfSjan 1741ccb96312Sdlg if (ixl_dmamem_alloc(sc, &sc->sc_atq, 1742ccb96312Sdlg sizeof(struct ixl_aq_desc) * IXL_AQ_NUM, IXL_AQ_ALIGN) != 0) { 1743ccb96312Sdlg printf("\n" "%s: unable to allocate atq\n", DEVNAME(sc)); 1744ccb96312Sdlg goto unmap; 1745ccb96312Sdlg } 1746ccb96312Sdlg 1747ccb96312Sdlg SIMPLEQ_INIT(&sc->sc_arq_idle); 1748ccb96312Sdlg SIMPLEQ_INIT(&sc->sc_arq_live); 1749ccb96312Sdlg if_rxr_init(&sc->sc_arq_ring, 2, IXL_AQ_NUM - 1); 1750ccb96312Sdlg task_set(&sc->sc_arq_task, ixl_arq, sc); 1751ccb96312Sdlg sc->sc_arq_cons = 0; 1752ccb96312Sdlg sc->sc_arq_prod = 0; 1753ccb96312Sdlg 1754ccb96312Sdlg if (ixl_dmamem_alloc(sc, &sc->sc_arq, 1755ccb96312Sdlg sizeof(struct ixl_aq_desc) * IXL_AQ_NUM, IXL_AQ_ALIGN) != 0) { 1756ccb96312Sdlg printf("\n" "%s: unable to allocate arq\n", DEVNAME(sc)); 1757ccb96312Sdlg goto free_atq; 1758ccb96312Sdlg } 1759ccb96312Sdlg 1760ccb96312Sdlg if (!ixl_arq_fill(sc)) { 1761ccb96312Sdlg printf("\n" "%s: unable to fill arq descriptors\n", 1762ccb96312Sdlg DEVNAME(sc)); 1763ccb96312Sdlg goto free_arq; 1764ccb96312Sdlg } 1765ccb96312Sdlg 1766ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 1767ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), 1768ccb96312Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1769ccb96312Sdlg 1770ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_arq), 1771ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_arq), 1772ccb96312Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1773ccb96312Sdlg 1774ccb96312Sdlg for (tries = 0; tries < 10; tries++) { 1775ccb96312Sdlg int rv; 1776ccb96312Sdlg 1777ccb96312Sdlg sc->sc_atq_cons = 0; 1778ccb96312Sdlg sc->sc_atq_prod = 0; 1779ccb96312Sdlg 1780ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_head, 0); 1781ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_head, 0); 1782ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_tail, 0); 1783ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_tail, 0); 1784ccb96312Sdlg 1785ccb96312Sdlg ixl_barrier(sc, 0, sc->sc_mems, BUS_SPACE_BARRIER_WRITE); 1786ccb96312Sdlg 1787ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_bal, 1788ccb96312Sdlg ixl_dmamem_lo(&sc->sc_atq)); 1789ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_bah, 1790ccb96312Sdlg ixl_dmamem_hi(&sc->sc_atq)); 1791ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_len, 1792ccb96312Sdlg sc->sc_aq_regs->atq_len_enable | IXL_AQ_NUM); 1793ccb96312Sdlg 1794ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_bal, 1795ccb96312Sdlg ixl_dmamem_lo(&sc->sc_arq)); 1796ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_bah, 1797ccb96312Sdlg ixl_dmamem_hi(&sc->sc_arq)); 1798ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_len, 1799ccb96312Sdlg sc->sc_aq_regs->arq_len_enable | IXL_AQ_NUM); 1800ccb96312Sdlg 1801ccb96312Sdlg rv = ixl_get_version(sc); 1802ccb96312Sdlg if (rv == 0) 1803ccb96312Sdlg break; 1804ccb96312Sdlg if (rv != ETIMEDOUT) { 1805ccb96312Sdlg printf(", unable to get firmware version\n"); 1806ccb96312Sdlg goto shutdown; 1807ccb96312Sdlg } 1808ccb96312Sdlg 1809ccb96312Sdlg delaymsec(100); 1810ccb96312Sdlg } 1811ccb96312Sdlg 1812ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_tail, sc->sc_arq_prod); 1813ccb96312Sdlg 1814ccb96312Sdlg if (ixl_pxe_clear(sc) != 0) { 1815ccb96312Sdlg /* error printed by ixl_pxe_clear */ 1816ccb96312Sdlg goto shutdown; 1817ccb96312Sdlg } 1818ccb96312Sdlg 1819ccb96312Sdlg if (ixl_get_mac(sc) != 0) { 1820ccb96312Sdlg /* error printed by ixl_get_mac */ 1821ccb96312Sdlg goto shutdown; 1822ccb96312Sdlg } 1823ccb96312Sdlg 18249b0c6e1eSjmatthew if (pci_intr_map_msix(pa, 0, &sc->sc_ih) == 0) { 1825bc8858ceSjmatthew int nmsix = pci_intr_msix_count(pa); 1826e01adc04Sdlg if (nmsix > 1) { /* we used 1 (the 0th) for the adminq */ 1827e01adc04Sdlg nmsix--; 1828e01adc04Sdlg 1829e01adc04Sdlg sc->sc_intrmap = intrmap_create(&sc->sc_dev, 1830e01adc04Sdlg nmsix, IXL_MAX_VECTORS, INTRMAP_POWEROF2); 1831e01adc04Sdlg nqueues = intrmap_count(sc->sc_intrmap); 1832e01adc04Sdlg KASSERT(nqueues > 0); 1833e01adc04Sdlg KASSERT(powerof2(nqueues)); 1834e01adc04Sdlg sc->sc_nqueues = fls(nqueues) - 1; 18359b0c6e1eSjmatthew } 18369b0c6e1eSjmatthew } else { 1837ccb96312Sdlg if (pci_intr_map_msi(pa, &sc->sc_ih) != 0 && 1838ccb96312Sdlg pci_intr_map(pa, &sc->sc_ih) != 0) { 1839ccb96312Sdlg printf(", unable to map interrupt\n"); 1840ccb96312Sdlg goto shutdown; 1841ccb96312Sdlg } 18429b0c6e1eSjmatthew } 1843ccb96312Sdlg 1844e01adc04Sdlg nqueues = ixl_nqueues(sc); 1845e01adc04Sdlg 18469b0c6e1eSjmatthew printf(", %s, %d queue%s, address %s\n", 18479b0c6e1eSjmatthew pci_intr_string(sc->sc_pc, sc->sc_ih), ixl_nqueues(sc), 1848e01adc04Sdlg (nqueues > 1 ? "s" : ""), 1849ccb96312Sdlg ether_sprintf(sc->sc_ac.ac_enaddr)); 1850ccb96312Sdlg 1851ccb96312Sdlg if (ixl_hmc(sc) != 0) { 1852ccb96312Sdlg /* error printed by ixl_hmc */ 1853ccb96312Sdlg goto shutdown; 1854ccb96312Sdlg } 1855ccb96312Sdlg 1856ccb96312Sdlg if (ixl_lldp_shut(sc) != 0) { 1857ccb96312Sdlg /* error printed by ixl_lldp_shut */ 1858eb1b42e4Sdlg goto free_hmc; 1859ccb96312Sdlg } 1860ccb96312Sdlg 1861ccb96312Sdlg if (ixl_phy_mask_ints(sc) != 0) { 1862ccb96312Sdlg /* error printed by ixl_phy_mask_ints */ 1863eb1b42e4Sdlg goto free_hmc; 1864ccb96312Sdlg } 1865ccb96312Sdlg 1866ccb96312Sdlg if (ixl_restart_an(sc) != 0) { 1867ccb96312Sdlg /* error printed by ixl_restart_an */ 1868eb1b42e4Sdlg goto free_hmc; 1869ccb96312Sdlg } 1870ccb96312Sdlg 1871ccb96312Sdlg if (ixl_get_switch_config(sc) != 0) { 1872ccb96312Sdlg /* error printed by ixl_get_switch_config */ 1873eb1b42e4Sdlg goto free_hmc; 1874ccb96312Sdlg } 1875ccb96312Sdlg 187625fbbcc0Sdlg if (ixl_get_phy_types(sc, &phy_types) != 0) { 1877ccb96312Sdlg /* error printed by ixl_get_phy_abilities */ 1878eb1b42e4Sdlg goto free_hmc; 1879ccb96312Sdlg } 1880ccb96312Sdlg 1881608c7d94Sbluhm mtx_init(&sc->sc_link_state_mtx, IPL_NET); 1882ccb96312Sdlg if (ixl_get_link_status(sc) != 0) { 1883ccb96312Sdlg /* error printed by ixl_get_link_status */ 1884eb1b42e4Sdlg goto free_hmc; 1885ccb96312Sdlg } 1886ccb96312Sdlg 18872bb8400cSjmatthew if (ixl_dmamem_alloc(sc, &sc->sc_scratch, 1888ccb96312Sdlg sizeof(struct ixl_aq_vsi_data), 8) != 0) { 18892bb8400cSjmatthew printf("%s: unable to allocate scratch buffer\n", DEVNAME(sc)); 1890eb1b42e4Sdlg goto free_hmc; 1891ccb96312Sdlg } 1892ccb96312Sdlg 1893ccb96312Sdlg if (ixl_get_vsi(sc) != 0) { 1894ccb96312Sdlg /* error printed by ixl_get_vsi */ 18952bb8400cSjmatthew goto free_hmc; 1896ccb96312Sdlg } 1897ccb96312Sdlg 1898ccb96312Sdlg if (ixl_set_vsi(sc) != 0) { 1899ccb96312Sdlg /* error printed by ixl_set_vsi */ 19002bb8400cSjmatthew goto free_scratch; 1901ccb96312Sdlg } 1902ccb96312Sdlg 1903ccb96312Sdlg sc->sc_ihc = pci_intr_establish(sc->sc_pc, sc->sc_ih, 19049b0c6e1eSjmatthew IPL_NET | IPL_MPSAFE, ixl_intr0, sc, DEVNAME(sc)); 1905ccb96312Sdlg if (sc->sc_ihc == NULL) { 1906ccb96312Sdlg printf("%s: unable to establish interrupt handler\n", 1907ccb96312Sdlg DEVNAME(sc)); 19082bb8400cSjmatthew goto free_scratch; 1909ccb96312Sdlg } 1910ccb96312Sdlg 1911e01adc04Sdlg sc->sc_vectors = mallocarray(sizeof(*sc->sc_vectors), nqueues, 1912e01adc04Sdlg M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); 1913e01adc04Sdlg if (sc->sc_vectors == NULL) { 1914e01adc04Sdlg printf("%s: unable to allocate vectors\n", DEVNAME(sc)); 19159b0c6e1eSjmatthew goto free_scratch; 19169b0c6e1eSjmatthew } 19179b0c6e1eSjmatthew 1918e01adc04Sdlg for (i = 0; i < nqueues; i++) { 1919e01adc04Sdlg struct ixl_vector *iv = &sc->sc_vectors[i]; 1920e01adc04Sdlg iv->iv_sc = sc; 1921e01adc04Sdlg iv->iv_qid = i; 1922e01adc04Sdlg snprintf(iv->iv_name, sizeof(iv->iv_name), 1923e01adc04Sdlg "%s:%u", DEVNAME(sc), i); /* truncated? */ 1924e01adc04Sdlg } 1925e01adc04Sdlg 1926e01adc04Sdlg if (sc->sc_intrmap) { 1927e01adc04Sdlg for (i = 0; i < nqueues; i++) { 1928e01adc04Sdlg struct ixl_vector *iv = &sc->sc_vectors[i]; 1929e01adc04Sdlg pci_intr_handle_t ih; 1930e01adc04Sdlg int v = i + 1; /* 0 is used for adminq */ 1931e01adc04Sdlg 1932e01adc04Sdlg if (pci_intr_map_msix(pa, v, &ih)) { 1933e01adc04Sdlg printf("%s: unable to map msi-x vector %d\n", 1934e01adc04Sdlg DEVNAME(sc), v); 1935e01adc04Sdlg goto free_vectors; 1936e01adc04Sdlg } 1937e01adc04Sdlg 1938e01adc04Sdlg iv->iv_ihc = pci_intr_establish_cpu(sc->sc_pc, ih, 1939e01adc04Sdlg IPL_NET | IPL_MPSAFE, 1940e01adc04Sdlg intrmap_cpu(sc->sc_intrmap, i), 1941e01adc04Sdlg ixl_intr_vector, iv, iv->iv_name); 1942e01adc04Sdlg if (iv->iv_ihc == NULL) { 1943e01adc04Sdlg printf("%s: unable to establish interrupt %d\n", 1944e01adc04Sdlg DEVNAME(sc), v); 1945e01adc04Sdlg goto free_vectors; 1946e01adc04Sdlg } 1947e01adc04Sdlg 1948e01adc04Sdlg ixl_wr(sc, I40E_PFINT_DYN_CTLN(i), 1949e01adc04Sdlg I40E_PFINT_DYN_CTLN_INTENA_MASK | 1950e01adc04Sdlg I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | 1951e01adc04Sdlg (IXL_NOITR << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)); 1952e01adc04Sdlg } 1953e01adc04Sdlg } 1954e01adc04Sdlg 1955f5777d33Sdlg /* fixup the chip ops for older fw releases */ 1956f5777d33Sdlg if (sc->sc_chip == &ixl_710 && 1957f5777d33Sdlg sc->sc_api_major == 1 && sc->sc_api_minor < 5) 1958f5777d33Sdlg sc->sc_chip = &ixl_710_decrepit; 1959f5777d33Sdlg 1960ccb96312Sdlg ifp->if_softc = sc; 1961ccb96312Sdlg ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1962ccb96312Sdlg ifp->if_xflags = IFXF_MPSAFE; 1963ccb96312Sdlg ifp->if_ioctl = ixl_ioctl; 1964ccb96312Sdlg ifp->if_qstart = ixl_start; 1965ccb96312Sdlg ifp->if_watchdog = ixl_watchdog; 1966ccb96312Sdlg ifp->if_hardmtu = IXL_HARDMTU; 1967ccb96312Sdlg strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); 1968cf96265bSbluhm ifq_init_maxlen(&ifp->if_snd, sc->sc_tx_ring_ndescs); 1969ccb96312Sdlg 1970*60b8dadeSjan ifp->if_capabilities = IFCAP_VLAN_MTU; 1971*60b8dadeSjan #if NVLAN > 0 1972*60b8dadeSjan ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 1973*60b8dadeSjan #endif 197404206048Sdlg ifp->if_capabilities |= IFCAP_CSUM_IPv4 | 197504206048Sdlg IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 | 197604206048Sdlg IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6; 1977f77c9c95Sjan ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6; 1978ccb96312Sdlg 1979ccb96312Sdlg ifmedia_init(&sc->sc_media, 0, ixl_media_change, ixl_media_status); 1980ccb96312Sdlg 1981ccb96312Sdlg ixl_media_add(sc, phy_types); 1982ccb96312Sdlg ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 1983ccb96312Sdlg ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 1984ccb96312Sdlg 1985ccb96312Sdlg if_attach(ifp); 1986ccb96312Sdlg ether_ifattach(ifp); 1987ccb96312Sdlg 1988e01adc04Sdlg if_attach_queues(ifp, nqueues); 1989e01adc04Sdlg if_attach_iqueues(ifp, nqueues); 1990ccb96312Sdlg 199110e66d97Sjmatthew task_set(&sc->sc_link_state_task, ixl_link_state_update, sc); 1992ccb96312Sdlg ixl_wr(sc, I40E_PFINT_ICR0_ENA, 1993ccb96312Sdlg I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK | 1994ccb96312Sdlg I40E_PFINT_ICR0_ENA_ADMINQ_MASK); 1995ccb96312Sdlg ixl_wr(sc, I40E_PFINT_STAT_CTL0, 1996ccb96312Sdlg IXL_NOITR << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT); 1997ccb96312Sdlg 19982bb8400cSjmatthew /* remove default mac filter and replace it so we can see vlans */ 19992bb8400cSjmatthew ixl_remove_macvlan(sc, sc->sc_ac.ac_enaddr, 0, 0); 20002bb8400cSjmatthew ixl_remove_macvlan(sc, sc->sc_ac.ac_enaddr, 0, 20012bb8400cSjmatthew IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN); 20022bb8400cSjmatthew ixl_add_macvlan(sc, sc->sc_ac.ac_enaddr, 0, 20032bb8400cSjmatthew IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN); 200445e31cb9Sjmatthew ixl_add_macvlan(sc, etherbroadcastaddr, 0, 200545e31cb9Sjmatthew IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN); 200656319b45Sjmatthew memcpy(sc->sc_enaddr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); 20072bb8400cSjmatthew 2008ccb96312Sdlg ixl_intr_enable(sc); 2009ccb96312Sdlg 20102ee1fcb3Sdlg #if NKSTAT > 0 20112ee1fcb3Sdlg ixl_kstat_attach(sc); 20122ee1fcb3Sdlg #endif 20132ee1fcb3Sdlg 2014ccb96312Sdlg return; 2015e01adc04Sdlg free_vectors: 2016e01adc04Sdlg if (sc->sc_intrmap != NULL) { 2017e01adc04Sdlg for (i = 0; i < nqueues; i++) { 2018e01adc04Sdlg struct ixl_vector *iv = &sc->sc_vectors[i]; 2019e01adc04Sdlg if (iv->iv_ihc == NULL) 2020e01adc04Sdlg continue; 2021e01adc04Sdlg pci_intr_disestablish(sc->sc_pc, iv->iv_ihc); 2022e01adc04Sdlg } 2023e01adc04Sdlg } 2024e01adc04Sdlg free(sc->sc_vectors, M_DEVBUF, nqueues * sizeof(*sc->sc_vectors)); 20252bb8400cSjmatthew free_scratch: 20262bb8400cSjmatthew ixl_dmamem_free(sc, &sc->sc_scratch); 2027eb1b42e4Sdlg free_hmc: 2028eb1b42e4Sdlg ixl_hmc_free(sc); 2029ccb96312Sdlg shutdown: 2030ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_head, 0); 2031ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_head, 0); 2032ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_tail, 0); 2033ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_tail, 0); 2034ccb96312Sdlg 2035ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_bal, 0); 2036ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_bah, 0); 2037ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_len, 0); 2038ccb96312Sdlg 2039ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_bal, 0); 2040ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_bah, 0); 2041ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_len, 0); 2042ccb96312Sdlg 2043ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_arq), 2044ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_arq), 2045ccb96312Sdlg BUS_DMASYNC_POSTREAD); 2046ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 2047ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), 2048ccb96312Sdlg BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2049ccb96312Sdlg 2050ccb96312Sdlg ixl_arq_unfill(sc); 20519b0c6e1eSjmatthew 2052ccb96312Sdlg free_arq: 2053ccb96312Sdlg ixl_dmamem_free(sc, &sc->sc_arq); 2054ccb96312Sdlg free_atq: 2055ccb96312Sdlg ixl_dmamem_free(sc, &sc->sc_atq); 2056ccb96312Sdlg unmap: 2057ccb96312Sdlg bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems); 2058ccb96312Sdlg sc->sc_mems = 0; 2059e01adc04Sdlg 2060e01adc04Sdlg if (sc->sc_intrmap != NULL) 2061e01adc04Sdlg intrmap_destroy(sc->sc_intrmap); 2062ccb96312Sdlg } 2063ccb96312Sdlg 2064ccb96312Sdlg static void 2065ccb96312Sdlg ixl_media_add(struct ixl_softc *sc, uint64_t phy_types) 2066ccb96312Sdlg { 2067ccb96312Sdlg struct ifmedia *ifm = &sc->sc_media; 2068ccb96312Sdlg const struct ixl_phy_type *itype; 2069ccb96312Sdlg unsigned int i; 2070ccb96312Sdlg 2071ccb96312Sdlg for (i = 0; i < nitems(ixl_phy_type_map); i++) { 2072ccb96312Sdlg itype = &ixl_phy_type_map[i]; 2073ccb96312Sdlg 2074ccb96312Sdlg if (ISSET(phy_types, itype->phy_type)) 2075ccb96312Sdlg ifmedia_add(ifm, IFM_ETHER | itype->ifm_type, 0, NULL); 2076ccb96312Sdlg } 2077ccb96312Sdlg } 2078ccb96312Sdlg 2079ccb96312Sdlg static int 2080ccb96312Sdlg ixl_media_change(struct ifnet *ifp) 2081ccb96312Sdlg { 2082ccb96312Sdlg /* ignore? */ 2083ccb96312Sdlg return (EOPNOTSUPP); 2084ccb96312Sdlg } 2085ccb96312Sdlg 2086ccb96312Sdlg static void 2087ccb96312Sdlg ixl_media_status(struct ifnet *ifp, struct ifmediareq *ifm) 2088ccb96312Sdlg { 2089ccb96312Sdlg struct ixl_softc *sc = ifp->if_softc; 2090ccb96312Sdlg 209191afdc87Sbluhm KERNEL_ASSERT_LOCKED(); 2092ccb96312Sdlg 2093fea9c2abSbluhm mtx_enter(&sc->sc_link_state_mtx); 2094ccb96312Sdlg ifm->ifm_status = sc->sc_media_status; 2095ccb96312Sdlg ifm->ifm_active = sc->sc_media_active; 2096fea9c2abSbluhm mtx_leave(&sc->sc_link_state_mtx); 2097ccb96312Sdlg } 2098ccb96312Sdlg 2099ccb96312Sdlg static void 2100ccb96312Sdlg ixl_watchdog(struct ifnet *ifp) 2101ccb96312Sdlg { 2102ccb96312Sdlg 2103ccb96312Sdlg } 2104ccb96312Sdlg 2105ccb96312Sdlg int 2106ccb96312Sdlg ixl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 2107ccb96312Sdlg { 2108ccb96312Sdlg struct ixl_softc *sc = (struct ixl_softc *)ifp->if_softc; 2109ccb96312Sdlg struct ifreq *ifr = (struct ifreq *)data; 2110300096a1Sjmatthew uint8_t addrhi[ETHER_ADDR_LEN], addrlo[ETHER_ADDR_LEN]; 2111300096a1Sjmatthew int aqerror, error = 0; 2112ccb96312Sdlg 2113ccb96312Sdlg switch (cmd) { 2114ccb96312Sdlg case SIOCSIFADDR: 2115ccb96312Sdlg ifp->if_flags |= IFF_UP; 2116ccb96312Sdlg /* FALLTHROUGH */ 2117ccb96312Sdlg 2118ccb96312Sdlg case SIOCSIFFLAGS: 2119ccb96312Sdlg if (ISSET(ifp->if_flags, IFF_UP)) { 2120ccb96312Sdlg if (ISSET(ifp->if_flags, IFF_RUNNING)) 2121ccb96312Sdlg error = ENETRESET; 2122ccb96312Sdlg else 2123ccb96312Sdlg error = ixl_up(sc); 2124ccb96312Sdlg } else { 2125ccb96312Sdlg if (ISSET(ifp->if_flags, IFF_RUNNING)) 2126ccb96312Sdlg error = ixl_down(sc); 2127ccb96312Sdlg } 2128ccb96312Sdlg break; 2129ccb96312Sdlg 2130ccb96312Sdlg case SIOCGIFMEDIA: 2131ccb96312Sdlg case SIOCSIFMEDIA: 2132ccb96312Sdlg error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 2133ccb96312Sdlg break; 2134ccb96312Sdlg 2135ccb96312Sdlg case SIOCGIFRXR: 2136ccb96312Sdlg error = ixl_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data); 2137ccb96312Sdlg break; 2138ccb96312Sdlg 2139300096a1Sjmatthew case SIOCADDMULTI: 2140300096a1Sjmatthew if (ether_addmulti(ifr, &sc->sc_ac) == ENETRESET) { 2141300096a1Sjmatthew error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 2142300096a1Sjmatthew if (error != 0) 2143300096a1Sjmatthew return (error); 2144300096a1Sjmatthew 2145300096a1Sjmatthew aqerror = ixl_add_macvlan(sc, addrlo, 0, 2146300096a1Sjmatthew IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN); 2147300096a1Sjmatthew if (aqerror == IXL_AQ_RC_ENOSPC) { 2148300096a1Sjmatthew ether_delmulti(ifr, &sc->sc_ac); 2149300096a1Sjmatthew error = ENOSPC; 2150300096a1Sjmatthew } 2151300096a1Sjmatthew 2152300096a1Sjmatthew if (sc->sc_ac.ac_multirangecnt > 0) { 2153300096a1Sjmatthew SET(ifp->if_flags, IFF_ALLMULTI); 2154300096a1Sjmatthew error = ENETRESET; 2155300096a1Sjmatthew } 2156300096a1Sjmatthew } 2157300096a1Sjmatthew break; 2158300096a1Sjmatthew 2159300096a1Sjmatthew case SIOCDELMULTI: 2160300096a1Sjmatthew if (ether_delmulti(ifr, &sc->sc_ac) == ENETRESET) { 2161300096a1Sjmatthew error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi); 2162300096a1Sjmatthew if (error != 0) 2163300096a1Sjmatthew return (error); 2164300096a1Sjmatthew 2165300096a1Sjmatthew ixl_remove_macvlan(sc, addrlo, 0, 2166300096a1Sjmatthew IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN); 2167300096a1Sjmatthew 2168300096a1Sjmatthew if (ISSET(ifp->if_flags, IFF_ALLMULTI) && 2169300096a1Sjmatthew sc->sc_ac.ac_multirangecnt == 0) { 2170300096a1Sjmatthew CLR(ifp->if_flags, IFF_ALLMULTI); 2171300096a1Sjmatthew error = ENETRESET; 2172300096a1Sjmatthew } 2173300096a1Sjmatthew } 2174300096a1Sjmatthew break; 2175300096a1Sjmatthew 21764eec9beaSdlg case SIOCGIFSFFPAGE: 21774eec9beaSdlg error = rw_enter(&ixl_sff_lock, RW_WRITE|RW_INTR); 21784eec9beaSdlg if (error != 0) 21794eec9beaSdlg break; 21804eec9beaSdlg 21814eec9beaSdlg error = ixl_get_sffpage(sc, (struct if_sffpage *)data); 21824eec9beaSdlg rw_exit(&ixl_sff_lock); 21834eec9beaSdlg break; 21844eec9beaSdlg 2185ccb96312Sdlg default: 2186ccb96312Sdlg error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 2187ccb96312Sdlg break; 2188ccb96312Sdlg } 2189ccb96312Sdlg 2190ccb96312Sdlg if (error == ENETRESET) 2191ccb96312Sdlg error = ixl_iff(sc); 2192ccb96312Sdlg 2193ccb96312Sdlg return (error); 2194ccb96312Sdlg } 2195ccb96312Sdlg 2196ccb96312Sdlg static inline void * 2197ccb96312Sdlg ixl_hmc_kva(struct ixl_softc *sc, unsigned int type, unsigned int i) 2198ccb96312Sdlg { 2199eb1b42e4Sdlg uint8_t *kva = IXL_DMA_KVA(&sc->sc_hmc_pd); 2200ccb96312Sdlg struct ixl_hmc_entry *e = &sc->sc_hmc_entries[type]; 2201ccb96312Sdlg 2202ccb96312Sdlg if (i >= e->hmc_count) 2203ccb96312Sdlg return (NULL); 2204ccb96312Sdlg 2205ccb96312Sdlg kva += e->hmc_base; 2206ccb96312Sdlg kva += i * e->hmc_size; 2207ccb96312Sdlg 2208ccb96312Sdlg return (kva); 2209ccb96312Sdlg } 2210ccb96312Sdlg 2211ccb96312Sdlg static inline size_t 2212ccb96312Sdlg ixl_hmc_len(struct ixl_softc *sc, unsigned int type) 2213ccb96312Sdlg { 2214ccb96312Sdlg struct ixl_hmc_entry *e = &sc->sc_hmc_entries[type]; 2215ccb96312Sdlg 2216ccb96312Sdlg return (e->hmc_size); 2217ccb96312Sdlg } 2218ccb96312Sdlg 2219ccb96312Sdlg static int 2220819ac441Sdlg ixl_configure_rss(struct ixl_softc *sc) 2221819ac441Sdlg { 2222819ac441Sdlg struct ixl_rss_key rsskey; 2223819ac441Sdlg struct ixl_rss_lut_128 lut; 2224819ac441Sdlg uint8_t *lute = (uint8_t *)&lut; 2225819ac441Sdlg uint64_t rss_hena; 2226819ac441Sdlg unsigned int i, nqueues; 2227819ac441Sdlg int error; 2228819ac441Sdlg 2229819ac441Sdlg #if 0 2230819ac441Sdlg /* if we want to do a 512 entry LUT, do this. */ 2231819ac441Sdlg uint32_t v = ixl_rd_ctl(sc, I40E_PFQF_CTL_0); 2232819ac441Sdlg SET(v, I40E_PFQF_CTL_0_HASHLUTSIZE_MASK); 2233819ac441Sdlg ixl_wr_ctl(sc, I40E_PFQF_CTL_0, v); 2234819ac441Sdlg #endif 2235819ac441Sdlg 2236819ac441Sdlg stoeplitz_to_key(&rsskey, sizeof(rsskey)); 2237819ac441Sdlg 2238819ac441Sdlg nqueues = ixl_nqueues(sc); 2239819ac441Sdlg for (i = 0; i < sizeof(lut); i++) { 2240819ac441Sdlg /* 2241819ac441Sdlg * ixl must have a power of 2 rings, so using mod 2242819ac441Sdlg * to populate the table is fine. 2243819ac441Sdlg */ 2244819ac441Sdlg lute[i] = i % nqueues; 2245819ac441Sdlg } 2246819ac441Sdlg 2247819ac441Sdlg error = ixl_set_rss_key(sc, &rsskey); 2248819ac441Sdlg if (error != 0) 2249819ac441Sdlg return (error); 2250819ac441Sdlg 2251819ac441Sdlg rss_hena = (uint64_t)ixl_rd_ctl(sc, I40E_PFQF_HENA(0)); 2252819ac441Sdlg rss_hena |= (uint64_t)ixl_rd_ctl(sc, I40E_PFQF_HENA(1)) << 32; 2253819ac441Sdlg rss_hena |= ixl_rss_hena(sc); 2254819ac441Sdlg ixl_wr_ctl(sc, I40E_PFQF_HENA(0), rss_hena); 2255819ac441Sdlg ixl_wr_ctl(sc, I40E_PFQF_HENA(1), rss_hena >> 32); 2256819ac441Sdlg 2257819ac441Sdlg error = ixl_set_rss_lut(sc, &lut); 2258819ac441Sdlg if (error != 0) 2259819ac441Sdlg return (error); 2260819ac441Sdlg 2261819ac441Sdlg /* nothing to clena up :( */ 2262819ac441Sdlg 2263819ac441Sdlg return (0); 2264819ac441Sdlg } 2265819ac441Sdlg 2266819ac441Sdlg static int 2267ccb96312Sdlg ixl_up(struct ixl_softc *sc) 2268ccb96312Sdlg { 2269ccb96312Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 2270e01adc04Sdlg struct ifqueue *ifq; 2271e01adc04Sdlg struct ifiqueue *ifiq; 2272e01adc04Sdlg struct ixl_vector *iv; 2273eb1b42e4Sdlg struct ixl_rx_ring *rxr; 2274eb1b42e4Sdlg struct ixl_tx_ring *txr; 2275eb1b42e4Sdlg unsigned int nqueues, i; 2276eb1b42e4Sdlg uint32_t reg; 2277eb1b42e4Sdlg int rv = ENOMEM; 2278ccb96312Sdlg 2279eb1b42e4Sdlg nqueues = ixl_nqueues(sc); 2280eb1b42e4Sdlg 2281d3ac7020Sdlg rw_enter_write(&sc->sc_cfg_lock); 2282d3ac7020Sdlg if (sc->sc_dead) { 2283d3ac7020Sdlg rw_exit_write(&sc->sc_cfg_lock); 2284d3ac7020Sdlg return (ENXIO); 2285d3ac7020Sdlg } 2286d3ac7020Sdlg 2287eb1b42e4Sdlg /* allocation is the only thing that can fail, so do it up front */ 2288eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2289eb1b42e4Sdlg rxr = ixl_rxr_alloc(sc, i); 2290eb1b42e4Sdlg if (rxr == NULL) 2291eb1b42e4Sdlg goto free; 2292eb1b42e4Sdlg 229300cd24f1Sdlg txr = ixl_txr_alloc(sc, i); 2294eb1b42e4Sdlg if (txr == NULL) { 2295eb1b42e4Sdlg ixl_rxr_free(sc, rxr); 2296eb1b42e4Sdlg goto free; 2297ccb96312Sdlg } 2298ccb96312Sdlg 2299e01adc04Sdlg /* wire everything together */ 2300e01adc04Sdlg iv = &sc->sc_vectors[i]; 2301e01adc04Sdlg iv->iv_rxr = rxr; 2302e01adc04Sdlg iv->iv_txr = txr; 2303e01adc04Sdlg 2304e01adc04Sdlg ifq = ifp->if_ifqs[i]; 2305e01adc04Sdlg ifq->ifq_softc = txr; 2306e01adc04Sdlg txr->txr_ifq = ifq; 2307e01adc04Sdlg 2308e01adc04Sdlg ifiq = ifp->if_iqs[i]; 2309e01adc04Sdlg ifiq->ifiq_softc = rxr; 2310e01adc04Sdlg rxr->rxr_ifiq = ifiq; 2311ccb96312Sdlg } 2312ccb96312Sdlg 2313eb1b42e4Sdlg /* XXX wait 50ms from completion of last RX queue disable */ 2314ccb96312Sdlg 2315eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2316e01adc04Sdlg iv = &sc->sc_vectors[i]; 2317e01adc04Sdlg rxr = iv->iv_rxr; 2318e01adc04Sdlg txr = iv->iv_txr; 2319eb1b42e4Sdlg 2320eb1b42e4Sdlg ixl_txr_qdis(sc, txr, 1); 2321eb1b42e4Sdlg 2322eb1b42e4Sdlg ixl_rxr_config(sc, rxr); 2323eb1b42e4Sdlg ixl_txr_config(sc, txr); 2324eb1b42e4Sdlg 2325eb1b42e4Sdlg ixl_wr(sc, I40E_QTX_CTL(i), I40E_QTX_CTL_PF_QUEUE | 2326ccb96312Sdlg (sc->sc_pf_id << I40E_QTX_CTL_PF_INDX_SHIFT)); 2327ccb96312Sdlg 2328eb1b42e4Sdlg ixl_wr(sc, rxr->rxr_tail, 0); 2329203b1b65Sdlg ixl_rxfill(sc, rxr); 2330eb1b42e4Sdlg 2331eb1b42e4Sdlg reg = ixl_rd(sc, I40E_QRX_ENA(i)); 2332eb1b42e4Sdlg SET(reg, I40E_QRX_ENA_QENA_REQ_MASK); 2333eb1b42e4Sdlg ixl_wr(sc, I40E_QRX_ENA(i), reg); 2334eb1b42e4Sdlg 2335eb1b42e4Sdlg reg = ixl_rd(sc, I40E_QTX_ENA(i)); 2336eb1b42e4Sdlg SET(reg, I40E_QTX_ENA_QENA_REQ_MASK); 2337eb1b42e4Sdlg ixl_wr(sc, I40E_QTX_ENA(i), reg); 2338eb1b42e4Sdlg } 2339eb1b42e4Sdlg 2340eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2341e01adc04Sdlg iv = &sc->sc_vectors[i]; 2342e01adc04Sdlg rxr = iv->iv_rxr; 2343e01adc04Sdlg txr = iv->iv_txr; 2344eb1b42e4Sdlg 2345eb1b42e4Sdlg if (ixl_rxr_enabled(sc, rxr) != 0) 2346eb1b42e4Sdlg goto down; 2347eb1b42e4Sdlg 2348eb1b42e4Sdlg if (ixl_txr_enabled(sc, txr) != 0) 2349eb1b42e4Sdlg goto down; 2350eb1b42e4Sdlg } 2351ccb96312Sdlg 2352819ac441Sdlg ixl_configure_rss(sc); 2353819ac441Sdlg 2354ccb96312Sdlg SET(ifp->if_flags, IFF_RUNNING); 2355ccb96312Sdlg 2356e01adc04Sdlg if (sc->sc_intrmap == NULL) { 2357eb1b42e4Sdlg ixl_wr(sc, I40E_PFINT_LNKLST0, 23589b0c6e1eSjmatthew (I40E_INTR_NOTX_QUEUE << 23599b0c6e1eSjmatthew I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) | 23609b0c6e1eSjmatthew (I40E_QUEUE_TYPE_RX << 23619b0c6e1eSjmatthew I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)); 2362eb1b42e4Sdlg 2363eb1b42e4Sdlg ixl_wr(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE), 2364eb1b42e4Sdlg (I40E_INTR_NOTX_INTR << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) | 2365eb1b42e4Sdlg (I40E_ITR_INDEX_RX << I40E_QINT_RQCTL_ITR_INDX_SHIFT) | 23669b0c6e1eSjmatthew (I40E_INTR_NOTX_RX_QUEUE << 23679b0c6e1eSjmatthew I40E_QINT_RQCTL_MSIX0_INDX_SHIFT) | 2368eb1b42e4Sdlg (I40E_INTR_NOTX_QUEUE << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | 2369646632e9Sjmatthew (I40E_QUEUE_TYPE_TX << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) | 2370646632e9Sjmatthew I40E_QINT_RQCTL_CAUSE_ENA_MASK); 2371eb1b42e4Sdlg 2372eb1b42e4Sdlg ixl_wr(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE), 2373eb1b42e4Sdlg (I40E_INTR_NOTX_INTR << I40E_QINT_TQCTL_MSIX_INDX_SHIFT) | 2374eb1b42e4Sdlg (I40E_ITR_INDEX_TX << I40E_QINT_TQCTL_ITR_INDX_SHIFT) | 23759b0c6e1eSjmatthew (I40E_INTR_NOTX_TX_QUEUE << 23769b0c6e1eSjmatthew I40E_QINT_TQCTL_MSIX0_INDX_SHIFT) | 2377eb1b42e4Sdlg (I40E_QUEUE_TYPE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) | 2378646632e9Sjmatthew (I40E_QUEUE_TYPE_RX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT) | 2379646632e9Sjmatthew I40E_QINT_TQCTL_CAUSE_ENA_MASK); 23809b0c6e1eSjmatthew } else { 23819b0c6e1eSjmatthew /* vector 0 has no queues */ 23829b0c6e1eSjmatthew ixl_wr(sc, I40E_PFINT_LNKLST0, 23839b0c6e1eSjmatthew I40E_QUEUE_TYPE_EOL << 23849b0c6e1eSjmatthew I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT); 23859b0c6e1eSjmatthew 23869b0c6e1eSjmatthew /* queue n is mapped to vector n+1 */ 2387e01adc04Sdlg for (i = 0; i < nqueues; i++) { 23889b0c6e1eSjmatthew /* LNKLSTN(i) configures vector i+1 */ 23899b0c6e1eSjmatthew ixl_wr(sc, I40E_PFINT_LNKLSTN(i), 23909b0c6e1eSjmatthew (i << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) | 23919b0c6e1eSjmatthew (I40E_QUEUE_TYPE_RX << 23929b0c6e1eSjmatthew I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)); 23939b0c6e1eSjmatthew ixl_wr(sc, I40E_QINT_RQCTL(i), 23949b0c6e1eSjmatthew ((i+1) << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) | 23959b0c6e1eSjmatthew (I40E_ITR_INDEX_RX << 23969b0c6e1eSjmatthew I40E_QINT_RQCTL_ITR_INDX_SHIFT) | 23979b0c6e1eSjmatthew (i << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | 23989b0c6e1eSjmatthew (I40E_QUEUE_TYPE_TX << 23999b0c6e1eSjmatthew I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) | 24009b0c6e1eSjmatthew I40E_QINT_RQCTL_CAUSE_ENA_MASK); 24019b0c6e1eSjmatthew ixl_wr(sc, I40E_QINT_TQCTL(i), 24029b0c6e1eSjmatthew ((i+1) << I40E_QINT_TQCTL_MSIX_INDX_SHIFT) | 24039b0c6e1eSjmatthew (I40E_ITR_INDEX_TX << 24049b0c6e1eSjmatthew I40E_QINT_TQCTL_ITR_INDX_SHIFT) | 24059b0c6e1eSjmatthew (I40E_QUEUE_TYPE_EOL << 24069b0c6e1eSjmatthew I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) | 24079b0c6e1eSjmatthew (I40E_QUEUE_TYPE_RX << 24089b0c6e1eSjmatthew I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT) | 24099b0c6e1eSjmatthew I40E_QINT_TQCTL_CAUSE_ENA_MASK); 24109b0c6e1eSjmatthew 24119b0c6e1eSjmatthew ixl_wr(sc, I40E_PFINT_ITRN(0, i), 0x7a); 24129b0c6e1eSjmatthew ixl_wr(sc, I40E_PFINT_ITRN(1, i), 0x7a); 24139b0c6e1eSjmatthew ixl_wr(sc, I40E_PFINT_ITRN(2, i), 0); 24149b0c6e1eSjmatthew } 24159b0c6e1eSjmatthew } 2416eb1b42e4Sdlg 2417eb1b42e4Sdlg ixl_wr(sc, I40E_PFINT_ITR0(0), 0x7a); 2418eb1b42e4Sdlg ixl_wr(sc, I40E_PFINT_ITR0(1), 0x7a); 2419eb1b42e4Sdlg ixl_wr(sc, I40E_PFINT_ITR0(2), 0); 2420eb1b42e4Sdlg 2421d3ac7020Sdlg rw_exit_write(&sc->sc_cfg_lock); 2422d3ac7020Sdlg 2423eb1b42e4Sdlg return (ENETRESET); 2424eb1b42e4Sdlg 2425eb1b42e4Sdlg free: 2426eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2427e01adc04Sdlg iv = &sc->sc_vectors[i]; 2428e01adc04Sdlg rxr = iv->iv_rxr; 2429e01adc04Sdlg txr = iv->iv_txr; 2430eb1b42e4Sdlg 2431eb1b42e4Sdlg if (rxr == NULL) { 2432eb1b42e4Sdlg /* 2433eb1b42e4Sdlg * tx and rx get set at the same time, so if one 2434eb1b42e4Sdlg * is NULL, the other is too. 2435eb1b42e4Sdlg */ 2436eb1b42e4Sdlg continue; 2437eb1b42e4Sdlg } 2438eb1b42e4Sdlg 2439eb1b42e4Sdlg ixl_txr_free(sc, txr); 2440eb1b42e4Sdlg ixl_rxr_free(sc, rxr); 2441eb1b42e4Sdlg } 2442d3ac7020Sdlg rw_exit_write(&sc->sc_cfg_lock); 2443ccb96312Sdlg return (rv); 2444eb1b42e4Sdlg down: 2445d3ac7020Sdlg rw_exit_write(&sc->sc_cfg_lock); 2446eb1b42e4Sdlg ixl_down(sc); 2447eb1b42e4Sdlg return (ETIMEDOUT); 2448ccb96312Sdlg } 2449ccb96312Sdlg 2450ccb96312Sdlg static int 2451ccb96312Sdlg ixl_iff(struct ixl_softc *sc) 2452ccb96312Sdlg { 2453ccb96312Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 2454ccb96312Sdlg struct ixl_atq iatq; 2455ccb96312Sdlg struct ixl_aq_desc *iaq; 2456ccb96312Sdlg struct ixl_aq_vsi_promisc_param *param; 2457ccb96312Sdlg 2458ccb96312Sdlg if (!ISSET(ifp->if_flags, IFF_RUNNING)) 2459ccb96312Sdlg return (0); 2460ccb96312Sdlg 2461ccb96312Sdlg memset(&iatq, 0, sizeof(iatq)); 2462ccb96312Sdlg 2463ccb96312Sdlg iaq = &iatq.iatq_desc; 2464ccb96312Sdlg iaq->iaq_opcode = htole16(IXL_AQ_OP_SET_VSI_PROMISC); 2465ccb96312Sdlg 2466ccb96312Sdlg param = (struct ixl_aq_vsi_promisc_param *)&iaq->iaq_param; 2467b4a9eb13Sdlg param->flags = htole16(IXL_AQ_VSI_PROMISC_FLAG_BCAST | 2468b4a9eb13Sdlg IXL_AQ_VSI_PROMISC_FLAG_VLAN); 24692bb8400cSjmatthew if (ISSET(ifp->if_flags, IFF_PROMISC)) { 2470ccb96312Sdlg param->flags |= htole16(IXL_AQ_VSI_PROMISC_FLAG_UCAST | 2471ccb96312Sdlg IXL_AQ_VSI_PROMISC_FLAG_MCAST); 2472300096a1Sjmatthew } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) { 2473300096a1Sjmatthew param->flags |= htole16(IXL_AQ_VSI_PROMISC_FLAG_MCAST); 24742bb8400cSjmatthew } 2475ccb96312Sdlg param->valid_flags = htole16(IXL_AQ_VSI_PROMISC_FLAG_UCAST | 2476b4a9eb13Sdlg IXL_AQ_VSI_PROMISC_FLAG_MCAST | IXL_AQ_VSI_PROMISC_FLAG_BCAST | 2477b4a9eb13Sdlg IXL_AQ_VSI_PROMISC_FLAG_VLAN); 2478ccb96312Sdlg param->seid = sc->sc_seid; 2479ccb96312Sdlg 2480ccb96312Sdlg ixl_atq_exec(sc, &iatq, "ixliff"); 2481ccb96312Sdlg 2482ccb96312Sdlg if (iaq->iaq_retval != htole16(IXL_AQ_RC_OK)) 2483ccb96312Sdlg return (EIO); 2484ccb96312Sdlg 248556319b45Sjmatthew if (memcmp(sc->sc_enaddr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN) != 0) { 248656319b45Sjmatthew ixl_remove_macvlan(sc, sc->sc_enaddr, 0, 248756319b45Sjmatthew IXL_AQ_OP_REMOVE_MACVLAN_IGNORE_VLAN); 248856319b45Sjmatthew ixl_add_macvlan(sc, sc->sc_ac.ac_enaddr, 0, 248956319b45Sjmatthew IXL_AQ_OP_ADD_MACVLAN_IGNORE_VLAN); 249056319b45Sjmatthew memcpy(sc->sc_enaddr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); 249156319b45Sjmatthew } 2492ccb96312Sdlg return (0); 2493ccb96312Sdlg } 2494ccb96312Sdlg 2495ccb96312Sdlg static int 2496ccb96312Sdlg ixl_down(struct ixl_softc *sc) 2497ccb96312Sdlg { 2498eb1b42e4Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 2499e01adc04Sdlg struct ixl_vector *iv; 2500eb1b42e4Sdlg struct ixl_rx_ring *rxr; 2501eb1b42e4Sdlg struct ixl_tx_ring *txr; 2502eb1b42e4Sdlg unsigned int nqueues, i; 2503eb1b42e4Sdlg uint32_t reg; 2504eb1b42e4Sdlg int error = 0; 2505ccb96312Sdlg 2506eb1b42e4Sdlg nqueues = ixl_nqueues(sc); 2507ccb96312Sdlg 2508d3ac7020Sdlg rw_enter_write(&sc->sc_cfg_lock); 2509d3ac7020Sdlg 2510eb1b42e4Sdlg CLR(ifp->if_flags, IFF_RUNNING); 2511ccb96312Sdlg 2512d3ac7020Sdlg NET_UNLOCK(); 2513d3ac7020Sdlg 2514eb1b42e4Sdlg /* mask interrupts */ 2515eb1b42e4Sdlg reg = ixl_rd(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE)); 2516eb1b42e4Sdlg CLR(reg, I40E_QINT_RQCTL_CAUSE_ENA_MASK); 2517eb1b42e4Sdlg ixl_wr(sc, I40E_QINT_RQCTL(I40E_INTR_NOTX_QUEUE), reg); 2518eb1b42e4Sdlg 2519eb1b42e4Sdlg reg = ixl_rd(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE)); 2520eb1b42e4Sdlg CLR(reg, I40E_QINT_TQCTL_CAUSE_ENA_MASK); 2521eb1b42e4Sdlg ixl_wr(sc, I40E_QINT_TQCTL(I40E_INTR_NOTX_QUEUE), reg); 2522eb1b42e4Sdlg 2523eb1b42e4Sdlg ixl_wr(sc, I40E_PFINT_LNKLST0, I40E_QUEUE_TYPE_EOL); 2524eb1b42e4Sdlg 2525eb1b42e4Sdlg /* make sure the no hw generated work is still in flight */ 2526eb1b42e4Sdlg intr_barrier(sc->sc_ihc); 2527e01adc04Sdlg if (sc->sc_intrmap != NULL) { 2528eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2529e01adc04Sdlg iv = &sc->sc_vectors[i]; 2530e01adc04Sdlg rxr = iv->iv_rxr; 2531e01adc04Sdlg txr = iv->iv_txr; 2532eb1b42e4Sdlg 2533eb1b42e4Sdlg ixl_txr_qdis(sc, txr, 0); 2534eb1b42e4Sdlg 2535e01adc04Sdlg ifq_barrier(txr->txr_ifq); 2536203b1b65Sdlg 2537c87f73ddSvisa timeout_del_barrier(&rxr->rxr_refill); 25389b0c6e1eSjmatthew 2539e01adc04Sdlg intr_barrier(iv->iv_ihc); 2540e01adc04Sdlg } 2541eb1b42e4Sdlg } 2542eb1b42e4Sdlg 2543eb1b42e4Sdlg /* XXX wait at least 400 usec for all tx queues in one go */ 2544eb1b42e4Sdlg delay(500); 2545eb1b42e4Sdlg 2546eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2547eb1b42e4Sdlg reg = ixl_rd(sc, I40E_QTX_ENA(i)); 2548eb1b42e4Sdlg CLR(reg, I40E_QTX_ENA_QENA_REQ_MASK); 2549eb1b42e4Sdlg ixl_wr(sc, I40E_QTX_ENA(i), reg); 2550eb1b42e4Sdlg 2551eb1b42e4Sdlg reg = ixl_rd(sc, I40E_QRX_ENA(i)); 2552eb1b42e4Sdlg CLR(reg, I40E_QRX_ENA_QENA_REQ_MASK); 2553eb1b42e4Sdlg ixl_wr(sc, I40E_QRX_ENA(i), reg); 2554eb1b42e4Sdlg } 2555eb1b42e4Sdlg 2556eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2557e01adc04Sdlg iv = &sc->sc_vectors[i]; 2558e01adc04Sdlg rxr = iv->iv_rxr; 2559e01adc04Sdlg txr = iv->iv_txr; 2560eb1b42e4Sdlg 2561eb1b42e4Sdlg if (ixl_txr_disabled(sc, txr) != 0) 2562d3ac7020Sdlg goto die; 2563eb1b42e4Sdlg 2564eb1b42e4Sdlg if (ixl_rxr_disabled(sc, rxr) != 0) 2565d3ac7020Sdlg goto die; 2566eb1b42e4Sdlg } 2567eb1b42e4Sdlg 2568eb1b42e4Sdlg for (i = 0; i < nqueues; i++) { 2569e01adc04Sdlg iv = &sc->sc_vectors[i]; 2570e01adc04Sdlg rxr = iv->iv_rxr; 2571e01adc04Sdlg txr = iv->iv_txr; 2572eb1b42e4Sdlg 2573eb1b42e4Sdlg ixl_txr_unconfig(sc, txr); 2574eb1b42e4Sdlg ixl_rxr_unconfig(sc, rxr); 2575eb1b42e4Sdlg 2576eb1b42e4Sdlg ixl_txr_clean(sc, txr); 2577eb1b42e4Sdlg ixl_rxr_clean(sc, rxr); 2578eb1b42e4Sdlg 2579eb1b42e4Sdlg ixl_txr_free(sc, txr); 2580eb1b42e4Sdlg ixl_rxr_free(sc, rxr); 2581ccb96312Sdlg 258200cd24f1Sdlg ifp->if_iqs[i]->ifiq_softc = NULL; 2583eb1b42e4Sdlg ifp->if_ifqs[i]->ifq_softc = NULL; 2584eb1b42e4Sdlg } 2585ccb96312Sdlg 2586d3ac7020Sdlg out: 2587d3ac7020Sdlg rw_exit_write(&sc->sc_cfg_lock); 2588d3ac7020Sdlg NET_LOCK(); 2589d3ac7020Sdlg return (error); 2590d3ac7020Sdlg die: 2591d3ac7020Sdlg sc->sc_dead = 1; 2592d3ac7020Sdlg log(LOG_CRIT, "%s: failed to shut down rings", DEVNAME(sc)); 2593d3ac7020Sdlg error = ETIMEDOUT; 2594d3ac7020Sdlg goto out; 2595ccb96312Sdlg } 2596ccb96312Sdlg 2597ccb96312Sdlg static struct ixl_tx_ring * 2598ccb96312Sdlg ixl_txr_alloc(struct ixl_softc *sc, unsigned int qid) 2599ccb96312Sdlg { 2600ccb96312Sdlg struct ixl_tx_ring *txr; 2601ccb96312Sdlg struct ixl_tx_map *maps, *txm; 2602ccb96312Sdlg unsigned int i; 2603ccb96312Sdlg 2604ccb96312Sdlg txr = malloc(sizeof(*txr), M_DEVBUF, M_WAITOK|M_CANFAIL); 2605ccb96312Sdlg if (txr == NULL) 2606ccb96312Sdlg return (NULL); 2607ccb96312Sdlg 2608ccb96312Sdlg maps = mallocarray(sizeof(*maps), 2609ccb96312Sdlg sc->sc_tx_ring_ndescs, M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); 2610ccb96312Sdlg if (maps == NULL) 2611ccb96312Sdlg goto free; 2612ccb96312Sdlg 2613ccb96312Sdlg if (ixl_dmamem_alloc(sc, &txr->txr_mem, 2614ccb96312Sdlg sizeof(struct ixl_tx_desc) * sc->sc_tx_ring_ndescs, 2615ccb96312Sdlg IXL_TX_QUEUE_ALIGN) != 0) 2616ccb96312Sdlg goto freemap; 2617ccb96312Sdlg 2618ccb96312Sdlg for (i = 0; i < sc->sc_tx_ring_ndescs; i++) { 2619ccb96312Sdlg txm = &maps[i]; 2620ccb96312Sdlg 2621ccb96312Sdlg if (bus_dmamap_create(sc->sc_dmat, 2622f77c9c95Sjan MAXMCLBYTES, IXL_TX_PKT_DESCS, IXL_MAX_DMA_SEG_SIZE, 0, 2623ccb96312Sdlg BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 2624ccb96312Sdlg &txm->txm_map) != 0) 2625ccb96312Sdlg goto uncreate; 2626ccb96312Sdlg 2627ccb96312Sdlg txm->txm_eop = -1; 2628ccb96312Sdlg txm->txm_m = NULL; 2629ccb96312Sdlg } 2630ccb96312Sdlg 2631ccb96312Sdlg txr->txr_cons = txr->txr_prod = 0; 2632ccb96312Sdlg txr->txr_maps = maps; 2633eb1b42e4Sdlg 2634ccb96312Sdlg txr->txr_tail = I40E_QTX_TAIL(qid); 2635ccb96312Sdlg txr->txr_qid = qid; 2636ccb96312Sdlg 2637ccb96312Sdlg return (txr); 2638ccb96312Sdlg 2639ccb96312Sdlg uncreate: 2640ccb96312Sdlg for (i = 0; i < sc->sc_tx_ring_ndescs; i++) { 2641ccb96312Sdlg txm = &maps[i]; 2642ccb96312Sdlg 2643ccb96312Sdlg if (txm->txm_map == NULL) 2644ccb96312Sdlg continue; 2645ccb96312Sdlg 2646ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, txm->txm_map); 2647ccb96312Sdlg } 2648ccb96312Sdlg 2649ccb96312Sdlg ixl_dmamem_free(sc, &txr->txr_mem); 2650ccb96312Sdlg freemap: 2651ccb96312Sdlg free(maps, M_DEVBUF, sizeof(*maps) * sc->sc_tx_ring_ndescs); 2652ccb96312Sdlg free: 2653ccb96312Sdlg free(txr, M_DEVBUF, sizeof(*txr)); 2654ccb96312Sdlg return (NULL); 2655ccb96312Sdlg } 2656ccb96312Sdlg 2657ccb96312Sdlg static void 2658eb1b42e4Sdlg ixl_txr_qdis(struct ixl_softc *sc, struct ixl_tx_ring *txr, int enable) 2659eb1b42e4Sdlg { 2660eb1b42e4Sdlg unsigned int qid; 2661eb1b42e4Sdlg bus_size_t reg; 2662eb1b42e4Sdlg uint32_t r; 2663eb1b42e4Sdlg 2664eb1b42e4Sdlg qid = txr->txr_qid + sc->sc_base_queue; 2665eb1b42e4Sdlg reg = I40E_GLLAN_TXPRE_QDIS(qid / 128); 2666eb1b42e4Sdlg qid %= 128; 2667eb1b42e4Sdlg 2668eb1b42e4Sdlg r = ixl_rd(sc, reg); 2669eb1b42e4Sdlg CLR(r, I40E_GLLAN_TXPRE_QDIS_QINDX_MASK); 2670eb1b42e4Sdlg SET(r, qid << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT); 2671eb1b42e4Sdlg SET(r, enable ? I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK : 2672eb1b42e4Sdlg I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK); 2673eb1b42e4Sdlg ixl_wr(sc, reg, r); 2674eb1b42e4Sdlg } 2675eb1b42e4Sdlg 2676eb1b42e4Sdlg static void 2677ccb96312Sdlg ixl_txr_config(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2678ccb96312Sdlg { 2679ccb96312Sdlg struct ixl_hmc_txq txq; 26802bb8400cSjmatthew struct ixl_aq_vsi_data *data = IXL_DMA_KVA(&sc->sc_scratch); 2681ccb96312Sdlg void *hmc; 2682ccb96312Sdlg 2683ccb96312Sdlg memset(&txq, 0, sizeof(txq)); 2684ccb96312Sdlg txq.head = htole16(0); 2685ccb96312Sdlg txq.new_context = 1; 2686ccb96312Sdlg htolem64(&txq.base, 2687eb1b42e4Sdlg IXL_DMA_DVA(&txr->txr_mem) / IXL_HMC_TXQ_BASE_UNIT); 2688ccb96312Sdlg txq.head_wb_ena = IXL_HMC_TXQ_DESC_WB; 2689ccb96312Sdlg htolem16(&txq.qlen, sc->sc_tx_ring_ndescs); 2690eb1b42e4Sdlg txq.tphrdesc_ena = 0; 2691eb1b42e4Sdlg txq.tphrpacket_ena = 0; 2692eb1b42e4Sdlg txq.tphwdesc_ena = 0; 2693ccb96312Sdlg txq.rdylist = data->qs_handle[0]; 2694ccb96312Sdlg 2695eb1b42e4Sdlg hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_TX, txr->txr_qid); 2696ccb96312Sdlg memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_TX)); 2697ccb96312Sdlg ixl_hmc_pack(hmc, &txq, ixl_hmc_pack_txq, nitems(ixl_hmc_pack_txq)); 2698ccb96312Sdlg } 2699ccb96312Sdlg 2700ccb96312Sdlg static void 2701ccb96312Sdlg ixl_txr_unconfig(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2702ccb96312Sdlg { 2703ccb96312Sdlg void *hmc; 2704ccb96312Sdlg 2705eb1b42e4Sdlg hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_TX, txr->txr_qid); 2706ccb96312Sdlg memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_TX)); 2707ccb96312Sdlg } 2708ccb96312Sdlg 2709ccb96312Sdlg static void 2710ccb96312Sdlg ixl_txr_clean(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2711ccb96312Sdlg { 2712ccb96312Sdlg struct ixl_tx_map *maps, *txm; 2713ccb96312Sdlg bus_dmamap_t map; 2714ccb96312Sdlg unsigned int i; 2715ccb96312Sdlg 2716ccb96312Sdlg maps = txr->txr_maps; 2717ccb96312Sdlg for (i = 0; i < sc->sc_tx_ring_ndescs; i++) { 2718ccb96312Sdlg txm = &maps[i]; 2719ccb96312Sdlg 2720ccb96312Sdlg if (txm->txm_m == NULL) 2721ccb96312Sdlg continue; 2722ccb96312Sdlg 2723ccb96312Sdlg map = txm->txm_map; 2724ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 2725ccb96312Sdlg BUS_DMASYNC_POSTWRITE); 2726ccb96312Sdlg bus_dmamap_unload(sc->sc_dmat, map); 2727ccb96312Sdlg 2728ccb96312Sdlg m_freem(txm->txm_m); 2729ccb96312Sdlg txm->txm_m = NULL; 2730ccb96312Sdlg } 2731ccb96312Sdlg } 2732ccb96312Sdlg 2733ccb96312Sdlg static int 2734eb1b42e4Sdlg ixl_txr_enabled(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2735ccb96312Sdlg { 2736ccb96312Sdlg bus_size_t ena = I40E_QTX_ENA(txr->txr_qid); 2737ccb96312Sdlg uint32_t reg; 2738ccb96312Sdlg int i; 2739ccb96312Sdlg 2740ccb96312Sdlg for (i = 0; i < 10; i++) { 2741ccb96312Sdlg reg = ixl_rd(sc, ena); 2742ccb96312Sdlg if (ISSET(reg, I40E_QTX_ENA_QENA_STAT_MASK)) 2743ccb96312Sdlg return (0); 2744ccb96312Sdlg 2745ccb96312Sdlg delaymsec(10); 2746ccb96312Sdlg } 2747ccb96312Sdlg 2748ccb96312Sdlg return (ETIMEDOUT); 2749ccb96312Sdlg } 2750ccb96312Sdlg 2751ccb96312Sdlg static int 2752eb1b42e4Sdlg ixl_txr_disabled(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2753ccb96312Sdlg { 2754ccb96312Sdlg bus_size_t ena = I40E_QTX_ENA(txr->txr_qid); 2755ccb96312Sdlg uint32_t reg; 2756ccb96312Sdlg int i; 2757ccb96312Sdlg 2758eb1b42e4Sdlg for (i = 0; i < 20; i++) { 2759ccb96312Sdlg reg = ixl_rd(sc, ena); 2760eb1b42e4Sdlg if (ISSET(reg, I40E_QTX_ENA_QENA_STAT_MASK) == 0) 2761ccb96312Sdlg return (0); 2762ccb96312Sdlg 2763ccb96312Sdlg delaymsec(10); 2764ccb96312Sdlg } 2765ccb96312Sdlg 2766ccb96312Sdlg return (ETIMEDOUT); 2767ccb96312Sdlg } 2768ccb96312Sdlg 2769ccb96312Sdlg static void 2770ccb96312Sdlg ixl_txr_free(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2771ccb96312Sdlg { 2772ccb96312Sdlg struct ixl_tx_map *maps, *txm; 2773ccb96312Sdlg unsigned int i; 2774ccb96312Sdlg 2775ccb96312Sdlg maps = txr->txr_maps; 2776ccb96312Sdlg for (i = 0; i < sc->sc_tx_ring_ndescs; i++) { 2777ccb96312Sdlg txm = &maps[i]; 2778ccb96312Sdlg 2779ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, txm->txm_map); 2780ccb96312Sdlg } 2781ccb96312Sdlg 2782ccb96312Sdlg ixl_dmamem_free(sc, &txr->txr_mem); 2783ccb96312Sdlg free(maps, M_DEVBUF, sizeof(*maps) * sc->sc_tx_ring_ndescs); 2784ccb96312Sdlg free(txr, M_DEVBUF, sizeof(*txr)); 2785ccb96312Sdlg } 2786ccb96312Sdlg 2787ccb96312Sdlg static inline int 2788ccb96312Sdlg ixl_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m) 2789ccb96312Sdlg { 2790ccb96312Sdlg int error; 2791ccb96312Sdlg 2792ccb96312Sdlg error = bus_dmamap_load_mbuf(dmat, map, m, 2793ccb96312Sdlg BUS_DMA_STREAMING | BUS_DMA_NOWAIT); 2794a78aaae2Sdlg if (error != EFBIG) 2795a78aaae2Sdlg return (error); 2796a78aaae2Sdlg 2797a78aaae2Sdlg error = m_defrag(m, M_DONTWAIT); 2798a78aaae2Sdlg if (error != 0) 2799ccb96312Sdlg return (error); 2800ccb96312Sdlg 2801ccb96312Sdlg return (bus_dmamap_load_mbuf(dmat, map, m, 2802ccb96312Sdlg BUS_DMA_STREAMING | BUS_DMA_NOWAIT)); 2803ccb96312Sdlg } 2804ccb96312Sdlg 280504206048Sdlg static uint64_t 2806f77c9c95Sjan ixl_tx_setup_offload(struct mbuf *m0, struct ixl_tx_ring *txr, 2807f77c9c95Sjan unsigned int prod) 280804206048Sdlg { 280926fd91ceSjan struct ether_extracted ext; 281004206048Sdlg uint64_t hlen; 281104206048Sdlg uint64_t offload = 0; 281204206048Sdlg 2813*60b8dadeSjan #if NVLAN > 0 2814983d220cSdlg if (ISSET(m0->m_flags, M_VLANTAG)) { 2815983d220cSdlg uint64_t vtag = m0->m_pkthdr.ether_vtag; 2816983d220cSdlg offload |= IXL_TX_DESC_CMD_IL2TAG1; 2817983d220cSdlg offload |= vtag << IXL_TX_DESC_L2TAG1_SHIFT; 2818983d220cSdlg } 2819*60b8dadeSjan #endif 2820983d220cSdlg 282104206048Sdlg if (!ISSET(m0->m_pkthdr.csum_flags, 2822f77c9c95Sjan M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_TCP_TSO)) 2823983d220cSdlg return (offload); 282404206048Sdlg 282526fd91ceSjan ether_extract_headers(m0, &ext); 282604206048Sdlg 282726fd91ceSjan if (ext.ip4) { 282804206048Sdlg offload |= ISSET(m0->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT) ? 282904206048Sdlg IXL_TX_DESC_CMD_IIPT_IPV4_CSUM : 283004206048Sdlg IXL_TX_DESC_CMD_IIPT_IPV4; 283104206048Sdlg #ifdef INET6 283226fd91ceSjan } else if (ext.ip6) { 283304206048Sdlg offload |= IXL_TX_DESC_CMD_IIPT_IPV6; 283404206048Sdlg #endif 283526fd91ceSjan } else { 283604206048Sdlg panic("CSUM_OUT set for non-IP packet"); 283704206048Sdlg /* NOTREACHED */ 283804206048Sdlg } 2839ac5f541aSbluhm hlen = ext.iphlen; 284004206048Sdlg 284104206048Sdlg offload |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT; 284204206048Sdlg offload |= (hlen >> 2) << IXL_TX_DESC_IPLEN_SHIFT; 284304206048Sdlg 284426fd91ceSjan if (ext.tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { 284504206048Sdlg offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; 2846e78a66e5Sbluhm offload |= (uint64_t)(ext.tcphlen >> 2) 2847e78a66e5Sbluhm << IXL_TX_DESC_L4LEN_SHIFT; 284826fd91ceSjan } else if (ext.udp && ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { 284904206048Sdlg offload |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; 2850e78a66e5Sbluhm offload |= (uint64_t)(sizeof(*ext.udp) >> 2) 2851e78a66e5Sbluhm << IXL_TX_DESC_L4LEN_SHIFT; 285204206048Sdlg } 285304206048Sdlg 2854f77c9c95Sjan if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO)) { 28557f8ccd64Sjan if (ext.tcp && m0->m_pkthdr.ph_mss > 0) { 2856f77c9c95Sjan struct ixl_tx_desc *ring, *txd; 2857dc62a2d5Sjan uint64_t cmd = 0, paylen, outlen; 2858f77c9c95Sjan 2859e78a66e5Sbluhm hlen += ext.tcphlen; 2860dc62a2d5Sjan 2861db052177Sjan /* 2862db052177Sjan * The MSS should not be set to a lower value than 64 2863db052177Sjan * or larger than 9668 bytes. 2864db052177Sjan */ 2865db052177Sjan outlen = MIN(9668, MAX(64, m0->m_pkthdr.ph_mss)); 2866dc62a2d5Sjan paylen = m0->m_pkthdr.len - ETHER_HDR_LEN - hlen; 2867dc62a2d5Sjan 2868f77c9c95Sjan ring = IXL_DMA_KVA(&txr->txr_mem); 2869f77c9c95Sjan txd = &ring[prod]; 2870f77c9c95Sjan 2871f77c9c95Sjan cmd |= IXL_TX_DESC_DTYPE_CONTEXT; 2872f77c9c95Sjan cmd |= IXL_TX_CTX_DESC_CMD_TSO; 2873dc62a2d5Sjan cmd |= paylen << IXL_TX_CTX_DESC_TLEN_SHIFT; 2874dc62a2d5Sjan cmd |= outlen << IXL_TX_CTX_DESC_MSS_SHIFT; 2875f77c9c95Sjan 2876f77c9c95Sjan htolem64(&txd->addr, 0); 2877f77c9c95Sjan htolem64(&txd->cmd, cmd); 2878dc62a2d5Sjan 2879dc62a2d5Sjan tcpstat_add(tcps_outpkttso, 2880dc62a2d5Sjan (paylen + outlen - 1) / outlen); 2881f77c9c95Sjan } else 2882f77c9c95Sjan tcpstat_inc(tcps_outbadtso); 2883f77c9c95Sjan } 2884f77c9c95Sjan 288504206048Sdlg return (offload); 288604206048Sdlg } 288704206048Sdlg 2888ccb96312Sdlg static void 2889ccb96312Sdlg ixl_start(struct ifqueue *ifq) 2890ccb96312Sdlg { 2891ccb96312Sdlg struct ifnet *ifp = ifq->ifq_if; 2892ccb96312Sdlg struct ixl_softc *sc = ifp->if_softc; 2893ccb96312Sdlg struct ixl_tx_ring *txr = ifq->ifq_softc; 2894ccb96312Sdlg struct ixl_tx_desc *ring, *txd; 2895ccb96312Sdlg struct ixl_tx_map *txm; 2896ccb96312Sdlg bus_dmamap_t map; 2897ccb96312Sdlg struct mbuf *m; 2898378d0f97Sderaadt uint64_t cmd; 2899ccb96312Sdlg unsigned int prod, free, last, i; 2900ccb96312Sdlg unsigned int mask; 2901ccb96312Sdlg int post = 0; 290204206048Sdlg uint64_t offload; 2903ccb96312Sdlg #if NBPFILTER > 0 2904ccb96312Sdlg caddr_t if_bpf; 2905ccb96312Sdlg #endif 2906ccb96312Sdlg 2907ccb96312Sdlg if (!LINK_STATE_IS_UP(ifp->if_link_state)) { 2908ccb96312Sdlg ifq_purge(ifq); 2909ccb96312Sdlg return; 2910ccb96312Sdlg } 2911ccb96312Sdlg 2912ccb96312Sdlg prod = txr->txr_prod; 2913ccb96312Sdlg free = txr->txr_cons; 2914ccb96312Sdlg if (free <= prod) 2915ccb96312Sdlg free += sc->sc_tx_ring_ndescs; 2916ccb96312Sdlg free -= prod; 2917ccb96312Sdlg 2918ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&txr->txr_mem), 2919ccb96312Sdlg 0, IXL_DMA_LEN(&txr->txr_mem), BUS_DMASYNC_POSTWRITE); 2920ccb96312Sdlg 2921ccb96312Sdlg ring = IXL_DMA_KVA(&txr->txr_mem); 2922ccb96312Sdlg mask = sc->sc_tx_ring_ndescs - 1; 2923ccb96312Sdlg 2924ccb96312Sdlg for (;;) { 2925f77c9c95Sjan /* We need one extra descriptor for TSO packets. */ 2926f77c9c95Sjan if (free <= (IXL_TX_PKT_DESCS + 1)) { 2927ccb96312Sdlg ifq_set_oactive(ifq); 2928ccb96312Sdlg break; 2929ccb96312Sdlg } 2930ccb96312Sdlg 2931ccb96312Sdlg m = ifq_dequeue(ifq); 2932ccb96312Sdlg if (m == NULL) 2933ccb96312Sdlg break; 2934ccb96312Sdlg 2935f77c9c95Sjan offload = ixl_tx_setup_offload(m, txr, prod); 293604206048Sdlg 2937ccb96312Sdlg txm = &txr->txr_maps[prod]; 2938ccb96312Sdlg map = txm->txm_map; 2939ccb96312Sdlg 2940f77c9c95Sjan if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) { 2941f77c9c95Sjan prod++; 2942f77c9c95Sjan prod &= mask; 2943f77c9c95Sjan free--; 2944f77c9c95Sjan } 2945f77c9c95Sjan 2946ccb96312Sdlg if (ixl_load_mbuf(sc->sc_dmat, map, m) != 0) { 2947a78aaae2Sdlg ifq->ifq_errors++; 2948ccb96312Sdlg m_freem(m); 2949ccb96312Sdlg continue; 2950ccb96312Sdlg } 2951ccb96312Sdlg 2952ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, map, 0, 2953ccb96312Sdlg map->dm_mapsize, BUS_DMASYNC_PREWRITE); 2954ccb96312Sdlg 2955ccb96312Sdlg for (i = 0; i < map->dm_nsegs; i++) { 2956ccb96312Sdlg txd = &ring[prod]; 2957ccb96312Sdlg 2958ccb96312Sdlg cmd = (uint64_t)map->dm_segs[i].ds_len << 2959ccb96312Sdlg IXL_TX_DESC_BSIZE_SHIFT; 2960ccb96312Sdlg cmd |= IXL_TX_DESC_DTYPE_DATA | IXL_TX_DESC_CMD_ICRC; 296104206048Sdlg cmd |= offload; 2962ccb96312Sdlg 2963ccb96312Sdlg htolem64(&txd->addr, map->dm_segs[i].ds_addr); 2964ccb96312Sdlg htolem64(&txd->cmd, cmd); 2965ccb96312Sdlg 2966ccb96312Sdlg last = prod; 2967ccb96312Sdlg 2968ccb96312Sdlg prod++; 2969ccb96312Sdlg prod &= mask; 2970ccb96312Sdlg } 2971ccb96312Sdlg cmd |= IXL_TX_DESC_CMD_EOP | IXL_TX_DESC_CMD_RS; 2972ccb96312Sdlg htolem64(&txd->cmd, cmd); 2973ccb96312Sdlg 2974ccb96312Sdlg txm->txm_m = m; 2975ccb96312Sdlg txm->txm_eop = last; 2976ccb96312Sdlg 2977ccb96312Sdlg #if NBPFILTER > 0 2978ccb96312Sdlg if_bpf = ifp->if_bpf; 2979ccb96312Sdlg if (if_bpf) 2980ccb96312Sdlg bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT); 2981ccb96312Sdlg #endif 2982ccb96312Sdlg 2983ccb96312Sdlg free -= i; 2984ccb96312Sdlg post = 1; 2985ccb96312Sdlg } 2986ccb96312Sdlg 2987ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&txr->txr_mem), 2988ccb96312Sdlg 0, IXL_DMA_LEN(&txr->txr_mem), BUS_DMASYNC_PREWRITE); 2989ccb96312Sdlg 2990ccb96312Sdlg if (post) { 2991ccb96312Sdlg txr->txr_prod = prod; 2992ccb96312Sdlg ixl_wr(sc, txr->txr_tail, prod); 2993ccb96312Sdlg } 2994ccb96312Sdlg } 2995ccb96312Sdlg 2996ccb96312Sdlg static int 2997e01adc04Sdlg ixl_txeof(struct ixl_softc *sc, struct ixl_tx_ring *txr) 2998ccb96312Sdlg { 2999e01adc04Sdlg struct ifqueue *ifq = txr->txr_ifq; 3000ccb96312Sdlg struct ixl_tx_desc *ring, *txd; 3001ccb96312Sdlg struct ixl_tx_map *txm; 3002ccb96312Sdlg bus_dmamap_t map; 3003ccb96312Sdlg unsigned int cons, prod, last; 3004ccb96312Sdlg unsigned int mask; 3005ccb96312Sdlg uint64_t dtype; 3006ccb96312Sdlg int done = 0; 3007ccb96312Sdlg 3008ccb96312Sdlg prod = txr->txr_prod; 3009ccb96312Sdlg cons = txr->txr_cons; 3010ccb96312Sdlg 3011ccb96312Sdlg if (cons == prod) 3012ccb96312Sdlg return (0); 3013ccb96312Sdlg 3014ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&txr->txr_mem), 3015ccb96312Sdlg 0, IXL_DMA_LEN(&txr->txr_mem), BUS_DMASYNC_POSTREAD); 3016ccb96312Sdlg 3017ccb96312Sdlg ring = IXL_DMA_KVA(&txr->txr_mem); 3018ccb96312Sdlg mask = sc->sc_tx_ring_ndescs - 1; 3019ccb96312Sdlg 3020ccb96312Sdlg do { 3021ccb96312Sdlg txm = &txr->txr_maps[cons]; 3022ccb96312Sdlg last = txm->txm_eop; 3023ccb96312Sdlg txd = &ring[last]; 3024ccb96312Sdlg 3025ccb96312Sdlg dtype = txd->cmd & htole64(IXL_TX_DESC_DTYPE_MASK); 3026ccb96312Sdlg if (dtype != htole64(IXL_TX_DESC_DTYPE_DONE)) 3027ccb96312Sdlg break; 3028ccb96312Sdlg 3029ccb96312Sdlg map = txm->txm_map; 3030ccb96312Sdlg 3031ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 3032ccb96312Sdlg BUS_DMASYNC_POSTWRITE); 3033ccb96312Sdlg bus_dmamap_unload(sc->sc_dmat, map); 3034ccb96312Sdlg m_freem(txm->txm_m); 3035ccb96312Sdlg 3036ccb96312Sdlg txm->txm_m = NULL; 3037ccb96312Sdlg txm->txm_eop = -1; 3038ccb96312Sdlg 3039ccb96312Sdlg cons = last + 1; 3040ccb96312Sdlg cons &= mask; 3041ccb96312Sdlg 3042ccb96312Sdlg done = 1; 3043ccb96312Sdlg } while (cons != prod); 3044ccb96312Sdlg 3045ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&txr->txr_mem), 3046ccb96312Sdlg 0, IXL_DMA_LEN(&txr->txr_mem), BUS_DMASYNC_PREREAD); 3047ccb96312Sdlg 3048ccb96312Sdlg txr->txr_cons = cons; 3049ccb96312Sdlg 3050ccb96312Sdlg //ixl_enable(sc, txr->txr_msix); 3051ccb96312Sdlg 3052ccb96312Sdlg if (ifq_is_oactive(ifq)) 3053ccb96312Sdlg ifq_restart(ifq); 3054ccb96312Sdlg 3055ccb96312Sdlg return (done); 3056ccb96312Sdlg } 3057ccb96312Sdlg 3058ccb96312Sdlg static struct ixl_rx_ring * 3059ccb96312Sdlg ixl_rxr_alloc(struct ixl_softc *sc, unsigned int qid) 3060ccb96312Sdlg { 3061ccb96312Sdlg struct ixl_rx_ring *rxr; 3062ccb96312Sdlg struct ixl_rx_map *maps, *rxm; 3063ccb96312Sdlg unsigned int i; 3064ccb96312Sdlg 3065ccb96312Sdlg rxr = malloc(sizeof(*rxr), M_DEVBUF, M_WAITOK|M_CANFAIL); 3066ccb96312Sdlg if (rxr == NULL) 3067ccb96312Sdlg return (NULL); 3068ccb96312Sdlg 3069ccb96312Sdlg maps = mallocarray(sizeof(*maps), 3070ccb96312Sdlg sc->sc_rx_ring_ndescs, M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); 3071ccb96312Sdlg if (maps == NULL) 3072ccb96312Sdlg goto free; 3073ccb96312Sdlg 3074ccb96312Sdlg if (ixl_dmamem_alloc(sc, &rxr->rxr_mem, 3075ccb96312Sdlg sizeof(struct ixl_rx_rd_desc_16) * sc->sc_rx_ring_ndescs, 3076ccb96312Sdlg IXL_RX_QUEUE_ALIGN) != 0) 3077ccb96312Sdlg goto freemap; 3078ccb96312Sdlg 3079ccb96312Sdlg for (i = 0; i < sc->sc_rx_ring_ndescs; i++) { 3080ccb96312Sdlg rxm = &maps[i]; 3081ccb96312Sdlg 3082ccb96312Sdlg if (bus_dmamap_create(sc->sc_dmat, 3083ccb96312Sdlg IXL_HARDMTU, 1, IXL_HARDMTU, 0, 3084ccb96312Sdlg BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 3085ccb96312Sdlg &rxm->rxm_map) != 0) 3086ccb96312Sdlg goto uncreate; 3087ccb96312Sdlg 3088ccb96312Sdlg rxm->rxm_m = NULL; 3089ccb96312Sdlg } 3090ccb96312Sdlg 309100cd24f1Sdlg rxr->rxr_sc = sc; 3092ccb96312Sdlg if_rxr_init(&rxr->rxr_acct, 17, sc->sc_rx_ring_ndescs - 1); 3093ccb96312Sdlg timeout_set(&rxr->rxr_refill, ixl_rxrefill, rxr); 3094ccb96312Sdlg rxr->rxr_cons = rxr->rxr_prod = 0; 3095ccb96312Sdlg rxr->rxr_m_head = NULL; 3096ccb96312Sdlg rxr->rxr_m_tail = &rxr->rxr_m_head; 3097ccb96312Sdlg rxr->rxr_maps = maps; 3098ccb96312Sdlg 3099ccb96312Sdlg rxr->rxr_tail = I40E_QRX_TAIL(qid); 3100ccb96312Sdlg rxr->rxr_qid = qid; 3101ccb96312Sdlg 3102ccb96312Sdlg return (rxr); 3103ccb96312Sdlg 3104ccb96312Sdlg uncreate: 3105ccb96312Sdlg for (i = 0; i < sc->sc_rx_ring_ndescs; i++) { 3106ccb96312Sdlg rxm = &maps[i]; 3107ccb96312Sdlg 3108ccb96312Sdlg if (rxm->rxm_map == NULL) 3109ccb96312Sdlg continue; 3110ccb96312Sdlg 3111ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, rxm->rxm_map); 3112ccb96312Sdlg } 3113ccb96312Sdlg 3114ccb96312Sdlg ixl_dmamem_free(sc, &rxr->rxr_mem); 3115ccb96312Sdlg freemap: 3116ccb96312Sdlg free(maps, M_DEVBUF, sizeof(*maps) * sc->sc_rx_ring_ndescs); 3117ccb96312Sdlg free: 3118ccb96312Sdlg free(rxr, M_DEVBUF, sizeof(*rxr)); 3119ccb96312Sdlg return (NULL); 3120ccb96312Sdlg } 3121ccb96312Sdlg 3122ccb96312Sdlg static void 3123ccb96312Sdlg ixl_rxr_clean(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3124ccb96312Sdlg { 3125ccb96312Sdlg struct ixl_rx_map *maps, *rxm; 3126ccb96312Sdlg bus_dmamap_t map; 3127ccb96312Sdlg unsigned int i; 3128ccb96312Sdlg 3129c87f73ddSvisa timeout_del_barrier(&rxr->rxr_refill); 3130ccb96312Sdlg 3131ccb96312Sdlg maps = rxr->rxr_maps; 3132ccb96312Sdlg for (i = 0; i < sc->sc_rx_ring_ndescs; i++) { 3133ccb96312Sdlg rxm = &maps[i]; 3134ccb96312Sdlg 3135ccb96312Sdlg if (rxm->rxm_m == NULL) 3136ccb96312Sdlg continue; 3137ccb96312Sdlg 3138ccb96312Sdlg map = rxm->rxm_map; 3139ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 3140ccb96312Sdlg BUS_DMASYNC_POSTWRITE); 3141ccb96312Sdlg bus_dmamap_unload(sc->sc_dmat, map); 3142ccb96312Sdlg 3143ccb96312Sdlg m_freem(rxm->rxm_m); 3144ccb96312Sdlg rxm->rxm_m = NULL; 3145ccb96312Sdlg } 3146ccb96312Sdlg 3147ccb96312Sdlg m_freem(rxr->rxr_m_head); 3148ccb96312Sdlg rxr->rxr_m_head = NULL; 3149ccb96312Sdlg rxr->rxr_m_tail = &rxr->rxr_m_head; 3150ccb96312Sdlg 3151ccb96312Sdlg rxr->rxr_prod = rxr->rxr_cons = 0; 3152ccb96312Sdlg } 3153ccb96312Sdlg 3154ccb96312Sdlg static int 3155eb1b42e4Sdlg ixl_rxr_enabled(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3156ccb96312Sdlg { 3157ccb96312Sdlg bus_size_t ena = I40E_QRX_ENA(rxr->rxr_qid); 3158ccb96312Sdlg uint32_t reg; 3159ccb96312Sdlg int i; 3160ccb96312Sdlg 3161ccb96312Sdlg for (i = 0; i < 10; i++) { 3162ccb96312Sdlg reg = ixl_rd(sc, ena); 3163ccb96312Sdlg if (ISSET(reg, I40E_QRX_ENA_QENA_STAT_MASK)) 3164ccb96312Sdlg return (0); 3165ccb96312Sdlg 3166ccb96312Sdlg delaymsec(10); 3167ccb96312Sdlg } 3168ccb96312Sdlg 3169ccb96312Sdlg return (ETIMEDOUT); 3170ccb96312Sdlg } 3171ccb96312Sdlg 3172eb1b42e4Sdlg static int 3173eb1b42e4Sdlg ixl_rxr_disabled(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3174eb1b42e4Sdlg { 3175eb1b42e4Sdlg bus_size_t ena = I40E_QRX_ENA(rxr->rxr_qid); 3176eb1b42e4Sdlg uint32_t reg; 3177eb1b42e4Sdlg int i; 3178eb1b42e4Sdlg 3179eb1b42e4Sdlg for (i = 0; i < 20; i++) { 3180eb1b42e4Sdlg reg = ixl_rd(sc, ena); 3181eb1b42e4Sdlg if (ISSET(reg, I40E_QRX_ENA_QENA_STAT_MASK) == 0) 3182eb1b42e4Sdlg return (0); 3183eb1b42e4Sdlg 3184eb1b42e4Sdlg delaymsec(10); 3185eb1b42e4Sdlg } 3186eb1b42e4Sdlg 3187eb1b42e4Sdlg return (ETIMEDOUT); 3188eb1b42e4Sdlg } 3189eb1b42e4Sdlg 3190ccb96312Sdlg static void 3191ccb96312Sdlg ixl_rxr_config(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3192ccb96312Sdlg { 3193ccb96312Sdlg struct ixl_hmc_rxq rxq; 3194ccb96312Sdlg void *hmc; 3195ccb96312Sdlg 3196ccb96312Sdlg memset(&rxq, 0, sizeof(rxq)); 3197ccb96312Sdlg 3198ccb96312Sdlg rxq.head = htole16(0); 3199ccb96312Sdlg htolem64(&rxq.base, 320000cd24f1Sdlg IXL_DMA_DVA(&rxr->rxr_mem) / IXL_HMC_RXQ_BASE_UNIT); 3201ccb96312Sdlg htolem16(&rxq.qlen, sc->sc_rx_ring_ndescs); 3202eb1b42e4Sdlg rxq.dbuff = htole16(MCLBYTES / IXL_HMC_RXQ_DBUFF_UNIT); 3203ccb96312Sdlg rxq.hbuff = 0; 3204ccb96312Sdlg rxq.dtype = IXL_HMC_RXQ_DTYPE_NOSPLIT; 3205ccb96312Sdlg rxq.dsize = IXL_HMC_RXQ_DSIZE_16; 3206ccb96312Sdlg rxq.crcstrip = 1; 3207555fd15dSdlg rxq.l2tsel = IXL_HMC_RXQ_L2TSEL_1ST_TAG_TO_L2TAG1; 3208ccb96312Sdlg rxq.showiv = 0; 3209bf059df2Sjmatthew rxq.rxmax = htole16(IXL_HARDMTU); 3210eb1b42e4Sdlg rxq.tphrdesc_ena = 0; 3211eb1b42e4Sdlg rxq.tphwdesc_ena = 0; 3212ccb96312Sdlg rxq.tphdata_ena = 0; 3213ccb96312Sdlg rxq.tphhead_ena = 0; 3214eb1b42e4Sdlg rxq.lrxqthresh = 0; 3215ccb96312Sdlg rxq.prefena = 1; 3216ccb96312Sdlg 3217ccb96312Sdlg hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_RX, rxr->rxr_qid); 3218ccb96312Sdlg memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_RX)); 3219ccb96312Sdlg ixl_hmc_pack(hmc, &rxq, ixl_hmc_pack_rxq, nitems(ixl_hmc_pack_rxq)); 3220ccb96312Sdlg } 3221ccb96312Sdlg 3222ccb96312Sdlg static void 3223ccb96312Sdlg ixl_rxr_unconfig(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3224ccb96312Sdlg { 3225ccb96312Sdlg void *hmc; 3226ccb96312Sdlg 3227ccb96312Sdlg hmc = ixl_hmc_kva(sc, IXL_HMC_LAN_RX, rxr->rxr_qid); 3228ccb96312Sdlg memset(hmc, 0, ixl_hmc_len(sc, IXL_HMC_LAN_RX)); 3229ccb96312Sdlg } 3230ccb96312Sdlg 3231ccb96312Sdlg static void 3232ccb96312Sdlg ixl_rxr_free(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3233ccb96312Sdlg { 3234ccb96312Sdlg struct ixl_rx_map *maps, *rxm; 3235ccb96312Sdlg unsigned int i; 3236ccb96312Sdlg 3237ccb96312Sdlg maps = rxr->rxr_maps; 3238ccb96312Sdlg for (i = 0; i < sc->sc_rx_ring_ndescs; i++) { 3239ccb96312Sdlg rxm = &maps[i]; 3240ccb96312Sdlg 3241ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, rxm->rxm_map); 3242ccb96312Sdlg } 3243ccb96312Sdlg 3244ccb96312Sdlg ixl_dmamem_free(sc, &rxr->rxr_mem); 3245ccb96312Sdlg free(maps, M_DEVBUF, sizeof(*maps) * sc->sc_rx_ring_ndescs); 3246ccb96312Sdlg free(rxr, M_DEVBUF, sizeof(*rxr)); 3247ccb96312Sdlg } 3248ccb96312Sdlg 3249ccb96312Sdlg static int 3250e01adc04Sdlg ixl_rxeof(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3251ccb96312Sdlg { 3252e01adc04Sdlg struct ifiqueue *ifiq = rxr->rxr_ifiq; 3253ccb96312Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 3254ccb96312Sdlg struct ixl_rx_wb_desc_16 *ring, *rxd; 3255ccb96312Sdlg struct ixl_rx_map *rxm; 3256ccb96312Sdlg bus_dmamap_t map; 3257ccb96312Sdlg unsigned int cons, prod; 3258ccb96312Sdlg struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 3259ccb96312Sdlg struct mbuf *m; 3260ccb96312Sdlg uint64_t word; 3261ccb96312Sdlg unsigned int len; 3262ccb96312Sdlg unsigned int mask; 3263ccb96312Sdlg int done = 0; 3264ccb96312Sdlg 3265ccb96312Sdlg prod = rxr->rxr_prod; 3266ccb96312Sdlg cons = rxr->rxr_cons; 3267ccb96312Sdlg 3268ccb96312Sdlg if (cons == prod) 3269ccb96312Sdlg return (0); 3270ccb96312Sdlg 3271ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&rxr->rxr_mem), 3272ccb96312Sdlg 0, IXL_DMA_LEN(&rxr->rxr_mem), 3273ccb96312Sdlg BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3274ccb96312Sdlg 3275ccb96312Sdlg ring = IXL_DMA_KVA(&rxr->rxr_mem); 3276ccb96312Sdlg mask = sc->sc_rx_ring_ndescs - 1; 3277ccb96312Sdlg 3278ccb96312Sdlg do { 3279ccb96312Sdlg rxd = &ring[cons]; 3280ccb96312Sdlg 3281ccb96312Sdlg word = lemtoh64(&rxd->qword1); 3282ccb96312Sdlg if (!ISSET(word, IXL_RX_DESC_DD)) 3283ccb96312Sdlg break; 3284ccb96312Sdlg 3285ccb96312Sdlg if_rxr_put(&rxr->rxr_acct, 1); 3286ccb96312Sdlg 3287ccb96312Sdlg rxm = &rxr->rxr_maps[cons]; 3288ccb96312Sdlg 3289ccb96312Sdlg map = rxm->rxm_map; 3290ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 3291ccb96312Sdlg BUS_DMASYNC_POSTREAD); 3292ccb96312Sdlg bus_dmamap_unload(sc->sc_dmat, map); 3293ccb96312Sdlg 3294ccb96312Sdlg m = rxm->rxm_m; 3295ccb96312Sdlg rxm->rxm_m = NULL; 3296ccb96312Sdlg 3297ccb96312Sdlg len = (word & IXL_RX_DESC_PLEN_MASK) >> IXL_RX_DESC_PLEN_SHIFT; 3298ccb96312Sdlg m->m_len = len; 3299ccb96312Sdlg m->m_pkthdr.len = 0; 3300ccb96312Sdlg 3301ccb96312Sdlg m->m_next = NULL; 3302ccb96312Sdlg *rxr->rxr_m_tail = m; 3303ccb96312Sdlg rxr->rxr_m_tail = &m->m_next; 3304ccb96312Sdlg 3305ccb96312Sdlg m = rxr->rxr_m_head; 3306ccb96312Sdlg m->m_pkthdr.len += len; 3307ccb96312Sdlg 3308ccb96312Sdlg if (ISSET(word, IXL_RX_DESC_EOP)) { 3309ccb96312Sdlg if (!ISSET(word, 3310ccb96312Sdlg IXL_RX_DESC_RXE | IXL_RX_DESC_OVERSIZE)) { 33116850335aSdlg if ((word & IXL_RX_DESC_FLTSTAT_MASK) == 33126850335aSdlg IXL_RX_DESC_FLTSTAT_RSS) { 33136850335aSdlg m->m_pkthdr.ph_flowid = 33146850335aSdlg lemtoh32(&rxd->filter_status); 33156850335aSdlg m->m_pkthdr.csum_flags |= M_FLOWID; 33166850335aSdlg } 33176850335aSdlg 3318*60b8dadeSjan #if NVLAN > 0 3319555fd15dSdlg if (ISSET(word, IXL_RX_DESC_L2TAG1P)) { 3320555fd15dSdlg m->m_pkthdr.ether_vtag = 3321555fd15dSdlg lemtoh16(&rxd->l2tag1); 3322555fd15dSdlg SET(m->m_flags, M_VLANTAG); 3323555fd15dSdlg } 3324*60b8dadeSjan #endif 3325555fd15dSdlg 332689760ddfSbluhm ixl_rx_checksum(m, word); 3327ccb96312Sdlg ml_enqueue(&ml, m); 3328ccb96312Sdlg } else { 3329ccb96312Sdlg ifp->if_ierrors++; /* XXX */ 3330ccb96312Sdlg m_freem(m); 3331ccb96312Sdlg } 3332ccb96312Sdlg 3333ccb96312Sdlg rxr->rxr_m_head = NULL; 3334ccb96312Sdlg rxr->rxr_m_tail = &rxr->rxr_m_head; 3335ccb96312Sdlg } 3336ccb96312Sdlg 3337ccb96312Sdlg cons++; 3338ccb96312Sdlg cons &= mask; 3339ccb96312Sdlg 3340ccb96312Sdlg done = 1; 3341ccb96312Sdlg } while (cons != prod); 3342ccb96312Sdlg 3343ccb96312Sdlg if (done) { 3344ccb96312Sdlg rxr->rxr_cons = cons; 33454cc26fbaSdlg if (ifiq_input(ifiq, &ml)) 33464cc26fbaSdlg if_rxr_livelocked(&rxr->rxr_acct); 3347eb1b42e4Sdlg ixl_rxfill(sc, rxr); 3348ccb96312Sdlg } 3349ccb96312Sdlg 3350ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&rxr->rxr_mem), 3351ccb96312Sdlg 0, IXL_DMA_LEN(&rxr->rxr_mem), 3352ccb96312Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 3353ccb96312Sdlg 3354ccb96312Sdlg return (done); 3355ccb96312Sdlg } 3356ccb96312Sdlg 3357ccb96312Sdlg static void 3358ccb96312Sdlg ixl_rxfill(struct ixl_softc *sc, struct ixl_rx_ring *rxr) 3359ccb96312Sdlg { 3360ccb96312Sdlg struct ixl_rx_rd_desc_16 *ring, *rxd; 3361ccb96312Sdlg struct ixl_rx_map *rxm; 3362ccb96312Sdlg bus_dmamap_t map; 3363ccb96312Sdlg struct mbuf *m; 3364ccb96312Sdlg unsigned int prod; 3365ccb96312Sdlg unsigned int slots; 3366ccb96312Sdlg unsigned int mask; 3367ccb96312Sdlg int post = 0; 3368ccb96312Sdlg 3369ccb96312Sdlg slots = if_rxr_get(&rxr->rxr_acct, sc->sc_rx_ring_ndescs); 3370ccb96312Sdlg if (slots == 0) 3371ccb96312Sdlg return; 3372ccb96312Sdlg 3373ccb96312Sdlg prod = rxr->rxr_prod; 3374ccb96312Sdlg 3375ccb96312Sdlg ring = IXL_DMA_KVA(&rxr->rxr_mem); 3376ccb96312Sdlg mask = sc->sc_rx_ring_ndescs - 1; 3377ccb96312Sdlg 3378ccb96312Sdlg do { 3379ccb96312Sdlg rxm = &rxr->rxr_maps[prod]; 3380ccb96312Sdlg 3381471f2571Sjan m = MCLGETL(NULL, M_DONTWAIT, MCLBYTES + ETHER_ALIGN); 3382ccb96312Sdlg if (m == NULL) 3383ccb96312Sdlg break; 3384b7d259d9Sdlg m->m_data += (m->m_ext.ext_size - (MCLBYTES + ETHER_ALIGN)); 3385ccb96312Sdlg m->m_len = m->m_pkthdr.len = MCLBYTES + ETHER_ALIGN; 3386ccb96312Sdlg 3387ccb96312Sdlg map = rxm->rxm_map; 3388ccb96312Sdlg 3389ccb96312Sdlg if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, 3390ccb96312Sdlg BUS_DMA_NOWAIT) != 0) { 3391ccb96312Sdlg m_freem(m); 3392ccb96312Sdlg break; 3393ccb96312Sdlg } 3394ccb96312Sdlg 3395ccb96312Sdlg rxm->rxm_m = m; 3396ccb96312Sdlg 3397ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 3398ccb96312Sdlg BUS_DMASYNC_PREREAD); 3399ccb96312Sdlg 3400ccb96312Sdlg rxd = &ring[prod]; 3401ccb96312Sdlg 3402ccb96312Sdlg htolem64(&rxd->paddr, map->dm_segs[0].ds_addr); 3403ccb96312Sdlg rxd->haddr = htole64(0); 3404ccb96312Sdlg 3405ccb96312Sdlg prod++; 3406ccb96312Sdlg prod &= mask; 3407ccb96312Sdlg 3408ccb96312Sdlg post = 1; 3409ccb96312Sdlg } while (--slots); 3410ccb96312Sdlg 3411ccb96312Sdlg if_rxr_put(&rxr->rxr_acct, slots); 3412ccb96312Sdlg 3413ccb96312Sdlg if (if_rxr_inuse(&rxr->rxr_acct) == 0) 3414ccb96312Sdlg timeout_add(&rxr->rxr_refill, 1); 3415ccb96312Sdlg else if (post) { 3416ccb96312Sdlg rxr->rxr_prod = prod; 3417ccb96312Sdlg ixl_wr(sc, rxr->rxr_tail, prod); 3418ccb96312Sdlg } 3419ccb96312Sdlg } 3420ccb96312Sdlg 3421ccb96312Sdlg void 3422ccb96312Sdlg ixl_rxrefill(void *arg) 3423ccb96312Sdlg { 3424ccb96312Sdlg struct ixl_rx_ring *rxr = arg; 3425ccb96312Sdlg struct ixl_softc *sc = rxr->rxr_sc; 3426ccb96312Sdlg 3427ccb96312Sdlg ixl_rxfill(sc, rxr); 3428ccb96312Sdlg } 3429ccb96312Sdlg 3430ccb96312Sdlg static int 343196438522Sjmatthew ixl_rxrinfo(struct ixl_softc *sc, struct if_rxrinfo *ifri) 343296438522Sjmatthew { 343396438522Sjmatthew struct ifnet *ifp = &sc->sc_ac.ac_if; 343496438522Sjmatthew struct if_rxring_info *ifr; 343596438522Sjmatthew struct ixl_rx_ring *ring; 343696438522Sjmatthew int i, rv; 343796438522Sjmatthew 343896438522Sjmatthew if (!ISSET(ifp->if_flags, IFF_RUNNING)) 343996438522Sjmatthew return (ENOTTY); 344096438522Sjmatthew 344196438522Sjmatthew ifr = mallocarray(sizeof(*ifr), ixl_nqueues(sc), M_TEMP, 344296438522Sjmatthew M_WAITOK|M_CANFAIL|M_ZERO); 344396438522Sjmatthew if (ifr == NULL) 344496438522Sjmatthew return (ENOMEM); 344596438522Sjmatthew 344696438522Sjmatthew for (i = 0; i < ixl_nqueues(sc); i++) { 344796438522Sjmatthew ring = ifp->if_iqs[i]->ifiq_softc; 3448bf059df2Sjmatthew ifr[i].ifr_size = MCLBYTES; 34497c56c775Sdlg snprintf(ifr[i].ifr_name, sizeof(ifr[i].ifr_name), "%d", i); 345096438522Sjmatthew ifr[i].ifr_info = ring->rxr_acct; 345196438522Sjmatthew } 345296438522Sjmatthew 345396438522Sjmatthew rv = if_rxr_info_ioctl(ifri, ixl_nqueues(sc), ifr); 345496438522Sjmatthew free(ifr, M_TEMP, ixl_nqueues(sc) * sizeof(*ifr)); 345596438522Sjmatthew 345696438522Sjmatthew return (rv); 345796438522Sjmatthew } 345896438522Sjmatthew 345989760ddfSbluhm static void 346089760ddfSbluhm ixl_rx_checksum(struct mbuf *m, uint64_t word) 346189760ddfSbluhm { 346289760ddfSbluhm if (!ISSET(word, IXL_RX_DESC_L3L4P)) 346389760ddfSbluhm return; 346489760ddfSbluhm 346589760ddfSbluhm if (ISSET(word, IXL_RX_DESC_IPE)) 346689760ddfSbluhm return; 346789760ddfSbluhm 346889760ddfSbluhm m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; 346989760ddfSbluhm 347089760ddfSbluhm if (ISSET(word, IXL_RX_DESC_L4E)) 347189760ddfSbluhm return; 347289760ddfSbluhm 347389760ddfSbluhm m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK; 347489760ddfSbluhm } 347589760ddfSbluhm 347696438522Sjmatthew static int 34779b0c6e1eSjmatthew ixl_intr0(void *xsc) 3478ccb96312Sdlg { 3479ccb96312Sdlg struct ixl_softc *sc = xsc; 348000cd24f1Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 3481ccb96312Sdlg uint32_t icr; 3482ccb96312Sdlg int rv = 0; 3483ccb96312Sdlg 3484646632e9Sjmatthew ixl_intr_enable(sc); 3485ccb96312Sdlg icr = ixl_rd(sc, I40E_PFINT_ICR0); 3486ccb96312Sdlg 3487eb1b42e4Sdlg if (ISSET(icr, I40E_PFINT_ICR0_ADMINQ_MASK)) { 3488eb1b42e4Sdlg ixl_atq_done(sc); 3489ccb96312Sdlg task_add(systq, &sc->sc_arq_task); 3490ccb96312Sdlg rv = 1; 3491eb1b42e4Sdlg } 3492ccb96312Sdlg 349310e66d97Sjmatthew if (ISSET(icr, I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK)) { 349410e66d97Sjmatthew task_add(systq, &sc->sc_link_state_task); 349510e66d97Sjmatthew rv = 1; 349610e66d97Sjmatthew } 349710e66d97Sjmatthew 3498e01adc04Sdlg if (ISSET(ifp->if_flags, IFF_RUNNING)) { 3499e01adc04Sdlg struct ixl_vector *iv = sc->sc_vectors; 3500eb1b42e4Sdlg if (ISSET(icr, I40E_INTR_NOTX_RX_MASK)) 3501e01adc04Sdlg rv |= ixl_rxeof(sc, iv->iv_rxr); 3502eb1b42e4Sdlg if (ISSET(icr, I40E_INTR_NOTX_TX_MASK)) 3503e01adc04Sdlg rv |= ixl_txeof(sc, iv->iv_txr); 3504e01adc04Sdlg } 3505ccb96312Sdlg 3506ccb96312Sdlg return (rv); 3507ccb96312Sdlg } 3508ccb96312Sdlg 35099b0c6e1eSjmatthew static int 3510e01adc04Sdlg ixl_intr_vector(void *v) 35119b0c6e1eSjmatthew { 3512e01adc04Sdlg struct ixl_vector *iv = v; 3513e01adc04Sdlg struct ixl_softc *sc = iv->iv_sc; 3514e01adc04Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 35159b0c6e1eSjmatthew int rv = 0; 35169b0c6e1eSjmatthew 3517e01adc04Sdlg if (ISSET(ifp->if_flags, IFF_RUNNING)) { 3518e01adc04Sdlg rv |= ixl_rxeof(sc, iv->iv_rxr); 3519e01adc04Sdlg rv |= ixl_txeof(sc, iv->iv_txr); 3520e01adc04Sdlg } 35219b0c6e1eSjmatthew 3522e01adc04Sdlg ixl_wr(sc, I40E_PFINT_DYN_CTLN(iv->iv_qid), 35239b0c6e1eSjmatthew I40E_PFINT_DYN_CTLN_INTENA_MASK | 35249b0c6e1eSjmatthew I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | 35259b0c6e1eSjmatthew (IXL_NOITR << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)); 35269b0c6e1eSjmatthew 35279b0c6e1eSjmatthew return (rv); 35289b0c6e1eSjmatthew } 35299b0c6e1eSjmatthew 3530ccb96312Sdlg static void 353135e06836Sdlg ixl_link_state_update_iaq(struct ixl_softc *sc, void *arg) 353210e66d97Sjmatthew { 353335e06836Sdlg struct ifnet *ifp = &sc->sc_ac.ac_if; 353435e06836Sdlg struct ixl_aq_desc *iaq = arg; 353535e06836Sdlg uint16_t retval; 353635e06836Sdlg int link_state; 35378014a50bSdlg int change = 0; 353835e06836Sdlg 353935e06836Sdlg retval = lemtoh16(&iaq->iaq_retval); 354035e06836Sdlg if (retval != IXL_AQ_RC_OK) { 354135e06836Sdlg printf("%s: LINK STATUS error %u\n", DEVNAME(sc), retval); 354235e06836Sdlg return; 354335e06836Sdlg } 354435e06836Sdlg 354535e06836Sdlg link_state = ixl_set_link_status(sc, iaq); 35468014a50bSdlg mtx_enter(&sc->sc_link_state_mtx); 354735e06836Sdlg if (ifp->if_link_state != link_state) { 354835e06836Sdlg ifp->if_link_state = link_state; 35498014a50bSdlg change = 1; 355035e06836Sdlg } 35518014a50bSdlg mtx_leave(&sc->sc_link_state_mtx); 35528014a50bSdlg 35538014a50bSdlg if (change) 35548014a50bSdlg if_link_state_change(ifp); 355510e66d97Sjmatthew } 355610e66d97Sjmatthew 355710e66d97Sjmatthew static void 355810e66d97Sjmatthew ixl_link_state_update(void *xsc) 355910e66d97Sjmatthew { 356010e66d97Sjmatthew struct ixl_softc *sc = xsc; 356110e66d97Sjmatthew struct ixl_aq_desc *iaq; 356210e66d97Sjmatthew struct ixl_aq_link_param *param; 356310e66d97Sjmatthew 356410e66d97Sjmatthew memset(&sc->sc_link_state_atq, 0, sizeof(sc->sc_link_state_atq)); 356510e66d97Sjmatthew iaq = &sc->sc_link_state_atq.iatq_desc; 356610e66d97Sjmatthew iaq->iaq_opcode = htole16(IXL_AQ_OP_PHY_LINK_STATUS); 356710e66d97Sjmatthew param = (struct ixl_aq_link_param *)iaq->iaq_param; 356810e66d97Sjmatthew param->notify = IXL_AQ_LINK_NOTIFY; 356910e66d97Sjmatthew 357035e06836Sdlg ixl_atq_set(&sc->sc_link_state_atq, ixl_link_state_update_iaq, iaq); 357110e66d97Sjmatthew ixl_atq_post(sc, &sc->sc_link_state_atq); 357210e66d97Sjmatthew } 357310e66d97Sjmatthew 3574ccb96312Sdlg #if 0 3575ccb96312Sdlg static void 3576ccb96312Sdlg ixl_aq_dump(const struct ixl_softc *sc, const struct ixl_aq_desc *iaq) 3577ccb96312Sdlg { 3578ccb96312Sdlg printf("%s: flags %b opcode %04x\n", DEVNAME(sc), 3579ccb96312Sdlg lemtoh16(&iaq->iaq_flags), IXL_AQ_FLAGS_FMT, 3580ccb96312Sdlg lemtoh16(&iaq->iaq_opcode)); 3581ccb96312Sdlg printf("%s: datalen %u retval %u\n", DEVNAME(sc), 3582ccb96312Sdlg lemtoh16(&iaq->iaq_datalen), lemtoh16(&iaq->iaq_retval)); 3583ccb96312Sdlg printf("%s: cookie %016llx\n", DEVNAME(sc), iaq->iaq_cookie); 3584ccb96312Sdlg printf("%s: %08x %08x %08x %08x\n", DEVNAME(sc), 3585ccb96312Sdlg lemtoh32(&iaq->iaq_param[0]), lemtoh32(&iaq->iaq_param[1]), 3586ccb96312Sdlg lemtoh32(&iaq->iaq_param[2]), lemtoh32(&iaq->iaq_param[3])); 3587ccb96312Sdlg } 3588ccb96312Sdlg #endif 3589ccb96312Sdlg 3590ccb96312Sdlg static void 3591ccb96312Sdlg ixl_arq(void *xsc) 3592ccb96312Sdlg { 3593ccb96312Sdlg struct ixl_softc *sc = xsc; 3594ccb96312Sdlg struct ixl_aq_desc *arq, *iaq; 3595ccb96312Sdlg struct ixl_aq_buf *aqb; 3596ccb96312Sdlg unsigned int cons = sc->sc_arq_cons; 3597ccb96312Sdlg unsigned int prod; 3598ccb96312Sdlg int done = 0; 3599ccb96312Sdlg 3600ccb96312Sdlg prod = ixl_rd(sc, sc->sc_aq_regs->arq_head) & 3601ccb96312Sdlg sc->sc_aq_regs->arq_head_mask; 3602ccb96312Sdlg 3603ccb96312Sdlg if (cons == prod) 3604ccb96312Sdlg goto done; 3605ccb96312Sdlg 3606ccb96312Sdlg arq = IXL_DMA_KVA(&sc->sc_arq); 3607ccb96312Sdlg 3608ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_arq), 3609ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_arq), 3610ccb96312Sdlg BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3611ccb96312Sdlg 3612ccb96312Sdlg do { 3613ccb96312Sdlg iaq = &arq[cons]; 3614ccb96312Sdlg 3615ccb96312Sdlg aqb = SIMPLEQ_FIRST(&sc->sc_arq_live); 361665ab43f2Syasuoka SIMPLEQ_REMOVE_HEAD(&sc->sc_arq_live, aqb_entry); 3617ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, aqb->aqb_map, 0, IXL_AQ_BUFLEN, 3618ccb96312Sdlg BUS_DMASYNC_POSTREAD); 3619ccb96312Sdlg 3620ccb96312Sdlg switch (iaq->iaq_opcode) { 3621ccb96312Sdlg case HTOLE16(IXL_AQ_OP_PHY_LINK_STATUS): 362235e06836Sdlg ixl_link_state_update_iaq(sc, iaq); 3623ccb96312Sdlg break; 3624ccb96312Sdlg } 3625ccb96312Sdlg 3626ccb96312Sdlg memset(iaq, 0, sizeof(*iaq)); 3627ccb96312Sdlg SIMPLEQ_INSERT_TAIL(&sc->sc_arq_idle, aqb, aqb_entry); 3628ccb96312Sdlg if_rxr_put(&sc->sc_arq_ring, 1); 3629ccb96312Sdlg 3630ccb96312Sdlg cons++; 3631ccb96312Sdlg cons &= IXL_AQ_MASK; 3632ccb96312Sdlg 3633ccb96312Sdlg done = 1; 3634ccb96312Sdlg } while (cons != prod); 3635ccb96312Sdlg 3636ccb96312Sdlg if (done && ixl_arq_fill(sc)) 3637ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->arq_tail, sc->sc_arq_prod); 3638ccb96312Sdlg 3639ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_arq), 3640ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_arq), 3641ccb96312Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 3642ccb96312Sdlg 3643ccb96312Sdlg sc->sc_arq_cons = cons; 3644ccb96312Sdlg 3645ccb96312Sdlg done: 3646ccb96312Sdlg ixl_intr_enable(sc); 3647ccb96312Sdlg } 3648ccb96312Sdlg 3649ccb96312Sdlg static void 3650ccb96312Sdlg ixl_atq_set(struct ixl_atq *iatq, 3651ccb96312Sdlg void (*fn)(struct ixl_softc *, void *), void *arg) 3652ccb96312Sdlg { 3653ccb96312Sdlg iatq->iatq_fn = fn; 3654ccb96312Sdlg iatq->iatq_arg = arg; 3655ccb96312Sdlg } 3656ccb96312Sdlg 3657ccb96312Sdlg static void 3658ccb96312Sdlg ixl_atq_post(struct ixl_softc *sc, struct ixl_atq *iatq) 3659ccb96312Sdlg { 3660ccb96312Sdlg struct ixl_aq_desc *atq, *slot; 3661ccb96312Sdlg unsigned int prod; 3662ccb96312Sdlg 366395f940dfSjan mtx_enter(&sc->sc_atq_mtx); 3664ccb96312Sdlg 3665ccb96312Sdlg atq = IXL_DMA_KVA(&sc->sc_atq); 3666ccb96312Sdlg prod = sc->sc_atq_prod; 3667ccb96312Sdlg slot = atq + prod; 3668ccb96312Sdlg 3669ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3670ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_POSTWRITE); 3671ccb96312Sdlg 3672ccb96312Sdlg *slot = iatq->iatq_desc; 3673ccb96312Sdlg slot->iaq_cookie = (uint64_t)iatq; 3674ccb96312Sdlg 3675ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3676ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_PREWRITE); 3677ccb96312Sdlg 3678ccb96312Sdlg prod++; 3679ccb96312Sdlg prod &= IXL_AQ_MASK; 3680ccb96312Sdlg sc->sc_atq_prod = prod; 3681ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_tail, prod); 368295f940dfSjan 368395f940dfSjan mtx_leave(&sc->sc_atq_mtx); 3684ccb96312Sdlg } 3685ccb96312Sdlg 3686ccb96312Sdlg static void 3687ccb96312Sdlg ixl_atq_done(struct ixl_softc *sc) 3688ccb96312Sdlg { 3689ccb96312Sdlg struct ixl_aq_desc *atq, *slot; 3690ccb96312Sdlg struct ixl_atq *iatq; 3691ccb96312Sdlg unsigned int cons; 3692ccb96312Sdlg unsigned int prod; 3693ccb96312Sdlg 369495f940dfSjan mtx_enter(&sc->sc_atq_mtx); 369595f940dfSjan 3696ccb96312Sdlg prod = sc->sc_atq_prod; 3697ccb96312Sdlg cons = sc->sc_atq_cons; 3698ccb96312Sdlg 369995f940dfSjan if (prod == cons) { 370095f940dfSjan mtx_leave(&sc->sc_atq_mtx); 3701ccb96312Sdlg return; 370295f940dfSjan } 3703ccb96312Sdlg 3704ccb96312Sdlg atq = IXL_DMA_KVA(&sc->sc_atq); 3705ccb96312Sdlg 3706ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3707ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), 3708ccb96312Sdlg BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3709ccb96312Sdlg 3710ccb96312Sdlg do { 3711ccb96312Sdlg slot = &atq[cons]; 37123701157fSdlg if (!ISSET(slot->iaq_flags, htole16(IXL_AQ_DD))) 37133701157fSdlg break; 3714ccb96312Sdlg 371595f940dfSjan KASSERT(slot->iaq_cookie != 0); 3716ccb96312Sdlg iatq = (struct ixl_atq *)slot->iaq_cookie; 3717ccb96312Sdlg iatq->iatq_desc = *slot; 3718ccb96312Sdlg 3719ccb96312Sdlg memset(slot, 0, sizeof(*slot)); 3720ccb96312Sdlg 37218434af05Sdlg (*iatq->iatq_fn)(sc, iatq->iatq_arg); 37228434af05Sdlg 3723ccb96312Sdlg cons++; 3724ccb96312Sdlg cons &= IXL_AQ_MASK; 3725ccb96312Sdlg } while (cons != prod); 3726ccb96312Sdlg 3727ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3728ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), 3729ccb96312Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 3730ccb96312Sdlg 3731ccb96312Sdlg sc->sc_atq_cons = cons; 373295f940dfSjan 373395f940dfSjan mtx_leave(&sc->sc_atq_mtx); 3734ccb96312Sdlg } 3735ccb96312Sdlg 3736ccb96312Sdlg static void 3737ccb96312Sdlg ixl_wakeup(struct ixl_softc *sc, void *arg) 3738ccb96312Sdlg { 3739b661852cSdlg struct cond *c = arg; 3740ccb96312Sdlg 3741b661852cSdlg cond_signal(c); 3742ccb96312Sdlg } 3743ccb96312Sdlg 3744ccb96312Sdlg static void 3745ccb96312Sdlg ixl_atq_exec(struct ixl_softc *sc, struct ixl_atq *iatq, const char *wmesg) 3746ccb96312Sdlg { 3747b661852cSdlg struct cond c = COND_INITIALIZER(); 3748ccb96312Sdlg 3749ccb96312Sdlg KASSERT(iatq->iatq_desc.iaq_cookie == 0); 3750ccb96312Sdlg 3751b661852cSdlg ixl_atq_set(iatq, ixl_wakeup, &c); 3752ccb96312Sdlg ixl_atq_post(sc, iatq); 3753ccb96312Sdlg 3754b661852cSdlg cond_wait(&c, wmesg); 3755ccb96312Sdlg } 3756ccb96312Sdlg 3757ccb96312Sdlg static int 3758ccb96312Sdlg ixl_atq_poll(struct ixl_softc *sc, struct ixl_aq_desc *iaq, unsigned int tm) 3759ccb96312Sdlg { 3760ccb96312Sdlg struct ixl_aq_desc *atq, *slot; 3761ccb96312Sdlg unsigned int prod; 3762ccb96312Sdlg unsigned int t = 0; 3763ccb96312Sdlg 376495f940dfSjan mtx_enter(&sc->sc_atq_mtx); 376595f940dfSjan 3766ccb96312Sdlg atq = IXL_DMA_KVA(&sc->sc_atq); 3767ccb96312Sdlg prod = sc->sc_atq_prod; 3768ccb96312Sdlg slot = atq + prod; 3769ccb96312Sdlg 3770ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3771ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_POSTWRITE); 3772ccb96312Sdlg 3773ccb96312Sdlg *slot = *iaq; 3774ccb96312Sdlg slot->iaq_flags |= htole16(IXL_AQ_SI); 3775ccb96312Sdlg 3776ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3777ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_PREWRITE); 3778ccb96312Sdlg 3779ccb96312Sdlg prod++; 3780ccb96312Sdlg prod &= IXL_AQ_MASK; 3781ccb96312Sdlg sc->sc_atq_prod = prod; 3782ccb96312Sdlg ixl_wr(sc, sc->sc_aq_regs->atq_tail, prod); 3783ccb96312Sdlg 3784ccb96312Sdlg while (ixl_rd(sc, sc->sc_aq_regs->atq_head) != prod) { 3785ccb96312Sdlg delaymsec(1); 3786ccb96312Sdlg 378795f940dfSjan if (t++ > tm) { 378895f940dfSjan mtx_leave(&sc->sc_atq_mtx); 3789ccb96312Sdlg return (ETIMEDOUT); 3790ccb96312Sdlg } 379195f940dfSjan } 3792ccb96312Sdlg 3793ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3794ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_POSTREAD); 3795ccb96312Sdlg *iaq = *slot; 3796ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq), 3797ccb96312Sdlg 0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_PREREAD); 3798ccb96312Sdlg 3799ccb96312Sdlg sc->sc_atq_cons = prod; 3800ccb96312Sdlg 380195f940dfSjan mtx_leave(&sc->sc_atq_mtx); 3802ccb96312Sdlg return (0); 3803ccb96312Sdlg } 3804ccb96312Sdlg 3805ccb96312Sdlg static int 3806ccb96312Sdlg ixl_get_version(struct ixl_softc *sc) 3807ccb96312Sdlg { 3808ccb96312Sdlg struct ixl_aq_desc iaq; 3809ccb96312Sdlg uint32_t fwbuild, fwver, apiver; 3810ccb96312Sdlg 3811ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 3812ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_GET_VERSION); 3813ccb96312Sdlg 3814ccb96312Sdlg if (ixl_atq_poll(sc, &iaq, 2000) != 0) 3815ccb96312Sdlg return (ETIMEDOUT); 3816ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) 3817ccb96312Sdlg return (EIO); 3818ccb96312Sdlg 3819ccb96312Sdlg fwbuild = lemtoh32(&iaq.iaq_param[1]); 3820ccb96312Sdlg fwver = lemtoh32(&iaq.iaq_param[2]); 3821ccb96312Sdlg apiver = lemtoh32(&iaq.iaq_param[3]); 3822ccb96312Sdlg 3823f5777d33Sdlg sc->sc_api_major = apiver & 0xffff; 3824f5777d33Sdlg sc->sc_api_minor = (apiver >> 16) & 0xffff; 3825f5777d33Sdlg 3826ccb96312Sdlg printf(", FW %hu.%hu.%05u API %hu.%hu", (uint16_t)fwver, 3827f5777d33Sdlg (uint16_t)(fwver >> 16), fwbuild, 3828f5777d33Sdlg sc->sc_api_major, sc->sc_api_minor); 3829ccb96312Sdlg 3830ccb96312Sdlg return (0); 3831ccb96312Sdlg } 3832ccb96312Sdlg 3833ccb96312Sdlg static int 3834ccb96312Sdlg ixl_pxe_clear(struct ixl_softc *sc) 3835ccb96312Sdlg { 3836ccb96312Sdlg struct ixl_aq_desc iaq; 3837ccb96312Sdlg 3838ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 3839ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_CLEAR_PXE_MODE); 3840ccb96312Sdlg iaq.iaq_param[0] = htole32(0x2); 3841ccb96312Sdlg 3842ccb96312Sdlg if (ixl_atq_poll(sc, &iaq, 250) != 0) { 3843ccb96312Sdlg printf(", CLEAR PXE MODE timeout\n"); 3844ccb96312Sdlg return (-1); 3845ccb96312Sdlg } 3846ccb96312Sdlg 3847ccb96312Sdlg switch (iaq.iaq_retval) { 3848ccb96312Sdlg case HTOLE16(IXL_AQ_RC_OK): 3849ccb96312Sdlg case HTOLE16(IXL_AQ_RC_EEXIST): 3850ccb96312Sdlg break; 3851ccb96312Sdlg default: 3852ccb96312Sdlg printf(", CLEAR PXE MODE error\n"); 3853ccb96312Sdlg return (-1); 3854ccb96312Sdlg } 3855ccb96312Sdlg 3856ccb96312Sdlg return (0); 3857ccb96312Sdlg } 3858ccb96312Sdlg 3859ccb96312Sdlg static int 3860ccb96312Sdlg ixl_lldp_shut(struct ixl_softc *sc) 3861ccb96312Sdlg { 3862ccb96312Sdlg struct ixl_aq_desc iaq; 3863ccb96312Sdlg 3864ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 3865ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_LLDP_STOP_AGENT); 3866ccb96312Sdlg iaq.iaq_param[0] = htole32(IXL_LLDP_SHUTDOWN); 3867ccb96312Sdlg 3868ccb96312Sdlg if (ixl_atq_poll(sc, &iaq, 250) != 0) { 3869ccb96312Sdlg printf(", STOP LLDP AGENT timeout\n"); 3870ccb96312Sdlg return (-1); 3871ccb96312Sdlg } 3872ccb96312Sdlg 3873ccb96312Sdlg switch (iaq.iaq_retval) { 3874ccb96312Sdlg case HTOLE16(IXL_AQ_RC_EMODE): 3875ccb96312Sdlg case HTOLE16(IXL_AQ_RC_EPERM): 3876ccb96312Sdlg /* ignore silently */ 3877ccb96312Sdlg default: 3878ccb96312Sdlg break; 3879ccb96312Sdlg } 3880ccb96312Sdlg 3881ccb96312Sdlg return (0); 3882ccb96312Sdlg } 3883ccb96312Sdlg 3884ccb96312Sdlg static int 3885ccb96312Sdlg ixl_get_mac(struct ixl_softc *sc) 3886ccb96312Sdlg { 3887ccb96312Sdlg struct ixl_dmamem idm; 3888ccb96312Sdlg struct ixl_aq_desc iaq; 3889ccb96312Sdlg struct ixl_aq_mac_addresses *addrs; 3890ccb96312Sdlg int rv; 3891ccb96312Sdlg 389212b3627cSjmatthew #ifdef __sparc64__ 389312b3627cSjmatthew if (OF_getprop(PCITAG_NODE(sc->sc_tag), "local-mac-address", 389412b3627cSjmatthew sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN) == ETHER_ADDR_LEN) 389512b3627cSjmatthew return (0); 389612b3627cSjmatthew #endif 389712b3627cSjmatthew 3898ccb96312Sdlg if (ixl_dmamem_alloc(sc, &idm, sizeof(*addrs), 0) != 0) { 3899ccb96312Sdlg printf(", unable to allocate mac addresses\n"); 3900ccb96312Sdlg return (-1); 3901ccb96312Sdlg } 3902ccb96312Sdlg 3903ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 3904ccb96312Sdlg iaq.iaq_flags = htole16(IXL_AQ_BUF); 3905ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_MAC_ADDRESS_READ); 3906ccb96312Sdlg iaq.iaq_datalen = htole16(sizeof(*addrs)); 3907ccb96312Sdlg ixl_aq_dva(&iaq, IXL_DMA_DVA(&idm)); 3908ccb96312Sdlg 3909ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&idm), 0, IXL_DMA_LEN(&idm), 3910ccb96312Sdlg BUS_DMASYNC_PREREAD); 3911ccb96312Sdlg 3912ccb96312Sdlg rv = ixl_atq_poll(sc, &iaq, 250); 3913ccb96312Sdlg 3914ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&idm), 0, IXL_DMA_LEN(&idm), 3915ccb96312Sdlg BUS_DMASYNC_POSTREAD); 3916ccb96312Sdlg 3917ccb96312Sdlg if (rv != 0) { 3918ccb96312Sdlg printf(", MAC ADDRESS READ timeout\n"); 3919ccb96312Sdlg rv = -1; 3920ccb96312Sdlg goto done; 3921ccb96312Sdlg } 3922ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 3923ccb96312Sdlg printf(", MAC ADDRESS READ error\n"); 3924ccb96312Sdlg rv = -1; 3925ccb96312Sdlg goto done; 3926ccb96312Sdlg } 3927ccb96312Sdlg 3928ccb96312Sdlg addrs = IXL_DMA_KVA(&idm); 3929ccb96312Sdlg if (!ISSET(iaq.iaq_param[0], htole32(IXL_AQ_MAC_PORT_VALID))) { 3930ccb96312Sdlg printf(", port address is not valid\n"); 3931ccb96312Sdlg goto done; 3932ccb96312Sdlg } 3933ccb96312Sdlg 3934ccb96312Sdlg memcpy(sc->sc_ac.ac_enaddr, addrs->port, ETHER_ADDR_LEN); 3935ccb96312Sdlg rv = 0; 3936ccb96312Sdlg 3937ccb96312Sdlg done: 3938ccb96312Sdlg ixl_dmamem_free(sc, &idm); 3939ccb96312Sdlg return (rv); 3940ccb96312Sdlg } 3941ccb96312Sdlg 3942ccb96312Sdlg static int 3943ccb96312Sdlg ixl_get_switch_config(struct ixl_softc *sc) 3944ccb96312Sdlg { 3945ccb96312Sdlg struct ixl_dmamem idm; 3946ccb96312Sdlg struct ixl_aq_desc iaq; 3947ccb96312Sdlg struct ixl_aq_switch_config *hdr; 3948ccb96312Sdlg struct ixl_aq_switch_config_element *elms, *elm; 3949ccb96312Sdlg unsigned int nelm; 3950ccb96312Sdlg int rv; 3951ccb96312Sdlg 3952ccb96312Sdlg if (ixl_dmamem_alloc(sc, &idm, IXL_AQ_BUFLEN, 0) != 0) { 3953ccb96312Sdlg printf("%s: unable to allocate switch config buffer\n", 3954ccb96312Sdlg DEVNAME(sc)); 3955ccb96312Sdlg return (-1); 3956ccb96312Sdlg } 3957ccb96312Sdlg 3958ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 3959ccb96312Sdlg iaq.iaq_flags = htole16(IXL_AQ_BUF | 3960ccb96312Sdlg (IXL_AQ_BUFLEN > I40E_AQ_LARGE_BUF ? IXL_AQ_LB : 0)); 3961ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_SWITCH_GET_CONFIG); 3962ccb96312Sdlg iaq.iaq_datalen = htole16(IXL_AQ_BUFLEN); 3963ccb96312Sdlg ixl_aq_dva(&iaq, IXL_DMA_DVA(&idm)); 3964ccb96312Sdlg 3965ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&idm), 0, IXL_DMA_LEN(&idm), 3966ccb96312Sdlg BUS_DMASYNC_PREREAD); 3967ccb96312Sdlg 3968ccb96312Sdlg rv = ixl_atq_poll(sc, &iaq, 250); 3969ccb96312Sdlg 3970ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&idm), 0, IXL_DMA_LEN(&idm), 3971ccb96312Sdlg BUS_DMASYNC_POSTREAD); 3972ccb96312Sdlg 3973ccb96312Sdlg if (rv != 0) { 3974ccb96312Sdlg printf("%s: GET SWITCH CONFIG timeout\n", DEVNAME(sc)); 3975ccb96312Sdlg rv = -1; 3976ccb96312Sdlg goto done; 3977ccb96312Sdlg } 3978ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 3979ccb96312Sdlg printf("%s: GET SWITCH CONFIG error\n", DEVNAME(sc)); 3980ccb96312Sdlg rv = -1; 3981ccb96312Sdlg goto done; 3982ccb96312Sdlg } 3983ccb96312Sdlg 3984ccb96312Sdlg hdr = IXL_DMA_KVA(&idm); 3985ccb96312Sdlg elms = (struct ixl_aq_switch_config_element *)(hdr + 1); 3986ccb96312Sdlg 3987ccb96312Sdlg nelm = lemtoh16(&hdr->num_reported); 3988ccb96312Sdlg if (nelm < 1) { 3989ccb96312Sdlg printf("%s: no switch config available\n", DEVNAME(sc)); 3990ccb96312Sdlg rv = -1; 3991ccb96312Sdlg goto done; 3992ccb96312Sdlg } 3993ccb96312Sdlg 3994ccb96312Sdlg #if 0 3995ccb96312Sdlg for (i = 0; i < nelm; i++) { 3996ccb96312Sdlg elm = &elms[i]; 3997ccb96312Sdlg 3998ccb96312Sdlg printf("%s: type %x revision %u seid %04x\n", DEVNAME(sc), 3999ccb96312Sdlg elm->type, elm->revision, lemtoh16(&elm->seid)); 4000ccb96312Sdlg printf("%s: uplink %04x downlink %04x\n", DEVNAME(sc), 4001ccb96312Sdlg lemtoh16(&elm->uplink_seid), 4002ccb96312Sdlg lemtoh16(&elm->downlink_seid)); 4003ccb96312Sdlg printf("%s: conntype %x scheduler %04x extra %04x\n", 4004ccb96312Sdlg DEVNAME(sc), elm->connection_type, 4005ccb96312Sdlg lemtoh16(&elm->scheduler_id), 4006ccb96312Sdlg lemtoh16(&elm->element_info)); 4007ccb96312Sdlg } 4008ccb96312Sdlg #endif 4009ccb96312Sdlg 4010ccb96312Sdlg elm = &elms[0]; 4011ccb96312Sdlg 4012ccb96312Sdlg sc->sc_uplink_seid = elm->uplink_seid; 4013ccb96312Sdlg sc->sc_downlink_seid = elm->downlink_seid; 4014ccb96312Sdlg sc->sc_seid = elm->seid; 4015ccb96312Sdlg 4016ccb96312Sdlg if ((sc->sc_uplink_seid == htole16(0)) != 4017ccb96312Sdlg (sc->sc_downlink_seid == htole16(0))) { 4018ccb96312Sdlg printf("%s: SEIDs are misconfigured\n", DEVNAME(sc)); 4019ccb96312Sdlg rv = -1; 4020ccb96312Sdlg goto done; 4021ccb96312Sdlg } 4022ccb96312Sdlg 4023ccb96312Sdlg done: 4024ccb96312Sdlg ixl_dmamem_free(sc, &idm); 4025ccb96312Sdlg return (rv); 4026ccb96312Sdlg } 4027ccb96312Sdlg 4028ccb96312Sdlg static int 4029ccb96312Sdlg ixl_phy_mask_ints(struct ixl_softc *sc) 4030ccb96312Sdlg { 4031ccb96312Sdlg struct ixl_aq_desc iaq; 4032ccb96312Sdlg 4033ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 4034ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_PHY_SET_EVENT_MASK); 4035ccb96312Sdlg iaq.iaq_param[2] = htole32(IXL_AQ_PHY_EV_MASK & 4036ccb96312Sdlg ~(IXL_AQ_PHY_EV_LINK_UPDOWN | IXL_AQ_PHY_EV_MODULE_QUAL_FAIL | 4037ccb96312Sdlg IXL_AQ_PHY_EV_MEDIA_NA)); 4038ccb96312Sdlg 4039ccb96312Sdlg if (ixl_atq_poll(sc, &iaq, 250) != 0) { 4040ccb96312Sdlg printf("%s: SET PHY EVENT MASK timeout\n", DEVNAME(sc)); 4041ccb96312Sdlg return (-1); 4042ccb96312Sdlg } 4043ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 4044ccb96312Sdlg printf("%s: SET PHY EVENT MASK error\n", DEVNAME(sc)); 4045ccb96312Sdlg return (-1); 4046ccb96312Sdlg } 4047ccb96312Sdlg 4048ccb96312Sdlg return (0); 4049ccb96312Sdlg } 4050ccb96312Sdlg 4051ccb96312Sdlg static int 405225fbbcc0Sdlg ixl_get_phy_abilities(struct ixl_softc *sc,struct ixl_dmamem *idm) 405325fbbcc0Sdlg { 405425fbbcc0Sdlg struct ixl_aq_desc iaq; 405525fbbcc0Sdlg int rv; 405625fbbcc0Sdlg 405725fbbcc0Sdlg memset(&iaq, 0, sizeof(iaq)); 405825fbbcc0Sdlg iaq.iaq_flags = htole16(IXL_AQ_BUF | 405925fbbcc0Sdlg (IXL_DMA_LEN(idm) > I40E_AQ_LARGE_BUF ? IXL_AQ_LB : 0)); 406025fbbcc0Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_PHY_GET_ABILITIES); 406125fbbcc0Sdlg htolem16(&iaq.iaq_datalen, IXL_DMA_LEN(idm)); 406225fbbcc0Sdlg iaq.iaq_param[0] = htole32(IXL_AQ_PHY_REPORT_INIT); 406325fbbcc0Sdlg ixl_aq_dva(&iaq, IXL_DMA_DVA(idm)); 406425fbbcc0Sdlg 406525fbbcc0Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(idm), 0, IXL_DMA_LEN(idm), 406625fbbcc0Sdlg BUS_DMASYNC_PREREAD); 406725fbbcc0Sdlg 406825fbbcc0Sdlg rv = ixl_atq_poll(sc, &iaq, 250); 406925fbbcc0Sdlg 407025fbbcc0Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(idm), 0, IXL_DMA_LEN(idm), 407125fbbcc0Sdlg BUS_DMASYNC_POSTREAD); 407225fbbcc0Sdlg 407325fbbcc0Sdlg if (rv != 0) 407425fbbcc0Sdlg return (-1); 407525fbbcc0Sdlg 407625fbbcc0Sdlg return (lemtoh16(&iaq.iaq_retval)); 407725fbbcc0Sdlg } 407825fbbcc0Sdlg 407925fbbcc0Sdlg static int 408025fbbcc0Sdlg ixl_get_phy_types(struct ixl_softc *sc, uint64_t *phy_types_ptr) 4081ccb96312Sdlg { 4082ccb96312Sdlg struct ixl_dmamem idm; 4083ccb96312Sdlg struct ixl_aq_phy_abilities *phy; 4084ccb96312Sdlg uint64_t phy_types; 4085ccb96312Sdlg int rv; 4086ccb96312Sdlg 4087ccb96312Sdlg if (ixl_dmamem_alloc(sc, &idm, IXL_AQ_BUFLEN, 0) != 0) { 4088ae4c4765Sdlg printf("%s: unable to allocate phy abilities buffer\n", 4089ccb96312Sdlg DEVNAME(sc)); 4090ccb96312Sdlg return (-1); 4091ccb96312Sdlg } 4092ccb96312Sdlg 409325fbbcc0Sdlg rv = ixl_get_phy_abilities(sc, &idm); 409425fbbcc0Sdlg switch (rv) { 409525fbbcc0Sdlg case -1: 4096ccb96312Sdlg printf("%s: GET PHY ABILITIES timeout\n", DEVNAME(sc)); 40974497d183Sdlg goto err; 409825fbbcc0Sdlg case IXL_AQ_RC_OK: 4099ccb96312Sdlg break; 410025fbbcc0Sdlg case IXL_AQ_RC_EIO: 41014497d183Sdlg /* API is too old to handle this command */ 41024497d183Sdlg phy_types = 0; 41034497d183Sdlg goto done; 4104ccb96312Sdlg default: 41054b1a56afSjsg printf("%s: GET PHY ABILITIES error %u\n", DEVNAME(sc), rv); 41064497d183Sdlg goto err; 4107ccb96312Sdlg } 4108ccb96312Sdlg 4109ccb96312Sdlg phy = IXL_DMA_KVA(&idm); 4110ccb96312Sdlg 4111ccb96312Sdlg phy_types = lemtoh32(&phy->phy_type); 41127e7a8c99Sdlg phy_types |= (uint64_t)phy->phy_type_ext << 32; 4113ccb96312Sdlg 41144497d183Sdlg done: 4115ccb96312Sdlg *phy_types_ptr = phy_types; 4116ccb96312Sdlg 4117ccb96312Sdlg rv = 0; 4118ccb96312Sdlg 41194497d183Sdlg err: 4120ccb96312Sdlg ixl_dmamem_free(sc, &idm); 4121ccb96312Sdlg return (rv); 4122ccb96312Sdlg } 4123ccb96312Sdlg 41241d70c39eSdlg /* 41251d70c39eSdlg * this returns -2 on software/driver failure, -1 for problems 41261d70c39eSdlg * talking to the hardware, or the sff module type. 41271d70c39eSdlg */ 41281d70c39eSdlg 412925fbbcc0Sdlg static int 413025fbbcc0Sdlg ixl_get_module_type(struct ixl_softc *sc) 413125fbbcc0Sdlg { 413225fbbcc0Sdlg struct ixl_dmamem idm; 413325fbbcc0Sdlg struct ixl_aq_phy_abilities *phy; 413425fbbcc0Sdlg int rv; 413525fbbcc0Sdlg 413625fbbcc0Sdlg if (ixl_dmamem_alloc(sc, &idm, IXL_AQ_BUFLEN, 0) != 0) 41371d70c39eSdlg return (-2); 413825fbbcc0Sdlg 413925fbbcc0Sdlg rv = ixl_get_phy_abilities(sc, &idm); 414025fbbcc0Sdlg if (rv != IXL_AQ_RC_OK) { 414125fbbcc0Sdlg rv = -1; 414225fbbcc0Sdlg goto done; 414325fbbcc0Sdlg } 414425fbbcc0Sdlg 414525fbbcc0Sdlg phy = IXL_DMA_KVA(&idm); 414625fbbcc0Sdlg 414725fbbcc0Sdlg rv = phy->module_type[0]; 414825fbbcc0Sdlg 414925fbbcc0Sdlg done: 415025fbbcc0Sdlg ixl_dmamem_free(sc, &idm); 415125fbbcc0Sdlg return (rv); 415225fbbcc0Sdlg } 415325fbbcc0Sdlg 4154ccb96312Sdlg static int 4155ccb96312Sdlg ixl_get_link_status(struct ixl_softc *sc) 4156ccb96312Sdlg { 4157ccb96312Sdlg struct ixl_aq_desc iaq; 41587f4b2a0fSjmatthew struct ixl_aq_link_param *param; 4159ccb96312Sdlg 4160ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 4161ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_PHY_LINK_STATUS); 41627f4b2a0fSjmatthew param = (struct ixl_aq_link_param *)iaq.iaq_param; 41637f4b2a0fSjmatthew param->notify = IXL_AQ_LINK_NOTIFY; 4164ccb96312Sdlg 4165ccb96312Sdlg if (ixl_atq_poll(sc, &iaq, 250) != 0) { 4166ccb96312Sdlg printf("%s: GET LINK STATUS timeout\n", DEVNAME(sc)); 4167ccb96312Sdlg return (-1); 4168ccb96312Sdlg } 4169ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 4170ccb96312Sdlg printf("%s: GET LINK STATUS error\n", DEVNAME(sc)); 4171ccb96312Sdlg return (0); 4172ccb96312Sdlg } 4173ccb96312Sdlg 4174ccb96312Sdlg sc->sc_ac.ac_if.if_link_state = ixl_set_link_status(sc, &iaq); 4175ccb96312Sdlg 4176ccb96312Sdlg return (0); 4177ccb96312Sdlg } 4178ccb96312Sdlg 417925fbbcc0Sdlg struct ixl_sff_ops { 418025fbbcc0Sdlg int (*open)(struct ixl_softc *sc, struct if_sffpage *, uint8_t *); 418125fbbcc0Sdlg int (*get)(struct ixl_softc *sc, struct if_sffpage *, size_t); 418225fbbcc0Sdlg int (*close)(struct ixl_softc *sc, struct if_sffpage *, uint8_t); 418325fbbcc0Sdlg }; 418425fbbcc0Sdlg 418525fbbcc0Sdlg static int 418625fbbcc0Sdlg ixl_sfp_open(struct ixl_softc *sc, struct if_sffpage *sff, uint8_t *page) 418725fbbcc0Sdlg { 418825fbbcc0Sdlg int error; 418925fbbcc0Sdlg 419025fbbcc0Sdlg if (sff->sff_addr != IFSFF_ADDR_EEPROM) 419125fbbcc0Sdlg return (0); 419225fbbcc0Sdlg 419325fbbcc0Sdlg error = ixl_sff_get_byte(sc, IFSFF_ADDR_EEPROM, 127, page); 419425fbbcc0Sdlg if (error != 0) 419525fbbcc0Sdlg return (error); 419625fbbcc0Sdlg if (*page == sff->sff_page) 419725fbbcc0Sdlg return (0); 419825fbbcc0Sdlg error = ixl_sff_set_byte(sc, IFSFF_ADDR_EEPROM, 127, sff->sff_page); 419925fbbcc0Sdlg if (error != 0) 420025fbbcc0Sdlg return (error); 420125fbbcc0Sdlg 420225fbbcc0Sdlg return (0); 420325fbbcc0Sdlg } 420425fbbcc0Sdlg 420525fbbcc0Sdlg static int 420625fbbcc0Sdlg ixl_sfp_get(struct ixl_softc *sc, struct if_sffpage *sff, size_t i) 420725fbbcc0Sdlg { 420825fbbcc0Sdlg return (ixl_sff_get_byte(sc, sff->sff_addr, i, &sff->sff_data[i])); 420925fbbcc0Sdlg } 421025fbbcc0Sdlg 421125fbbcc0Sdlg static int 421225fbbcc0Sdlg ixl_sfp_close(struct ixl_softc *sc, struct if_sffpage *sff, uint8_t page) 421325fbbcc0Sdlg { 421425fbbcc0Sdlg int error; 421525fbbcc0Sdlg 421625fbbcc0Sdlg if (sff->sff_addr != IFSFF_ADDR_EEPROM) 421725fbbcc0Sdlg return (0); 421825fbbcc0Sdlg 421925fbbcc0Sdlg if (page == sff->sff_page) 422025fbbcc0Sdlg return (0); 422125fbbcc0Sdlg 422225fbbcc0Sdlg error = ixl_sff_set_byte(sc, IFSFF_ADDR_EEPROM, 127, page); 422325fbbcc0Sdlg if (error != 0) 422425fbbcc0Sdlg return (error); 422525fbbcc0Sdlg 422625fbbcc0Sdlg return (0); 422725fbbcc0Sdlg } 422825fbbcc0Sdlg 422925fbbcc0Sdlg static const struct ixl_sff_ops ixl_sfp_ops = { 423025fbbcc0Sdlg ixl_sfp_open, 423125fbbcc0Sdlg ixl_sfp_get, 423225fbbcc0Sdlg ixl_sfp_close, 423325fbbcc0Sdlg }; 423425fbbcc0Sdlg 423525fbbcc0Sdlg static int 423625fbbcc0Sdlg ixl_qsfp_open(struct ixl_softc *sc, struct if_sffpage *sff, uint8_t *page) 423725fbbcc0Sdlg { 423825fbbcc0Sdlg if (sff->sff_addr != IFSFF_ADDR_EEPROM) 423925fbbcc0Sdlg return (EIO); 424025fbbcc0Sdlg 424125fbbcc0Sdlg return (0); 424225fbbcc0Sdlg } 424325fbbcc0Sdlg 424425fbbcc0Sdlg static int 424525fbbcc0Sdlg ixl_qsfp_get(struct ixl_softc *sc, struct if_sffpage *sff, size_t i) 424625fbbcc0Sdlg { 424725fbbcc0Sdlg return (ixl_sff_get_byte(sc, sff->sff_page, i, &sff->sff_data[i])); 424825fbbcc0Sdlg } 424925fbbcc0Sdlg 425025fbbcc0Sdlg static int 425125fbbcc0Sdlg ixl_qsfp_close(struct ixl_softc *sc, struct if_sffpage *sff, uint8_t page) 425225fbbcc0Sdlg { 425325fbbcc0Sdlg return (0); 425425fbbcc0Sdlg } 425525fbbcc0Sdlg 425625fbbcc0Sdlg static const struct ixl_sff_ops ixl_qsfp_ops = { 425725fbbcc0Sdlg ixl_qsfp_open, 425825fbbcc0Sdlg ixl_qsfp_get, 425925fbbcc0Sdlg ixl_qsfp_close, 426025fbbcc0Sdlg }; 426125fbbcc0Sdlg 4262ccb96312Sdlg static int 42634eec9beaSdlg ixl_get_sffpage(struct ixl_softc *sc, struct if_sffpage *sff) 42644eec9beaSdlg { 426525fbbcc0Sdlg const struct ixl_sff_ops *ops; 426625fbbcc0Sdlg uint8_t page; 42674eec9beaSdlg size_t i; 42684eec9beaSdlg int error; 42694eec9beaSdlg 427025fbbcc0Sdlg switch (ixl_get_module_type(sc)) { 42711d70c39eSdlg case -2: 42721d70c39eSdlg return (ENOMEM); 427325fbbcc0Sdlg case -1: 42741d70c39eSdlg return (ENXIO); 427525fbbcc0Sdlg case IXL_SFF8024_ID_SFP: 427625fbbcc0Sdlg ops = &ixl_sfp_ops; 427725fbbcc0Sdlg break; 427825fbbcc0Sdlg case IXL_SFF8024_ID_QSFP: 427925fbbcc0Sdlg case IXL_SFF8024_ID_QSFP_PLUS: 428025fbbcc0Sdlg case IXL_SFF8024_ID_QSFP28: 428125fbbcc0Sdlg ops = &ixl_qsfp_ops; 428225fbbcc0Sdlg break; 428325fbbcc0Sdlg default: 428425fbbcc0Sdlg return (EOPNOTSUPP); 428525fbbcc0Sdlg } 428625fbbcc0Sdlg 428725fbbcc0Sdlg error = (*ops->open)(sc, sff, &page); 42884eec9beaSdlg if (error != 0) 42894eec9beaSdlg return (error); 42904eec9beaSdlg 42914eec9beaSdlg for (i = 0; i < sizeof(sff->sff_data); i++) { 429225fbbcc0Sdlg error = (*ops->get)(sc, sff, i); 42934eec9beaSdlg if (error != 0) 42944eec9beaSdlg return (error); 42954eec9beaSdlg } 42964eec9beaSdlg 429725fbbcc0Sdlg error = (*ops->close)(sc, sff, page); 42984eec9beaSdlg 42994eec9beaSdlg return (0); 43004eec9beaSdlg } 43014eec9beaSdlg 43024eec9beaSdlg static int 43034eec9beaSdlg ixl_sff_get_byte(struct ixl_softc *sc, uint8_t dev, uint32_t reg, uint8_t *p) 43044eec9beaSdlg { 43054eec9beaSdlg struct ixl_atq iatq; 43064eec9beaSdlg struct ixl_aq_desc *iaq; 43074eec9beaSdlg struct ixl_aq_phy_reg_access *param; 43084eec9beaSdlg 43094eec9beaSdlg memset(&iatq, 0, sizeof(iatq)); 43104eec9beaSdlg iaq = &iatq.iatq_desc; 43114eec9beaSdlg iaq->iaq_opcode = htole16(IXL_AQ_OP_PHY_GET_REGISTER); 43124eec9beaSdlg param = (struct ixl_aq_phy_reg_access *)iaq->iaq_param; 43134eec9beaSdlg param->phy_iface = IXL_AQ_PHY_IF_MODULE; 43144eec9beaSdlg param->dev_addr = dev; 43154eec9beaSdlg htolem32(¶m->reg, reg); 43164eec9beaSdlg 43174eec9beaSdlg ixl_atq_exec(sc, &iatq, "ixlsffget"); 43184eec9beaSdlg 431999da00d3Sdlg if (ISSET(sc->sc_ac.ac_if.if_flags, IFF_DEBUG)) { 432099da00d3Sdlg printf("%s: %s(dev 0x%02x, reg 0x%02x) -> %04x\n", 432199da00d3Sdlg DEVNAME(sc), __func__, 432299da00d3Sdlg dev, reg, lemtoh16(&iaq->iaq_retval)); 432399da00d3Sdlg } 432499da00d3Sdlg 43254eec9beaSdlg switch (iaq->iaq_retval) { 43264eec9beaSdlg case htole16(IXL_AQ_RC_OK): 43274eec9beaSdlg break; 43284eec9beaSdlg case htole16(IXL_AQ_RC_EBUSY): 43294eec9beaSdlg return (EBUSY); 43304eec9beaSdlg case htole16(IXL_AQ_RC_ESRCH): 43314eec9beaSdlg return (ENODEV); 43324eec9beaSdlg case htole16(IXL_AQ_RC_EIO): 43334eec9beaSdlg case htole16(IXL_AQ_RC_EINVAL): 43344eec9beaSdlg default: 43354eec9beaSdlg return (EIO); 43364eec9beaSdlg } 43374eec9beaSdlg 43384eec9beaSdlg *p = lemtoh32(¶m->val); 43394eec9beaSdlg 43404eec9beaSdlg return (0); 43414eec9beaSdlg } 43424eec9beaSdlg 43434eec9beaSdlg static int 43444eec9beaSdlg ixl_sff_set_byte(struct ixl_softc *sc, uint8_t dev, uint32_t reg, uint8_t v) 43454eec9beaSdlg { 43464eec9beaSdlg struct ixl_atq iatq; 43474eec9beaSdlg struct ixl_aq_desc *iaq; 43484eec9beaSdlg struct ixl_aq_phy_reg_access *param; 43494eec9beaSdlg 43504eec9beaSdlg memset(&iatq, 0, sizeof(iatq)); 43514eec9beaSdlg iaq = &iatq.iatq_desc; 43524eec9beaSdlg iaq->iaq_opcode = htole16(IXL_AQ_OP_PHY_SET_REGISTER); 43534eec9beaSdlg param = (struct ixl_aq_phy_reg_access *)iaq->iaq_param; 43544eec9beaSdlg param->phy_iface = IXL_AQ_PHY_IF_MODULE; 43554eec9beaSdlg param->dev_addr = dev; 43564eec9beaSdlg htolem32(¶m->reg, reg); 43574eec9beaSdlg htolem32(¶m->val, v); 43584eec9beaSdlg 43594eec9beaSdlg ixl_atq_exec(sc, &iatq, "ixlsffset"); 43604eec9beaSdlg 436199da00d3Sdlg if (ISSET(sc->sc_ac.ac_if.if_flags, IFF_DEBUG)) { 436299da00d3Sdlg printf("%s: %s(dev 0x%02x, reg 0x%02x, val 0x%02x) -> %04x\n", 436399da00d3Sdlg DEVNAME(sc), __func__, 436499da00d3Sdlg dev, reg, v, lemtoh16(&iaq->iaq_retval)); 436599da00d3Sdlg } 436699da00d3Sdlg 43674eec9beaSdlg switch (iaq->iaq_retval) { 43684eec9beaSdlg case htole16(IXL_AQ_RC_OK): 43694eec9beaSdlg break; 43704eec9beaSdlg case htole16(IXL_AQ_RC_EBUSY): 43714eec9beaSdlg return (EBUSY); 43724eec9beaSdlg case htole16(IXL_AQ_RC_ESRCH): 43734eec9beaSdlg return (ENODEV); 43744eec9beaSdlg case htole16(IXL_AQ_RC_EIO): 43754eec9beaSdlg case htole16(IXL_AQ_RC_EINVAL): 43764eec9beaSdlg default: 43774eec9beaSdlg return (EIO); 43784eec9beaSdlg } 43794eec9beaSdlg 43804eec9beaSdlg return (0); 43814eec9beaSdlg } 43824eec9beaSdlg 43834eec9beaSdlg static int 4384ccb96312Sdlg ixl_get_vsi(struct ixl_softc *sc) 4385ccb96312Sdlg { 43862bb8400cSjmatthew struct ixl_dmamem *vsi = &sc->sc_scratch; 4387ccb96312Sdlg struct ixl_aq_desc iaq; 4388ccb96312Sdlg struct ixl_aq_vsi_param *param; 4389ccb96312Sdlg struct ixl_aq_vsi_reply *reply; 4390ccb96312Sdlg int rv; 4391ccb96312Sdlg 4392ccb96312Sdlg /* grumble, vsi info isn't "known" at compile time */ 4393ccb96312Sdlg 4394ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 4395ccb96312Sdlg htolem16(&iaq.iaq_flags, IXL_AQ_BUF | 4396ccb96312Sdlg (IXL_DMA_LEN(vsi) > I40E_AQ_LARGE_BUF ? IXL_AQ_LB : 0)); 4397ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_GET_VSI_PARAMS); 4398ccb96312Sdlg htolem16(&iaq.iaq_datalen, IXL_DMA_LEN(vsi)); 4399ccb96312Sdlg ixl_aq_dva(&iaq, IXL_DMA_DVA(vsi)); 4400ccb96312Sdlg 4401ccb96312Sdlg param = (struct ixl_aq_vsi_param *)iaq.iaq_param; 4402ccb96312Sdlg param->uplink_seid = sc->sc_seid; 4403ccb96312Sdlg 4404ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(vsi), 0, IXL_DMA_LEN(vsi), 4405ccb96312Sdlg BUS_DMASYNC_PREREAD); 4406ccb96312Sdlg 4407ccb96312Sdlg rv = ixl_atq_poll(sc, &iaq, 250); 4408ccb96312Sdlg 4409ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(vsi), 0, IXL_DMA_LEN(vsi), 4410ccb96312Sdlg BUS_DMASYNC_POSTREAD); 4411ccb96312Sdlg 4412ccb96312Sdlg if (rv != 0) { 4413ccb96312Sdlg printf("%s: GET VSI timeout\n", DEVNAME(sc)); 4414ccb96312Sdlg return (-1); 4415ccb96312Sdlg } 4416ccb96312Sdlg 4417ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 4418ccb96312Sdlg printf("%s: GET VSI error %u\n", DEVNAME(sc), 4419ccb96312Sdlg lemtoh16(&iaq.iaq_retval)); 4420ccb96312Sdlg return (-1); 4421ccb96312Sdlg } 4422ccb96312Sdlg 4423ccb96312Sdlg reply = (struct ixl_aq_vsi_reply *)iaq.iaq_param; 4424ccb96312Sdlg sc->sc_vsi_number = reply->vsi_number; 4425ccb96312Sdlg 4426ccb96312Sdlg return (0); 4427ccb96312Sdlg } 4428ccb96312Sdlg 4429ccb96312Sdlg static int 4430ccb96312Sdlg ixl_set_vsi(struct ixl_softc *sc) 4431ccb96312Sdlg { 44322bb8400cSjmatthew struct ixl_dmamem *vsi = &sc->sc_scratch; 4433ccb96312Sdlg struct ixl_aq_desc iaq; 4434ccb96312Sdlg struct ixl_aq_vsi_param *param; 4435ccb96312Sdlg struct ixl_aq_vsi_data *data = IXL_DMA_KVA(vsi); 4436ccb96312Sdlg int rv; 4437ccb96312Sdlg 4438ccb96312Sdlg data->valid_sections = htole16(IXL_AQ_VSI_VALID_QUEUE_MAP | 4439ccb96312Sdlg IXL_AQ_VSI_VALID_VLAN); 4440ccb96312Sdlg 4441ccb96312Sdlg CLR(data->mapping_flags, htole16(IXL_AQ_VSI_QUE_MAP_MASK)); 4442ccb96312Sdlg SET(data->mapping_flags, htole16(IXL_AQ_VSI_QUE_MAP_CONTIG)); 4443eb1b42e4Sdlg data->queue_mapping[0] = htole16(0); 4444ccb96312Sdlg data->tc_mapping[0] = htole16((0 << IXL_AQ_VSI_TC_Q_OFFSET_SHIFT) | 4445ccb96312Sdlg (sc->sc_nqueues << IXL_AQ_VSI_TC_Q_NUMBER_SHIFT)); 4446ccb96312Sdlg 4447ccb96312Sdlg CLR(data->port_vlan_flags, 4448ccb96312Sdlg htole16(IXL_AQ_VSI_PVLAN_MODE_MASK | IXL_AQ_VSI_PVLAN_EMOD_MASK)); 4449555fd15dSdlg SET(data->port_vlan_flags, htole16(IXL_AQ_VSI_PVLAN_MODE_ALL | 4450555fd15dSdlg IXL_AQ_VSI_PVLAN_EMOD_STR_BOTH)); 4451ccb96312Sdlg 4452ccb96312Sdlg /* grumble, vsi info isn't "known" at compile time */ 4453ccb96312Sdlg 4454ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 4455ccb96312Sdlg htolem16(&iaq.iaq_flags, IXL_AQ_BUF | IXL_AQ_RD | 4456ccb96312Sdlg (IXL_DMA_LEN(vsi) > I40E_AQ_LARGE_BUF ? IXL_AQ_LB : 0)); 4457ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_UPD_VSI_PARAMS); 4458ccb96312Sdlg htolem16(&iaq.iaq_datalen, IXL_DMA_LEN(vsi)); 4459ccb96312Sdlg ixl_aq_dva(&iaq, IXL_DMA_DVA(vsi)); 4460ccb96312Sdlg 4461ccb96312Sdlg param = (struct ixl_aq_vsi_param *)iaq.iaq_param; 4462ccb96312Sdlg param->uplink_seid = sc->sc_seid; 4463ccb96312Sdlg 4464ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(vsi), 0, IXL_DMA_LEN(vsi), 4465ccb96312Sdlg BUS_DMASYNC_PREWRITE); 4466ccb96312Sdlg 4467ccb96312Sdlg rv = ixl_atq_poll(sc, &iaq, 250); 4468ccb96312Sdlg 4469ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(vsi), 0, IXL_DMA_LEN(vsi), 4470ccb96312Sdlg BUS_DMASYNC_POSTWRITE); 4471ccb96312Sdlg 4472ccb96312Sdlg if (rv != 0) { 4473ccb96312Sdlg printf("%s: UPDATE VSI timeout\n", DEVNAME(sc)); 4474ccb96312Sdlg return (-1); 4475ccb96312Sdlg } 4476ccb96312Sdlg 4477ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 4478ccb96312Sdlg printf("%s: UPDATE VSI error %u\n", DEVNAME(sc), 4479ccb96312Sdlg lemtoh16(&iaq.iaq_retval)); 4480ccb96312Sdlg return (-1); 4481ccb96312Sdlg } 4482ccb96312Sdlg 4483ccb96312Sdlg return (0); 4484ccb96312Sdlg } 4485ccb96312Sdlg 4486ccb96312Sdlg static const struct ixl_phy_type * 4487ccb96312Sdlg ixl_search_phy_type(uint8_t phy_type) 4488ccb96312Sdlg { 4489ccb96312Sdlg const struct ixl_phy_type *itype; 4490ccb96312Sdlg uint64_t mask; 4491ccb96312Sdlg unsigned int i; 4492ccb96312Sdlg 4493ccb96312Sdlg if (phy_type >= 64) 4494ccb96312Sdlg return (NULL); 4495ccb96312Sdlg 4496ccb96312Sdlg mask = 1ULL << phy_type; 4497ccb96312Sdlg 4498ccb96312Sdlg for (i = 0; i < nitems(ixl_phy_type_map); i++) { 4499ccb96312Sdlg itype = &ixl_phy_type_map[i]; 4500ccb96312Sdlg 4501ccb96312Sdlg if (ISSET(itype->phy_type, mask)) 4502ccb96312Sdlg return (itype); 4503ccb96312Sdlg } 4504ccb96312Sdlg 4505ccb96312Sdlg return (NULL); 4506ccb96312Sdlg } 4507ccb96312Sdlg 4508ccb96312Sdlg static uint64_t 4509ccb96312Sdlg ixl_search_link_speed(uint8_t link_speed) 4510ccb96312Sdlg { 4511ccb96312Sdlg const struct ixl_speed_type *type; 4512ccb96312Sdlg unsigned int i; 4513ccb96312Sdlg 4514be3123b0Sjsg for (i = 0; i < nitems(ixl_speed_type_map); i++) { 4515ccb96312Sdlg type = &ixl_speed_type_map[i]; 4516ccb96312Sdlg 4517ccb96312Sdlg if (ISSET(type->dev_speed, link_speed)) 4518ccb96312Sdlg return (type->net_speed); 4519ccb96312Sdlg } 4520ccb96312Sdlg 4521ccb96312Sdlg return (0); 4522ccb96312Sdlg } 4523ccb96312Sdlg 4524ccb96312Sdlg static int 4525ccb96312Sdlg ixl_set_link_status(struct ixl_softc *sc, const struct ixl_aq_desc *iaq) 4526ccb96312Sdlg { 4527ccb96312Sdlg const struct ixl_aq_link_status *status; 4528ccb96312Sdlg const struct ixl_phy_type *itype; 4529ccb96312Sdlg uint64_t ifm_active = IFM_ETHER; 4530ccb96312Sdlg uint64_t ifm_status = IFM_AVALID; 4531ccb96312Sdlg int link_state = LINK_STATE_DOWN; 4532ccb96312Sdlg uint64_t baudrate = 0; 4533ccb96312Sdlg 4534ccb96312Sdlg status = (const struct ixl_aq_link_status *)iaq->iaq_param; 4535ccb96312Sdlg if (!ISSET(status->link_info, IXL_AQ_LINK_UP_FUNCTION)) 4536ccb96312Sdlg goto done; 4537ccb96312Sdlg 4538ccb96312Sdlg ifm_active |= IFM_FDX; 4539ccb96312Sdlg ifm_status |= IFM_ACTIVE; 4540ccb96312Sdlg link_state = LINK_STATE_FULL_DUPLEX; 4541ccb96312Sdlg 4542ccb96312Sdlg itype = ixl_search_phy_type(status->phy_type); 4543ccb96312Sdlg if (itype != NULL) 4544ccb96312Sdlg ifm_active |= itype->ifm_type; 4545ccb96312Sdlg 4546ccb96312Sdlg if (ISSET(status->an_info, IXL_AQ_LINK_PAUSE_TX)) 4547ccb96312Sdlg ifm_active |= IFM_ETH_TXPAUSE; 4548ccb96312Sdlg if (ISSET(status->an_info, IXL_AQ_LINK_PAUSE_RX)) 4549ccb96312Sdlg ifm_active |= IFM_ETH_RXPAUSE; 4550ccb96312Sdlg 4551ccb96312Sdlg baudrate = ixl_search_link_speed(status->link_speed); 4552ccb96312Sdlg 4553ccb96312Sdlg done: 4554fea9c2abSbluhm mtx_enter(&sc->sc_link_state_mtx); 4555ccb96312Sdlg sc->sc_media_active = ifm_active; 4556ccb96312Sdlg sc->sc_media_status = ifm_status; 4557ccb96312Sdlg sc->sc_ac.ac_if.if_baudrate = baudrate; 4558fea9c2abSbluhm mtx_leave(&sc->sc_link_state_mtx); 4559ccb96312Sdlg 4560ccb96312Sdlg return (link_state); 4561ccb96312Sdlg } 4562ccb96312Sdlg 4563ccb96312Sdlg static int 4564ccb96312Sdlg ixl_restart_an(struct ixl_softc *sc) 4565ccb96312Sdlg { 4566ccb96312Sdlg struct ixl_aq_desc iaq; 4567ccb96312Sdlg 4568ccb96312Sdlg memset(&iaq, 0, sizeof(iaq)); 4569ccb96312Sdlg iaq.iaq_opcode = htole16(IXL_AQ_OP_PHY_RESTART_AN); 4570ccb96312Sdlg iaq.iaq_param[0] = 4571ccb96312Sdlg htole32(IXL_AQ_PHY_RESTART_AN | IXL_AQ_PHY_LINK_ENABLE); 4572ccb96312Sdlg 4573ccb96312Sdlg if (ixl_atq_poll(sc, &iaq, 250) != 0) { 4574ccb96312Sdlg printf("%s: RESTART AN timeout\n", DEVNAME(sc)); 4575ccb96312Sdlg return (-1); 4576ccb96312Sdlg } 4577ccb96312Sdlg if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) { 4578ccb96312Sdlg printf("%s: RESTART AN error\n", DEVNAME(sc)); 4579ccb96312Sdlg return (-1); 4580ccb96312Sdlg } 4581ccb96312Sdlg 4582ccb96312Sdlg return (0); 4583ccb96312Sdlg } 4584ccb96312Sdlg 4585ccb96312Sdlg static int 45862bb8400cSjmatthew ixl_add_macvlan(struct ixl_softc *sc, uint8_t *macaddr, uint16_t vlan, uint16_t flags) 45872bb8400cSjmatthew { 45882bb8400cSjmatthew struct ixl_aq_desc iaq; 45892bb8400cSjmatthew struct ixl_aq_add_macvlan *param; 45902bb8400cSjmatthew struct ixl_aq_add_macvlan_elem *elem; 45912bb8400cSjmatthew 45922bb8400cSjmatthew memset(&iaq, 0, sizeof(iaq)); 45932bb8400cSjmatthew iaq.iaq_flags = htole16(IXL_AQ_BUF | IXL_AQ_RD); 45942bb8400cSjmatthew iaq.iaq_opcode = htole16(IXL_AQ_OP_ADD_MACVLAN); 45952bb8400cSjmatthew iaq.iaq_datalen = htole16(sizeof(*elem)); 45962bb8400cSjmatthew ixl_aq_dva(&iaq, IXL_DMA_DVA(&sc->sc_scratch)); 45972bb8400cSjmatthew 45982bb8400cSjmatthew param = (struct ixl_aq_add_macvlan *)&iaq.iaq_param; 45992bb8400cSjmatthew param->num_addrs = htole16(1); 46002bb8400cSjmatthew param->seid0 = htole16(0x8000) | sc->sc_seid; 46012bb8400cSjmatthew param->seid1 = 0; 46022bb8400cSjmatthew param->seid2 = 0; 46032bb8400cSjmatthew 46042bb8400cSjmatthew elem = IXL_DMA_KVA(&sc->sc_scratch); 46052bb8400cSjmatthew memset(elem, 0, sizeof(*elem)); 46062bb8400cSjmatthew memcpy(elem->macaddr, macaddr, ETHER_ADDR_LEN); 46072bb8400cSjmatthew elem->flags = htole16(IXL_AQ_OP_ADD_MACVLAN_PERFECT_MATCH | flags); 46082bb8400cSjmatthew elem->vlan = htole16(vlan); 46092bb8400cSjmatthew 46102bb8400cSjmatthew if (ixl_atq_poll(sc, &iaq, 250) != 0) { 46112bb8400cSjmatthew printf("%s: ADD_MACVLAN timeout\n", DEVNAME(sc)); 46122bb8400cSjmatthew return (IXL_AQ_RC_EINVAL); 46132bb8400cSjmatthew } 46142bb8400cSjmatthew 46152bb8400cSjmatthew return letoh16(iaq.iaq_retval); 46162bb8400cSjmatthew } 46172bb8400cSjmatthew 46182bb8400cSjmatthew static int 46192bb8400cSjmatthew ixl_remove_macvlan(struct ixl_softc *sc, uint8_t *macaddr, uint16_t vlan, uint16_t flags) 46202bb8400cSjmatthew { 46212bb8400cSjmatthew struct ixl_aq_desc iaq; 46222bb8400cSjmatthew struct ixl_aq_remove_macvlan *param; 46232bb8400cSjmatthew struct ixl_aq_remove_macvlan_elem *elem; 46242bb8400cSjmatthew 46252bb8400cSjmatthew memset(&iaq, 0, sizeof(iaq)); 46262bb8400cSjmatthew iaq.iaq_flags = htole16(IXL_AQ_BUF | IXL_AQ_RD); 46272bb8400cSjmatthew iaq.iaq_opcode = htole16(IXL_AQ_OP_REMOVE_MACVLAN); 46282bb8400cSjmatthew iaq.iaq_datalen = htole16(sizeof(*elem)); 46292bb8400cSjmatthew ixl_aq_dva(&iaq, IXL_DMA_DVA(&sc->sc_scratch)); 46302bb8400cSjmatthew 46312bb8400cSjmatthew param = (struct ixl_aq_remove_macvlan *)&iaq.iaq_param; 46322bb8400cSjmatthew param->num_addrs = htole16(1); 46332bb8400cSjmatthew param->seid0 = htole16(0x8000) | sc->sc_seid; 46342bb8400cSjmatthew param->seid1 = 0; 46352bb8400cSjmatthew param->seid2 = 0; 46362bb8400cSjmatthew 46372bb8400cSjmatthew elem = IXL_DMA_KVA(&sc->sc_scratch); 46382bb8400cSjmatthew memset(elem, 0, sizeof(*elem)); 46392bb8400cSjmatthew memcpy(elem->macaddr, macaddr, ETHER_ADDR_LEN); 46402bb8400cSjmatthew elem->flags = htole16(IXL_AQ_OP_REMOVE_MACVLAN_PERFECT_MATCH | flags); 46412bb8400cSjmatthew elem->vlan = htole16(vlan); 46422bb8400cSjmatthew 46432bb8400cSjmatthew if (ixl_atq_poll(sc, &iaq, 250) != 0) { 46442bb8400cSjmatthew printf("%s: REMOVE_MACVLAN timeout\n", DEVNAME(sc)); 46452bb8400cSjmatthew return (IXL_AQ_RC_EINVAL); 46462bb8400cSjmatthew } 46472bb8400cSjmatthew 46482bb8400cSjmatthew return letoh16(iaq.iaq_retval); 46492bb8400cSjmatthew } 46502bb8400cSjmatthew 46512bb8400cSjmatthew static int 4652ccb96312Sdlg ixl_hmc(struct ixl_softc *sc) 4653ccb96312Sdlg { 4654ccb96312Sdlg struct { 4655eb1b42e4Sdlg uint32_t count; 4656ccb96312Sdlg uint32_t minsize; 4657ccb96312Sdlg bus_size_t maxcnt; 4658ccb96312Sdlg bus_size_t setoff; 4659ccb96312Sdlg bus_size_t setcnt; 4660eb1b42e4Sdlg } regs[] = { 4661ccb96312Sdlg { 4662eb1b42e4Sdlg 0, 4663ccb96312Sdlg IXL_HMC_TXQ_MINSIZE, 4664ccb96312Sdlg I40E_GLHMC_LANTXOBJSZ, 4665ccb96312Sdlg I40E_GLHMC_LANTXBASE(sc->sc_pf_id), 4666ccb96312Sdlg I40E_GLHMC_LANTXCNT(sc->sc_pf_id), 4667ccb96312Sdlg }, 4668ccb96312Sdlg { 4669eb1b42e4Sdlg 0, 4670ccb96312Sdlg IXL_HMC_RXQ_MINSIZE, 4671ccb96312Sdlg I40E_GLHMC_LANRXOBJSZ, 4672ccb96312Sdlg I40E_GLHMC_LANRXBASE(sc->sc_pf_id), 4673ccb96312Sdlg I40E_GLHMC_LANRXCNT(sc->sc_pf_id), 4674eb1b42e4Sdlg }, 4675eb1b42e4Sdlg { 4676eb1b42e4Sdlg 0, 4677eb1b42e4Sdlg 0, 4678eb1b42e4Sdlg I40E_GLHMC_FCOEMAX, 4679eb1b42e4Sdlg I40E_GLHMC_FCOEDDPBASE(sc->sc_pf_id), 4680eb1b42e4Sdlg I40E_GLHMC_FCOEDDPCNT(sc->sc_pf_id), 4681eb1b42e4Sdlg }, 4682eb1b42e4Sdlg { 4683eb1b42e4Sdlg 0, 4684eb1b42e4Sdlg 0, 4685eb1b42e4Sdlg I40E_GLHMC_FCOEFMAX, 4686eb1b42e4Sdlg I40E_GLHMC_FCOEFBASE(sc->sc_pf_id), 4687eb1b42e4Sdlg I40E_GLHMC_FCOEFCNT(sc->sc_pf_id), 4688eb1b42e4Sdlg }, 4689ccb96312Sdlg }; 4690ccb96312Sdlg struct ixl_hmc_entry *e; 4691eb1b42e4Sdlg uint64_t size, dva; 4692ccb96312Sdlg uint8_t *kva; 4693ccb96312Sdlg uint64_t *sdpage; 4694ccb96312Sdlg unsigned int i; 4695ccb96312Sdlg int npages, tables; 4696ccb96312Sdlg 4697ccb96312Sdlg CTASSERT(nitems(regs) <= nitems(sc->sc_hmc_entries)); 4698ccb96312Sdlg 4699eb1b42e4Sdlg regs[IXL_HMC_LAN_TX].count = regs[IXL_HMC_LAN_RX].count = 4700eb1b42e4Sdlg ixl_rd(sc, I40E_GLHMC_LANQMAX); 4701ccb96312Sdlg 4702ccb96312Sdlg size = 0; 4703ccb96312Sdlg for (i = 0; i < nitems(regs); i++) { 4704ccb96312Sdlg e = &sc->sc_hmc_entries[i]; 4705ccb96312Sdlg 4706eb1b42e4Sdlg e->hmc_count = regs[i].count; 4707ccb96312Sdlg e->hmc_size = 1U << ixl_rd(sc, regs[i].maxcnt); 4708ccb96312Sdlg e->hmc_base = size; 4709ccb96312Sdlg 4710ccb96312Sdlg if ((e->hmc_size * 8) < regs[i].minsize) { 4711ccb96312Sdlg printf("%s: kernel hmc entry is too big\n", 4712ccb96312Sdlg DEVNAME(sc)); 4713ccb96312Sdlg return (-1); 4714ccb96312Sdlg } 4715ccb96312Sdlg 4716ccb96312Sdlg size += roundup(e->hmc_size * e->hmc_count, IXL_HMC_ROUNDUP); 4717ccb96312Sdlg } 4718ccb96312Sdlg size = roundup(size, IXL_HMC_PGSIZE); 4719ccb96312Sdlg npages = size / IXL_HMC_PGSIZE; 4720ccb96312Sdlg 4721eb1b42e4Sdlg tables = roundup(size, IXL_HMC_L2SZ) / IXL_HMC_L2SZ; 4722eb1b42e4Sdlg 4723eb1b42e4Sdlg if (ixl_dmamem_alloc(sc, &sc->sc_hmc_pd, size, IXL_HMC_PGSIZE) != 0) { 4724eb1b42e4Sdlg printf("%s: unable to allocate hmc pd memory\n", DEVNAME(sc)); 4725ccb96312Sdlg return (-1); 4726ccb96312Sdlg } 4727ccb96312Sdlg 4728eb1b42e4Sdlg if (ixl_dmamem_alloc(sc, &sc->sc_hmc_sd, tables * IXL_HMC_PGSIZE, 4729eb1b42e4Sdlg IXL_HMC_PGSIZE) != 0) { 4730eb1b42e4Sdlg printf("%s: unable to allocate hmc sd memory\n", DEVNAME(sc)); 4731eb1b42e4Sdlg ixl_dmamem_free(sc, &sc->sc_hmc_pd); 4732eb1b42e4Sdlg return (-1); 4733ccb96312Sdlg } 4734ccb96312Sdlg 4735eb1b42e4Sdlg kva = IXL_DMA_KVA(&sc->sc_hmc_pd); 4736eb1b42e4Sdlg memset(kva, 0, IXL_DMA_LEN(&sc->sc_hmc_pd)); 4737eb1b42e4Sdlg 4738eb1b42e4Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_hmc_pd), 4739eb1b42e4Sdlg 0, IXL_DMA_LEN(&sc->sc_hmc_pd), 4740ccb96312Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 4741ccb96312Sdlg 4742eb1b42e4Sdlg dva = IXL_DMA_DVA(&sc->sc_hmc_pd); 4743eb1b42e4Sdlg sdpage = IXL_DMA_KVA(&sc->sc_hmc_sd); 4744eb1b42e4Sdlg for (i = 0; i < npages; i++) { 4745eb1b42e4Sdlg htolem64(sdpage++, dva | IXL_HMC_PDVALID); 4746eb1b42e4Sdlg 4747eb1b42e4Sdlg dva += IXL_HMC_PGSIZE; 4748eb1b42e4Sdlg } 4749eb1b42e4Sdlg 4750eb1b42e4Sdlg bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_hmc_sd), 4751eb1b42e4Sdlg 0, IXL_DMA_LEN(&sc->sc_hmc_sd), 4752eb1b42e4Sdlg BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 4753eb1b42e4Sdlg 4754eb1b42e4Sdlg dva = IXL_DMA_DVA(&sc->sc_hmc_sd); 4755ccb96312Sdlg for (i = 0; i < tables; i++) { 4756ccb96312Sdlg uint32_t count; 4757ccb96312Sdlg 4758ccb96312Sdlg KASSERT(npages >= 0); 4759ccb96312Sdlg 4760ccb96312Sdlg count = (npages > IXL_HMC_PGS) ? IXL_HMC_PGS : npages; 4761ccb96312Sdlg 4762eb1b42e4Sdlg ixl_wr(sc, I40E_PFHMC_SDDATAHIGH, dva >> 32); 4763eb1b42e4Sdlg ixl_wr(sc, I40E_PFHMC_SDDATALOW, dva | 4764ccb96312Sdlg (count << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | 4765ccb96312Sdlg (1U << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)); 4766ccb96312Sdlg ixl_barrier(sc, 0, sc->sc_mems, BUS_SPACE_BARRIER_WRITE); 4767ccb96312Sdlg ixl_wr(sc, I40E_PFHMC_SDCMD, 4768ccb96312Sdlg (1U << I40E_PFHMC_SDCMD_PMSDWR_SHIFT) | i); 4769ccb96312Sdlg 4770ccb96312Sdlg npages -= IXL_HMC_PGS; 4771eb1b42e4Sdlg dva += IXL_HMC_PGSIZE; 4772ccb96312Sdlg } 4773ccb96312Sdlg 4774ccb96312Sdlg for (i = 0; i < nitems(regs); i++) { 4775ccb96312Sdlg e = &sc->sc_hmc_entries[i]; 4776ccb96312Sdlg 4777ccb96312Sdlg ixl_wr(sc, regs[i].setoff, e->hmc_base / IXL_HMC_ROUNDUP); 4778ccb96312Sdlg ixl_wr(sc, regs[i].setcnt, e->hmc_count); 4779ccb96312Sdlg } 4780ccb96312Sdlg 4781ccb96312Sdlg return (0); 4782ccb96312Sdlg } 4783ccb96312Sdlg 4784ccb96312Sdlg static void 4785eb1b42e4Sdlg ixl_hmc_free(struct ixl_softc *sc) 4786eb1b42e4Sdlg { 4787eb1b42e4Sdlg ixl_dmamem_free(sc, &sc->sc_hmc_sd); 4788eb1b42e4Sdlg ixl_dmamem_free(sc, &sc->sc_hmc_pd); 4789eb1b42e4Sdlg } 4790eb1b42e4Sdlg 4791eb1b42e4Sdlg static void 4792ccb96312Sdlg ixl_hmc_pack(void *d, const void *s, const struct ixl_hmc_pack *packing, 4793ccb96312Sdlg unsigned int npacking) 4794ccb96312Sdlg { 4795ccb96312Sdlg uint8_t *dst = d; 4796ccb96312Sdlg const uint8_t *src = s; 4797ccb96312Sdlg unsigned int i; 4798ccb96312Sdlg 4799ccb96312Sdlg for (i = 0; i < npacking; i++) { 4800ccb96312Sdlg const struct ixl_hmc_pack *pack = &packing[i]; 4801ccb96312Sdlg unsigned int offset = pack->lsb / 8; 4802ccb96312Sdlg unsigned int align = pack->lsb % 8; 4803ccb96312Sdlg const uint8_t *in = src + pack->offset; 4804ccb96312Sdlg uint8_t *out = dst + offset; 4805ccb96312Sdlg int width = pack->width; 4806ccb96312Sdlg unsigned int inbits = 0; 4807ccb96312Sdlg 4808ccb96312Sdlg if (align) { 480985fe2b3fSjmatthew inbits = (*in++) << align; 481085fe2b3fSjmatthew *out++ |= (inbits & 0xff); 481185fe2b3fSjmatthew inbits >>= 8; 4812ccb96312Sdlg 4813ccb96312Sdlg width -= 8 - align; 4814ccb96312Sdlg } 4815ccb96312Sdlg 4816ccb96312Sdlg while (width >= 8) { 481785fe2b3fSjmatthew inbits |= (*in++) << align; 481885fe2b3fSjmatthew *out++ = (inbits & 0xff); 481985fe2b3fSjmatthew inbits >>= 8; 4820ccb96312Sdlg 4821ccb96312Sdlg width -= 8; 4822ccb96312Sdlg } 4823ccb96312Sdlg 482485fe2b3fSjmatthew if (width > 0) { 482585fe2b3fSjmatthew inbits |= (*in) << align; 482685fe2b3fSjmatthew *out |= (inbits & ((1 << width) - 1)); 482785fe2b3fSjmatthew } 4828ccb96312Sdlg } 4829ccb96312Sdlg } 4830ccb96312Sdlg 4831ccb96312Sdlg static struct ixl_aq_buf * 4832ccb96312Sdlg ixl_aqb_alloc(struct ixl_softc *sc) 4833ccb96312Sdlg { 4834ccb96312Sdlg struct ixl_aq_buf *aqb; 4835ccb96312Sdlg 4836ccb96312Sdlg aqb = malloc(sizeof(*aqb), M_DEVBUF, M_WAITOK); 4837ccb96312Sdlg if (aqb == NULL) 4838ccb96312Sdlg return (NULL); 4839ccb96312Sdlg 4840ccb96312Sdlg aqb->aqb_data = dma_alloc(IXL_AQ_BUFLEN, PR_WAITOK); 4841ccb96312Sdlg if (aqb->aqb_data == NULL) 4842ccb96312Sdlg goto free; 4843ccb96312Sdlg 4844ccb96312Sdlg if (bus_dmamap_create(sc->sc_dmat, IXL_AQ_BUFLEN, 1, 4845ccb96312Sdlg IXL_AQ_BUFLEN, 0, 4846ccb96312Sdlg BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 4847ccb96312Sdlg &aqb->aqb_map) != 0) 4848ccb96312Sdlg goto dma_free; 4849ccb96312Sdlg 4850ccb96312Sdlg if (bus_dmamap_load(sc->sc_dmat, aqb->aqb_map, aqb->aqb_data, 4851ccb96312Sdlg IXL_AQ_BUFLEN, NULL, BUS_DMA_WAITOK) != 0) 4852ccb96312Sdlg goto destroy; 4853ccb96312Sdlg 4854ccb96312Sdlg return (aqb); 4855ccb96312Sdlg 4856ccb96312Sdlg destroy: 4857ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, aqb->aqb_map); 4858ccb96312Sdlg dma_free: 4859ccb96312Sdlg dma_free(aqb->aqb_data, IXL_AQ_BUFLEN); 4860ccb96312Sdlg free: 4861ccb96312Sdlg free(aqb, M_DEVBUF, sizeof(*aqb)); 4862ccb96312Sdlg 4863ccb96312Sdlg return (NULL); 4864ccb96312Sdlg } 4865ccb96312Sdlg 4866ccb96312Sdlg static void 4867ccb96312Sdlg ixl_aqb_free(struct ixl_softc *sc, struct ixl_aq_buf *aqb) 4868ccb96312Sdlg { 4869ccb96312Sdlg bus_dmamap_unload(sc->sc_dmat, aqb->aqb_map); 4870ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, aqb->aqb_map); 4871ccb96312Sdlg dma_free(aqb->aqb_data, IXL_AQ_BUFLEN); 4872ccb96312Sdlg free(aqb, M_DEVBUF, sizeof(*aqb)); 4873ccb96312Sdlg } 4874ccb96312Sdlg 4875ccb96312Sdlg static int 4876ccb96312Sdlg ixl_arq_fill(struct ixl_softc *sc) 4877ccb96312Sdlg { 4878ccb96312Sdlg struct ixl_aq_buf *aqb; 4879ccb96312Sdlg struct ixl_aq_desc *arq, *iaq; 4880ccb96312Sdlg unsigned int prod = sc->sc_arq_prod; 4881ccb96312Sdlg unsigned int n; 4882ccb96312Sdlg int post = 0; 4883ccb96312Sdlg 4884ccb96312Sdlg n = if_rxr_get(&sc->sc_arq_ring, IXL_AQ_NUM); 4885ccb96312Sdlg arq = IXL_DMA_KVA(&sc->sc_arq); 4886ccb96312Sdlg 4887ccb96312Sdlg while (n > 0) { 4888ccb96312Sdlg aqb = SIMPLEQ_FIRST(&sc->sc_arq_idle); 4889ccb96312Sdlg if (aqb != NULL) 4890ccb96312Sdlg SIMPLEQ_REMOVE_HEAD(&sc->sc_arq_idle, aqb_entry); 4891ccb96312Sdlg else if ((aqb = ixl_aqb_alloc(sc)) == NULL) 4892ccb96312Sdlg break; 4893ccb96312Sdlg 4894ccb96312Sdlg memset(aqb->aqb_data, 0, IXL_AQ_BUFLEN); 4895ccb96312Sdlg 4896ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, aqb->aqb_map, 0, IXL_AQ_BUFLEN, 4897ccb96312Sdlg BUS_DMASYNC_PREREAD); 4898ccb96312Sdlg 4899ccb96312Sdlg iaq = &arq[prod]; 4900ccb96312Sdlg iaq->iaq_flags = htole16(IXL_AQ_BUF | 4901ccb96312Sdlg (IXL_AQ_BUFLEN > I40E_AQ_LARGE_BUF ? IXL_AQ_LB : 0)); 4902ccb96312Sdlg iaq->iaq_opcode = 0; 4903ccb96312Sdlg iaq->iaq_datalen = htole16(IXL_AQ_BUFLEN); 4904ccb96312Sdlg iaq->iaq_retval = 0; 4905ccb96312Sdlg iaq->iaq_cookie = 0; 4906ccb96312Sdlg iaq->iaq_param[0] = 0; 4907ccb96312Sdlg iaq->iaq_param[1] = 0; 4908ccb96312Sdlg ixl_aq_dva(iaq, aqb->aqb_map->dm_segs[0].ds_addr); 4909ccb96312Sdlg 4910ccb96312Sdlg SIMPLEQ_INSERT_TAIL(&sc->sc_arq_live, aqb, aqb_entry); 4911ccb96312Sdlg 4912ccb96312Sdlg prod++; 4913ccb96312Sdlg prod &= IXL_AQ_MASK; 4914ccb96312Sdlg 4915ccb96312Sdlg post = 1; 4916ccb96312Sdlg 4917ccb96312Sdlg n--; 4918ccb96312Sdlg } 4919ccb96312Sdlg 4920ccb96312Sdlg if_rxr_put(&sc->sc_arq_ring, n); 4921ccb96312Sdlg sc->sc_arq_prod = prod; 4922ccb96312Sdlg 4923ccb96312Sdlg return (post); 4924ccb96312Sdlg } 4925ccb96312Sdlg 4926ccb96312Sdlg static void 4927ccb96312Sdlg ixl_arq_unfill(struct ixl_softc *sc) 4928ccb96312Sdlg { 4929ccb96312Sdlg struct ixl_aq_buf *aqb; 4930ccb96312Sdlg 4931ccb96312Sdlg while ((aqb = SIMPLEQ_FIRST(&sc->sc_arq_live)) != NULL) { 4932ccb96312Sdlg SIMPLEQ_REMOVE_HEAD(&sc->sc_arq_live, aqb_entry); 4933ccb96312Sdlg 4934ccb96312Sdlg bus_dmamap_sync(sc->sc_dmat, aqb->aqb_map, 0, IXL_AQ_BUFLEN, 4935ccb96312Sdlg BUS_DMASYNC_POSTREAD); 4936ccb96312Sdlg ixl_aqb_free(sc, aqb); 4937ccb96312Sdlg } 4938ccb96312Sdlg } 4939ccb96312Sdlg 4940ccb96312Sdlg static void 4941ccb96312Sdlg ixl_clear_hw(struct ixl_softc *sc) 4942ccb96312Sdlg { 4943ccb96312Sdlg uint32_t num_queues, base_queue; 4944ccb96312Sdlg uint32_t num_pf_int; 4945ccb96312Sdlg uint32_t num_vf_int; 4946ccb96312Sdlg uint32_t num_vfs; 4947ccb96312Sdlg uint32_t i, j; 4948ccb96312Sdlg uint32_t val; 4949ccb96312Sdlg 4950ccb96312Sdlg /* get number of interrupts, queues, and vfs */ 4951ccb96312Sdlg val = ixl_rd(sc, I40E_GLPCI_CNF2); 4952ccb96312Sdlg num_pf_int = (val & I40E_GLPCI_CNF2_MSI_X_PF_N_MASK) >> 4953ccb96312Sdlg I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT; 4954ccb96312Sdlg num_vf_int = (val & I40E_GLPCI_CNF2_MSI_X_VF_N_MASK) >> 4955ccb96312Sdlg I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT; 4956ccb96312Sdlg 4957ccb96312Sdlg val = ixl_rd(sc, I40E_PFLAN_QALLOC); 4958ccb96312Sdlg base_queue = (val & I40E_PFLAN_QALLOC_FIRSTQ_MASK) >> 4959ccb96312Sdlg I40E_PFLAN_QALLOC_FIRSTQ_SHIFT; 4960ccb96312Sdlg j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >> 4961ccb96312Sdlg I40E_PFLAN_QALLOC_LASTQ_SHIFT; 4962ccb96312Sdlg if (val & I40E_PFLAN_QALLOC_VALID_MASK) 4963ccb96312Sdlg num_queues = (j - base_queue) + 1; 4964ccb96312Sdlg else 4965ccb96312Sdlg num_queues = 0; 4966ccb96312Sdlg 4967ccb96312Sdlg val = ixl_rd(sc, I40E_PF_VT_PFALLOC); 4968ccb96312Sdlg i = (val & I40E_PF_VT_PFALLOC_FIRSTVF_MASK) >> 4969ccb96312Sdlg I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT; 4970ccb96312Sdlg j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >> 4971ccb96312Sdlg I40E_PF_VT_PFALLOC_LASTVF_SHIFT; 4972ccb96312Sdlg if (val & I40E_PF_VT_PFALLOC_VALID_MASK) 4973ccb96312Sdlg num_vfs = (j - i) + 1; 4974ccb96312Sdlg else 4975ccb96312Sdlg num_vfs = 0; 4976ccb96312Sdlg 4977ccb96312Sdlg /* stop all the interrupts */ 4978ccb96312Sdlg ixl_wr(sc, I40E_PFINT_ICR0_ENA, 0); 4979ccb96312Sdlg val = 0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT; 4980ccb96312Sdlg for (i = 0; i < num_pf_int - 2; i++) 4981ccb96312Sdlg ixl_wr(sc, I40E_PFINT_DYN_CTLN(i), val); 4982ccb96312Sdlg 4983ccb96312Sdlg /* Set the FIRSTQ_INDX field to 0x7FF in PFINT_LNKLSTx */ 498424f8ee69Smpi val = I40E_QUEUE_TYPE_EOL << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT; 4985ccb96312Sdlg ixl_wr(sc, I40E_PFINT_LNKLST0, val); 4986ccb96312Sdlg for (i = 0; i < num_pf_int - 2; i++) 4987ccb96312Sdlg ixl_wr(sc, I40E_PFINT_LNKLSTN(i), val); 498824f8ee69Smpi val = I40E_QUEUE_TYPE_EOL << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT; 4989ccb96312Sdlg for (i = 0; i < num_vfs; i++) 4990ccb96312Sdlg ixl_wr(sc, I40E_VPINT_LNKLST0(i), val); 4991ccb96312Sdlg for (i = 0; i < num_vf_int - 2; i++) 4992ccb96312Sdlg ixl_wr(sc, I40E_VPINT_LNKLSTN(i), val); 4993ccb96312Sdlg 4994ccb96312Sdlg /* warn the HW of the coming Tx disables */ 4995ccb96312Sdlg for (i = 0; i < num_queues; i++) { 4996ccb96312Sdlg uint32_t abs_queue_idx = base_queue + i; 4997ccb96312Sdlg uint32_t reg_block = 0; 4998ccb96312Sdlg 4999ccb96312Sdlg if (abs_queue_idx >= 128) { 5000ccb96312Sdlg reg_block = abs_queue_idx / 128; 5001ccb96312Sdlg abs_queue_idx %= 128; 5002ccb96312Sdlg } 5003ccb96312Sdlg 5004ccb96312Sdlg val = ixl_rd(sc, I40E_GLLAN_TXPRE_QDIS(reg_block)); 5005ccb96312Sdlg val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK; 5006ccb96312Sdlg val |= (abs_queue_idx << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT); 5007ccb96312Sdlg val |= I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK; 5008ccb96312Sdlg 5009ccb96312Sdlg ixl_wr(sc, I40E_GLLAN_TXPRE_QDIS(reg_block), val); 5010ccb96312Sdlg } 5011ccb96312Sdlg delaymsec(400); 5012ccb96312Sdlg 5013ccb96312Sdlg /* stop all the queues */ 5014ccb96312Sdlg for (i = 0; i < num_queues; i++) { 5015ccb96312Sdlg ixl_wr(sc, I40E_QINT_TQCTL(i), 0); 5016ccb96312Sdlg ixl_wr(sc, I40E_QTX_ENA(i), 0); 5017ccb96312Sdlg ixl_wr(sc, I40E_QINT_RQCTL(i), 0); 5018ccb96312Sdlg ixl_wr(sc, I40E_QRX_ENA(i), 0); 5019ccb96312Sdlg } 5020ccb96312Sdlg 5021ccb96312Sdlg /* short wait for all queue disables to settle */ 5022ccb96312Sdlg delaymsec(50); 5023ccb96312Sdlg } 5024ccb96312Sdlg 5025ccb96312Sdlg static int 5026ccb96312Sdlg ixl_pf_reset(struct ixl_softc *sc) 5027ccb96312Sdlg { 5028ccb96312Sdlg uint32_t cnt = 0; 5029ccb96312Sdlg uint32_t cnt1 = 0; 5030ccb96312Sdlg uint32_t reg = 0; 5031ccb96312Sdlg uint32_t grst_del; 5032ccb96312Sdlg 5033ccb96312Sdlg /* 5034ccb96312Sdlg * Poll for Global Reset steady state in case of recent GRST. 5035ccb96312Sdlg * The grst delay value is in 100ms units, and we'll wait a 5036ccb96312Sdlg * couple counts longer to be sure we don't just miss the end. 5037ccb96312Sdlg */ 5038ccb96312Sdlg grst_del = ixl_rd(sc, I40E_GLGEN_RSTCTL); 5039ccb96312Sdlg grst_del &= I40E_GLGEN_RSTCTL_GRSTDEL_MASK; 5040ccb96312Sdlg grst_del >>= I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT; 5041ccb96312Sdlg grst_del += 10; 5042ccb96312Sdlg 5043ccb96312Sdlg for (cnt = 0; cnt < grst_del; cnt++) { 5044ccb96312Sdlg reg = ixl_rd(sc, I40E_GLGEN_RSTAT); 5045ccb96312Sdlg if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK)) 5046ccb96312Sdlg break; 5047ccb96312Sdlg delaymsec(100); 5048ccb96312Sdlg } 5049ccb96312Sdlg if (reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK) { 5050ccb96312Sdlg printf(", Global reset polling failed to complete\n"); 5051ccb96312Sdlg return (-1); 5052ccb96312Sdlg } 5053ccb96312Sdlg 5054ccb96312Sdlg /* Now Wait for the FW to be ready */ 5055ccb96312Sdlg for (cnt1 = 0; cnt1 < I40E_PF_RESET_WAIT_COUNT; cnt1++) { 5056ccb96312Sdlg reg = ixl_rd(sc, I40E_GLNVM_ULD); 5057ccb96312Sdlg reg &= (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | 5058ccb96312Sdlg I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK); 5059ccb96312Sdlg if (reg == (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | 5060ccb96312Sdlg I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK)) 5061ccb96312Sdlg break; 5062ccb96312Sdlg 5063ccb96312Sdlg delaymsec(10); 5064ccb96312Sdlg } 5065ccb96312Sdlg if (!(reg & (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | 5066ccb96312Sdlg I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK))) { 5067ccb96312Sdlg printf(", wait for FW Reset complete timed out " 5068ccb96312Sdlg "(I40E_GLNVM_ULD = 0x%x)\n", reg); 5069ccb96312Sdlg return (-1); 5070ccb96312Sdlg } 5071ccb96312Sdlg 5072ccb96312Sdlg /* 5073ccb96312Sdlg * If there was a Global Reset in progress when we got here, 5074ccb96312Sdlg * we don't need to do the PF Reset 5075ccb96312Sdlg */ 5076ccb96312Sdlg if (cnt == 0) { 5077ccb96312Sdlg reg = ixl_rd(sc, I40E_PFGEN_CTRL); 5078ccb96312Sdlg ixl_wr(sc, I40E_PFGEN_CTRL, reg | I40E_PFGEN_CTRL_PFSWR_MASK); 5079ccb96312Sdlg for (cnt = 0; cnt < I40E_PF_RESET_WAIT_COUNT; cnt++) { 5080ccb96312Sdlg reg = ixl_rd(sc, I40E_PFGEN_CTRL); 5081ccb96312Sdlg if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK)) 5082ccb96312Sdlg break; 5083ccb96312Sdlg delaymsec(1); 5084ccb96312Sdlg } 5085ccb96312Sdlg if (reg & I40E_PFGEN_CTRL_PFSWR_MASK) { 5086ccb96312Sdlg printf(", PF reset polling failed to complete" 5087ccb96312Sdlg "(I40E_PFGEN_CTRL= 0x%x)\n", reg); 5088ccb96312Sdlg return (-1); 5089ccb96312Sdlg } 5090ccb96312Sdlg } 5091ccb96312Sdlg 5092ccb96312Sdlg return (0); 5093ccb96312Sdlg } 5094ccb96312Sdlg 5095819ac441Sdlg static uint32_t 5096819ac441Sdlg ixl_710_rd_ctl(struct ixl_softc *sc, uint32_t r) 5097819ac441Sdlg { 5098819ac441Sdlg struct ixl_atq iatq; 5099819ac441Sdlg struct ixl_aq_desc *iaq; 5100819ac441Sdlg uint16_t retval; 5101819ac441Sdlg 5102819ac441Sdlg memset(&iatq, 0, sizeof(iatq)); 5103819ac441Sdlg iaq = &iatq.iatq_desc; 5104819ac441Sdlg iaq->iaq_opcode = htole16(IXL_AQ_OP_RX_CTL_READ); 5105819ac441Sdlg htolem32(&iaq->iaq_param[1], r); 5106819ac441Sdlg 5107819ac441Sdlg ixl_atq_exec(sc, &iatq, "ixl710rd"); 5108819ac441Sdlg 5109819ac441Sdlg retval = lemtoh16(&iaq->iaq_retval); 5110819ac441Sdlg if (retval != IXL_AQ_RC_OK) { 5111819ac441Sdlg printf("%s: %s failed (%u)\n", DEVNAME(sc), __func__, retval); 5112819ac441Sdlg return (~0U); 5113819ac441Sdlg } 5114819ac441Sdlg 5115819ac441Sdlg return (lemtoh32(&iaq->iaq_param[3])); 5116819ac441Sdlg } 5117819ac441Sdlg 5118819ac441Sdlg static void 5119819ac441Sdlg ixl_710_wr_ctl(struct ixl_softc *sc, uint32_t r, uint32_t v) 5120819ac441Sdlg { 5121819ac441Sdlg struct ixl_atq iatq; 5122819ac441Sdlg struct ixl_aq_desc *iaq; 5123819ac441Sdlg uint16_t retval; 5124819ac441Sdlg 5125819ac441Sdlg memset(&iatq, 0, sizeof(iatq)); 5126819ac441Sdlg iaq = &iatq.iatq_desc; 5127819ac441Sdlg iaq->iaq_opcode = htole16(IXL_AQ_OP_RX_CTL_WRITE); 5128819ac441Sdlg htolem32(&iaq->iaq_param[1], r); 5129819ac441Sdlg htolem32(&iaq->iaq_param[3], v); 5130819ac441Sdlg 5131819ac441Sdlg ixl_atq_exec(sc, &iatq, "ixl710wr"); 5132819ac441Sdlg 5133819ac441Sdlg retval = lemtoh16(&iaq->iaq_retval); 51340a1169f5Sdlg if (retval != IXL_AQ_RC_OK) { 51350a1169f5Sdlg printf("%s: %s %08x=%08x failed (%u)\n", 51360a1169f5Sdlg DEVNAME(sc), __func__, r, v, retval); 51370a1169f5Sdlg } 5138819ac441Sdlg } 5139819ac441Sdlg 5140819ac441Sdlg static int 5141819ac441Sdlg ixl_710_set_rss_key(struct ixl_softc *sc, const struct ixl_rss_key *rsskey) 5142819ac441Sdlg { 5143819ac441Sdlg unsigned int i; 5144819ac441Sdlg 5145819ac441Sdlg for (i = 0; i < nitems(rsskey->key); i++) 5146f5777d33Sdlg ixl_wr_ctl(sc, I40E_PFQF_HKEY(i), rsskey->key[i]); 5147819ac441Sdlg 5148819ac441Sdlg return (0); 5149819ac441Sdlg } 5150819ac441Sdlg 5151819ac441Sdlg static int 5152819ac441Sdlg ixl_710_set_rss_lut(struct ixl_softc *sc, const struct ixl_rss_lut_128 *lut) 5153819ac441Sdlg { 5154819ac441Sdlg unsigned int i; 5155819ac441Sdlg 5156819ac441Sdlg for (i = 0; i < nitems(lut->entries); i++) 51570a1169f5Sdlg ixl_wr(sc, I40E_PFQF_HLUT(i), lut->entries[i]); 5158819ac441Sdlg 5159819ac441Sdlg return (0); 5160819ac441Sdlg } 5161819ac441Sdlg 5162819ac441Sdlg static uint32_t 5163819ac441Sdlg ixl_722_rd_ctl(struct ixl_softc *sc, uint32_t r) 5164819ac441Sdlg { 5165819ac441Sdlg return (ixl_rd(sc, r)); 5166819ac441Sdlg } 5167819ac441Sdlg 5168819ac441Sdlg static void 5169819ac441Sdlg ixl_722_wr_ctl(struct ixl_softc *sc, uint32_t r, uint32_t v) 5170819ac441Sdlg { 5171819ac441Sdlg ixl_wr(sc, r, v); 5172819ac441Sdlg } 5173819ac441Sdlg 5174819ac441Sdlg static int 5175819ac441Sdlg ixl_722_set_rss_key(struct ixl_softc *sc, const struct ixl_rss_key *rsskey) 5176819ac441Sdlg { 5177819ac441Sdlg /* XXX */ 5178819ac441Sdlg 5179819ac441Sdlg return (0); 5180819ac441Sdlg } 5181819ac441Sdlg 5182819ac441Sdlg static int 5183819ac441Sdlg ixl_722_set_rss_lut(struct ixl_softc *sc, const struct ixl_rss_lut_128 *lut) 5184819ac441Sdlg { 5185819ac441Sdlg /* XXX */ 5186819ac441Sdlg 5187819ac441Sdlg return (0); 5188819ac441Sdlg } 5189819ac441Sdlg 5190ccb96312Sdlg static int 5191ccb96312Sdlg ixl_dmamem_alloc(struct ixl_softc *sc, struct ixl_dmamem *ixm, 5192ccb96312Sdlg bus_size_t size, u_int align) 5193ccb96312Sdlg { 5194ccb96312Sdlg ixm->ixm_size = size; 5195ccb96312Sdlg 5196ccb96312Sdlg if (bus_dmamap_create(sc->sc_dmat, ixm->ixm_size, 1, 5197ccb96312Sdlg ixm->ixm_size, 0, 5198ccb96312Sdlg BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 5199ccb96312Sdlg &ixm->ixm_map) != 0) 5200ccb96312Sdlg return (1); 5201ccb96312Sdlg if (bus_dmamem_alloc(sc->sc_dmat, ixm->ixm_size, 5202ccb96312Sdlg align, 0, &ixm->ixm_seg, 1, &ixm->ixm_nsegs, 5203ccb96312Sdlg BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) 5204ccb96312Sdlg goto destroy; 5205ccb96312Sdlg if (bus_dmamem_map(sc->sc_dmat, &ixm->ixm_seg, ixm->ixm_nsegs, 5206ccb96312Sdlg ixm->ixm_size, &ixm->ixm_kva, BUS_DMA_WAITOK) != 0) 5207ccb96312Sdlg goto free; 5208ccb96312Sdlg if (bus_dmamap_load(sc->sc_dmat, ixm->ixm_map, ixm->ixm_kva, 5209ccb96312Sdlg ixm->ixm_size, NULL, BUS_DMA_WAITOK) != 0) 5210ccb96312Sdlg goto unmap; 5211ccb96312Sdlg 5212ccb96312Sdlg return (0); 5213ccb96312Sdlg unmap: 5214ccb96312Sdlg bus_dmamem_unmap(sc->sc_dmat, ixm->ixm_kva, ixm->ixm_size); 5215ccb96312Sdlg free: 5216ccb96312Sdlg bus_dmamem_free(sc->sc_dmat, &ixm->ixm_seg, 1); 5217ccb96312Sdlg destroy: 5218ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, ixm->ixm_map); 5219ccb96312Sdlg return (1); 5220ccb96312Sdlg } 5221ccb96312Sdlg 5222ccb96312Sdlg static void 5223ccb96312Sdlg ixl_dmamem_free(struct ixl_softc *sc, struct ixl_dmamem *ixm) 5224ccb96312Sdlg { 5225ccb96312Sdlg bus_dmamap_unload(sc->sc_dmat, ixm->ixm_map); 5226ccb96312Sdlg bus_dmamem_unmap(sc->sc_dmat, ixm->ixm_kva, ixm->ixm_size); 5227ccb96312Sdlg bus_dmamem_free(sc->sc_dmat, &ixm->ixm_seg, 1); 5228ccb96312Sdlg bus_dmamap_destroy(sc->sc_dmat, ixm->ixm_map); 5229ccb96312Sdlg } 52302ee1fcb3Sdlg 52312ee1fcb3Sdlg #if NKSTAT > 0 52322ee1fcb3Sdlg 52332ee1fcb3Sdlg CTASSERT(KSTAT_KV_U_NONE <= 0xffU); 52342ee1fcb3Sdlg CTASSERT(KSTAT_KV_U_PACKETS <= 0xffU); 52352ee1fcb3Sdlg CTASSERT(KSTAT_KV_U_BYTES <= 0xffU); 52362ee1fcb3Sdlg 52372ee1fcb3Sdlg struct ixl_counter { 52382ee1fcb3Sdlg const char *c_name; 52392ee1fcb3Sdlg uint32_t c_base; 52402ee1fcb3Sdlg uint8_t c_width; 52412ee1fcb3Sdlg uint8_t c_type; 52422ee1fcb3Sdlg }; 52432ee1fcb3Sdlg 52442ee1fcb3Sdlg const struct ixl_counter ixl_port_counters[] = { 52452ee1fcb3Sdlg /* GORC */ 52462ee1fcb3Sdlg { "rx bytes", 0x00300000, 48, KSTAT_KV_U_BYTES }, 52472ee1fcb3Sdlg /* MLFC */ 52482ee1fcb3Sdlg { "mac local errs", 0x00300020, 32, KSTAT_KV_U_NONE }, 52492ee1fcb3Sdlg /* MRFC */ 52502ee1fcb3Sdlg { "mac remote errs", 0x00300040, 32, KSTAT_KV_U_NONE }, 52512ee1fcb3Sdlg /* MSPDC */ 52522ee1fcb3Sdlg { "mac short", 0x00300060, 32, KSTAT_KV_U_PACKETS }, 52532ee1fcb3Sdlg /* CRCERRS */ 52542ee1fcb3Sdlg { "crc errs", 0x00300080, 32, KSTAT_KV_U_PACKETS }, 52552ee1fcb3Sdlg /* RLEC */ 52562ee1fcb3Sdlg { "rx len errs", 0x003000a0, 32, KSTAT_KV_U_PACKETS }, 52572ee1fcb3Sdlg /* ERRBC */ 52582ee1fcb3Sdlg { "byte errs", 0x003000c0, 32, KSTAT_KV_U_PACKETS }, 52592ee1fcb3Sdlg /* ILLERRC */ 52602ee1fcb3Sdlg { "illegal byte", 0x003000d0, 32, KSTAT_KV_U_PACKETS }, 52612ee1fcb3Sdlg /* RUC */ 52622ee1fcb3Sdlg { "rx undersize", 0x00300100, 32, KSTAT_KV_U_PACKETS }, 52632ee1fcb3Sdlg /* ROC */ 52642ee1fcb3Sdlg { "rx oversize", 0x00300120, 32, KSTAT_KV_U_PACKETS }, 52652ee1fcb3Sdlg /* LXONRXCNT */ 52662ee1fcb3Sdlg { "rx link xon", 0x00300140, 32, KSTAT_KV_U_PACKETS }, 52672ee1fcb3Sdlg /* LXOFFRXCNT */ 52682ee1fcb3Sdlg { "rx link xoff", 0x00300160, 32, KSTAT_KV_U_PACKETS }, 52692ee1fcb3Sdlg 52702ee1fcb3Sdlg /* Priority XON Received Count */ 52712ee1fcb3Sdlg /* Priority XOFF Received Count */ 52722ee1fcb3Sdlg /* Priority XON to XOFF Count */ 52732ee1fcb3Sdlg 52742ee1fcb3Sdlg /* PRC64 */ 52752ee1fcb3Sdlg { "rx 64B", 0x00300480, 48, KSTAT_KV_U_PACKETS }, 52762ee1fcb3Sdlg /* PRC127 */ 52772ee1fcb3Sdlg { "rx 65-127B", 0x003004A0, 48, KSTAT_KV_U_PACKETS }, 52782ee1fcb3Sdlg /* PRC255 */ 52792ee1fcb3Sdlg { "rx 128-255B", 0x003004C0, 48, KSTAT_KV_U_PACKETS }, 52802ee1fcb3Sdlg /* PRC511 */ 52812ee1fcb3Sdlg { "rx 256-511B", 0x003004E0, 48, KSTAT_KV_U_PACKETS }, 52822ee1fcb3Sdlg /* PRC1023 */ 52832ee1fcb3Sdlg { "rx 512-1023B", 0x00300500, 48, KSTAT_KV_U_PACKETS }, 52842ee1fcb3Sdlg /* PRC1522 */ 52852ee1fcb3Sdlg { "rx 1024-1522B", 0x00300520, 48, KSTAT_KV_U_PACKETS }, 52862ee1fcb3Sdlg /* PRC9522 */ 52872ee1fcb3Sdlg { "rx 1523-9522B", 0x00300540, 48, KSTAT_KV_U_PACKETS }, 52882ee1fcb3Sdlg /* ROC */ 52892ee1fcb3Sdlg { "rx fragment", 0x00300560, 32, KSTAT_KV_U_PACKETS }, 52902ee1fcb3Sdlg /* RJC */ 52912ee1fcb3Sdlg { "rx jabber", 0x00300580, 32, KSTAT_KV_U_PACKETS }, 52922ee1fcb3Sdlg /* UPRC */ 52932ee1fcb3Sdlg { "rx ucasts", 0x003005a0, 48, KSTAT_KV_U_PACKETS }, 52942ee1fcb3Sdlg /* MPRC */ 52952ee1fcb3Sdlg { "rx mcasts", 0x003005c0, 48, KSTAT_KV_U_PACKETS }, 52962ee1fcb3Sdlg /* BPRC */ 52972ee1fcb3Sdlg { "rx bcasts", 0x003005e0, 48, KSTAT_KV_U_PACKETS }, 52982ee1fcb3Sdlg /* RDPC */ 52992ee1fcb3Sdlg { "rx discards", 0x00300600, 32, KSTAT_KV_U_PACKETS }, 53002ee1fcb3Sdlg /* LDPC */ 53012ee1fcb3Sdlg { "rx lo discards", 0x00300620, 32, KSTAT_KV_U_PACKETS }, 53022ee1fcb3Sdlg /* RUPP */ 53032ee1fcb3Sdlg { "rx no dest", 0x00300660, 32, KSTAT_KV_U_PACKETS }, 53042ee1fcb3Sdlg 53052ee1fcb3Sdlg /* GOTC */ 53062ee1fcb3Sdlg { "tx bytes", 0x00300680, 48, KSTAT_KV_U_BYTES }, 53072ee1fcb3Sdlg /* PTC64 */ 53082ee1fcb3Sdlg { "tx 64B", 0x003006A0, 48, KSTAT_KV_U_PACKETS }, 53092ee1fcb3Sdlg /* PTC127 */ 53102ee1fcb3Sdlg { "tx 65-127B", 0x003006C0, 48, KSTAT_KV_U_PACKETS }, 53112ee1fcb3Sdlg /* PTC255 */ 53122ee1fcb3Sdlg { "tx 128-255B", 0x003006E0, 48, KSTAT_KV_U_PACKETS }, 53132ee1fcb3Sdlg /* PTC511 */ 53142ee1fcb3Sdlg { "tx 256-511B", 0x00300700, 48, KSTAT_KV_U_PACKETS }, 53152ee1fcb3Sdlg /* PTC1023 */ 53162ee1fcb3Sdlg { "tx 512-1023B", 0x00300720, 48, KSTAT_KV_U_PACKETS }, 53172ee1fcb3Sdlg /* PTC1522 */ 53182ee1fcb3Sdlg { "tx 1024-1522B", 0x00300740, 48, KSTAT_KV_U_PACKETS }, 53192ee1fcb3Sdlg /* PTC9522 */ 53202ee1fcb3Sdlg { "tx 1523-9522B", 0x00300760, 48, KSTAT_KV_U_PACKETS }, 53212ee1fcb3Sdlg 53222ee1fcb3Sdlg /* Priority XON Transmitted Count */ 53232ee1fcb3Sdlg /* Priority XOFF Transmitted Count */ 53242ee1fcb3Sdlg 53252ee1fcb3Sdlg /* LXONTXC */ 53262ee1fcb3Sdlg { "tx link xon", 0x00300980, 48, KSTAT_KV_U_PACKETS }, 53272ee1fcb3Sdlg /* LXOFFTXC */ 53282ee1fcb3Sdlg { "tx link xoff", 0x003009a0, 48, KSTAT_KV_U_PACKETS }, 53292ee1fcb3Sdlg /* UPTC */ 53302ee1fcb3Sdlg { "tx ucasts", 0x003009c0, 48, KSTAT_KV_U_PACKETS }, 53312ee1fcb3Sdlg /* MPTC */ 53322ee1fcb3Sdlg { "tx mcasts", 0x003009e0, 48, KSTAT_KV_U_PACKETS }, 53332ee1fcb3Sdlg /* BPTC */ 53342ee1fcb3Sdlg { "tx bcasts", 0x00300a00, 48, KSTAT_KV_U_PACKETS }, 53352ee1fcb3Sdlg /* TDOLD */ 53362ee1fcb3Sdlg { "tx link down", 0x00300a20, 48, KSTAT_KV_U_PACKETS }, 53372ee1fcb3Sdlg }; 53382ee1fcb3Sdlg 53392ee1fcb3Sdlg const struct ixl_counter ixl_vsi_counters[] = { 53402ee1fcb3Sdlg /* VSI RDPC */ 53412ee1fcb3Sdlg { "rx discards", 0x00310000, 32, KSTAT_KV_U_PACKETS }, 53422ee1fcb3Sdlg /* VSI GOTC */ 53432ee1fcb3Sdlg { "tx bytes", 0x00328000, 48, KSTAT_KV_U_BYTES }, 53442ee1fcb3Sdlg /* VSI UPTC */ 53452ee1fcb3Sdlg { "tx ucasts", 0x0033c000, 48, KSTAT_KV_U_PACKETS }, 53462ee1fcb3Sdlg /* VSI MPTC */ 53472ee1fcb3Sdlg { "tx mcasts", 0x0033cc00, 48, KSTAT_KV_U_PACKETS }, 53482ee1fcb3Sdlg /* VSI BPTC */ 53492ee1fcb3Sdlg { "tx bcasts", 0x0033d800, 48, KSTAT_KV_U_PACKETS }, 53502ee1fcb3Sdlg /* VSI TEPC */ 53512ee1fcb3Sdlg { "tx errs", 0x00344000, 48, KSTAT_KV_U_PACKETS }, 53522ee1fcb3Sdlg /* VSI TDPC */ 53532ee1fcb3Sdlg { "tx discards", 0x00348000, 48, KSTAT_KV_U_PACKETS }, 53542ee1fcb3Sdlg /* VSI GORC */ 53552ee1fcb3Sdlg { "rx bytes", 0x00358000, 48, KSTAT_KV_U_BYTES }, 53562ee1fcb3Sdlg /* VSI UPRC */ 53572ee1fcb3Sdlg { "rx ucasts", 0x0036c000, 48, KSTAT_KV_U_PACKETS }, 53582ee1fcb3Sdlg /* VSI MPRC */ 53592ee1fcb3Sdlg { "rx mcasts", 0x0036cc00, 48, KSTAT_KV_U_PACKETS }, 53602ee1fcb3Sdlg /* VSI BPRC */ 53612ee1fcb3Sdlg { "rx bcasts", 0x0036d800, 48, KSTAT_KV_U_PACKETS }, 53622ee1fcb3Sdlg /* VSI RUPP */ 53632ee1fcb3Sdlg { "rx noproto", 0x0036e400, 32, KSTAT_KV_U_PACKETS }, 53642ee1fcb3Sdlg }; 53652ee1fcb3Sdlg 53662ee1fcb3Sdlg struct ixl_counter_state { 53672ee1fcb3Sdlg const struct ixl_counter 53682ee1fcb3Sdlg *counters; 53692ee1fcb3Sdlg uint64_t *values; 53702ee1fcb3Sdlg size_t n; 53712ee1fcb3Sdlg uint32_t index; 53722ee1fcb3Sdlg unsigned int gen; 53732ee1fcb3Sdlg }; 53742ee1fcb3Sdlg 53752ee1fcb3Sdlg static void 53762ee1fcb3Sdlg ixl_rd_counters(struct ixl_softc *sc, const struct ixl_counter_state *state, 53772ee1fcb3Sdlg uint64_t *vs) 53782ee1fcb3Sdlg { 53792ee1fcb3Sdlg const struct ixl_counter *c; 53802ee1fcb3Sdlg bus_addr_t r; 53812ee1fcb3Sdlg uint64_t v; 53822ee1fcb3Sdlg size_t i; 53832ee1fcb3Sdlg 53842ee1fcb3Sdlg for (i = 0; i < state->n; i++) { 53852ee1fcb3Sdlg c = &state->counters[i]; 53862ee1fcb3Sdlg 53872ee1fcb3Sdlg r = c->c_base + (state->index * 8); 53882ee1fcb3Sdlg 53892ee1fcb3Sdlg if (c->c_width == 32) 53902ee1fcb3Sdlg v = bus_space_read_4(sc->sc_memt, sc->sc_memh, r); 53912ee1fcb3Sdlg else 53922ee1fcb3Sdlg v = bus_space_read_8(sc->sc_memt, sc->sc_memh, r); 53932ee1fcb3Sdlg 53942ee1fcb3Sdlg vs[i] = v; 53952ee1fcb3Sdlg } 53962ee1fcb3Sdlg } 53972ee1fcb3Sdlg 53982ee1fcb3Sdlg static int 53992ee1fcb3Sdlg ixl_kstat_read(struct kstat *ks) 54002ee1fcb3Sdlg { 54012ee1fcb3Sdlg struct ixl_softc *sc = ks->ks_softc; 54022ee1fcb3Sdlg struct kstat_kv *kvs = ks->ks_data; 54032ee1fcb3Sdlg struct ixl_counter_state *state = ks->ks_ptr; 54042ee1fcb3Sdlg unsigned int gen = (state->gen++) & 1; 54052ee1fcb3Sdlg uint64_t *ovs = state->values + (gen * state->n); 54062ee1fcb3Sdlg uint64_t *nvs = state->values + (!gen * state->n); 54072ee1fcb3Sdlg size_t i; 54082ee1fcb3Sdlg 54092ee1fcb3Sdlg ixl_rd_counters(sc, state, nvs); 54102ee1fcb3Sdlg getnanouptime(&ks->ks_updated); 54112ee1fcb3Sdlg 54122ee1fcb3Sdlg for (i = 0; i < state->n; i++) { 54132ee1fcb3Sdlg const struct ixl_counter *c = &state->counters[i]; 54142ee1fcb3Sdlg uint64_t n = nvs[i], o = ovs[i]; 54152ee1fcb3Sdlg 54162ee1fcb3Sdlg if (c->c_width < 64) { 54172ee1fcb3Sdlg if (n < o) 54182ee1fcb3Sdlg n += (1ULL << c->c_width); 54192ee1fcb3Sdlg } 54202ee1fcb3Sdlg 54212ee1fcb3Sdlg kstat_kv_u64(&kvs[i]) += (n - o); 54222ee1fcb3Sdlg } 54232ee1fcb3Sdlg 54242ee1fcb3Sdlg return (0); 54252ee1fcb3Sdlg } 54262ee1fcb3Sdlg 54272ee1fcb3Sdlg static void 54282ee1fcb3Sdlg ixl_kstat_tick(void *arg) 54292ee1fcb3Sdlg { 54302ee1fcb3Sdlg struct ixl_softc *sc = arg; 54312ee1fcb3Sdlg 54322ee1fcb3Sdlg timeout_add_sec(&sc->sc_kstat_tmo, 4); 54332ee1fcb3Sdlg 5434cd21026bSdlg mtx_enter(&sc->sc_kstat_mtx); 54352ee1fcb3Sdlg 54362ee1fcb3Sdlg ixl_kstat_read(sc->sc_port_kstat); 54372ee1fcb3Sdlg ixl_kstat_read(sc->sc_vsi_kstat); 54382ee1fcb3Sdlg 54392ee1fcb3Sdlg mtx_leave(&sc->sc_kstat_mtx); 54402ee1fcb3Sdlg } 54412ee1fcb3Sdlg 54422ee1fcb3Sdlg static struct kstat * 54432ee1fcb3Sdlg ixl_kstat_create(struct ixl_softc *sc, const char *name, 54442ee1fcb3Sdlg const struct ixl_counter *counters, size_t n, uint32_t index) 54452ee1fcb3Sdlg { 54462ee1fcb3Sdlg struct kstat *ks; 54472ee1fcb3Sdlg struct kstat_kv *kvs; 54482ee1fcb3Sdlg struct ixl_counter_state *state; 54492ee1fcb3Sdlg const struct ixl_counter *c; 54502ee1fcb3Sdlg unsigned int i; 54512ee1fcb3Sdlg 54522ee1fcb3Sdlg ks = kstat_create(DEVNAME(sc), 0, name, 0, KSTAT_T_KV, 0); 54532ee1fcb3Sdlg if (ks == NULL) { 54542ee1fcb3Sdlg /* unable to create kstats */ 54552ee1fcb3Sdlg return (NULL); 54562ee1fcb3Sdlg } 54572ee1fcb3Sdlg 54582ee1fcb3Sdlg kvs = mallocarray(n, sizeof(*kvs), M_DEVBUF, M_WAITOK|M_ZERO); 54592ee1fcb3Sdlg for (i = 0; i < n; i++) { 54602ee1fcb3Sdlg c = &counters[i]; 54612ee1fcb3Sdlg 54622ee1fcb3Sdlg kstat_kv_unit_init(&kvs[i], c->c_name, 54632ee1fcb3Sdlg KSTAT_KV_T_COUNTER64, c->c_type); 54642ee1fcb3Sdlg } 54652ee1fcb3Sdlg 54662ee1fcb3Sdlg ks->ks_data = kvs; 54672ee1fcb3Sdlg ks->ks_datalen = n * sizeof(*kvs); 54682ee1fcb3Sdlg ks->ks_read = ixl_kstat_read; 54692ee1fcb3Sdlg 54702ee1fcb3Sdlg state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK|M_ZERO); 54712ee1fcb3Sdlg state->counters = counters; 54722ee1fcb3Sdlg state->n = n; 54732ee1fcb3Sdlg state->values = mallocarray(n * 2, sizeof(*state->values), 54742ee1fcb3Sdlg M_DEVBUF, M_WAITOK|M_ZERO); 54752ee1fcb3Sdlg state->index = index; 54762ee1fcb3Sdlg ks->ks_ptr = state; 54772ee1fcb3Sdlg 54782ee1fcb3Sdlg kstat_set_mutex(ks, &sc->sc_kstat_mtx); 54792ee1fcb3Sdlg ks->ks_softc = sc; 54802ee1fcb3Sdlg kstat_install(ks); 54812ee1fcb3Sdlg 54822ee1fcb3Sdlg /* fetch a baseline */ 54832ee1fcb3Sdlg ixl_rd_counters(sc, state, state->values); 54842ee1fcb3Sdlg 54852ee1fcb3Sdlg return (ks); 54862ee1fcb3Sdlg } 54872ee1fcb3Sdlg 54882ee1fcb3Sdlg static void 54892ee1fcb3Sdlg ixl_kstat_attach(struct ixl_softc *sc) 54902ee1fcb3Sdlg { 54912ee1fcb3Sdlg mtx_init(&sc->sc_kstat_mtx, IPL_SOFTCLOCK); 54922ee1fcb3Sdlg timeout_set(&sc->sc_kstat_tmo, ixl_kstat_tick, sc); 54932ee1fcb3Sdlg 54942ee1fcb3Sdlg sc->sc_port_kstat = ixl_kstat_create(sc, "ixl-port", 54952ee1fcb3Sdlg ixl_port_counters, nitems(ixl_port_counters), sc->sc_port); 54962ee1fcb3Sdlg sc->sc_vsi_kstat = ixl_kstat_create(sc, "ixl-vsi", 54972ee1fcb3Sdlg ixl_vsi_counters, nitems(ixl_vsi_counters), 54982ee1fcb3Sdlg lemtoh16(&sc->sc_vsi_number)); 54992ee1fcb3Sdlg 55002ee1fcb3Sdlg /* ixl counters go up even when the interface is down */ 55012ee1fcb3Sdlg timeout_add_sec(&sc->sc_kstat_tmo, 4); 55022ee1fcb3Sdlg } 55032ee1fcb3Sdlg 55042ee1fcb3Sdlg #endif /* NKSTAT > 0 */ 5505