From owner-svn-src-head@freebsd.org Fri May 19 08:24:24 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A58EFD74F3A; Fri, 19 May 2017 08:24:24 +0000 (UTC) (envelope-from wma@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 77E2777F; Fri, 19 May 2017 08:24:24 +0000 (UTC) (envelope-from wma@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4J8ONOx007273; Fri, 19 May 2017 08:24:23 GMT (envelope-from wma@FreeBSD.org) Received: (from wma@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4J8ON6X007271; Fri, 19 May 2017 08:24:23 GMT (envelope-from wma@FreeBSD.org) Message-Id: <201705190824.v4J8ON6X007271@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: wma set sender to wma@FreeBSD.org using -f From: Wojciech Macek Date: Fri, 19 May 2017 08:24:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r318524 - head/sys/dev/etherswitch/e6000sw X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 May 2017 08:24:24 -0000 Author: wma Date: Fri May 19 08:24:23 2017 New Revision: 318524 URL: https://svnweb.freebsd.org/changeset/base/318524 Log: Poll PHY status using internal e6000sw registers e6000sw family automatically reflects PHY status in each port's registers. Therefore it is not necessary to do a full PHY polling squence, which results in much quicker operation and much less significant usage of the SMI bus. Care must be taken that the resulting ifmedia_active is identical to what the PHY will compute, or gratuitous link status changes will occur whenever the PHYs update function is called. This patch implements above improvement. On the occasion set a pointer to the proc structure to be part of software context instead of being a global variable. Submitted by: Marcin Wojtas Obtained from: Semihalf Sponsored by: Stormshield Reviewed by: loos Differential revision: https://reviews.freebsd.org/D10714 Modified: head/sys/dev/etherswitch/e6000sw/e6000sw.c head/sys/dev/etherswitch/e6000sw/e6000swreg.h Modified: head/sys/dev/etherswitch/e6000sw/e6000sw.c ============================================================================== --- head/sys/dev/etherswitch/e6000sw/e6000sw.c Fri May 19 08:19:51 2017 (r318523) +++ head/sys/dev/etherswitch/e6000sw/e6000sw.c Fri May 19 08:24:23 2017 (r318524) @@ -89,7 +89,7 @@ typedef struct e6000sw_softc { char *ifname[E6000SW_MAX_PORTS]; device_t miibus[E6000SW_MAX_PORTS]; struct mii_data *mii[E6000SW_MAX_PORTS]; - struct callout tick_callout; + struct proc *kproc; uint32_t cpuports_mask; uint32_t fixed_mask; @@ -149,8 +149,6 @@ static __inline int e6000sw_is_phyport(e static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *sc, unsigned int phy); -static struct proc *e6000sw_kproc; - static device_method_t e6000sw_methods[] = { /* device interface */ DEVMETHOD(device_identify, e6000sw_identify), @@ -419,8 +417,7 @@ e6000sw_attach(device_t dev) bus_generic_probe(dev); bus_generic_attach(dev); - kproc_create(e6000sw_tick, sc, &e6000sw_kproc, 0, 0, - "e6000sw tick kproc"); + kproc_create(e6000sw_tick, sc, &sc->kproc, 0, 0, "e6000sw tick kproc"); return (0); @@ -1010,23 +1007,65 @@ e6000sw_get_pvid(e6000sw_softc_t *sc, in return (0); } +/* + * Convert port status to ifmedia. + */ +static void +e6000sw_update_ifmedia(uint16_t portstatus, u_int *media_status, u_int *media_active) +{ + *media_active = IFM_ETHER; + *media_status = IFM_AVALID; + + if ((portstatus & PORT_STATUS_LINK_MASK) != 0) + *media_status |= IFM_ACTIVE; + else { + *media_active |= IFM_NONE; + return; + } + + switch (portstatus & PORT_STATUS_SPEED_MASK) { + case PORT_STATUS_SPEED_10: + *media_active |= IFM_10_T; + break; + case PORT_STATUS_SPEED_100: + *media_active |= IFM_100_TX; + break; + case PORT_STATUS_SPEED_1000: + *media_active |= IFM_1000_T; + break; + } + + if ((portstatus & PORT_STATUS_DUPLEX_MASK) == 0) + *media_active |= IFM_FDX; + else + *media_active |= IFM_HDX; +} + static void e6000sw_tick (void *arg) { e6000sw_softc_t *sc; struct mii_softc *miisc; + uint16_t portstatus; int port; sc = arg; E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); + for (;;) { E6000SW_LOCK(sc); for (port = 0; port < sc->num_ports; port++) { /* Tick only on PHY ports */ if (!e6000sw_is_phyport(sc, port)) continue; - mii_tick(sc->mii[port]); + + portstatus = e6000sw_readreg(sc, REG_PORT(port), PORT_STATUS); + + e6000sw_update_ifmedia(portstatus, + &sc->mii[port]->mii_media_status, + &sc->mii[port]->mii_media_active); + LIST_FOREACH(miisc, &sc->mii[port]->mii_phys, mii_list) { if (IFM_INST(sc->mii[port]->mii_media.ifm_cur->ifm_media) != miisc->mii_inst) Modified: head/sys/dev/etherswitch/e6000sw/e6000swreg.h ============================================================================== --- head/sys/dev/etherswitch/e6000sw/e6000swreg.h Fri May 19 08:19:51 2017 (r318523) +++ head/sys/dev/etherswitch/e6000sw/e6000swreg.h Fri May 19 08:24:23 2017 (r318524) @@ -55,6 +55,14 @@ struct atu_opt { * Per-Port Switch Registers */ #define PORT_STATUS 0x0 +#define PORT_STATUS_SPEED_MASK 0x300 +#define PORT_STATUS_SPEED_10 0 +#define PORT_STATUS_SPEED_100 1 +#define PORT_STATUS_SPEED_1000 2 +#define PORT_STATUS_DUPLEX_MASK (1 << 10) +#define PORT_STATUS_LINK_MASK (1 << 11) +#define PORT_STATUS_PHY_DETECT_MASK (1 << 12) + #define PSC_CONTROL 0x1 #define SWITCH_ID 0x3 #define PORT_CONTROL 0x4