No idea, but I've got a slightly updated patch by now, which I
haven't gotten around to submit again. :)

Daniel Golle wrote:
> I just tested this patch, it works very nice on all systems I got here!
> 
> Thanks a lot!
> 
> Is there any reason why it's not being committed?
> 
> 
> On 06/05/12 03:46, Tobias Diedrich wrote:
> > Third time's a charm.
> > 
> > This patch adds swconfig support for ramips_esw:
> > 
> > Tested on both D-LINK DIR-300 B1 and Sitecom WL-351 (external
> > rtl8366rb on internal port 5).
> > I've made sure that in the enable_vlan=0 case it behaves like a dumb switch,
> > so external switches should work fine with vlans and verified this
> > on the WL-351.
> > 
> > Also I've taken some more care than before to make sure it doesn't change 
> > the
> > pre-existing behaviour in case swconfig is not available or an external 
> > switch
> > is used.
> > 
> > The current state shown by swconfig is always read directly from HW 
> > registers,
> > new settings only show after 'swconfig dev rt305x set apply'.
> > 
> > Note that I have renamed RT305X_ESW_REG_POC[123] to RT305X_ESW_REG_POC[012] 
> > to
> > better match the datasheet (which has a typo on POC0, which probably lead to
> > the confusing POC[123] naming).
> > 
> > Default on D-LINK DIR-300 B1 after first boot:
> > |root@OpenWrt:/# swconfig dev rt305x show
> > |Global attributes:
> > |        enable_vlan: 1
> > |        alternate_vlan_disable: 0
> > |Port 0:
> > |        disable: 0
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 2185
> > |        pvid: 1
> > |        link: port:0 link:up speed:100baseT full-duplex
> > |Port 1:
> > |        disable: 0
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 1
> > |        link: port:1 link:down
> > |Port 2:
> > |        disable: 0
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 1
> > |        link: port:2 link:down
> > |Port 3:
> > |        disable: 0
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 1
> > |        link: port:3 link:down
> > |Port 4:
> > |        disable: 0
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 0
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 2
> > |        link: port:4 link:up speed:100baseT full-duplex
> > |Port 5:
> > |        disable: 1
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: ???
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 1
> > |        link: port:5 link:down
> > |Port 6:
> > |        disable: 0
> > |        doubletag: 0
> > |        en_vlan: 1
> > |        untag: 0
> > |        led: ???
> > |        lan: ???
> > |        recv_bad: ???
> > |        recv_good: ???
> > |        pvid: 1
> > |        link: port:6 link:up speed:1000baseT full-duplex
> > |VLAN 1:
> > |        ports: 0 1 2 3 6t
> > |VLAN 2:
> > |        ports: 4 6t
> > 
> > With enable_vlan=0:
> > |Global attributes:
> > |        enable_vlan: 0
> > |        alternate_vlan_disable: 0
> > |Port 0:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 2381
> > |        pvid: 0
> > |        link: port:0 link:up speed:100baseT full-duplex
> > |Port 1:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:1 link:down
> > |Port 2:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:2 link:down
> > |Port 3:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:3 link:down
> > |Port 4:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 0
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:4 link:up speed:100baseT full-duplex
> > |Port 5:
> > |        disable: 1
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: ???
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:5 link:down
> > |Port 6:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: ???
> > |        lan: ???
> > |        recv_bad: ???
> > |        recv_good: ???
> > |        pvid: 0
> > |        link: port:6 link:up speed:1000baseT full-duplex
> > |VLAN 0:
> > |        ports: 0 1 2 3 4 5 6
> > 
> > Default on Sitecom WL-351 after boot:
> > |root@OpenWrt:~# swconfig dev rt305x show
> > |Global attributes:
> > |        enable_vlan: 0
> > |        alternate_vlan_disable: 0
> > |Port 0:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:0 link:down
> > |Port 1:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:1 link:down
> > |Port 2:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:2 link:down
> > |Port 3:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:3 link:down
> > |Port 4:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: 0
> > |        lan: 1
> > |        recv_bad: 0
> > |        recv_good: 0
> > |        pvid: 0
> > |        link: port:4 link:down
> > |Port 5:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: ???
> > |        lan: 1
> > |        recv_bad: 1
> > |        recv_good: 65693
> > |        pvid: 0
> > |        link: port:5 link:up speed:1000baseT full-duplex
> > |Port 6:
> > |        disable: 0
> > |        doubletag: 1
> > |        en_vlan: 1
> > |        untag: 1
> > |        led: ???
> > |        lan: ???
> > |        recv_bad: ???
> > |        recv_good: ???
> > |        pvid: 0
> > |        link: port:6 link:up speed:1000baseT full-duplex
> > |VLAN 0:
> > |        ports: 0 1 2 3 4 5 6
> > |root@OpenWrt:~# swconfig dev rtl8366rb show
> > |Global attributes:
> > |        enable_learning: 1
> > |        enable_vlan: 1
> > |        enable_vlan4k: 0
> > |        blinkrate: 0
> > |        enable_qos: 1
> > |Port 0:
> > |        mib: Port 0 MIB counters
> > [...]
> > |        led: ???
> > |        disable: 0
> > |        rate_in: 1048512
> > |        rate_out: 1048512
> > |        pvid: 2
> > |        link: port:5 link:up speed:1000baseT full-duplex txflow rxflow auto
> > |VLAN 1:
> > |        info: VLAN 1: Ports: '01235t', members=002f, untag=000f, fid=0
> > |        fid: 0
> > |        ports: 0 1 2 3 5t
> > |VLAN 2:
> > |        info: VLAN 2: Ports: '45t', members=0030, untag=0010, fid=0
> > |        fid: 0
> > |        ports: 4 5t
> > 
> > Closes: https://dev.openwrt.org/ticket/11327
> > 
> > Signed-off-by: Tobias Diedrich <ranma+open...@tdiedrich.de>
> > 
> > 
> > Index: target/linux/ramips/files/arch/mips/ralink/rt305x/mach-wl351.c
> > ===================================================================
> > --- target/linux/ramips/files/arch/mips/ralink/rt305x/mach-wl351.c      
> > (revision 31618)
> > +++ target/linux/ramips/files/arch/mips/ralink/rt305x/mach-wl351.c      
> > (working copy)
> > @@ -98,7 +98,7 @@
> >                                      ARRAY_SIZE(wl351_gpio_buttons),
> >                                      wl351_gpio_buttons);
> >         // external rtl8366rb
> > -       rt305x_esw_data.vlan_config = RT305X_ESW_VLAN_CONFIG_BYPASS;
> > +       rt305x_esw_data.vlan_config = RT305X_ESW_VLAN_CONFIG_NONE;
> >         rt305x_esw_data.reg_initval_fct2 = 0x0002500c;
> >         rt305x_esw_data.reg_initval_fpa2 = 0x1f003fff;
> >         rt305x_register_ethernet();
> > Index: 
> > target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
> > ===================================================================
> > --- 
> > target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
> >    (revision 31618)
> > +++ 
> > target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
> >    (working copy)
> > @@ -13,7 +13,6 @@
> > 
> >  enum {
> >         RT305X_ESW_VLAN_CONFIG_NONE = 0,
> > -       RT305X_ESW_VLAN_CONFIG_BYPASS,
> >         RT305X_ESW_VLAN_CONFIG_LLLLW,
> >         RT305X_ESW_VLAN_CONFIG_WLLLL,
> >  };
> > Index: target/linux/ramips/files/drivers/net/ethernet/ramips/Kconfig
> > ===================================================================
> > --- target/linux/ramips/files/drivers/net/ethernet/ramips/Kconfig       
> > (revision 31618)
> > +++ target/linux/ramips/files/drivers/net/ethernet/ramips/Kconfig       
> > (working copy)
> > @@ -2,6 +2,7 @@
> >         tristate "Ralink RT288X/RT3X5X/RT3662/RT3883 ethernet driver"
> >         depends on MIPS_RALINK
> >         select PHYLIB if (SOC_RT288X || SOC_RT3883)
> > +       select SWCONFIG
> >         help
> >           This driver supports the etehrnet mac inside the ralink wisocs
> > 
> > Index: target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_esw.c
> > ===================================================================
> > --- target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_esw.c  
> > (revision 31618)
> > +++ target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_esw.c  
> > (working copy)
> > @@ -1,19 +1,29 @@
> >  #include <linux/ioport.h>
> > +#include <linux/switch.h>
> > 
> >  #include <rt305x_regs.h>
> >  #include <rt305x_esw_platform.h>
> > 
> > +/*
> > + * HW limitations for this switch:
> > + * - no large frame support (PKT_MAX_LEN at most 1536)
> > + * - can't have untagged vlan and tagged vlan on one port at the same time,
> > + *   though this might be possible using the undocumented PPE
> > + */
> > +
> >  #define RT305X_ESW_REG_FCT0            0x08
> >  #define RT305X_ESW_REG_PFC1            0x14
> >  #define RT305X_ESW_REG_PVIDC(_n)       (0x40 + 4 * (_n))
> >  #define RT305X_ESW_REG_VLANI(_n)       (0x50 + 4 * (_n))
> >  #define RT305X_ESW_REG_VMSC(_n)                (0x70 + 4 * (_n))
> > +#define RT305X_ESW_REG_POA             0x80
> >  #define RT305X_ESW_REG_FPA             0x84
> >  #define RT305X_ESW_REG_SOCPC           0x8c
> > -#define RT305X_ESW_REG_POC1            0x90
> > -#define RT305X_ESW_REG_POC2            0x94
> > -#define RT305X_ESW_REG_POC3            0x98
> > +#define RT305X_ESW_REG_POC0            0x90
> > +#define RT305X_ESW_REG_POC1            0x94
> > +#define RT305X_ESW_REG_POC2            0x98
> >  #define RT305X_ESW_REG_SGC             0x9c
> > +#define RT305X_ESW_REG_STRT            0xa0
> >  #define RT305X_ESW_REG_PCR0            0xc0
> >  #define RT305X_ESW_REG_PCR1            0xc4
> >  #define RT305X_ESW_REG_FPA2            0xc8
> > @@ -24,7 +34,30 @@
> >  #define RT305X_ESW_REG_P2LED   0xac
> >  #define RT305X_ESW_REG_P3LED   0xb0
> >  #define RT305X_ESW_REG_P4LED   0xb4
> > +#define RT305X_ESW_REG_P0PC    0xe8
> > +#define RT305X_ESW_REG_P1PC    0xec
> > +#define RT305X_ESW_REG_P2PC    0xf0
> > +#define RT305X_ESW_REG_P3PC    0xf4
> > +#define RT305X_ESW_REG_P4PC    0xf8
> > +#define RT305X_ESW_REG_P5PC    0xfc
> > 
> > +#define RT305X_ESW_LED_LINK            0
> > +#define RT305X_ESW_LED_100M            1
> > +#define RT305X_ESW_LED_DUPLEX          2
> > +#define RT305X_ESW_LED_ACTIVITY                3
> > +#define RT305X_ESW_LED_COLLISION       4
> > +#define RT305X_ESW_LED_LINKACT         5
> > +#define RT305X_ESW_LED_DUPLCOLL                6
> > +#define RT305X_ESW_LED_10MACT          7
> > +#define RT305X_ESW_LED_100MACT         8
> > +// Additional led states not in datasheet:
> > +#define RT305X_ESW_LED_BLINK           10
> > +#define RT305X_ESW_LED_ON              12
> > +
> > +#define RT305X_ESW_LINK_S      25
> > +#define RT305X_ESW_DUPLEX_S    9
> > +#define RT305X_ESW_SPD_S       0
> > +
> >  #define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
> >  #define RT305X_ESW_PCR0_WT_PHY_CMD     BIT(13)
> >  #define RT305X_ESW_PCR0_CPU_PHY_REG_S  8
> > @@ -47,15 +80,28 @@
> >  #define RT305X_ESW_SOCPC_DISBC2CPU_S   16
> >  #define RT305X_ESW_SOCPC_CRC_PADDING   BIT(25)
> > 
> > -#define RT305X_ESW_POC1_EN_BP_S                0
> > -#define RT305X_ESW_POC1_EN_FC_S                8
> > -#define RT305X_ESW_POC1_DIS_RMC2CPU_S  16
> > -#define RT305X_ESW_POC1_DIS_PORT_S     23
> > +#define RT305X_ESW_POC0_EN_BP_S                0
> > +#define RT305X_ESW_POC0_EN_FC_S                8
> > +#define RT305X_ESW_POC0_DIS_RMC2CPU_S  16
> > +#define RT305X_ESW_POC0_DIS_PORT_M     0x7f
> > +#define RT305X_ESW_POC0_DIS_PORT_S     23
> > 
> > -#define RT305X_ESW_POC3_UNTAG_EN_S     0
> > -#define RT305X_ESW_POC3_ENAGING_S      8
> > -#define RT305X_ESW_POC3_DIS_UC_PAUSE_S 16
> > +#define RT305X_ESW_POC2_UNTAG_EN_M     0xff
> > +#define RT305X_ESW_POC2_UNTAG_EN_S     0
> > +#define RT305X_ESW_POC2_ENAGING_S      8
> > +#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
> > 
> > +#define RT305X_ESW_SGC2_DOUBLE_TAG_M   0x7f
> > +#define RT305X_ESW_SGC2_DOUBLE_TAG_S   0
> > +#define RT305X_ESW_SGC2_LAN_PMAP_M     0x3f
> > +#define RT305X_ESW_SGC2_LAN_PMAP_S     24
> > +
> > +#define RT305X_ESW_PFC1_EN_VLAN_M      0xff
> > +#define RT305X_ESW_PFC1_EN_VLAN_S      16
> > +#define RT305X_ESW_PFC1_EN_TOS_S       24
> > +
> > +#define RT305X_ESW_VLAN_NONE           0xfff
> > +
> >  #define RT305X_ESW_PORT0               0
> >  #define RT305X_ESW_PORT1               1
> >  #define RT305X_ESW_PORT2               2
> > @@ -64,6 +110,12 @@
> >  #define RT305X_ESW_PORT5               5
> >  #define RT305X_ESW_PORT6               6
> > 
> > +#define RT305X_ESW_PORTS_NONE          0
> > +
> > +#define RT305X_ESW_PMAP_LLLLL          0x00
> > +#define RT305X_ESW_PMAP_LLLLW          0x10
> > +#define RT305X_ESW_PMAP_WLLLL          0x01
> > +
> >  #define RT305X_ESW_PORTS_INTERNAL                                      \
> >                 (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) |        \
> >                  BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) |        \
> > @@ -78,12 +130,56 @@
> >                 (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
> > 
> >  #define RT305X_ESW_NUM_VLANS   16
> > +#define RT305X_ESW_NUM_VIDS    4096
> >  #define RT305X_ESW_NUM_PORTS   7
> > +#define RT305X_ESW_NUM_LANWAN  6
> > +#define RT305X_ESW_NUM_LEDS    5
> > 
> > +enum {
> > +       /* global attributes */
> > +       RT305X_ESW_ATTR_ENABLE_VLAN,
> > +       RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
> > +       /* port attributes */
> > +       RT305X_ESW_ATTR_PORT_DISABLE,
> > +       RT305X_ESW_ATTR_PORT_DOUBLETAG,
> > +       RT305X_ESW_ATTR_PORT_EN_VLAN,
> > +       RT305X_ESW_ATTR_PORT_UNTAG,
> > +       RT305X_ESW_ATTR_PORT_LED,
> > +       RT305X_ESW_ATTR_PORT_LAN,
> > +       RT305X_ESW_ATTR_PORT_RECV_BAD,
> > +       RT305X_ESW_ATTR_PORT_RECV_GOOD,
> > +};
> > +
> > +struct rt305x_esw_bools {
> > +       u16     reg;
> > +       u16     shift;
> > +};
> > +
> > +struct rt305x_esw_port {
> > +       bool    disable;
> > +       bool    doubletag;
> > +       bool    untag;
> > +       bool    en_vlan;
> > +       u8      led;
> > +       u16     pvid;
> > +};
> > +
> > +struct rt305x_esw_vlan {
> > +       u8      ports;
> > +       u16     vid;
> > +};
> > +
> >  struct rt305x_esw {
> > +       struct switch_dev swdev;
> >         void __iomem *base;
> >         struct rt305x_esw_platform_data *pdata;
> >         spinlock_t reg_rw_lock;
> > +
> > +       bool global_vlan_enable;
> > +       bool alt_vlan_disable;
> > +       u8 pmap;
> > +       struct rt305x_esw_vlan vlans[RT305X_ESW_NUM_VLANS];
> > +       struct rt305x_esw_port ports[RT305X_ESW_NUM_PORTS];
> >  };
> > 
> >  static inline void
> > @@ -160,6 +256,19 @@
> >         return ret;
> >  }
> > 
> > +static unsigned
> > +rt305x_esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan)
> > +{
> > +       unsigned s;
> > +       unsigned val;
> > +
> > +       s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
> > +       val = rt305x_esw_rr(esw, RT305X_ESW_REG_VLANI(vlan / 2));
> > +       val = (val >> s) & RT305X_ESW_VLANI_VID_M;
> > +
> > +       return val;
> > +}
> > +
> >  static void
> >  rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid)
> >  {
> > @@ -172,6 +281,17 @@
> >                        (vid & RT305X_ESW_VLANI_VID_M) << s);
> >  }
> > 
> > +static unsigned
> > +rt305x_esw_get_pvid(struct rt305x_esw *esw, unsigned port)
> > +{
> > +       unsigned s, val;
> > +
> > +       s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
> > +       val = rt305x_esw_rr(esw,
> > +                      RT305X_ESW_REG_PVIDC(port / 2));
> > +       return (val >> s) & RT305X_ESW_PVIDC_PVID_M;
> > +}
> > +
> >  static void
> >  rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid)
> >  {
> > @@ -184,6 +304,18 @@
> >                        (pvid & RT305X_ESW_PVIDC_PVID_M) << s);
> >  }
> > 
> > +static unsigned
> > +rt305x_esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan)
> > +{
> > +       unsigned s, val;
> > +
> > +       s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
> > +       val = rt305x_esw_rr(esw, RT305X_ESW_REG_VMSC(vlan / 4));
> > +       val = (val >> s) & RT305X_ESW_VMSC_MSC_M;
> > +
> > +       return val;
> > +}
> > +
> >  static void
> >  rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
> >  {
> > @@ -196,6 +328,9 @@
> >                        (msc & RT305X_ESW_VMSC_MSC_M) << s);
> >  }
> > 
> > +static int
> > +rt305x_esw_apply_config(struct switch_dev *dev);
> > +
> >  static void
> >  rt305x_esw_hw_init(struct rt305x_esw *esw)
> >  {
> > @@ -203,23 +338,30 @@
> > 
> >         /* vodoo from original driver */
> >         rt305x_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
> > -       rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2);
> > -       rt305x_esw_wr(esw, 0x00405555, RT305X_ESW_REG_PFC1);
> > +       /* port priority 1 for all ports, vlan enabled */
> > +       rt305x_esw_wr(esw, 0x00005555 |
> > +                     (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S),
> > +                     RT305X_ESW_REG_PFC1);
> > +       /* Enable Aging, and VLAN TAG removal */
> > +       rt305x_esw_wr(esw,
> > +                     ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) |
> > +                      (RT305X_ESW_PORTS_NOCPU << 
> > RT305X_ESW_POC2_UNTAG_EN_S)),
> > +                     RT305X_ESW_REG_POC2);
> > 
> >         /* Enable Back Pressure, and Flow Control */
> >         rt305x_esw_wr(esw,
> > -                     ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC1_EN_BP_S) |
> > -                      (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC1_EN_FC_S)),
> > -                     RT305X_ESW_REG_POC1);
> > +                     ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) |
> > +                      (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)),
> > +                     RT305X_ESW_REG_POC0);
> > 
> > -       /* Enable Aging, and VLAN TAG removal */
> > -       rt305x_esw_wr(esw,
> > -                     ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC3_ENAGING_S) |
> > -                      (RT305X_ESW_PORTS_NOCPU << 
> > RT305X_ESW_POC3_UNTAG_EN_S)),
> > -                     RT305X_ESW_REG_POC3);
> > +       rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, 
> > RT305X_ESW_REG_FCT2);
> > 
> > -       rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, 
> > RT305X_ESW_REG_FCT2);
> > +       /* 300s aging timer, max packet len 1536, broadcast storm 
> > prevention disabled,
> > +        * disable collision abort, mac xor48 hash, 10 packet back pressure 
> > jam,
> > +        * GMII disable was_transmit, back pressure disabled, 30ms led 
> > flash,
> > +        * unmatched IGMP as broadcast, rmc tb fault to all ports */
> >         rt305x_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC);
> > +       rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2);
> > 
> >         /* Setup SoC Port control register */
> >         rt305x_esw_wr(esw,
> > @@ -265,66 +407,609 @@
> >         /* select local register */
> >         rt305x_mii_write(esw, 0, 31, 0x8000);
> > 
> > +       /* set up logical config and apply */
> >         for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
> > -               rt305x_esw_set_vlan_id(esw, i, 0);
> > -               rt305x_esw_set_vmsc(esw, i, 0);
> > +               esw->vlans[i].vid = RT305X_ESW_VLAN_NONE;
> > +               esw->vlans[i].ports = RT305X_ESW_PORTS_NONE;
> >         }
> > 
> > -       for (i = 0; i < RT305X_ESW_NUM_PORTS; i++)
> > -               rt305x_esw_set_pvid(esw, i, 1);
> > +       for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
> > +               esw->ports[i].pvid = 1;
> > +               esw->ports[i].en_vlan = 1;
> > +               esw->ports[i].untag = i != RT305X_ESW_PORT6;
> > +       }
> > 
> >         switch (esw->pdata->vlan_config) {
> >         case RT305X_ESW_VLAN_CONFIG_NONE:
> > +               esw->global_vlan_enable = 0;
> > +               esw->pmap = RT305X_ESW_PMAP_LLLLL;
> >                 break;
> > 
> > -       case RT305X_ESW_VLAN_CONFIG_BYPASS:
> > -               /* Pass all vlan tags to all ports */
> > -               for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
> > -                       rt305x_esw_set_vlan_id(esw, i, i+1);
> > -                       rt305x_esw_set_vmsc(esw, i, RT305X_ESW_PORTS_ALL);
> > -               }
> > -               /* Disable VLAN TAG removal, keep aging on. */
> > -               rt305x_esw_wr(esw,
> > -                             RT305X_ESW_PORTS_ALL << 
> > RT305X_ESW_POC3_ENAGING_S,
> > -                             RT305X_ESW_REG_POC3);
> > -               break;
> > -
> >         case RT305X_ESW_VLAN_CONFIG_LLLLW:
> > -               rt305x_esw_set_vlan_id(esw, 0, 1);
> > -               rt305x_esw_set_vlan_id(esw, 1, 2);
> > -               rt305x_esw_set_pvid(esw, RT305X_ESW_PORT4, 2);
> > -
> > -               rt305x_esw_set_vmsc(esw, 0,
> > +               esw->global_vlan_enable = 1;
> > +               esw->pmap = RT305X_ESW_PMAP_LLLLW;
> > +               esw->vlans[0].vid = 1;
> > +               esw->vlans[1].vid = 2;
> > +               esw->ports[4].pvid = 2;
> > +               esw->ports[5].disable = 1;
> > +               esw->vlans[0].ports =
> >                                 BIT(RT305X_ESW_PORT0) | 
> > BIT(RT305X_ESW_PORT1) |
> >                                 BIT(RT305X_ESW_PORT2) | 
> > BIT(RT305X_ESW_PORT3) |
> > -                               BIT(RT305X_ESW_PORT6));
> > -               rt305x_esw_set_vmsc(esw, 1,
> > -                               BIT(RT305X_ESW_PORT4) | 
> > BIT(RT305X_ESW_PORT6));
> > +                               BIT(RT305X_ESW_PORT6);
> > +               esw->vlans[1].ports =
> > +                               BIT(RT305X_ESW_PORT4) | 
> > BIT(RT305X_ESW_PORT6);
> >                 break;
> > 
> >         case RT305X_ESW_VLAN_CONFIG_WLLLL:
> > -               rt305x_esw_set_vlan_id(esw, 0, 1);
> > -               rt305x_esw_set_vlan_id(esw, 1, 2);
> > -               rt305x_esw_set_pvid(esw, RT305X_ESW_PORT0, 2);
> > -
> > -               rt305x_esw_set_vmsc(esw, 0,
> > -                               BIT(RT305X_ESW_PORT1) | 
> > BIT(RT305X_ESW_PORT2) |
> > -                               BIT(RT305X_ESW_PORT3) | 
> > BIT(RT305X_ESW_PORT4) |
> > -                               BIT(RT305X_ESW_PORT6));
> > -               rt305x_esw_set_vmsc(esw, 1,
> > -                               BIT(RT305X_ESW_PORT0) | 
> > BIT(RT305X_ESW_PORT6));
> > +               esw->global_vlan_enable = 1;
> > +               esw->pmap = RT305X_ESW_PMAP_WLLLL;
> > +               esw->vlans[0].vid = 1;
> > +               esw->vlans[1].vid = 2;
> > +               esw->ports[0].pvid = 2;
> > +               esw->ports[5].disable = 1;
> > +               esw->vlans[0].ports =
> > +                       BIT(RT305X_ESW_PORT1) | BIT(RT305X_ESW_PORT2) |
> > +                       BIT(RT305X_ESW_PORT3) | BIT(RT305X_ESW_PORT4) |
> > +                       BIT(RT305X_ESW_PORT6);
> > +               esw->vlans[1].ports =
> > +                               BIT(RT305X_ESW_PORT0) | 
> > BIT(RT305X_ESW_PORT6);
> >                 break;
> > 
> >         default:
> >                 BUG();
> >         }
> > +
> > +       rt305x_esw_apply_config(&esw->swdev);
> >  }
> > 
> >  static int
> > +rt305x_esw_apply_config(struct switch_dev *dev)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int i;
> > +       u8 disable = 0;
> > +       u8 doubletag = 0;
> > +       u8 en_vlan = 0;
> > +       u8 untag = 0;
> > +
> > +       for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
> > +               u32 vid, vmsc;
> > +               if (esw->global_vlan_enable) {
> > +                       vid = esw->vlans[i].vid;
> > +                       vmsc = esw->vlans[i].ports;
> > +               } else {
> > +                       vid = RT305X_ESW_VLAN_NONE;
> > +                       vmsc = RT305X_ESW_PORTS_NONE;
> > +               }
> > +               rt305x_esw_set_vlan_id(esw, i, vid);
> > +               rt305x_esw_set_vmsc(esw, i, vmsc);
> > +       }
> > +
> > +       for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
> > +               u32 pvid;
> > +               disable |= esw->ports[i].disable << i;
> > +               if (esw->global_vlan_enable) {
> > +                       doubletag |= esw->ports[i].doubletag << i;
> > +                       en_vlan   |= esw->ports[i].en_vlan   << i;
> > +                       untag     |= esw->ports[i].untag     << i;
> > +                       pvid       = esw->ports[i].pvid;
> > +               } else {
> > +                       int x = esw->alt_vlan_disable ? 0 : 1;
> > +                       doubletag |= x << i;
> > +                       en_vlan   |= x << i;
> > +                       untag     |= x << i;
> > +                       pvid       = 0;
> > +               }
> > +               rt305x_esw_set_pvid(esw, i, pvid);
> > +               if (i < RT305X_ESW_NUM_LEDS)
> > +                       rt305x_esw_wr(esw, esw->ports[i].led,
> > +                                     RT305X_ESW_REG_P0LED + 4*i);
> > +       }
> > +
> > +       rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
> > +                      RT305X_ESW_POC0_DIS_PORT_M << 
> > RT305X_ESW_POC0_DIS_PORT_S,
> > +                      disable << RT305X_ESW_POC0_DIS_PORT_S);
> > +       rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
> > +                      RT305X_ESW_SGC2_DOUBLE_TAG_M << 
> > RT305X_ESW_SGC2_DOUBLE_TAG_S,
> > +                      doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S);
> > +       rt305x_esw_rmw(esw, RT305X_ESW_REG_PFC1,
> > +                      RT305X_ESW_PFC1_EN_VLAN_M << 
> > RT305X_ESW_PFC1_EN_VLAN_S,
> > +                      en_vlan << RT305X_ESW_PFC1_EN_VLAN_S);
> > +       rt305x_esw_rmw(esw, RT305X_ESW_REG_POC2,
> > +                      RT305X_ESW_POC2_UNTAG_EN_M << 
> > RT305X_ESW_POC2_UNTAG_EN_S,
> > +                      untag << RT305X_ESW_POC2_UNTAG_EN_S);
> > +       /* unused feature, but still nice to be consistent here... */
> > +       rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
> > +                      RT305X_ESW_SGC2_LAN_PMAP_M << 
> > RT305X_ESW_SGC2_LAN_PMAP_S,
> > +                      ~esw->pmap << RT305X_ESW_SGC2_LAN_PMAP_S);
> > +
> > +       if (!esw->global_vlan_enable) {
> > +               /* Still need to put all ports into vlan 0 or they'll be 
> > isolated */
> > +               /* NOTE: vlan 0 is special, no vlan tag is prepended */
> > +               rt305x_esw_set_vlan_id(esw, 0, 0);
> > +               rt305x_esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_reset_switch(struct switch_dev *dev)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       esw->global_vlan_enable = 0;
> > +       memset(esw->ports, 0, sizeof(esw->ports));
> > +       memset(esw->vlans, 0, sizeof(esw->vlans));
> > +       rt305x_esw_hw_init(esw);
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_vlan_enable(struct switch_dev *dev,
> > +                           const struct switch_attr *attr,
> > +                           struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +
> > +       val->value.i = esw->global_vlan_enable;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_set_vlan_enable(struct switch_dev *dev,
> > +                           const struct switch_attr *attr,
> > +                           struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +
> > +       esw->global_vlan_enable = val->value.i != 0;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_alt_vlan_disable(struct switch_dev *dev,
> > +                                const struct switch_attr *attr,
> > +                                struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +
> > +       val->value.i = esw->alt_vlan_disable;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_set_alt_vlan_disable(struct switch_dev *dev,
> > +                                const struct switch_attr *attr,
> > +                                struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +
> > +       esw->alt_vlan_disable = val->value.i != 0;
> > +
> > +       return 0;
> > +}
> > +
> > +
> > +static int
> > +rt305x_esw_get_port_link(struct switch_dev *dev,
> > +                         int port,
> > +                         struct switch_port_link *link)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       u32 speed, poa;
> > +
> > +       if (port < 0 || port >= RT305X_ESW_NUM_PORTS)
> > +               return -EINVAL;
> > +
> > +       poa = rt305x_esw_rr(esw, RT305X_ESW_REG_POA) >> port;
> > +
> > +       link->link = (poa >> RT305X_ESW_LINK_S) & 1;
> > +       link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1;
> > +       if (port < RT305X_ESW_NUM_LEDS) {
> > +               speed = (poa >> RT305X_ESW_SPD_S) & 1;
> > +       } else {
> > +               if(port == RT305X_ESW_NUM_PORTS - 1)
> > +                       poa >>= 1;
> > +               speed = (poa >> RT305X_ESW_SPD_S) & 3;
> > +       }
> > +       switch (speed) {
> > +       case 0:
> > +               link->speed = SWITCH_PORT_SPEED_10;
> > +               break;
> > +       case 1:
> > +               link->speed = SWITCH_PORT_SPEED_100;
> > +               break;
> > +       case 2:
> > +       case 3: /* forced gige speed can be 2 or 3 */
> > +               link->speed = SWITCH_PORT_SPEED_1000;
> > +               break;
> > +       default:
> > +               link->speed = SWITCH_PORT_SPEED_UNKNOWN;
> > +               break;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_port_bool(struct switch_dev *dev,
> > +                         const struct switch_attr *attr,
> > +                         struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int idx = val->port_vlan;
> > +       u32 x, reg, shift;
> > +
> > +       if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS)
> > +               return -EINVAL;
> > +
> > +       switch (attr->id) {
> > +       case RT305X_ESW_ATTR_PORT_DISABLE:
> > +               reg = RT305X_ESW_REG_POC0;
> > +               shift = RT305X_ESW_POC0_DIS_PORT_S;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_DOUBLETAG:
> > +               reg = RT305X_ESW_REG_SGC2;
> > +               shift = RT305X_ESW_SGC2_DOUBLE_TAG_S;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_EN_VLAN:
> > +               reg = RT305X_ESW_REG_PFC1;
> > +               shift = RT305X_ESW_PFC1_EN_VLAN_S;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_UNTAG:
> > +               reg = RT305X_ESW_REG_POC2;
> > +               shift = RT305X_ESW_POC2_UNTAG_EN_S;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_LAN:
> > +               reg = RT305X_ESW_REG_SGC2;
> > +               shift = RT305X_ESW_SGC2_LAN_PMAP_S;
> > +               if (idx >= RT305X_ESW_NUM_LANWAN)
> > +                       return -EINVAL;
> > +               break;
> > +       default:
> > +               return -EINVAL;
> > +       }
> > +
> > +       x = rt305x_esw_rr(esw, reg);
> > +       val->value.i = (x >> (idx + shift)) & 1;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_set_port_bool(struct switch_dev *dev,
> > +                         const struct switch_attr *attr,
> > +                         struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int idx = val->port_vlan;
> > +
> > +       if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
> > +           val->value.i < 0 || val->value.i > 1)
> > +               return -EINVAL;
> > +
> > +       switch (attr->id) {
> > +       case RT305X_ESW_ATTR_PORT_DISABLE:
> > +               esw->ports[idx].disable = val->value.i;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_DOUBLETAG:
> > +               esw->ports[idx].doubletag = val->value.i;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_EN_VLAN:
> > +               esw->ports[idx].en_vlan = val->value.i;
> > +               break;
> > +       case RT305X_ESW_ATTR_PORT_UNTAG:
> > +               esw->ports[idx].untag = val->value.i;
> > +               break;
> > +       default:
> > +               return -EINVAL;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_port_recv_badgood(struct switch_dev *dev,
> > +                                 const struct switch_attr *attr,
> > +                                 struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int idx = val->port_vlan;
> > +       int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16;
> > +
> > +       if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN)
> > +               return -EINVAL;
> > +
> > +       val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0PC + 4*idx) >> 
> > shift;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_port_led(struct switch_dev *dev,
> > +                        const struct switch_attr *attr,
> > +                        struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int idx = val->port_vlan;
> > +
> > +       if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
> > +           idx >= RT305X_ESW_NUM_LEDS)
> > +               return -EINVAL;
> > +
> > +       val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0LED + 4*idx);
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_set_port_led(struct switch_dev *dev,
> > +                        const struct switch_attr *attr,
> > +                        struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int idx = val->port_vlan;
> > +
> > +       if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS)
> > +               return -EINVAL;
> > +
> > +       esw->ports[idx].led = val->value.i;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_port_pvid(struct switch_dev *dev, int port, int *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +
> > +       if (port >= RT305X_ESW_NUM_PORTS)
> > +               return -EINVAL;
> > +
> > +       *val = rt305x_esw_get_pvid(esw, port);
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_set_port_pvid(struct switch_dev *dev, int port, int val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +
> > +       if (port >= RT305X_ESW_NUM_PORTS)
> > +               return -EINVAL;
> > +
> > +       esw->ports[port].pvid = val;
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       u32 vmsc, poc2;
> > +       int vlan_idx = -1;
> > +       int i;
> > +
> > +       val->len = 0;
> > +
> > +       if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS)
> > +               return -EINVAL;
> > +
> > +       // valid vlan?
> > +       for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
> > +               if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan &&
> > +                   rt305x_esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) {
> > +                       vlan_idx = i;
> > +                       break;
> > +               }
> > +       }
> > +
> > +       if (vlan_idx == -1)
> > +               return -EINVAL;
> > +
> > +       vmsc = rt305x_esw_get_vmsc(esw, vlan_idx);
> > +       poc2 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC2);
> > +
> > +       for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
> > +               struct switch_port *p;
> > +               int port_mask = 1 << i;
> > +
> > +               if (!(vmsc & port_mask))
> > +                       continue;
> > +
> > +               p = &val->value.ports[val->len++];
> > +               p->id = i;
> > +               if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S))
> > +                       p->flags = 0;
> > +               else
> > +                       p->flags = 1 << SWITCH_PORT_FLAG_TAGGED;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> > +rt305x_esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
> > +{
> > +       struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, 
> > swdev);
> > +       int ports;
> > +       int vlan_idx = -1;
> > +       int i;
> > +
> > +       if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS ||
> > +           val->len > RT305X_ESW_NUM_PORTS)
> > +               return -EINVAL;
> > +
> > +       // one of the already defined vlans?
> > +       for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
> > +               if (esw->vlans[i].vid == val->port_vlan &&
> > +                   esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) {
> > +                       vlan_idx = i;
> > +                       break;
> > +               }
> > +       }
> > +
> > +       // select a free slot
> > +       for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) {
> > +               if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE)
> > +                       vlan_idx = i;
> > +       }
> > +
> > +       // bail if all slots are in use
> > +       if (vlan_idx == -1)
> > +               return -EINVAL;
> > +
> > +       ports = RT305X_ESW_PORTS_NONE;
> > +       for (i = 0; i < val->len; i++) {
> > +               struct switch_port *p = &val->value.ports[i];
> > +               int port_mask = 1 << p->id;
> > +               bool untagged = !(p->flags & (1 << 
> > SWITCH_PORT_FLAG_TAGGED));
> > +
> > +               if (p->id >= RT305X_ESW_NUM_PORTS)
> > +                       return -EINVAL;
> > +
> > +               ports |= port_mask;
> > +               esw->ports[p->id].untag = untagged;
> > +       }
> > +       esw->vlans[vlan_idx].ports = ports;
> > +       if (ports == RT305X_ESW_PORTS_NONE)
> > +               esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE;
> > +       else
> > +               esw->vlans[vlan_idx].vid = val->port_vlan;
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct switch_attr rt305x_esw_global[] = {
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "enable_vlan",
> > +               .description = "VLAN mode (1:enabled)",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_ENABLE_VLAN,
> > +               .get = rt305x_esw_get_vlan_enable,
> > +               .set = rt305x_esw_set_vlan_enable,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "alternate_vlan_disable",
> > +               .description = "Use en_vlan instead of doubletag to disable 
> > VLAN mode",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
> > +               .get = rt305x_esw_get_alt_vlan_disable,
> > +               .set = rt305x_esw_set_alt_vlan_disable,
> > +       },
> > +};
> > +
> > +static const struct switch_attr rt305x_esw_port[] = {
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "disable",
> > +               .description = "Port state (1:disabled)",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_PORT_DISABLE,
> > +               .get = rt305x_esw_get_port_bool,
> > +               .set = rt305x_esw_set_port_bool,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "doubletag",
> > +               .description = "Double tagging for incoming vlan packets 
> > (1:enabled)",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_PORT_DOUBLETAG,
> > +               .get = rt305x_esw_get_port_bool,
> > +               .set = rt305x_esw_set_port_bool,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "en_vlan",
> > +               .description = "VLAN enabled (1:enabled)",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_PORT_EN_VLAN,
> > +               .get = rt305x_esw_get_port_bool,
> > +               .set = rt305x_esw_set_port_bool,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "untag",
> > +               .description = "Untag (1:strip outgoing vlan tag)",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_PORT_UNTAG,
> > +               .get = rt305x_esw_get_port_bool,
> > +               .set = rt305x_esw_set_port_bool,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "led",
> > +               .description = "LED mode (0:link, 1:100m, 2:duplex, 
> > 3:activity, "
> > +                              "4:collision, 5:linkact, 6:duplcoll, 
> > 7:10mact, "
> > +                              "8:100mact, 10:blink, 12:on)",
> > +               .max = 15,
> > +               .id = RT305X_ESW_ATTR_PORT_LED,
> > +               .get = rt305x_esw_get_port_led,
> > +               .set = rt305x_esw_set_port_led,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "lan",
> > +               .description = "HW port group (0:wan, 1:lan)",
> > +               .max = 1,
> > +               .id = RT305X_ESW_ATTR_PORT_LAN,
> > +               .get = rt305x_esw_get_port_bool,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "recv_bad",
> > +               .description = "Receive bad packet counter",
> > +               .id = RT305X_ESW_ATTR_PORT_RECV_BAD,
> > +               .get = rt305x_esw_get_port_recv_badgood,
> > +       },
> > +       {
> > +               .type = SWITCH_TYPE_INT,
> > +               .name = "recv_good",
> > +               .description = "Receive good packet counter",
> > +               .id = RT305X_ESW_ATTR_PORT_RECV_GOOD,
> > +               .get = rt305x_esw_get_port_recv_badgood,
> > +       },
> > +};
> > +
> > +static const struct switch_attr rt305x_esw_vlan[] = {
> > +};
> > +
> > +static const struct switch_dev_ops rt305x_esw_ops = {
> > +       .attr_global = {
> > +               .attr = rt305x_esw_global,
> > +               .n_attr = ARRAY_SIZE(rt305x_esw_global),
> > +       },
> > +       .attr_port = {
> > +               .attr = rt305x_esw_port,
> > +               .n_attr = ARRAY_SIZE(rt305x_esw_port),
> > +       },
> > +       .attr_vlan = {
> > +               .attr = rt305x_esw_vlan,
> > +               .n_attr = ARRAY_SIZE(rt305x_esw_vlan),
> > +       },
> > +       .get_vlan_ports = rt305x_esw_get_vlan_ports,
> > +       .set_vlan_ports = rt305x_esw_set_vlan_ports,
> > +       .get_port_pvid = rt305x_esw_get_port_pvid,
> > +       .set_port_pvid = rt305x_esw_set_port_pvid,
> > +       .get_port_link = rt305x_esw_get_port_link,
> > +       .apply_config = rt305x_esw_apply_config,
> > +       .reset_switch = rt305x_esw_reset_switch,
> > +};
> > +
> > +static int
> >  rt305x_esw_probe(struct platform_device *pdev)
> >  {
> >         struct rt305x_esw_platform_data *pdata;
> >         struct rt305x_esw *esw;
> > +       struct switch_dev *swdev;
> >         struct resource *res;
> >         int err;
> > 
> > @@ -351,6 +1036,20 @@
> >                 goto free_esw;
> >         }
> > 
> > +       swdev = &esw->swdev;
> > +       swdev->name = "rt305x-esw";
> > +       swdev->alias = "rt305x";
> > +       swdev->cpu_port = RT305X_ESW_PORT6;
> > +       swdev->ports = RT305X_ESW_NUM_PORTS;
> > +       swdev->vlans = RT305X_ESW_NUM_VIDS;
> > +       swdev->ops = &rt305x_esw_ops;
> > +
> > +       err = register_switch(swdev, NULL);
> > +       if (err < 0) {
> > +               dev_err(&pdev->dev, "register_switch failed\n");
> > +               goto free_esw;
> > +       }
> > +
> >         platform_set_drvdata(pdev, esw);
> > 
> >         esw->pdata = pdata;
> > @@ -371,6 +1070,7 @@
> > 
> >         esw = platform_get_drvdata(pdev);
> >         if (esw) {
> > +               unregister_switch(&esw->swdev);
> >                 platform_set_drvdata(pdev, NULL);
> >                 iounmap(esw->base);
> >                 kfree(esw);
> > Index: target/linux/ramips/base-files/etc/uci-defaults/network
> > ===================================================================
> > --- target/linux/ramips/base-files/etc/uci-defaults/network     (revision 
> > 31618)
> > +++ target/linux/ramips/base-files/etc/uci-defaults/network     (working 
> > copy)
> > @@ -9,6 +9,31 @@
> >         return
> >  fi
> > 
> > +ramips_setup_rt3x5x_vlans()
> > +{
> > +       if [ ! -x /sbin/swconfig ]; then
> > +               # legacy default
> > +               ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2"
> > +               return
> > +       fi
> > +       local wanports=""
> > +       local lanports=""
> > +       for port in 5 4 3 2 1 0; do
> > +               if [ `swconfig dev rt305x port $port get disable` = "1" ]; 
> > then
> > +                       continue
> > +               fi
> > +               if [ `swconfig dev rt305x port $port get lan` = "0" ]; then
> > +                       wanports="$port $wanports"
> > +               else
> > +                       lanports="$port $lanports"
> > +               fi
> > +       done
> > +       ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2"
> > +       ucidef_add_switch "rt305x" "1" "1"
> > +       ucidef_add_switch_vlan "rt305x" "1" "$lanports 6t"
> > +       ucidef_add_switch_vlan "rt305x" "2" "$wanports 6t"
> > +}
> > +
> >  ramips_setup_interfaces()
> >  {
> >         local board="$1"
> > @@ -70,7 +95,7 @@
> >         *)
> >                 RT3X5X=`cat /proc/cpuinfo | grep RT3.5`
> >                 if [ -n "${RT3X5X}" ]; then
> > -                       ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2"
> > +                       ramips_setup_rt3x5x_vlans
> >                 else
> >                         ucidef_set_interfaces_lan_wan "eth0" "eth1"
> >                 fi
> > _______________________________________________
> > openwrt-devel mailing list
> > openwrt-devel@lists.openwrt.org
> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
> > 
> 
> 
> -- 
> ALLNET GmbH ; Maistr. 2 ; D-82110 Germering ; Germany
> Tel. +49-89-89422217 - Fax +49-89-89422233
> http://www.allnet.de
> email: Daniel Golle <dgo...@allnet.de>
> Schulungs-/Veranstaltungsprogramm: http://www.802lab.de<http://www.802lab.de/>
> Geschäftsführer: Wolfgang Marcus Bauer
> Handelsregister München B 95922 ; UST-ID-Nr. DE 128214294 ;
> St.-Nr.117/115/00164
> WEEE-Reg.-NR. DE 13101093
> Bankverbindung:
> Sparkasse Fürstenfeldbruck KTO: 2774594 ; BLZ: 70053070
> Swift-Code: BYLADEM1FFB ; IBAN: DE61700530700002774594

-- 
Tobias                                          PGP: http://8ef7ddba.uguu.de
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to