Several small fixes for ar8216 driver (patch by Jonas Gorski)
authorFelix Fietkau <nbd@openwrt.org>
Tue, 9 Mar 2010 14:35:41 +0000 (14:35 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 9 Mar 2010 14:35:41 +0000 (14:35 +0000)
 * 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).

SVN-Revision: 20083

target/linux/generic-2.6/files/drivers/net/phy/ar8216.c
target/linux/generic-2.6/files/drivers/net/phy/ar8216.h

index 92cc9f384b98981b9212cbbc13fdab55c96b75fb..0a6eed9577a87d823159b1abae41cc5759b488f3 100644 (file)
@@ -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;
 
index 741dce917dfc6b49c72c27fb46fb978b6ea40da4..c1b8fdbd8cfe5bcea4859cf3ae6e417eaf108cf5 100644 (file)
 #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)
 #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,