From 7e033f0ade8fa9d650d7ae313187332132feaa12 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski+openwrt@gmail.com>
Date: Tue, 9 Mar 2010 12:11:04 +0100
Subject: [PATCH] Several small fixes for ar8216 driver.

This patch makes the following changes:

 * Create defines for some magic values/masks.

 * Change vlan_id to u16, to allow VIDs > 255.

 * Add a range check to set_pvid as it isn't a VID, but the index
   in the vlan table.

 * Set the max VID to 4094, since 4095 is a reserved value and
   should not be used.

 * In mangle_rx replace the provided VID with the VID of the table
   entry of the port, not the index of the table.

 * In hw_apply, remove a redundant emptyness check (was already
   checked several lines above).

 * In no vlan mode do not set the ingress mode to secure, as there
   are no vlan table entries, but to use the port's destination
   masks. Otherwise the switch won't forward anything.

 * In read_status tell that the phy is up (taken from the rtl8306
   driver).
---
 .../generic-2.6/files/drivers/net/phy/ar8216.c     |   31 +++++++++++++------
 .../generic-2.6/files/drivers/net/phy/ar8216.h     |   18 +++++++++--
 2 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c b/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c
index 92cc9f3..0a6eed9 100644
--- a/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c
@@ -42,7 +42,7 @@ struct ar8216_priv {
 
 	/* all fields below are cleared on reset */
 	bool vlan;
-	u8 vlan_id[AR8216_NUM_VLANS];
+	u16 vlan_id[AR8216_NUM_VLANS];
 	u8 vlan_table[AR8216_NUM_VLANS];
 	u8 vlan_tagged;
 	u16 pvid[AR8216_NUM_PORTS];
@@ -133,6 +133,12 @@ static int
 ar8216_set_pvid(struct switch_dev *dev, int port, int vlan)
 {
 	struct ar8216_priv *priv = to_ar8216(dev);
+
+	/* make sure no invalid PVIDs get set */
+
+	if (vlan >= AR8216_NUM_VLANS)
+		return -EINVAL;
+
 	priv->pvid[port] = vlan;
 	return 0;
 }
@@ -228,7 +234,7 @@ ar8216_mangle_rx(struct sk_buff *skb, int napi)
 		goto recv;
 
 	/* lookup port vid from local table, the switch passes an invalid vlan id */
-	vlan = priv->pvid[port];
+	vlan = priv->vlan_id[priv->pvid[port]];
 
 	buf[14 + 2] &= 0xf0;
 	buf[14 + 2] |= vlan >> 8;
@@ -282,7 +288,7 @@ static struct switch_attr ar8216_vlan[] = {
 		.description = "VLAN ID",
 		.set = ar8216_set_vid,
 		.get = ar8216_get_vid,
-		.max = 4095,
+		.max = 4094,
 	},
 };
 
@@ -396,9 +402,6 @@ ar8216_hw_apply(struct switch_dev *dev)
 					portmask[i] |= vp & ~mask;
 			}
 
-			if (!priv->vlan_table[j])
-				continue;
-
 			ar8216_vtu_op(priv,
 				AR8216_VTU_OP_LOAD |
 				(priv->vlan_id[j] << AR8216_VTU_VID_S),
@@ -432,7 +435,11 @@ ar8216_hw_apply(struct switch_dev *dev)
 		} else {
 			egress = AR8216_OUT_STRIP_VLAN;
 		}
