On 02/11/2013 10:33 PM, Rafał Miłecki wrote:
> 2013/2/11 Rafał Miłecki <[email protected]>:
>> I've compiled two extra tools: tcpdump and arp.
>>
>> It seems that OpenWRT can't understand ARP response. See attached
>> tcpdump.and.ping.all.on.router.txt - it's a ping and tcpdump both
>> running on OpenWRT router.
>>
>> Router want to ping 192.168.1.2, so it's sending ARP request:
>> FF FF FF FF FF FF (dest)
>> C8 3A 35 40 C1 A8 (src)
>> 81 00 00 00 (vlan0)
>> 08 06 (arp)
>>
>> My PC replies to the request:
>> C8 3A 35 40 C1 A8 (dest)
>> 00 1D BA 19 9E DB (src)
>> 81 00 00 01 (vlan1)
>> 08 06 (arp)
>>
>> And... nothing! There isn't ICMP request sent by the router. I've
>> decided to check the arp table:
>> # arp
>> IP address       HW type     Flags       HW address            Mask     
>> Device
>> 192.168.1.2      0x1         0x0         00:00:00:00:00:00     *        
>> br-lan
>>
>> Is this the reason? Linux can't parse ARP response from the PC and
>> doesn't know it's MAC?
> 
> That theory makes even more sense after re-thinking it.
> 
> When I ping router from my PC, there are three packets repeated over and over:
> 1) PC sends ICMP request
> 2) Router sends ARP requres
> 3) PC sends ARP reply
> but nothing more... Router seems to ignore/don't understand ARP reply
> and can't reply for ICMP request.
> 
> Do you remember me saying that for a few seconds after doing
> brctl delif br-lan eth0
> brctl addif br-lan eth0.0
> I can still ping the router? It looks it could be thanks to the ARP
> cache. When using eth0 for br-lan router received and parsed ARP
> response. After a switching back to eth0.0 (from eth0) router was
> still using arp cache table until it expired.
> Make sense to me.
> 
> The only question... WHY router can't understand ARP responses over
> br-lan connected to eth0.0? :(
> 

I now got my device with BCM4706 and BCM53125 working. The last problem
was that the switch removed the vlan tags on the CPU port. I used
current OpenWrt trunk + the attached patch. This patch partly contains
the stuff from https://dev.openwrt.org/ticket/7198#comment:61 . I will
commit it to OpenWrt in the next days.

Hauke
diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c
index f3a0eac..08592e8 100644
--- a/package/switch/src/switch-robo.c
+++ b/package/switch/src/switch-robo.c
@@ -17,7 +17,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  */
 
@@ -29,6 +29,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <asm/uaccess.h>
 
 #include "switch-core.h"
@@ -62,6 +63,7 @@
 #define  ROBO_DEVICE_ID_5397	0x97
 #define  ROBO_DEVICE_ID_5398	0x98
 #define  ROBO_DEVICE_ID_53115	0x3115
+#define  ROBO_DEVICE_ID_53125	0x3125
 
 /* Private et.o ioctls */
 #define SIOCGETCPHYRD           (SIOCDEVPRIVATE + 9)
@@ -75,7 +77,7 @@ struct robo_switch {
 	u8 gmii;			/* gigabit mii */
 	struct ifreq ifr;
 	struct net_device *dev;
-	unsigned char port[6];
+	unsigned char port[9];
 };
 
 /* Currently we can only have one device in the system. */
@@ -247,9 +249,16 @@ static int robo_switch_enable(void)
 		}
 
 		last_port = (robo.devid == ROBO_DEVICE_ID_5398) ?
-				ROBO_PORT6_CTRL : ROBO_PORT3_CTRL;
-		for (i = ROBO_PORT0_CTRL; i < last_port + 1; i++)
+				ROBO_PORT7_CTRL : ROBO_PORT4_CTRL;
+		for (i = ROBO_PORT0_CTRL; i <= last_port; i++)
 			robo_write16(ROBO_CTRL_PAGE, i, 0);
