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