diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2019-04-10 09:55:03 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2019-04-10 09:55:03 +0000 |
commit | ede166c3581794ee7e7d568b025363fd37c6046d (patch) | |
tree | 77f14f05619b39a01c603d681ec09a92ceb2336f /sys/dev | |
parent | 579c07513bb9e4718897ec05bd7bc43dff9b9d31 (diff) |
add support for SIOCGIFSFFPAGE so userland can read sfp module info
access to the ioctl is serialised by a per ifp rwlock so userland
reads of different pages in the same device address do not confuse
each other.
this was pretty straightforward because a lot of the plumbing for
accessing the i2c bus was already in place.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_ix.c | 58 | ||||
-rw-r--r-- | sys/dev/pci/if_ix.h | 3 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_type.h | 6 |
3 files changed, 64 insertions, 3 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index c8cef1c6390..e29fc0aa07f 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ix.c,v 1.156 2019/03/01 06:15:59 dlg Exp $ */ +/* $OpenBSD: if_ix.c,v 1.157 2019/04/10 09:55:02 dlg Exp $ */ /****************************************************************************** @@ -96,6 +96,7 @@ int ixgbe_detach(struct device *, int); void ixgbe_start(struct ifqueue *); int ixgbe_ioctl(struct ifnet *, u_long, caddr_t); int ixgbe_rxrinfo(struct ix_softc *, struct if_rxrinfo *); +int ixgbe_get_sffpage(struct ix_softc *, struct if_sffpage *); void ixgbe_watchdog(struct ifnet *); void ixgbe_init(void *); void ixgbe_stop(void *); @@ -225,6 +226,8 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux) sc->osdep.os_sc = sc; sc->osdep.os_pa = *pa; + rw_init(&sc->sfflock, "ixsff"); + /* Set up the timer callout */ timeout_set(&sc->timer, ixgbe_local_timer, sc); timeout_set(&sc->rx_refill, ixgbe_rxrefill, sc); @@ -498,6 +501,15 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) error = ixgbe_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data); break; + case SIOCGIFSFFPAGE: + error = rw_enter(&sc->sfflock, RW_WRITE|RW_INTR); + if (error != 0) + break; + + error = ixgbe_get_sffpage(sc, (struct if_sffpage *)data); + rw_exit(&sc->sfflock); + break; + default: error = ether_ioctl(ifp, &sc->arpcom, command, data); } @@ -516,6 +528,50 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) } int +ixgbe_get_sffpage(struct ix_softc *sc, struct if_sffpage *sff) +{ + struct ixgbe_hw *hw = &sc->hw; + uint32_t swfw_mask = hw->phy.phy_semaphore_mask; + uint8_t page; + size_t i; + int error = EIO; + + if (hw->phy.type == ixgbe_phy_fw) + return (ENODEV); + + if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) + return (EBUSY); /* XXX */ + + if (sff->sff_addr == IFSFF_ADDR_EEPROM) { + if (hw->phy.ops.read_i2c_byte_unlocked(hw, 127, + IFSFF_ADDR_EEPROM, &page)) + goto error; + if (page != sff->sff_page && + hw->phy.ops.write_i2c_byte_unlocked(hw, 127, + IFSFF_ADDR_EEPROM, sff->sff_page)) + goto error; + } + + for (i = 0; i < sizeof(sff->sff_data); i++) { + if (hw->phy.ops.read_i2c_byte_unlocked(hw, i, + sff->sff_addr, &sff->sff_data[i])) + goto error; + } + + if (sff->sff_addr == IFSFF_ADDR_EEPROM) { + if (page != sff->sff_page && + hw->phy.ops.write_i2c_byte_unlocked(hw, 127, + IFSFF_ADDR_EEPROM, page)) + goto error; + } + + error = 0; +error: + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + return (error); +} + +int ixgbe_rxrinfo(struct ix_softc *sc, struct if_rxrinfo *ifri) { struct if_rxring_info *ifr, ifr1; diff --git a/sys/dev/pci/if_ix.h b/sys/dev/pci/if_ix.h index fff1967133b..753a2bfb78a 100644 --- a/sys/dev/pci/if_ix.h +++ b/sys/dev/pci/if_ix.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ix.h,v 1.33 2019/02/21 03:16:47 dlg Exp $ */ +/* $OpenBSD: if_ix.h,v 1.34 2019/04/10 09:55:02 dlg Exp $ */ /****************************************************************************** @@ -251,6 +251,7 @@ struct ix_softc { uint32_t link_speed; bool link_up; uint32_t linkvec; + struct rwlock sfflock; /* Mbuf cluster size */ uint32_t rx_mbuf_sz; diff --git a/sys/dev/pci/ixgbe_type.h b/sys/dev/pci/ixgbe_type.h index aeea522f457..ce851315392 100644 --- a/sys/dev/pci/ixgbe_type.h +++ b/sys/dev/pci/ixgbe_type.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe_type.h,v 1.31 2016/11/18 14:16:10 mikeb Exp $ */ +/* $OpenBSD: ixgbe_type.h,v 1.32 2019/04/10 09:55:02 dlg Exp $ */ /****************************************************************************** @@ -3142,7 +3142,9 @@ enum ixgbe_phy_type { ixgbe_phy_aq, ixgbe_phy_x550em_kr, ixgbe_phy_x550em_kx4, + ixgbe_phy_x550em_xfi, ixgbe_phy_x550em_ext_t, + ixgbe_phy_ext_1g_t, ixgbe_phy_cu_unknown, ixgbe_phy_qt, ixgbe_phy_xaui, @@ -3160,6 +3162,8 @@ enum ixgbe_phy_type { ixgbe_phy_qsfp_intel, ixgbe_phy_qsfp_unknown, ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/ + ixgbe_phy_sgmii, + ixgbe_phy_fw, ixgbe_phy_generic }; |