kernel: update phy drivers for 4.9
[openwrt/staging/yousong.git] / target / linux / generic / files / drivers / net / phy / mvswitch.c
index c2f32457205f6f958ad59d620f346139c0be0bd2..a20fce342edb5554225ba70fd1b5091388461141 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Marvell 88E6060 switch driver
- * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (c) 2008 Felix Fietkau <nbd@nbd.name>
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of the GNU General Public License v2 as published by the
@@ -41,9 +41,7 @@ MODULE_LICENSE("GPL");
 #define MVSWITCH_MAGIC 0x88E6060
 
 struct mvswitch_priv {
-       const struct net_device_ops *ndo_old;
-       struct net_device_ops ndo;
-       struct vlan_group *grp;
+       netdev_features_t orig_features;
        u8 vlans[16];
 };
 
@@ -52,18 +50,22 @@ struct mvswitch_priv {
 static inline u16
 r16(struct phy_device *phydev, int addr, int reg)
 {
-       return phydev->bus->read(phydev->bus, addr, reg);
+       struct mii_bus *bus = phydev->mdio.bus;
+
+       return bus->read(bus, addr, reg);
 }
 
 static inline void
 w16(struct phy_device *phydev, int addr, int reg, u16 val)
 {
-       phydev->bus->write(phydev->bus, addr, reg, val);
+       struct mii_bus *bus = phydev->mdio.bus;
+
+       bus->write(bus, addr, reg, val);
 }
 
 
-static int
-mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
+static struct sk_buff *
+mvswitch_mangle_tx(struct net_device *dev, struct sk_buff *skb)
 {
        struct mvswitch_priv *priv;
        char *buf = NULL;
@@ -133,7 +135,7 @@ mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
        ));
 #endif
 
-       return priv->ndo_old->ndo_start_xmit(skb, dev);
+       return skb;
 
 error_expand:
        if (net_ratelimit())
@@ -142,28 +144,20 @@ error_expand:
 error:
        /* any errors? drop the packet! */
        dev_kfree_skb_any(skb);
-       return 0;
+       return NULL;
 }
 
-static int
-mvswitch_mangle_rx(struct sk_buff *skb, int napi)
+static void
+mvswitch_mangle_rx(struct net_device *dev, struct sk_buff *skb)
 {
        struct mvswitch_priv *priv;
-       struct net_device *dev;
-       int vlan = -1;
        unsigned char *buf;
+       int vlan = -1;
        int i;
 
-       dev = skb->dev;
-       if (!dev)
-               goto error;
-
        priv = dev->phy_ptr;
-       if (!priv)
-               goto error;
-
-       if (!priv->grp)
-               goto error;
+       if (WARN_ON_ONCE(!priv))
+               return;
 
 #ifdef HEADER_MODE
        buf = skb->data;
@@ -171,7 +165,7 @@ mvswitch_mangle_rx(struct sk_buff *skb, int napi)
 #else
        buf = skb->data + skb->len - MV_TRAILER_SIZE;
        if (buf[0] != 0x80)
-               goto error;
+               return;
 #endif
 
        /* look for the vlan matching the incoming port */
@@ -181,40 +175,9 @@ mvswitch_mangle_rx(struct sk_buff *skb, int napi)
        }
 
        if (vlan == -1)
-               goto error;
-
-       skb->protocol = eth_type_trans(skb, skb->dev);
-
-       if (napi)
-               return vlan_hwaccel_receive_skb(skb, priv->grp, vlan);
-       else
-               return vlan_hwaccel_rx(skb, priv->grp, vlan);
+               return;
 
-error:
-       /* no vlan? eat the packet! */
-       dev_kfree_skb_any(skb);
-       return 0;
-}
-
-
-static int
-mvswitch_netif_rx(struct sk_buff *skb)
-{
-       return mvswitch_mangle_rx(skb, 0);
-}
-
-static int
-mvswitch_netif_receive_skb(struct sk_buff *skb)
-{
-       return mvswitch_mangle_rx(skb, 1);
-}
-
-
-static void
-mvswitch_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-       struct mvswitch_priv *priv = dev->phy_ptr;
-       priv->grp = grp;
+       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan);
 }
 
 
