aboutsummaryrefslogtreecommitdiffstats
path: root/package/switch
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2013-02-13 16:04:50 +0000
committerHauke Mehrtens <hauke@hauke-m.de>2013-02-13 16:04:50 +0000
commit43b4f67f25ade4fdec8354df37051059c2fc839b (patch)
treeafad2dace3cc5ba9d91a1ad373b0fb80f03457fe /package/switch
parent8ab78d10969f47e62881ae083e19828856fd2421 (diff)
downloadupstream-43b4f67f25ade4fdec8354df37051059c2fc839b.tar.gz
upstream-43b4f67f25ade4fdec8354df37051059c2fc839b.tar.bz2
upstream-43b4f67f25ade4fdec8354df37051059c2fc839b.zip
switch: read and write vlan config from and to gigabit switches
This patch makes it possible to read and write the vlan config from and to recent switchs. This is based on a patch by jcharest and the Broadcom SDK. SVN-Revision: 35584
Diffstat (limited to 'package/switch')
-rw-r--r--package/switch/src/switch-robo.c135
1 files changed, 105 insertions, 30 deletions
diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c
index 41f0c1826d..aaccdd9f6b 100644
--- a/package/switch/src/switch-robo.c
+++ b/package/switch/src/switch-robo.c
@@ -74,6 +74,7 @@ struct robo_switch {
u16 devid; /* ROBO_DEVICE_ID_53xx */
bool is_5365;
bool gmii; /* gigabit mii */
+ u8 corerev;
int gpio_robo_reset;
int gpio_lanports_enable;
struct ifreq ifr;
@@ -419,8 +420,7 @@ err_done:
return err;
}
-
-static int handle_vlan_port_read(void *driver, char *buf, int nr)
+static int handle_vlan_port_read_old(switch_driver *d, char *buf, int nr)
{
__u16 val16;
int len = 0;
@@ -433,11 +433,11 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr)
/* actual read */
val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
if ((val16 & (1 << 14)) /* valid */) {
- for (j = 0; j < 6; j++) {
+ for (j = 0; j < d->ports; j++) {
if (val16 & (1 << j)) {
len += sprintf(buf + len, "%d", j);
if (val16 & (1 << (j + 7))) {
- if (j == 5)
+ if (j == d->cpuport)
buf[len++] = 'u';
} else {
buf[len++] = 't';
@@ -455,11 +455,11 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr)
/* actual read */
val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
if ((val32 & (1 << 20)) /* valid */) {
- for (j = 0; j < 6; j++) {
+ for (j = 0; j < d->ports; j++) {
if (val32 & (1 << j)) {
len += sprintf(buf + len, "%d", j);
- if (val32 & (1 << (j + 6))) {
- if (j == 5)
+ if (val32 & (1 << (j + d->ports))) {
+ if (j == d->cpuport)
buf[len++] = 'u';
} else {
buf[len++] = 't';
@@ -478,45 +478,120 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr)
return len;
}
-static int handle_vlan_port_write(void *driver, char *buf, int nr)
+static int handle_vlan_port_read_new(switch_driver *d, char *buf, int nr)
{
- switch_driver *d = (switch_driver *) driver;
- switch_vlan_config *c = switch_parse_vlan(d, buf);
+ __u8 vtbl_entry, vtbl_index, vtbl_access;
+ __u32 val32;
+ int len = 0;
int j;
- __u16 val16;
- if (c == NULL)
- return -EINVAL;
+ if ((robo.devid == ROBO_DEVICE_ID_5395) ||
+ (robo.devid == ROBO_DEVICE_ID_53115)) {
+ vtbl_access = ROBO_VTBL_ACCESS_5395;
+ vtbl_index = ROBO_VTBL_INDX_5395;
+ vtbl_entry = ROBO_VTBL_ENTRY_5395;
+ } else {
+ vtbl_access = ROBO_VTBL_ACCESS;
+ vtbl_index = ROBO_VTBL_INDX;
+ vtbl_entry = ROBO_VTBL_ENTRY;
+ }
+ robo_write16(ROBO_ARLIO_PAGE, vtbl_index, nr);
+ robo_write16(ROBO_ARLIO_PAGE, vtbl_access, (1 << 7) | (1 << 0));
+ val32 = robo_read32(ROBO_ARLIO_PAGE, vtbl_entry);
for (j = 0; j < d->ports; j++) {
- if ((c->untag | c->pvid) & (1 << j))
- /* change default vlan tag */
- robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr);
+ if (val32 & (1 << j)) {
+ len += sprintf(buf + len, "%d", j);
+ if (val32 & (1 << (j + d->ports))) {
+ if (j == d->cpuport)
+ buf[len++] = 'u';
+ } else {
+ buf[len++] = 't';
+ if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
+ buf[len++] = '*';
+ }
+ buf[len++] = '\t';
+ }
}
+ len += sprintf(buf + len, "\n");
+ buf[len] = '\0';
+ return len;
+}
- /* write config now */
+static int handle_vlan_port_read(void *driver, char *buf, int nr)
+{
+ switch_driver *d = (switch_driver *) driver;
- if (robo.devid != ROBO_DEVICE_ID_5325) {
- __u8 regoff = ((robo.devid == ROBO_DEVICE_ID_5395) ||
- (robo.devid == ROBO_DEVICE_ID_53115)) ? 0x20 : 0;
+ if (robo.devid != ROBO_DEVICE_ID_5325)
+ return handle_vlan_port_read_new(d, buf, nr);
+ else
+ return handle_vlan_port_read_old(d, buf, nr);
+}
- robo_write32(ROBO_ARLIO_PAGE, 0x63 + regoff, (c->untag << 9) | c->port);
- robo_write16(ROBO_ARLIO_PAGE, 0x61 + regoff, nr);
- robo_write16(ROBO_ARLIO_PAGE, 0x60 + regoff, 1 << 7);
- kfree(c);
- return 0;
- }
+static void handle_vlan_port_write_old(switch_driver *d, switch_vlan_config *c, int nr)
+{
+ __u16 val16;
+ __u32 val32;
+ __u32 untag = ((c->untag & ~(1 << d->cpuport)) << d->ports);
+ /* write config now */
val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
if (robo.is_5365) {
- robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5365,
- (1 << 14) /* valid */ | (c->untag << 7) | c->port);
+ robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5365,
+ (1 << 14) /* valid */ | (untag << 1 ) | c->port);
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5365, val16);
} else {
- robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
- (1 << 20) /* valid */ | (c->untag << 6) | c->port);
+ if (robo.corerev < 3)
+ val32 = (1 << 20) | ((nr >> 4) << 12) | untag | c->port;
+ else
+ val32 = (1 << 24) | (nr << 12) | untag | c->port;
+ robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, val32);
robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
}
+}
+
+static void handle_vlan_port_write_new(switch_driver *d, switch_vlan_config *c, int nr)
+{
+ __u8 vtbl_entry, vtbl_index, vtbl_access;
+ __u32 untag = ((c->untag & ~(1 << d->cpuport)) << d->ports);
+
+ /* write config now */
+ if ((robo.devid == ROBO_DEVICE_ID_5395) ||
+ (robo.devid == ROBO_DEVICE_ID_53115)) {
+ vtbl_access = ROBO_VTBL_ACCESS_5395;
+ vtbl_index = ROBO_VTBL_INDX_5395;
+ vtbl_entry = ROBO_VTBL_ENTRY_5395;
+ } else {
+ vtbl_access = ROBO_VTBL_ACCESS;
+ vtbl_index = ROBO_VTBL_INDX;
+ vtbl_entry = ROBO_VTBL_ENTRY;
+ }
+
+ robo_write32(ROBO_ARLIO_PAGE, vtbl_entry, untag | c->port);
+ robo_write16(ROBO_ARLIO_PAGE, vtbl_index, nr);
+ robo_write16(ROBO_ARLIO_PAGE, vtbl_access, 1 << 7);
+}
+
+static int handle_vlan_port_write(void *driver, char *buf, int nr)
+{
+ switch_driver *d = (switch_driver *)driver;
+ switch_vlan_config *c = switch_parse_vlan(d, buf);
+ int j;
+
+ if (c == NULL)
+ return -EINVAL;
+
+ for (j = 0; j < d->ports; j++) {
+ if ((c->untag | c->pvid) & (1 << j)) {
+ /* change default vlan tag */
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr);
+ }
+ }
+
+ if (robo.devid != ROBO_DEVICE_ID_5325)
+ handle_vlan_port_write_new(d, c, nr);
+ else
+ handle_vlan_port_write_old(d, c, nr);
kfree(c);
return 0;