+		robo_write16(ROBO_CTRL_PAGE, ROBO_IM_PORT_CTRL, 0);
+	}
+
+	if (robo.devid == ROBO_DEVICE_ID_53115 || robo.devid == ROBO_DEVICE_ID_53125) {
+		/* Make IM port status link by default */
+		val = robo_read16(ROBO_CTRL_PAGE, ROBO_PORT_OVERRIDE_CTRL) | 0x81;
+		robo_write16(ROBO_CTRL_PAGE, ROBO_PORT_OVERRIDE_CTRL, val);
 	}
 
 #ifdef CONFIG_BCM47XX
@@ -274,12 +283,34 @@ static void robo_switch_reset(void)
 	}
 }
 
+#ifdef CONFIG_BCM47XX
+static int get_gpio_pin(const char *name)
+{
+	int i, err;
+	char nvram_var[10];
+	char buf[30];
+
+	for (i = 0; i < 16; i++) {
+		err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
+		if (err <= 0)
+			continue;
+		err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
+		if (err <= 0)
+			continue;
+		if (!strcmp(name, buf))
+			return i;
+	}
+	return -1;
+}
+#endif
+
 static int robo_probe(char *devname)
 {
 	__u32 phyid;
 	unsigned int i;
 	int err = 1;
 	struct mii_ioctl_data *mii;
+	int lanports_enable, robo_reset;
 
 	printk(KERN_INFO PFX "Probing device '%s'\n", devname);
 	strcpy(robo.ifr.ifr_name, devname);
@@ -294,9 +325,6 @@ static int robo_probe(char *devname)
 	}
 
 	robo.device = devname;
-	for (i = 0; i < 5; i++)
-		robo.port[i] = i;
-	robo.port[5] = 8;
 
 	/* try access using MII ioctls - get phy address */
 	err = do_ioctl(SIOCGMIIPHY);
@@ -311,14 +339,37 @@ static int robo_probe(char *devname)
 	    (mii->phy_id != ROBO_PHY_ADDR_BCM63XX) &&
 	    (mii->phy_id != ROBO_PHY_ADDR_TG3)) {
 		printk(KERN_ERR PFX "Invalid phy address (%d)\n", mii->phy_id);
+		err = -1;
 		goto done;
 	}
 
-	phyid = mdio_read(ROBO_PHY_ADDR, 0x2) | 
+#ifdef CONFIG_BCM47XX
+	lanports_enable = get_gpio_pin("lanports_enable");
+	if (lanports_enable >= 0) {
+		gpio_direction_output(lanports_enable, 1);
+		mdelay(5);
+	}
+
+	robo_reset = get_gpio_pin("robo_reset");
+	if (robo_reset >= 0) {
+		gpio_set_value(robo_reset, 0);
+		gpio_direction_output(robo_reset, 1);
+		gpio_set_value(robo_reset, 0);
+		mdelay(50);
+
+		gpio_set_value(robo_reset, 1);
+		mdelay(20);
+	} else {
+		// TODO: reset the internal robo switch
+	}
+#endif
+
+	phyid = mdio_read(ROBO_PHY_ADDR, 0x2) |
 		(mdio_read(ROBO_PHY_ADDR, 0x3) << 16);
 
 	if (phyid == 0xffffffff || phyid == 0x55210022) {
 		printk(KERN_ERR PFX "No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid);
+		err = -1;
 		goto done;
 	}
 
@@ -333,6 +384,18 @@ static int robo_probe(char *devname)
 		robo.devid = ROBO_DEVICE_ID_5325; /* Fake it */
 	robo.is_5350 = robo_vlan5350(phyid);
 
+	/* Fill ports */
+	if (robo.devid != ROBO_DEVICE_ID_5325) {
+		for (i = 0; i < 5; i++)
+			robo.port[i] = i;
+	}
+	else
+	{
+		for (i = 0; i < 8; i++)
+			robo.port[i] = i;
+	}
+	robo.port[i] = ROBO_IM_PORT_CTRL;
+
 	robo_switch_reset();
 	err = robo_switch_enable();
 	if (err)
@@ -353,43 +416,57 @@ done:
 
 static int handle_vlan_port_read(void *driver, char *buf, int nr)
 {
+	switch_driver *d = (switch_driver *) driver;
 	__u16 val16;
+	__u32 val32;
 	int len = 0;
 	int j;
 
 	val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
 
-	if (robo.is_5350) {
-		u32 val32;
-		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
-		/* actual read */
-		val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
-		if ((val32 & (1 << 20)) /* valid */) {
-			for (j = 0; j < 6; j++) {
-				if (val32 & (1 << j)) {
-					len += sprintf(buf + len, "%d", j);
-					if (val32 & (1 << (j + 6))) {
-						if (j == 5) 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';
+
+	if (robo.devid != ROBO_DEVICE_ID_5325) {
+		__u8 vtbl_entry, vtbl_index, vtbl_access;
+
+		if ((robo.devid == ROBO_DEVICE_ID_5395) ||
+		    (robo.devid == ROBO_DEVICE_ID_53115) ||
+		    (robo.devid == ROBO_DEVICE_ID_53125)) {
+			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 (val32 & (1 << j)) {
+				len += sprintf(buf + len, "%d", j);
+				if (val32 & (1 << (j + d->ports))) {
+					if (j == d->ports - 1) 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");
 		}
+		len += sprintf(buf + len, "\n");
 	} else {
-		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
 		/* actual read */
-		val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
-		if ((val16 & (1 << 14)) /* valid */) {
-			for (j = 0; j < 6; j++) {
-				if (val16 & (1 << j)) {
+		val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
+		if ((val32 & (1 << 20)) /* valid */) {
+			for (j = 0; j < d->ports; j++) {
+				if (val32 & (1 << j)) {
 					len += sprintf(buf + len, "%d", j);
-					if (val16 & (1 << (j + 7))) {
-						if (j == 5) buf[len++] = 'u';
+					if (val32 & (1 << (j + d->ports))) {
+						if (j == d->ports - 1) buf[len++] = 'u';
 					} else {
 						buf[len++] = 't';
 						if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
@@ -418,33 +495,44 @@ static int handle_vlan_port_write(void *driver, char *buf, int nr)
 		return -EINVAL;
 
 	for (j = 0; j < d->ports; j++) {
-		if ((c->untag | c->pvid) & (1 << 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);
+		}
 	}
 
 	/* write config now */
-
 	if (robo.devid != ROBO_DEVICE_ID_5325) {
-		__u8 regoff = ((robo.devid == ROBO_DEVICE_ID_5395) ||
-			(robo.devid == ROBO_DEVICE_ID_53115)) ? 0x20 : 0;
+		__u8 vtbl_entry, vtbl_index, vtbl_access;
+
+		if ((robo.devid == ROBO_DEVICE_ID_5395) ||
+		    (robo.devid == ROBO_DEVICE_ID_53115) ||
+		    (robo.devid == ROBO_DEVICE_ID_53125)) {
+			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, 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;
+		robo_write32(ROBO_ARLIO_PAGE, vtbl_entry, ((c->untag  & ~(1 << d->cpuport)) << d->ports) | c->port);
+		robo_write16(ROBO_ARLIO_PAGE, vtbl_index, nr);
+		robo_write16(ROBO_ARLIO_PAGE, vtbl_access, 1 << 7);
 	}
-
-	val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
-	if (robo.is_5350) {
-		robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350,
-			(1 << 20) /* valid */ | (c->untag << 6) | c->port);
-		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
-	} else {
-		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
-			(1 << 14)  /* valid */ | (c->untag << 7) | c->port);
-		robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+	else
+	{
+		val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+		if (robo.is_5350) {
+			robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350,
+				(1 << 20) /* valid */ | (c->untag << 6) | c->port);
+			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+		} else {
+			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
+				(1 << 14)  /* valid */ | (c->untag << 7) | c->port);
+			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+		}
 	}
 
 	kfree(c);
@@ -534,7 +622,7 @@ static int handle_port_media_write(void *driver, char *buf, int nr)
 	}
 
 	bmcr_mask = ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_ANRESTART);
-	mdio_write(robo.port[nr], MII_BMCR, 
+	mdio_write(robo.port[nr], MII_BMCR,
 		(mdio_read(robo.port[nr], MII_BMCR) & bmcr_mask) | bmcr);
 
 	return 0;
@@ -548,11 +636,15 @@ static int handle_enable_vlan_read(void *driver, char *buf, int nr)
 static int handle_enable_vlan_write(void *driver, char *buf, int nr)
 {
 	int disable = ((buf[0] != '1') ? 1 : 0);
+	__u16 val16;
 
+	val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0);
 	robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 :
-		(1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
+		val16 | (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
+
+	val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1);
 	robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1, disable ? 0 :
-		(robo.devid == ROBO_DEVICE_ID_5325 ? (1 << 1) :
+		val16 | (robo.devid == ROBO_DEVICE_ID_5325 ? (1 << 1) :
 		0) | (1 << 2) | (1 << 3)); /* RSV multicast */
 
 	if (robo.devid != ROBO_DEVICE_ID_5325)
@@ -576,16 +668,34 @@ static int handle_reset(void *driver, char *buf, int nr)
 	set_switch(0);
 
 	/* reset vlans */
-	for (j = 0; j <= ((robo.is_5350) ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) {
-		/* write config now */
-		val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
-		if (robo.is_5350)
+	if (robo.devid != ROBO_DEVICE_ID_5325) {
+		__u8 vtbl_entry, vtbl_index, vtbl_access;
+
+		if ((robo.devid == ROBO_DEVICE_ID_5395) ||
+		    (robo.devid == ROBO_DEVICE_ID_53115) ||
+		    (robo.devid == ROBO_DEVICE_ID_53125)) {
+			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;
+		}
+
+		for (j = 0; j <= ((robo.is_5350) ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) {
+			/* write config now */
+			robo_write32(ROBO_ARLIO_PAGE, vtbl_entry, 0);
+			robo_write16(ROBO_ARLIO_PAGE, vtbl_index, j);
+			robo_write16(ROBO_ARLIO_PAGE, vtbl_access, 1 << 7);
+		}
+	} else {
+		for (j = 0; j <= VLAN_ID_MAX5350; j++) {
+			/* write config now */
+			val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
 			robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0);
-		else
-			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0);
-		robo_write16(ROBO_VLAN_PAGE, robo.is_5350 ? ROBO_VLAN_TABLE_ACCESS_5350 :
-							    ROBO_VLAN_TABLE_ACCESS,
-			     val16);
+			robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+		}
 	}
 
 	/* reset ports to a known good state */
diff --git a/target/linux/brcm47xx/base-files/etc/init.d/netconfig b/target/linux/brcm47xx/base-files/etc/init.d/netconfig
index 303ab56..0dcebab 100755
--- a/target/linux/brcm47xx/base-files/etc/init.d/netconfig
+++ b/target/linux/brcm47xx/base-files/etc/init.d/netconfig
@@ -166,7 +166,9 @@ start() {
 		}
 
 		# generic broadcom 4716 processor with 53115 switch
-		if (tolower(nvram["boardtype"]) == "0x04cf") {
+		if ((tolower(nvram["boardtype"]) == "0x04cf") || \
+			(tolower(nvram["boardtype"]) == "0xf5b2") || \
+			(tolower(nvram["boardtype"]) == "0xf52e")) {
 			c["vlan0ports"] = "1 2 3 4 8*"
 			c["vlan1ports"] = "0 8"
 		}
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to