-		ingress = AR8216_IN_SECURE;
+		if (priv->vlan) {
+			ingress = AR8216_IN_SECURE;
+		} else {
+			ingress = AR8216_IN_PORT_ONLY;
+		}
 
 		ar8216_rmw(priv, AR8216_REG_PORT_CTRL(i),
 			AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE |
@@ -478,7 +485,7 @@ ar8216_reset_switch(struct switch_dev *dev)
 		if (i == AR8216_PORT_CPU) {
 			priv->write(priv, AR8216_REG_PORT_STATUS(i),
 				AR8216_PORT_STATUS_LINK_UP |
-				AR8216_PORT_STATUS_SPEED |
+				AR8216_PORT_SPEED_100M |
 				AR8216_PORT_STATUS_TXMAC |
 				AR8216_PORT_STATUS_RXMAC |
 				AR8216_PORT_STATUS_DUPLEX);
@@ -554,6 +561,10 @@ ar8216_read_status(struct phy_device *phydev)
 
 	priv->write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH);
 
+	phydev->state = PHY_RUNNING;
+	netif_carrier_on(phydev->attached_dev);
+	phydev->adjust_link(phydev->attached_dev);
+
 	return 0;
 }
 
@@ -573,8 +584,8 @@ ar8216_probe(struct phy_device *pdev)
 
 	priv.phy = pdev;
 	val = ar8216_mii_read(&priv, AR8216_REG_CTRL);
-	rev = val & 0xff;
-	id = (val >> 8) & 0xff;
+	rev = val & AR8216_CTRL_REVISION;
+	id = (val & AR8216_CTRL_VERSION) >> AR8216_CTRL_VERSION_S;
 	if ((id != 1) || (rev != 1))
 		return -ENODEV;
 
diff --git a/target/linux/generic-2.6/files/drivers/net/phy/ar8216.h b/target/linux/generic-2.6/files/drivers/net/phy/ar8216.h
index 741dce9..5501f76 100644
--- a/target/linux/generic-2.6/files/drivers/net/phy/ar8216.h
+++ b/target/linux/generic-2.6/files/drivers/net/phy/ar8216.h
@@ -24,10 +24,14 @@
 #define AR8216_NUM_VLANS	16
 
 #define AR8216_REG_CTRL			0x0000
+#define   AR8216_CTRL_REVISION		BITS(0, 8)
+#define   AR8216_CTRL_REVISION_S	0
+#define   AR8216_CTRL_VERSION		BITS(8, 8)
+#define   AR8216_CTRL_VERSION_S		8
 #define   AR8216_CTRL_RESET		BIT(31)
 
 #define AR8216_REG_GLOBAL_CTRL		0x0030
-#define   AR8216_GCTRL_MTU		BITS(0, 10)
+#define   AR8216_GCTRL_MTU		BITS(0, 14)
 
 #define AR8216_REG_VTU			0x0040
 #define   AR8216_VTU_OP			BITS(0, 3)
@@ -73,8 +77,8 @@
 
 #define AR8216_PORT_OFFSET(_i)		(0x0100 * (_i + 1))
 #define AR8216_REG_PORT_STATUS(_i)	(AR8216_PORT_OFFSET(_i) + 0x0000)
-#define   AR8216_PORT_STATUS_SPEED	BIT(0)
-#define   AR8216_PORT_STATUS_SPEED_ERR	BIT(1)
+#define   AR8216_PORT_STATUS_SPEED	BITS(0,2)
+#define   AR8216_PORT_STATUS_SPEED_S	0
 #define   AR8216_PORT_STATUS_TXMAC	BIT(2)
 #define   AR8216_PORT_STATUS_RXMAC	BIT(3)
 #define   AR8216_PORT_STATUS_TXFLOW	BIT(4)
@@ -126,6 +130,14 @@
 #define AR8216_REG_PORT_RATE(_i)	(AR8216_PORT_OFFSET(_i) + 0x000c)
 #define AR8216_REG_PORT_PRIO(_i)	(AR8216_PORT_OFFSET(_i) + 0x0010)
 
+/* port speed */
+enum {
+        AR8216_PORT_SPEED_10M = 0,
+        AR8216_PORT_SPEED_100M = 1,
+        AR8216_PORT_SPEED_1000M = 2,
+        AR8216_PORT_SPEED_ERR = 3,
+};
+
 /* ingress 802.1q mode */
 enum {
 	AR8216_IN_PORT_ONLY = 0,
-- 
1.7.0

