From: Stefan Sperling Subject: ifconfig transceiver support for ice(4) To: tech@openbsd.org Date: Fri, 15 Aug 2025 11:43:14 +0200 This patch makes ifconfig ice0 transceiver (as root) display information about inserted transceivers. ok? M sys/dev/pci/if_ice.c | 113+ 0- M sys/dev/pci/if_icevar.h | 2+ 0- 2 files changed, 115 insertions(+), 0 deletions(-) commit - f8d6ec95fb2ba7d8706e3c32ac858af54a306b15 commit + d980c1256612baaf0dc40c0794b3556a724e0bad blob - 16687434ef41bfc3779d7f511b14e64aacc54602 blob + 188a1de7816a1d009d9bdea306227a11654ae3e2 --- sys/dev/pci/if_ice.c +++ sys/dev/pci/if_ice.c @@ -261,6 +261,8 @@ struct ice_intr_vector { #define ICE_MAX_VECTORS 8 /* XXX this is pretty arbitrary */ +static struct rwlock ice_sff_lock = RWLOCK_INITIALIZER("icesff"); + struct ice_softc { struct device sc_dev; struct arpcom sc_ac; @@ -13568,7 +13570,111 @@ ice_down(struct ice_softc *sc) return 0; } +/* Read/Write SFF EEPROM (0x06EE) */ int +ice_aq_sff_eeprom(struct ice_hw *hw, uint16_t lport, uint8_t bus_addr, + uint16_t mem_addr, uint8_t page, uint8_t set_page, uint8_t *data, + uint8_t length, struct ice_sq_cd *cd) +{ + struct ice_aqc_sff_eeprom *cmd; + struct ice_aq_desc desc; + int status; + + if (!data || (mem_addr & 0xff00)) + return ICE_ERR_PARAM; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom); + cmd = &desc.params.read_write_sff_param; + desc.flags = htole16(ICE_AQ_FLAG_RD); + cmd->lport_num = (uint8_t)(lport & 0xff); + cmd->lport_num_valid = (uint8_t)((lport >> 8) & 0x01); + cmd->i2c_bus_addr = htole16( + ((bus_addr >> 1) & ICE_AQC_SFF_I2CBUS_7BIT_M) | + ((set_page << ICE_AQC_SFF_SET_EEPROM_PAGE_S) & + ICE_AQC_SFF_SET_EEPROM_PAGE_M)); + cmd->i2c_mem_addr = htole16(mem_addr & 0xff); + cmd->eeprom_page = htole16((uint16_t)page << ICE_AQC_SFF_EEPROM_PAGE_S); + + status = ice_aq_send_cmd(hw, &desc, data, length, cd); + return status; +} + +/* + * Read from the SFF eeprom. + * The I2C device address is typically 0xA0 or 0xA2. For more details on + * the contents of an SFF eeprom, refer to SFF-8724 (SFP), SFF-8636 (QSFP), + * and SFF-8024 (both). + */ +int +ice_read_sff_eeprom(struct ice_softc *sc, uint16_t dev_addr, uint16_t offset, + uint8_t* data, uint16_t length) +{ + struct ice_hw *hw = &sc->hw; + int ret = 0, retries = 0; + int status; + + if (length > 16) + return (EINVAL); + + if (ice_test_state(&sc->state, ICE_STATE_RECOVERY_MODE)) + return (ENOSYS); + + if (ice_test_state(&sc->state, ICE_STATE_NO_MEDIA)) + return (ENXIO); + + do { + status = ice_aq_sff_eeprom(hw, 0, dev_addr, + offset, 0, 0, data, length, NULL); + if (!status) { + ret = 0; + break; + } + if (status == ICE_ERR_AQ_ERROR && + hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) { + ret = EBUSY; + continue; + } + if (status == ICE_ERR_AQ_ERROR && + hw->adminq.sq_last_status == ICE_AQ_RC_EACCES) { + /* FW says I2C access isn't supported */ + ret = EACCES; + break; + } + if (status == ICE_ERR_AQ_ERROR && + hw->adminq.sq_last_status == ICE_AQ_RC_EPERM) { + ret = EPERM; + break; + } else { + ret = EIO; + break; + } + } while (retries++ < ICE_I2C_MAX_RETRIES); + + return (ret); +} + +int +ice_get_sffpage(struct ice_softc *sc, struct if_sffpage *sff) +{ + const uint16_t chunksize = 16; + uint16_t offset = 0; + int error; + + if (sff->sff_addr != IFSFF_ADDR_EEPROM && + sff->sff_addr != IFSFF_ADDR_DDM) + return (EINVAL); + + for (; offset <= IFSFF_DATA_LEN - chunksize; offset += chunksize) { + error = ice_read_sff_eeprom(sc, sff->sff_addr, offset, + &sff->sff_data[0] + offset, chunksize); + if (error) + return error; + } + + return 0; +} + +int ice_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ice_softc *sc = ifp->if_softc; @@ -13637,6 +13743,13 @@ ice_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } } break; + case SIOCGIFSFFPAGE: + error = rw_enter(&ice_sff_lock, RW_WRITE|RW_INTR); + if (error) + break; + error = ice_get_sffpage(sc, (struct if_sffpage *)data); + rw_exit(&ice_sff_lock); + break; default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; blob - b73c60d9c9575c5ccdb6e9795b8d170fa16d1af3 blob + 6f02d39411437519a5da618307f55fc27765b826 --- sys/dev/pci/if_icevar.h +++ sys/dev/pci/if_icevar.h @@ -4694,3 +4694,5 @@ struct ice_vsi { /* Driver always calls main vsi_handle first */ #define ICE_MAIN_VSI_HANDLE 0 + +#define ICE_I2C_MAX_RETRIES 10