diff -B -w -ur ethtool-6-spidcom/ethtool.c ethtool-6/ethtool.c --- ethtool-6-spidcom/ethtool.c 2010-10-01 18:01:46.000000000 +0200 +++ ethtool-6/ethtool.c 2010-10-01 17:46:05.000000000 +0200 @@ -90,6 +90,7 @@ MODE_GOFFLOAD, MODE_SOFFLOAD, MODE_GSTATS, + MODE_SVLAN_SPIDCOM, } mode = MODE_GSET; static struct option { @@ -109,6 +110,11 @@ " [ wol p|u|m|b|a|g|s|d... ]\n" " [ sopass %%x:%%x:%%x:%%x:%%x:%%x ]\n" " [ msglvl %%d ] \n" }, + { "-vl", "--vlanoptions", MODE_SVLAN_SPIDCOM, "vlan administration", + " [ print ] \n" + " [ set-phy-vid %%d:%%d ] \n" + " [ set-phy-prio %%d:%%d ] \n" + " [ set-phy-state %%d:on|off ]\n" }, { "-a", "--show-pause", MODE_GPAUSE, "Show pause options" }, { "-A", "--pause", MODE_SPAUSE, "Set pause options", " [ autoneg on|off ]\n" @@ -155,6 +161,7 @@ { "-i", "--driver", MODE_GDRV, "Show driver information" }, { "-d", "--register-dump", MODE_GREGS, "Do a register dump", " [ raw on|off ]\n" + " [ hex on|off ]\n" " [ file FILENAME ]\n" }, { "-e", "--eeprom-dump", MODE_GEEPROM, "Do a EEPROM dump", " [ raw on|off ]\n" @@ -193,6 +200,13 @@ static char *devname = NULL; +static struct ethtool_vlanparam evlanparam; +static int svlan_changed = 0; +static char *svlan_state_wanted = NULL; +static char *svlan_vid_wanted = NULL; +static char *svlan_prio_wanted = NULL; +static int svlan_print_wanted = -1; + static int goffload_changed = 0; static int off_csum_rx_wanted = -1; static int off_csum_tx_wanted = -1; @@ -312,6 +326,12 @@ { "gso", CMDL_BOOL, &off_gso_wanted, NULL }, }; +static struct cmdline_info cmdline_svlan[] = { + { "set-phy-vid", CMDL_STR, &svlan_vid_wanted, NULL }, + { "set-phy-prio", CMDL_STR, &svlan_prio_wanted, NULL }, + { "set-phy-state", CMDL_STR, &svlan_state_wanted, NULL }, +}; + static struct cmdline_info cmdline_pause[] = { { "autoneg", CMDL_BOOL, &pause_autoneg_wanted, &epause.autoneg }, { "rx", CMDL_BOOL, &pause_rx_wanted, &epause.rx_pause }, @@ -430,7 +450,8 @@ (mode == MODE_GOFFLOAD) || (mode == MODE_SOFFLOAD) || (mode == MODE_GSTATS) || - (mode == MODE_PHYS_ID)) { + (mode == MODE_PHYS_ID) || + (mode == MODE_SVLAN_SPIDCOM)) { devname = argp[i]; break; } @@ -509,6 +530,21 @@ i = argc; break; } + if (mode == MODE_SVLAN_SPIDCOM) { + int l; + parse_generic_cmdline(argc, argp, i, + &svlan_changed, + cmdline_svlan, + ARRAY_SIZE(cmdline_svlan)); + + for (l = 3; l < argc; l++) { + if (!strcmp(argp[l], "print")) { + svlan_print_wanted = 1; + } + } + i = argc; + break; + } if (mode != MODE_SSET) show_usage(1); if (!strcmp(argp[i], "speed")) { @@ -1226,6 +1262,114 @@ return 0; } +static int do_svlan(int fd, struct ifreq *ifr) +{ + int err, changed = 0; + + evlanparam.cmd = ETHTOOL_RVLAN_TABLE; + ifr->ifr_data = (caddr_t)&evlanparam; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot get current device settings"); + return 0; + } + + if (svlan_changed) { + if (svlan_vid_wanted != NULL) { + unsigned int phy, vid; + //format is [ set-phy-vid %%u:%%u ] + sscanf (svlan_vid_wanted, "%u:%u", &phy, &vid); + + // VID is 12 bits. + if (phy >= MAX_VLAN_SUPPORTED) { + perror("Cannot set vlan parameters : phy range from 0 to 4\n"); + return 0; + } + + if (vid > 0xFFF) { + perror("Cannot set vlan parameters : VID range from 0 to 4095\n"); + return 0; + } + + evlanparam.vlan_table[phy].vlan = (evlanparam.vlan_table[phy].vlan & ~0x0fff) | vid; + } + + if (svlan_prio_wanted != NULL) { + unsigned int phy, prio; + //format is [ set-phy-prio %%u:%%u ] + sscanf (svlan_prio_wanted, "%u:%u", &phy, &prio); + + // prio is 3 bits. + if (phy >= MAX_VLAN_SUPPORTED) { + perror("Cannot set vlan parameters : phy range from 0 to 4\n"); + return 0; + } + + if (prio > 7) { + perror("Cannot set vlan parameters : prio range from 0 to 7\n"); + return 0; + } + + evlanparam.vlan_table[phy].vlan = (evlanparam.vlan_table[phy].vlan & ~0xe000) | (prio << 13); + } + + if (svlan_state_wanted != NULL) { + unsigned int phy; + char *state; + char *ptr; + //format is [ set-phy-state %%d:on|off ] + if ((ptr = strchr (svlan_state_wanted, ':')) == NULL) + { + perror ("Bad format for phy state setting\n"); + return 0; + } + *ptr = '\0'; + sscanf (svlan_state_wanted, "%u", &phy); + state = ptr + 1; + // VID is 12 bits. + if (phy >= MAX_VLAN_SUPPORTED) { + perror("Cannot set vlan parameters : phy range from 0 to 4\n"); + return 0; + } + + if (!strcmp (state, "on")) + evlanparam.vlan_table[phy].state = VLAN_ON; + else if (!strcmp(state, "off")) + evlanparam.vlan_table[phy].state = VLAN_OFF; + else + show_usage(1); + } + + evlanparam.cmd = ETHTOOL_SVLAN_TABLE; + ifr->ifr_data = (caddr_t)&evlanparam; + err = ioctl(fd, SIOCETHTOOL, ifr); + if (err) { + perror("Cannot set vlan parameters : socket fail\n"); + return 0; + } + } + + if (svlan_print_wanted != -1) { + int i; + + fprintf(stdout, "vlan table:\n"); + fprintf(stdout, " %3s | %5s | %5s | %5s\n", "phy", "vid", "prio", "state"); + + for (i=0; i> 13), + (evlanparam.vlan_table[i].state == VLAN_ON) ? "on" : "off"); + } + fprintf(stdout, "\n"); + } + + return 0; +} + + + static int doit(void) { struct ifreq ifr; @@ -1249,6 +1393,8 @@ return do_gset(fd, &ifr); } else if (mode == MODE_SSET) { return do_sset(fd, &ifr); + } else if (mode == MODE_SVLAN_SPIDCOM) { + return do_svlan(fd, &ifr); } else if (mode == MODE_GREGS) { return do_gregs(fd, &ifr); } else if (mode == MODE_NWAY_RST) { @@ -1648,6 +1794,9 @@ fprintf(stdout, "Settings for %s:\n", devname); + if (phyad_wanted != -1) + ecmd.phy_address = phyad_wanted; + ecmd.cmd = ETHTOOL_GSET; ifr->ifr_data = (caddr_t)&ecmd; err = ioctl(fd, SIOCETHTOOL, ifr); diff -B -w -ur ethtool-6-spidcom/ethtool-copy.h ethtool-6/ethtool-copy.h --- ethtool-6-spidcom/ethtool-copy.h 2010-10-01 18:01:46.000000000 +0200 +++ ethtool-6/ethtool-copy.h 2010-10-01 17:46:05.000000000 +0200 @@ -221,6 +221,19 @@ ETH_SS_STATS, }; +#define MAX_VLAN_SUPPORTED 5 +#define VLAN_OFF 0 +#define VLAN_ON 1 + +struct ethtool_vlanparam { + u32 cmd; /* ETHTOOL_RVLAN_TABLE, ETHTOOL_SVLAN_TABLE*/ + + struct { + u8 state; + u16 vlan; + }vlan_table[MAX_VLAN_SUPPORTED]; +}; + /* for passing string sets for data tagging */ struct ethtool_gstrings { __u32 cmd; /* ETHTOOL_GSTRINGS */ @@ -414,6 +427,8 @@ #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ #define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ #define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ +#define ETHTOOL_RVLAN_TABLE 0x00000029 /* Read VLAN Table (SPIDCOM Code) */ +#define ETHTOOL_SVLAN_TABLE 0x0000002a /* WriteVLAN Table (SPIDCOM Code) */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET