From owner-svn-src-head@freebsd.org Thu Aug 4 17:45:37 2016 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 81B09BAD615; Thu, 4 Aug 2016 17:45:37 +0000 (UTC) (envelope-from adrian@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 433881469; Thu, 4 Aug 2016 17:45:37 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u74HjaPU036193; Thu, 4 Aug 2016 17:45:36 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u74HjaHA036188; Thu, 4 Aug 2016 17:45:36 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201608041745.u74HjaHA036188@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Thu, 4 Aug 2016 17:45:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r303751 - in head/sys/dev/etherswitch: . arswitch 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.22 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: Thu, 04 Aug 2016 17:45:37 -0000 Author: adrian Date: Thu Aug 4 17:45:35 2016 New Revision: 303751 URL: https://svnweb.freebsd.org/changeset/base/303751 Log: [etherswitch] add in an initial API for controlling per-port LED behaviour. This is just implemented for the AR8327 for now. Submitted by: Dan Nelson Modified: head/sys/dev/etherswitch/arswitch/arswitch.c head/sys/dev/etherswitch/arswitch/arswitch_8327.c head/sys/dev/etherswitch/arswitch/arswitch_8327.h head/sys/dev/etherswitch/arswitch/arswitchvar.h head/sys/dev/etherswitch/etherswitch.h Modified: head/sys/dev/etherswitch/arswitch/arswitch.c ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch.c Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitch.c Thu Aug 4 17:45:35 2016 (r303751) @@ -77,6 +77,14 @@ static SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch"); #endif +/* Map ETHERSWITCH_PORT_LED_* to Atheros pattern codes */ +static int led_pattern_table[] = { + [ETHERSWITCH_PORT_LED_DEFAULT] = 0x3, + [ETHERSWITCH_PORT_LED_ON] = 0x2, + [ETHERSWITCH_PORT_LED_OFF] = 0x0, + [ETHERSWITCH_PORT_LED_BLINK] = 0x1 +}; + static inline int arswitch_portforphy(int phy); static void arswitch_tick(void *arg); static int arswitch_ifmedia_upd(struct ifnet *); @@ -85,6 +93,8 @@ static int ar8xxx_port_vlan_setup(struct etherswitch_port_t *p); static int ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p); +static int arswitch_setled(struct arswitch_softc *sc, int phy, int led, + int style); static int arswitch_probe(device_t dev) @@ -188,9 +198,23 @@ arswitch_attach_phys(struct arswitch_sof device_printf(sc->sc_dev, "attaching PHY %d failed\n", phy); + return (err); + } + + if (AR8X16_IS_SWITCH(sc, AR8327)) { + int led; + char ledname[IFNAMSIZ+4]; + + for (led = 0; led < 3; led++) { + sprintf(ledname, "%s%dled%d", name, + arswitch_portforphy(phy), led+1); + sc->dev_led[phy][led].sc = sc; + sc->dev_led[phy][led].phy = phy; + sc->dev_led[phy][led].lednum = led; + } } } - return (err); + return (0); } static int @@ -683,6 +707,38 @@ arswitch_getport(device_t dev, etherswit } else { return (ENXIO); } + + if (!arswitch_is_cpuport(sc, p->es_port) && + AR8X16_IS_SWITCH(sc, AR8327)) { + int led; + p->es_nleds = 3; + + for (led = 0; led < p->es_nleds; led++) + { + int style; + uint32_t val; + + /* Find the right style enum for our pattern */ + val = arswitch_readreg(dev, + ar8327_led_mapping[p->es_port-1][led].reg); + val = (val>>ar8327_led_mapping[p->es_port-1][led].shift)&0x03; + + for (style = 0; style < ETHERSWITCH_PORT_LED_MAX; style++) + { + if (led_pattern_table[style] == val) break; + } + + /* can't happen */ + if (style == ETHERSWITCH_PORT_LED_MAX) + style = ETHERSWITCH_PORT_LED_DEFAULT; + + p->es_led[led] = style; + } + } else + { + p->es_nleds = 0; + } + return (0); } @@ -727,7 +783,7 @@ ar8xxx_port_vlan_setup(struct arswitch_s static int arswitch_setport(device_t dev, etherswitch_port_t *p) { - int err; + int err, i; struct arswitch_softc *sc; struct ifmedia *ifm; struct mii_data *mii; @@ -744,9 +800,20 @@ arswitch_setport(device_t dev, etherswit return (err); } - /* Do not allow media changes on CPU port. */ + /* Do not allow media or led changes on CPU port. */ if (arswitch_is_cpuport(sc, p->es_port)) return (0); + + if (AR8X16_IS_SWITCH(sc, AR8327)) + { + for (i = 0; i < 3; i++) + { + int err; + err = arswitch_setled(sc, p->es_port-1, i, p->es_led[i]); + if (err) + return (err); + } + } mii = arswitch_miiforport(sc, p->es_port); if (mii == NULL) @@ -758,6 +825,23 @@ arswitch_setport(device_t dev, etherswit return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA)); } +static int +arswitch_setled(struct arswitch_softc *sc, int phy, int led, int style) +{ + int shift; + + if (phy < 0 || phy > sc->numphys) + return EINVAL; + + if (style < 0 || style > ETHERSWITCH_PORT_LED_MAX) + return (EINVAL); + + shift = ar8327_led_mapping[phy][led].shift; + return (arswitch_modifyreg(sc->sc_dev, + ar8327_led_mapping[phy][led].reg, + 0x03 << shift, led_pattern_table[style] << shift)); +} + static void arswitch_statchg(device_t dev) { Modified: head/sys/dev/etherswitch/arswitch/arswitch_8327.c ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch_8327.c Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitch_8327.c Thu Aug 4 17:45:35 2016 (r303751) @@ -75,6 +75,36 @@ * lead to traffic storms/loops. */ +/* Map port+led to register+shift */ +struct ar8327_led_mapping ar8327_led_mapping[AR8327_NUM_PHYS][ETHERSWITCH_PORT_MAX_LEDS] = +{ + { /* PHY0 */ + {AR8327_REG_LED_CTRL0, 14 }, + {AR8327_REG_LED_CTRL1, 14 }, + {AR8327_REG_LED_CTRL2, 14 } + }, + { /* PHY1 */ + {AR8327_REG_LED_CTRL3, 8 }, + {AR8327_REG_LED_CTRL3, 10 }, + {AR8327_REG_LED_CTRL3, 12 } + }, + { /* PHY2 */ + {AR8327_REG_LED_CTRL3, 14 }, + {AR8327_REG_LED_CTRL3, 16 }, + {AR8327_REG_LED_CTRL3, 18 } + }, + { /* PHY3 */ + {AR8327_REG_LED_CTRL3, 20 }, + {AR8327_REG_LED_CTRL3, 22 }, + {AR8327_REG_LED_CTRL3, 24 } + }, + { /* PHY4 */ + {AR8327_REG_LED_CTRL0, 30 }, + {AR8327_REG_LED_CTRL1, 30 }, + {AR8327_REG_LED_CTRL2, 30 } + } +}; + static int ar8327_vlan_op(struct arswitch_softc *sc, uint32_t op, uint32_t vid, uint32_t data) Modified: head/sys/dev/etherswitch/arswitch/arswitch_8327.h ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch_8327.h Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitch_8327.h Thu Aug 4 17:45:35 2016 (r303751) @@ -85,6 +85,11 @@ struct ar8327_port_cfg { uint32_t rxpause; }; +extern struct ar8327_led_mapping { + int reg; + int shift; +} ar8327_led_mapping[AR8327_NUM_PHYS][ETHERSWITCH_PORT_MAX_LEDS]; + extern void ar8327_attach(struct arswitch_softc *sc); #endif /* __ARSWITCH_8327_H__ */ Modified: head/sys/dev/etherswitch/arswitch/arswitchvar.h ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitchvar.h Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitchvar.h Thu Aug 4 17:45:35 2016 (r303751) @@ -48,6 +48,15 @@ typedef enum { #define ARSWITCH_NUM_PORTS MAX(AR8327_NUM_PORTS, AR8X16_NUM_PORTS) #define ARSWITCH_NUM_PHYS MAX(AR8327_NUM_PHYS, AR8X16_NUM_PHYS) +#define ARSWITCH_NUM_LEDS 3 + +struct arswitch_dev_led { + struct arswitch_softc *sc; + struct cdev *led; + int phy; + int lednum; +}; + struct arswitch_softc { struct mtx sc_mtx; /* serialize access to softc */ device_t sc_dev; @@ -66,6 +75,7 @@ struct arswitch_softc { char *ifname[ARSWITCH_NUM_PHYS]; device_t miibus[ARSWITCH_NUM_PHYS]; struct ifnet *ifp[ARSWITCH_NUM_PHYS]; + struct arswitch_dev_led dev_led[ARSWITCH_NUM_PHYS][ARSWITCH_NUM_LEDS]; struct callout callout_tick; etherswitch_info_t info; Modified: head/sys/dev/etherswitch/etherswitch.h ============================================================================== --- head/sys/dev/etherswitch/etherswitch.h Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/etherswitch.h Thu Aug 4 17:45:35 2016 (r303751) @@ -14,7 +14,7 @@ extern driver_t etherswitch_driv struct etherswitch_reg { uint16_t reg; - uint16_t val; + uint32_t val; }; typedef struct etherswitch_reg etherswitch_reg_t; @@ -64,10 +64,23 @@ typedef struct etherswitch_conf etherswi #define ETHERSWITCH_PORT_FLAGS_BITS \ "\020\1CPUPORT\2STRIPTAG\3ADDTAG\4FIRSTLOCK\5DROPUNTAGGED\6QinQ\7INGRESS" +#define ETHERSWITCH_PORT_MAX_LEDS 3 + +enum etherswitch_port_led { + ETHERSWITCH_PORT_LED_DEFAULT, + ETHERSWITCH_PORT_LED_ON, + ETHERSWITCH_PORT_LED_OFF, + ETHERSWITCH_PORT_LED_BLINK, + ETHERSWITCH_PORT_LED_MAX +}; +typedef enum etherswitch_port_led etherswitch_port_led_t; + struct etherswitch_port { int es_port; int es_pvid; + int es_nleds; uint32_t es_flags; + etherswitch_port_led_t es_led[ETHERSWITCH_PORT_MAX_LEDS]; union { struct ifreq es_uifr; struct ifmediareq es_uifmr;