treewide: replace nbd@openwrt.org with nbd@nbd.name
[openwrt/staging/wigyori.git] / target / linux / generic / files / drivers / net / phy / mvswitch.c
index 1324a80a6056da432a9f7d486ad93c028a55335c..af31d0b5ac009e818903d285214ad92b02d3adb0 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,8 +41,7 @@ MODULE_LICENSE("GPL");
 #define MVSWITCH_MAGIC 0x88E6060
 
 struct mvswitch_priv {
-       const struct net_device_ops *ndo_old;
-       struct net_device_ops ndo;
+       netdev_features_t orig_features;
        u8 vlans[16];
 };
 
@@ -61,8 +60,8 @@ w16(struct phy_device *phydev, int addr, int reg, u16 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;
@@ -132,7 +131,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())
@@ -141,25 +140,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 (WARN_ON_ONCE(!priv))
+               return;
 
 #ifdef HEADER_MODE
        buf = skb->data;
@@ -167,7 +161,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 */
@@ -177,33 +171,9 @@ mvswitch_mangle_rx(struct sk_buff *skb, int napi)
        }
 
        if (vlan == -1)
-               goto error;
-
-       skb->protocol = eth_type_trans(skb, skb->dev);
-
-       __vlan_hwaccel_put_tag(skb, vlan);
-       if (napi)
-               return netif_receive_skb(skb);
-       else
-               return netif_rx(skb);
-
-error:
-       /* no vlan? eat the packet! */
-       dev_kfree_skb_any(skb);
-       return 0;
-}
-
+               return;
 
-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);
+       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan);
 }
 
 
@@ -331,19 +301,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;
-       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;
@@ -382,16 +348,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);
 }
 
@@ -433,6 +409,7 @@ 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,