@@ -247,7 +210,7 @@ mvswitch_config_init(struct phy_device *pdev)
        pdev->supported = ADVERTISED_100baseT_Full;
        pdev->advertising = ADVERTISED_100baseT_Full;
        dev->phy_ptr = priv;
-       dev->irq = PHY_POLL;
+       pdev->irq = PHY_POLL;
 #ifdef HEADER_MODE
        dev->flags |= IFF_PROMISC;
 #endif
@@ -342,20 +305,15 @@ mvswitch_config_init(struct phy_device *pdev)
                MV_SWITCHCTL_DROP
        );
 
-       /* hook into the tx function */
-       priv->ndo_old = dev->netdev_ops;
-       memcpy(&priv->ndo, priv->ndo_old, sizeof(struct net_device_ops));
-       priv->ndo.ndo_start_xmit = mvswitch_mangle_tx;
-       priv->ndo.ndo_vlan_rx_register = mvswitch_vlan_rx_register;
-       dev->netdev_ops = &priv->ndo;
+       dev->eth_mangle_rx = mvswitch_mangle_rx;
+       dev->eth_mangle_tx = mvswitch_mangle_tx;
+       priv->orig_features = dev->features;
 
-       pdev->pkt_align = 2;
-       pdev->netif_receive_skb = mvswitch_netif_receive_skb;
-       pdev->netif_rx = mvswitch_netif_rx;
 #ifdef HEADER_MODE
-       dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
+       dev->priv_flags |= IFF_NO_IP_ALIGN;
+       dev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX;
 #else
-       dev->features |= NETIF_F_HW_VLAN_RX;
+       dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
 #endif
 
        return 0;
@@ -394,16 +352,26 @@ mvswitch_config_aneg(struct phy_device *phydev)
 }
 
 static void
-mvswitch_remove(struct phy_device *pdev)
+mvswitch_detach(struct phy_device *pdev)
 {
        struct mvswitch_priv *priv = to_mvsw(pdev);
        struct net_device *dev = pdev->attached_dev;
 
-       /* restore old netdev ops */
-       if (priv->ndo_old && dev)
-               dev->netdev_ops = priv->ndo_old;
+       if (!dev)
+               return;
+
        dev->phy_ptr = NULL;
-       dev->features &= ~NETIF_F_HW_VLAN_RX;
+       dev->eth_mangle_rx = NULL;
+       dev->eth_mangle_tx = NULL;
+       dev->features = priv->orig_features;
+       dev->priv_flags &= ~IFF_NO_IP_ALIGN;
+}
+
+static void
+mvswitch_remove(struct phy_device *pdev)
+{
+       struct mvswitch_priv *priv = to_mvsw(pdev);
+
        kfree(priv);
 }
 
@@ -424,12 +392,13 @@ mvswitch_probe(struct phy_device *pdev)
 static int
 mvswitch_fixup(struct phy_device *dev)
 {
+       struct mii_bus *bus = dev->mdio.bus;
        u16 reg;
 
-       if (dev->addr != 0x10)
+       if (dev->mdio.addr != 0x10)
                return 0;
 
-       reg = dev->bus->read(dev->bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
+       reg = bus->read(bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
        if (reg != MV_IDENT_VALUE)
                return 0;
 
@@ -445,17 +414,17 @@ static struct phy_driver mvswitch_driver = {
        .features       = PHY_BASIC_FEATURES,
        .probe          = &mvswitch_probe,
        .remove         = &mvswitch_remove,
+       .detach         = &mvswitch_detach,
        .config_init    = &mvswitch_config_init,
        .config_aneg    = &mvswitch_config_aneg,
        .read_status    = &mvswitch_read_status,
-       .driver         = { .owner = THIS_MODULE,},
 };
 
 static int __init
 mvswitch_init(void)
 {
        phy_register_fixup_for_id(PHY_ANY_ID, mvswitch_fixup);
-       return phy_driver_register(&mvswitch_driver);
+       return phy_driver_register(&mvswitch_driver, THIS_MODULE);
 }
 
 static void __exit