From c477dc486067e501aff8c5ba37ef18670c504e8e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Mar 2010 14:35:41 +0000 Subject: [PATCH] Several small fixes for ar8216 driver (patch by Jonas Gorski) * 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). git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20083 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../files/drivers/net/phy/ar8216.c | 31 +++++++++++++------ .../files/drivers/net/phy/ar8216.h | 16 ++++++++-- 2 files changed, 35 insertions(+), 12 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 92cc9f384b..0a6eed9577 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 741dce917d..c1b8fdbd8c 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,6 +24,10 @@ #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 @@ -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,