FreeBSD Bugzilla – Attachment 173123 Details for
Bug 211462
AR8327 Etherswitch led control patch
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
userland and kernel patch
etherswitch.diff (text/plain), 16.18 KB, created by
Dan Nelson
on 2016-07-30 16:53:06 UTC
(
hide
)
Description:
userland and kernel patch
Filename:
MIME Type:
Creator:
Dan Nelson
Created:
2016-07-30 16:53:06 UTC
Size:
16.18 KB
patch
obsolete
>Index: sbin/etherswitchcfg/etherswitchcfg.8 >=================================================================== >--- sbin/etherswitchcfg/etherswitchcfg.8 (revision 303538) >+++ sbin/etherswitchcfg/etherswitchcfg.8 (working copy) >@@ -33,26 +33,26 @@ > .Sh SYNOPSIS > .Nm > .Op Fl "f control file" >-.Ar info >+.Cm info > .Nm > .Op Fl "f control file" >-.Ar config >+.Cm config > .Ar command parameter > .Nm > .Op Fl "f control file" >-.Ar phy >+.Cm phy > .Ar phy.register[=value] > .Nm > .Op Fl "f control file" >-.Ar port%d >+.Cm port%d > .Ar [flags] command parameter > .Nm > .Op Fl "f control file" >-.Ar reg >+.Cm reg > .Ar register[=value] > .Nm > .Op Fl "f control file" >-.Ar vlangroup%d >+.Cm vlangroup%d > .Ar command parameter > .Sh DESCRIPTION > The >@@ -81,8 +81,8 @@ The config command provides access to global switc > parameters. > It support the following commands: > .Pp >-.Bl -tag -width ".Ar vlan_mode mode" -compact >-.It Ar vlan_mode mode >+.Bl -tag -width ".Cm vlan_mode mode" -compact >+.It Cm vlan_mode Ar mode > Sets the switch VLAN mode (depends on the hardware). > .El > .Ss phy >@@ -103,51 +103,60 @@ The port command selects one of the ports of the s > It supports the following commands: > .Pp > .Bl -tag -width ".Ar pvid number" -compact >-.It Ar pvid number >+.It Cm pvid Ar number > Sets the default port VID that is used to process incoming frames that are not tagged. >-.It Ar media mediaspec >+.It Cm media Ar mediaspec > Specifies the physical media configuration to be configured for a port. >-.It Ar mediaopt mediaoption >+.It Cm mediaopt Ar mediaoption > Specifies a list of media options for a port. > See > .Xr ifconfig 8 > for details on >-.Ar media >+.Cm media > and >-.Ar mediaopt . >+.Cm mediaopt . >+.It Cm led Ar number style >+Sets the display style for a given LED. Available styles are: >+.Cm default >+(usually flash on activity), >+.Cm on , >+.Cm off , >+and >+.Cm blink . >+Not all switches will support all styles. > .El > .Pp > And the following flags (please note that not all flags > are supported by all switch drivers): > .Pp >-.Bl -tag -width ".Ar addtag" -compact >-.It Ar addtag >+.Bl -tag -width ".Fl addtag" -compact >+.It Cm addtag > Add VLAN tag to each packet sent by the port. >-.It Ar -addtag >+.It Fl addtag > Disable the add VLAN tag option. >-.It Ar striptag >+.It Cm striptag > Strip the VLAN tags from the packets sent by the port. >-.It Ar -striptag >+.It Fl striptag > Disable the strip VLAN tag option. >-.It Ar firstlock >+.It Cm firstlock > This options makes the switch port lock on the first MAC address it sees. > After that, usually you need to reset the switch to learn different > MAC addresses. >-.It Ar -firstlock >+.It Fl firstlock > Disable the first lock option. > Note that sometimes you need to reset the > switch to really disable this option. >-.It Ar dropuntagged >+.It Cm dropuntagged > Drop packets without a VLAN tag. >-.It Ar -dropuntagged >+.It Fl dropuntagged > Disable the drop untagged packets option. >-.It Ar doubletag >+.It Cm doubletag > Enable QinQ for the port. >-.It Ar -doubletag >+.It Fl doubletag > Disable QinQ for the port. >-.It Ar ingress >+.It Cm ingress > Enable the ingress filter on the port. >-.It Ar -ingress >+.It Fl ingress > Disable the ingress filter. > .El > .Ss reg >@@ -156,14 +165,14 @@ The reg command provides access to the registers o > The vlangroup command selects one of the VLAN groups for configuration. > It supports the following commands: > .Pp >-.Bl -tag -width ".Ar vlangroup" -compact >-.It Ar vlan VID >+.Bl -tag -width ".Cm members" -compact >+.It Cm vlan Ar VID > Sets the VLAN ID (802.1q VID) for this VLAN group. > Frames transmitted on tagged member ports of this group will be tagged > with this VID. > Incoming frames carrying this tag will be forwarded according to the > configuration of this VLAN group. >-.It Ar members port,... >+.It Cm members Ar port,... > Configures which ports are to be a member of this VLAN group. > The port numbers are given as a comma-separated list. > Each port can optionally be followed by >Index: sbin/etherswitchcfg/etherswitchcfg.c >=================================================================== >--- sbin/etherswitchcfg/etherswitchcfg.c (revision 303538) >+++ sbin/etherswitchcfg/etherswitchcfg.c (working copy) >@@ -83,6 +83,8 @@ struct cmds { > }; > static struct cmds cmds[]; > >+/* Must match the ETHERSWITCH_PORT_LED_* enum order */ >+static const char *ledstyles[] = { "default", "on", "off", "blink", NULL }; > > /* > * Print a value a la the %b format of the kernel's printf. >@@ -270,6 +272,38 @@ set_port_mediaopt(struct cfg *cfg, char *argv[]) > } > > static void >+set_port_led(struct cfg *cfg, char *argv[]) >+{ >+ etherswitch_port_t p; >+ int led; >+ int i; >+ >+ bzero(&p, sizeof(p)); >+ p.es_port = cfg->unit; >+ if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) >+ err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); >+ >+ led = strtol(argv[1], NULL, 0); >+ if (led < 1 || led > p.es_nleds) >+ errx(EX_USAGE, "invalid led number %s; must be between 1 and %d", >+ argv[1], p.es_nleds); >+ >+ led--; >+ >+ for (i=0; ledstyles[i] != NULL; i++) { >+ if (strcmp(argv[2], ledstyles[i]) == 0) { >+ p.es_led[led] = i; >+ break; >+ } >+ } >+ if (ledstyles[i] == NULL) >+ errx(EX_USAGE, "invalid led style \"%s\"", argv[2]); >+ >+ if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) >+ err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); >+} >+ >+static void > set_vlangroup_vid(struct cfg *cfg, char *argv[]) > { > int v; >@@ -334,10 +368,10 @@ set_register(struct cfg *cfg, char *arg) > if (c==arg) > return (1); > if (*c == '=') { >- v = strtol(c+1, NULL, 0); >+ v = strtoul(c+1, NULL, 0); > write_register(cfg, a, v); > } >- printf("\treg 0x%04x=0x%04x\n", a, read_register(cfg, a)); >+ printf("\treg 0x%04x=0x%08x\n", a, read_register(cfg, a)); > return (0); > } > >@@ -357,7 +391,7 @@ set_phyregister(struct cfg *cfg, char *arg) > if (d == c) > return (1); > if (*c == '=') { >- val = strtol(c+1, NULL, 0); >+ val = strtoul(c+1, NULL, 0); > write_phyregister(cfg, phy, reg, val); > } > printf("\treg %d.0x%02x=0x%04x\n", phy, reg, read_phyregister(cfg, phy, reg)); >@@ -442,6 +476,13 @@ print_port(struct cfg *cfg, int port) > printf("\tpvid: %d\n", p.es_pvid); > printb("\tflags", p.es_flags, ETHERSWITCH_PORT_FLAGS_BITS); > printf("\n"); >+ if (p.es_nleds) { >+ printf("\tled: "); >+ for (i = 0; i < p.es_nleds; i++) { >+ printf("%d:%s%s", i+1, ledstyles[p.es_led[i]], (i==p.es_nleds-1)?"":" "); >+ } >+ printf("\n"); >+ } > printf("\tmedia: "); > print_media_word(p.es_ifmr.ifm_current, 1); > if (p.es_ifmr.ifm_active != p.es_ifmr.ifm_current) { >@@ -540,7 +581,7 @@ usage(struct cfg *cfg __unused, char *argv[] __unu > "phy.register[=value]\n"); > fprintf(stderr, "\tetherswitchcfg [-f control file] portX " > "[flags] command parameter\n"); >- fprintf(stderr, "\t\tport commands: pvid, media, mediaopt\n"); >+ fprintf(stderr, "\t\tport commands: pvid, media, mediaopt, led\n"); > fprintf(stderr, "\tetherswitchcfg [-f control file] reg " > "register[=value]\n"); > fprintf(stderr, "\tetherswitchcfg [-f control file] vlangroupX " >@@ -651,7 +692,7 @@ main(int argc, char *argv[]) > for(i=0; cmds[i].name != NULL; i++) { > if (cfg.mode == cmds[i].mode && strcmp(argv[0], cmds[i].name) == 0) { > if (argc < (cmds[i].args + 1)) { >- printf("%s needs an argument\n", cmds[i].name); >+ printf("%s needs %d argument%s\n", cmds[i].name, cmds[i].args, (cmds[i].args==1)?"":","); > break; > } > (cmds[i].f)(&cfg, argv); >@@ -691,6 +732,7 @@ static struct cmds cmds[] = { > { MODE_PORT, "pvid", 1, set_port_vid }, > { MODE_PORT, "media", 1, set_port_media }, > { MODE_PORT, "mediaopt", 1, set_port_mediaopt }, >+ { MODE_PORT, "led", 2, set_port_led }, > { MODE_PORT, "addtag", 0, set_port_flag }, > { MODE_PORT, "-addtag", 0, set_port_flag }, > { MODE_PORT, "ingress", 0, set_port_flag }, >Index: sys/dev/etherswitch/arswitch/arswitch.c >=================================================================== >--- sys/dev/etherswitch/arswitch/arswitch.c (revision 303538) >+++ sys/dev/etherswitch/arswitch/arswitch.c (working copy) >@@ -69,6 +69,8 @@ > #include <dev/etherswitch/arswitch/arswitch_8327.h> > #include <dev/etherswitch/arswitch/arswitch_9340.h> > >+#include <dev/led/led.h> >+ > #include "mdio_if.h" > #include "miibus_if.h" > #include "etherswitch_if.h" >@@ -77,6 +79,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 +95,9 @@ static int ar8xxx_port_vlan_setup(struct arswitch_ > 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 void arswitch_led_func(struct arswitch_dev_led *dev_led, int onoff); > > static int > arswitch_probe(device_t dev) >@@ -188,9 +201,26 @@ arswitch_attach_phys(struct arswitch_softc *sc) > 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].led = >+ led_create((led_t *)arswitch_led_func, >+ &sc->dev_led[phy][led], ledname); >+ sc->dev_led[phy][led].phy = phy; >+ sc->dev_led[phy][led].lednum = led; >+ } >+ } > } >- return (err); >+ return (0); > } > > static int >@@ -422,7 +452,7 @@ static int > arswitch_detach(device_t dev) > { > struct arswitch_softc *sc = device_get_softc(dev); >- int i; >+ int i, led; > > callout_drain(&sc->callout_tick); > >@@ -432,6 +462,9 @@ arswitch_detach(device_t dev) > if (sc->ifp[i] != NULL) > if_free(sc->ifp[i]); > free(sc->ifname[i], M_DEVBUF); >+ for (led=0; led < ARSWITCH_NUM_LEDS; led++) >+ if (sc->dev_led[i][led].led != NULL) >+ led_destroy(sc->dev_led[i][led].led); > } > > bus_generic_detach(dev); >@@ -683,6 +716,38 @@ arswitch_getport(device_t dev, etherswitch_port_t > } 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 +792,7 @@ ar8xxx_port_vlan_setup(struct arswitch_softc *sc, > 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 +809,20 @@ arswitch_setport(device_t dev, etherswitch_port_t > 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 +834,34 @@ arswitch_setport(device_t dev, etherswitch_port_t > return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA)); > } > >+/* >+ * led(4) callback function. That api only knows on/off; if you want to >+ * reset back to defaults, you'll need to use etherswitchcfg. >+ */ >+static void >+arswitch_led_func(struct arswitch_dev_led* dev_led, int onoff) >+{ >+ arswitch_setled(dev_led->sc, dev_led->phy, dev_led->lednum, >+ onoff ? ETHERSWITCH_PORT_LED_ON : ETHERSWITCH_PORT_LED_OFF); >+} >+ >+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) > { >Index: sys/dev/etherswitch/arswitch/arswitch_8327.c >=================================================================== >--- sys/dev/etherswitch/arswitch/arswitch_8327.c (revision 303538) >+++ sys/dev/etherswitch/arswitch/arswitch_8327.c (working copy) >@@ -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) >Index: sys/dev/etherswitch/arswitch/arswitch_8327.h >=================================================================== >--- sys/dev/etherswitch/arswitch/arswitch_8327.h (revision 303538) >+++ sys/dev/etherswitch/arswitch/arswitch_8327.h (working copy) >@@ -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__ */ >Index: sys/dev/etherswitch/arswitch/arswitchvar.h >=================================================================== >--- sys/dev/etherswitch/arswitch/arswitchvar.h (revision 303538) >+++ sys/dev/etherswitch/arswitch/arswitchvar.h (working copy) >@@ -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; > >Index: sys/dev/etherswitch/etherswitch.h >=================================================================== >--- sys/dev/etherswitch/etherswitch.h (revision 303538) >+++ sys/dev/etherswitch/etherswitch.h (working copy) >@@ -14,7 +14,7 @@ extern driver_t etherswitch_driver; > > 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 etherswitch_conf_t > #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;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 211462
: 173123