Module Name: src Committed By: yamaguchi Date: Fri Jan 17 09:42:05 UTC 2020
Modified Files: src/sys/dev/pci: if_ixl.c if_ixlvar.h Log Message: Print nvm version of ixl(4) when attaching reviewed by msaitoh To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.26 src/sys/dev/pci/if_ixl.c cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/if_ixlvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_ixl.c diff -u src/sys/dev/pci/if_ixl.c:1.25 src/sys/dev/pci/if_ixl.c:1.26 --- src/sys/dev/pci/if_ixl.c:1.25 Fri Jan 17 09:37:42 2020 +++ src/sys/dev/pci/if_ixl.c Fri Jan 17 09:42:05 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ixl.c,v 1.25 2020/01/17 09:37:42 yamaguchi Exp $ */ +/* $NetBSD: if_ixl.c,v 1.26 2020/01/17 09:42:05 yamaguchi Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -198,6 +198,8 @@ struct ixl_softc; /* defined */ #define IXL_ATQ_EXEC_TIMEOUT (10 * hz) +#define IXL_SRRD_SRCTL_ATTEMPTS 100000 + struct ixl_aq_regs { bus_size_t atq_tail; bus_size_t atq_head; @@ -653,11 +655,14 @@ struct ixl_softc { unsigned int sc_msix_vector_queue; struct ixl_dmamem sc_scratch; + struct ixl_dmamem sc_aqbuf; const struct ixl_aq_regs * sc_aq_regs; uint32_t sc_aq_flags; #define IXL_SC_AQ_FLAG_RXCTL __BIT(0) +#define IXL_SC_AQ_FLAG_NVMLOCK __BIT(1) +#define IXL_SC_AQ_FLAG_NVMREAD __BIT(2) kmutex_t sc_atq_lock; kcondvar_t sc_atq_cv; @@ -753,6 +758,7 @@ static int ixl_atq_post_locked(struct ix static void ixl_atq_done(struct ixl_softc *); static int ixl_atq_exec(struct ixl_softc *, struct ixl_atq *); static int ixl_get_version(struct ixl_softc *); +static int ixl_get_nvm_version(struct ixl_softc *); static int ixl_get_hw_capabilities(struct ixl_softc *); static int ixl_pxe_clear(struct ixl_softc *); static int ixl_lldp_shut(struct ixl_softc *); @@ -780,6 +786,7 @@ static void ixl_hmc_pack(void *, const v const struct ixl_hmc_pack *, unsigned int); static uint32_t ixl_rd_rx_csr(struct ixl_softc *, uint32_t); static void ixl_wr_rx_csr(struct ixl_softc *, uint32_t, uint32_t); +static int ixl_rd16_nvm(struct ixl_softc *, uint16_t, uint16_t *); static int ixl_match(device_t, cfdata_t, void *); static void ixl_attach(device_t, device_t, void *); @@ -1176,6 +1183,13 @@ ixl_attach(device_t parent, device_t sel ixl_wr(sc, sc->sc_aq_regs->arq_tail, sc->sc_arq_prod); + if (ixl_dmamem_alloc(sc, &sc->sc_aqbuf, IXL_AQ_BUFLEN, 0) != 0) { + aprint_error_dev(self, ", unable to allocate nvm buffer\n"); + goto shutdown; + } + + ixl_get_nvm_version(sc); + if (sc->sc_mac_type == I40E_MAC_X722) sc->sc_nqueue_pairs_device = 128; else @@ -1185,7 +1199,7 @@ ixl_attach(device_t parent, device_t sel if (rv != 0) { aprint_error(", GET HW CAPABILITIES %s\n", rv == ETIMEDOUT ? "timeout" : "error"); - goto shutdown; + goto free_aqbuf; } sc->sc_nqueue_pairs_max = MIN((int)sc->sc_nqueue_pairs_device, ncpu); @@ -1203,7 +1217,7 @@ ixl_attach(device_t parent, device_t sel if (ixl_get_mac(sc) != 0) { /* error printed by ixl_get_mac */ - goto shutdown; + goto free_aqbuf; } aprint_normal("\n"); @@ -1222,7 +1236,7 @@ ixl_attach(device_t parent, device_t sel if (ixl_hmc(sc) != 0) { /* error printed by ixl_hmc */ - goto shutdown; + goto free_aqbuf; } if (ixl_lldp_shut(sc) != 0) { @@ -1408,6 +1422,8 @@ free_scratch: ixl_dmamem_free(sc, &sc->sc_scratch); free_hmc: ixl_hmc_free(sc); +free_aqbuf: + ixl_dmamem_free(sc, &sc->sc_aqbuf); shutdown: ixl_wr(sc, sc->sc_aq_regs->atq_head, 0); ixl_wr(sc, sc->sc_aq_regs->arq_head, 0); @@ -1514,6 +1530,7 @@ ixl_detach(device_t self, int flags) ixl_dmamem_free(sc, &sc->sc_arq); ixl_dmamem_free(sc, &sc->sc_atq); + ixl_dmamem_free(sc, &sc->sc_aqbuf); cv_destroy(&sc->sc_atq_cv); mutex_destroy(&sc->sc_atq_lock); @@ -3789,11 +3806,17 @@ ixl_get_version(struct ixl_softc *sc) aprint_normal(", FW %hu.%hu.%05u API %hu.%hu", (uint16_t)fwver, (uint16_t)(fwver >> 16), fwbuild, api_maj_ver, api_min_ver); + if (sc->sc_mac_type == I40E_MAC_X722) { + SET(sc->sc_aq_flags, IXL_SC_AQ_FLAG_NVMLOCK | + IXL_SC_AQ_FLAG_NVMREAD); + } + #define IXL_API_VER(maj, min) (((uint32_t)(maj) << 16) | (min)) if (IXL_API_VER(api_maj_ver, api_min_ver) >= IXL_API_VER(1, 5)) { if (sc->sc_mac_type == I40E_MAC_X722) { SET(sc->sc_aq_flags, IXL_SC_AQ_FLAG_RXCTL); } + SET(sc->sc_aq_flags, IXL_SC_AQ_FLAG_NVMLOCK); } #undef IXL_API_VER @@ -3801,6 +3824,37 @@ ixl_get_version(struct ixl_softc *sc) } static int +ixl_get_nvm_version(struct ixl_softc *sc) +{ + uint16_t nvmver, cfg_ptr, eetrack_hi, eetrack_lo, oem_hi, oem_lo; + uint32_t eetrack, oem; + uint16_t nvm_maj_ver, nvm_min_ver, oem_build; + uint8_t oem_ver, oem_patch; + + nvmver = cfg_ptr = eetrack_hi = eetrack_lo = oem_hi = oem_lo = 0; + ixl_rd16_nvm(sc, I40E_SR_NVM_DEV_STARTER_VERSION, &nvmver); + ixl_rd16_nvm(sc, I40E_SR_NVM_EETRACK_HI, &eetrack_hi); + ixl_rd16_nvm(sc, I40E_SR_NVM_EETRACK_LO, &eetrack_lo); + ixl_rd16_nvm(sc, I40E_SR_BOOT_CONFIG_PTR, &cfg_ptr); + ixl_rd16_nvm(sc, cfg_ptr + I40E_NVM_OEM_VER_OFF, &oem_hi); + ixl_rd16_nvm(sc, cfg_ptr + I40E_NVM_OEM_VER_OFF + 1, &oem_lo); + + nvm_maj_ver = (uint16_t)__SHIFTOUT(nvmver, IXL_NVM_VERSION_HI_MASK); + nvm_min_ver = (uint16_t)__SHIFTOUT(nvmver, IXL_NVM_VERSION_LO_MASK); + eetrack = ((uint32_t)eetrack_hi << 16) | eetrack_lo; + oem = ((uint32_t)oem_hi << 16) | oem_lo; + oem_ver = __SHIFTOUT(oem, IXL_NVM_OEMVERSION_MASK); + oem_build = __SHIFTOUT(oem, IXL_NVM_OEMBUILD_MASK); + oem_patch = __SHIFTOUT(oem, IXL_NVM_OEMPATCH_MASK); + + aprint_normal(" nvm %x.%02x etid %08x oem %d.%d.%d", + nvm_maj_ver, nvm_min_ver, eetrack, + oem_ver, oem_build, oem_patch); + + return 0; +} + +static int ixl_pxe_clear(struct ixl_softc *sc) { struct ixl_aq_desc iaq; @@ -6344,6 +6398,208 @@ ixl_wr_rx_csr(struct ixl_softc *sc, uint ixl_wr(sc, reg, value); } +static int +ixl_nvm_lock(struct ixl_softc *sc, char rw) +{ + struct ixl_aq_desc iaq; + struct ixl_aq_req_resource_param *param; + int rv; + + if (!ISSET(sc->sc_aq_flags, IXL_SC_AQ_FLAG_NVMLOCK)) + return 0; + + memset(&iaq, 0, sizeof(iaq)); + iaq.iaq_opcode = htole16(IXL_AQ_OP_REQUEST_RESOURCE); + + param = (struct ixl_aq_req_resource_param *)&iaq.iaq_param; + param->resource_id = htole16(IXL_AQ_RESOURCE_ID_NVM); + if (rw == 'R') { + param->access_type = htole16(IXL_AQ_RESOURCE_ACCES_READ); + } else { + param->access_type = htole16(IXL_AQ_RESOURCE_ACCES_WRITE); + } + + rv = ixl_atq_poll(sc, &iaq, 250); + + if (rv != 0) + return ETIMEDOUT; + + switch (le16toh(iaq.iaq_retval)) { + case IXL_AQ_RC_OK: + break; + case IXL_AQ_RC_EACCES: + return EACCES; + case IXL_AQ_RC_EBUSY: + return EBUSY; + case IXL_AQ_RC_EPERM: + return EPERM; + } + + return 0; +} + +static int +ixl_nvm_unlock(struct ixl_softc *sc) +{ + struct ixl_aq_desc iaq; + struct ixl_aq_rel_resource_param *param; + int rv; + + if (!ISSET(sc->sc_aq_flags, IXL_SC_AQ_FLAG_NVMLOCK)) + return 0; + + memset(&iaq, 0, sizeof(iaq)); + iaq.iaq_opcode = htole16(IXL_AQ_OP_RELEASE_RESOURCE); + + param = (struct ixl_aq_rel_resource_param *)&iaq.iaq_param; + param->resource_id = htole16(IXL_AQ_RESOURCE_ID_NVM); + + rv = ixl_atq_poll(sc, &iaq, 250); + + if (rv != 0) + return ETIMEDOUT; + + switch (le16toh(iaq.iaq_retval)) { + case IXL_AQ_RC_OK: + break; + default: + return EIO; + } + return 0; +} + +static int +ixl_srdone_poll(struct ixl_softc *sc) +{ + int wait_count; + uint32_t reg; + + for (wait_count = 0; wait_count < IXL_SRRD_SRCTL_ATTEMPTS; + wait_count++) { + reg = ixl_rd(sc, I40E_GLNVM_SRCTL); + if (ISSET(reg, I40E_GLNVM_SRCTL_DONE_MASK)) + break; + + delaymsec(5); + } + + if (wait_count == IXL_SRRD_SRCTL_ATTEMPTS) + return -1; + + return 0; +} + +static int +ixl_nvm_read_srctl(struct ixl_softc *sc, uint16_t offset, uint16_t *data) +{ + uint32_t reg; + + if (ixl_srdone_poll(sc) != 0) + return ETIMEDOUT; + + reg = ((uint32_t)offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) | + __BIT(I40E_GLNVM_SRCTL_START_SHIFT); + ixl_wr(sc, I40E_GLNVM_SRCTL, reg); + + if (ixl_srdone_poll(sc) != 0) { + aprint_debug("NVM read error: couldn't access " + "Shadow RAM address: 0x%x\n", offset); + return ETIMEDOUT; + } + + reg = ixl_rd(sc, I40E_GLNVM_SRDATA); + *data = (uint16_t)__SHIFTOUT(reg, I40E_GLNVM_SRDATA_RDDATA_MASK); + + return 0; +} + +static int +ixl_nvm_read_aq(struct ixl_softc *sc, uint16_t offset_word, + void *data, size_t len) +{ + struct ixl_dmamem *idm; + struct ixl_aq_desc iaq; + struct ixl_aq_nvm_param *param; + uint32_t offset_bytes; + int rv; + + idm = &sc->sc_aqbuf; + if (len > IXL_DMA_LEN(idm)) + return ENOMEM; + + memset(IXL_DMA_KVA(idm), 0, IXL_DMA_LEN(idm)); + memset(&iaq, 0, sizeof(iaq)); + iaq.iaq_opcode = htole16(IXL_AQ_OP_NVM_READ); + iaq.iaq_flags = htole16(IXL_AQ_BUF | + ((len > I40E_AQ_LARGE_BUF) ? IXL_AQ_LB : 0)); + iaq.iaq_datalen = htole16(len); + ixl_aq_dva(&iaq, IXL_DMA_DVA(idm)); + + param = (struct ixl_aq_nvm_param *)iaq.iaq_param; + param->command_flags = IXL_AQ_NVM_LAST_CMD; + param->module_pointer = 0; + param->length = htole16(len); + offset_bytes = (uint32_t)offset_word * 2; + offset_bytes &= 0x00FFFFFF; + param->offset = htole32(offset_bytes); + + bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(idm), 0, IXL_DMA_LEN(idm), + BUS_DMASYNC_PREREAD); + + rv = ixl_atq_poll(sc, &iaq, 250); + + bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(idm), 0, IXL_DMA_LEN(idm), + BUS_DMASYNC_POSTREAD); + + if (rv != 0) { + return ETIMEDOUT; + } + + switch (le16toh(iaq.iaq_retval)) { + case IXL_AQ_RC_OK: + break; + case IXL_AQ_RC_EPERM: + return EPERM; + case IXL_AQ_RC_EINVAL: + return EINVAL; + case IXL_AQ_RC_EBUSY: + return EBUSY; + case IXL_AQ_RC_EIO: + default: + return EIO; + } + + memcpy(data, IXL_DMA_KVA(idm), len); + + return 0; +} + +static int +ixl_rd16_nvm(struct ixl_softc *sc, uint16_t offset, uint16_t *data) +{ + int error; + uint16_t buf; + + error = ixl_nvm_lock(sc, 'R'); + if (error) + return error; + + if (ISSET(sc->sc_aq_flags, IXL_SC_AQ_FLAG_NVMREAD)) { + error = ixl_nvm_read_aq(sc, offset, + &buf, sizeof(buf)); + if (error == 0) + *data = le16toh(buf); + } else { + error = ixl_nvm_read_srctl(sc, offset, &buf); + if (error == 0) + *data = buf; + } + + ixl_nvm_unlock(sc); + + return error; +} + MODULE(MODULE_CLASS_DRIVER, if_ixl, "pci"); #ifdef _MODULE Index: src/sys/dev/pci/if_ixlvar.h diff -u src/sys/dev/pci/if_ixlvar.h:1.3 src/sys/dev/pci/if_ixlvar.h:1.4 --- src/sys/dev/pci/if_ixlvar.h:1.3 Thu Dec 26 03:17:01 2019 +++ src/sys/dev/pci/if_ixlvar.h Fri Jan 17 09:42:05 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ixlvar.h,v 1.3 2019/12/26 03:17:01 yamaguchi Exp $ */ +/* $NetBSD: if_ixlvar.h,v 1.4 2020/01/17 09:42:05 yamaguchi Exp $ */ /* * Copyright (c) 2019 Internet Initiative Japan, Inc. @@ -129,6 +129,7 @@ struct ixl_aq_desc { #define IXL_AQ_OP_PHY_SET_EVENT_MASK 0x0613 #define IXL_AQ_OP_PHY_SET_REGISTER 0x0628 #define IXL_AQ_OP_PHY_GET_REGISTER 0x0629 +#define IXL_AQ_OP_NVM_READ 0x0701 #define IXL_AQ_OP_LLDP_GET_MIB 0x0a00 #define IXL_AQ_OP_LLDP_MIB_CHG_EV 0x0a01 #define IXL_AQ_OP_LLDP_ADD_TLV 0x0a02 @@ -656,6 +657,39 @@ struct ixl_aq_link_status { /* this occu #define IXL_AQ_PHY_EV_MODULE_QUAL_FAIL (1 << 8) #define IXL_AQ_PHY_EV_PORT_TX_SUSPENDED (1 << 9) +struct ixl_aq_req_resource_param { + uint16_t resource_id; +#define IXL_AQ_RESOURCE_ID_NVM 0x0001 +#define IXL_AQ_RESOURCE_ID_SDP 0x0002 + + uint16_t access_type; +#define IXL_AQ_RESOURCE_ACCES_READ 0x01 +#define IXL_AQ_RESOURCE_ACCES_WRITE 0x02 + + uint16_t timeout; + uint32_t resource_num; + uint32_t reserved; +} __packed __aligned(8); + +struct ixl_aq_rel_resource_param { + uint16_t resource_id; +/* defined in ixl_aq_req_resource_param */ + uint16_t _reserved1[3]; + uint32_t resource_num; + uint32_t _reserved2; +} __packed __aligned(8); + +struct ixl_aq_nvm_param { + uint8_t command_flags; +#define IXL_AQ_NVM_LAST_CMD (1 << 0) +#define IXL_AQ_NVM_FLASH_ONLY (1 << 7) + uint8_t module_pointer; + uint16_t length; + uint32_t offset; + uint32_t addr_hi; + uint32_t addr_lo; +} __packed __aligned(4); + /* aq response codes */ #define IXL_AQ_RC_OK 0 /* success */ #define IXL_AQ_RC_EPERM 1 /* Operation not permitted */ @@ -819,4 +853,20 @@ enum i40e_mac_type { I40E_MAC_GENERIC }; +#define I40E_SR_NVM_DEV_STARTER_VERSION 0x18 +#define I40E_SR_BOOT_CONFIG_PTR 0x17 +#define I40E_NVM_OEM_VER_OFF 0x83 +#define I40E_SR_NVM_EETRACK_LO 0x2D +#define I40E_SR_NVM_EETRACK_HI 0x2E + +#define IXL_NVM_VERSION_LO_SHIFT 0 +#define IXL_NVM_VERSION_LO_MASK (0xffUL << IXL_NVM_VERSION_LO_SHIFT) +#define IXL_NVM_VERSION_HI_SHIFT 12 +#define IXL_NVM_VERSION_HI_MASK (0xfUL << IXL_NVM_VERSION_HI_SHIFT) +#define IXL_NVM_OEMVERSION_SHIFT 24 +#define IXL_NVM_OEMVERSION_MASK (0xffUL << IXL_NVM_OEMVERSION_SHIFT) +#define IXL_NVM_OEMBUILD_SHIFT 8 +#define IXL_NVM_OEMBUILD_MASK (0xffffUL << IXL_NVM_OEMBUILD_SHIFT) +#define IXL_NVM_OEMPATCH_SHIFT 0 +#define IXL_NVM_OEMPATCH_MASK (0xff << IXL_NVM_OEMPATCH_SHIFT) #endif