MODULE_AUTHOR("Felix Fietkau");
MODULE_LICENSE("GPL");
+#define MVSWITCH_MAGIC 0x88E6060
+
struct mvswitch_priv {
- /* the driver's tx function */
- int (*hardstart)(struct sk_buff *skb, struct net_device *dev);
+ const struct net_device_ops *ndo_old;
+ struct net_device_ops ndo;
struct vlan_group *grp;
u8 vlans[16];
};
));
#endif
- return priv->hardstart(skb, dev);
+ return priv->ndo_old->ndo_start_xmit(skb, dev);
error_expand:
if (net_ratelimit())
pdev->advertising = ADVERTISED_100baseT_Full;
dev->phy_ptr = priv;
dev->irq = PHY_POLL;
+#ifdef HEADER_MODE
+ dev->flags |= IFF_PROMISC;
+#endif
/* initialize default vlans */
for (i = 0; i < MV_PORTS; i++)
- priv->vlans[(i == MV_WANPORT ? 1 : 0)] |= (1 << i);
+ priv->vlans[(i == MV_WANPORT ? 2 : 1)] |= (1 << i);
/* before entering reset, disable all ports */
for (i = 0; i < MV_PORTS; i++)
);
/* hook into the tx function */
- priv->hardstart = dev->hard_start_xmit;
+ 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;
+
+ pdev->pkt_align = 2;
pdev->netif_receive_skb = mvswitch_netif_receive_skb;
pdev->netif_rx = mvswitch_netif_rx;
- dev->hard_start_xmit = mvswitch_mangle_tx;
- dev->vlan_rx_register = mvswitch_vlan_rx_register;
#ifdef HEADER_MODE
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
#else
{
pdev->speed = SPEED_100;
pdev->duplex = DUPLEX_FULL;
- pdev->state = PHY_UP;
+ pdev->link = 1;
/* XXX ugly workaround: we can't force the switch
* to gracefully handle hosts moving from one port to another,
struct mvswitch_priv *priv = to_mvsw(pdev);
struct net_device *dev = pdev->attached_dev;
- /* restore old xmit handler */
- if (priv->hardstart && dev)
- dev->hard_start_xmit = priv->hardstart;
- dev->vlan_rx_register = NULL;
- dev->vlan_rx_kill_vid = NULL;
+ /* restore old netdev ops */
+ if (priv->ndo_old && dev)
+ dev->netdev_ops = priv->ndo_old;
dev->phy_ptr = NULL;
dev->features &= ~NETIF_F_HW_VLAN_RX;
kfree(priv);
}
-static bool
-mvswitch_detect(struct mii_bus *bus, int addr)
-{
- u16 reg;
- int i;
-
- /* we attach to phy id 31 to make sure that the late probe works */
- if (addr != 31)
- return false;
-
- /* look for the switch on the bus */
- reg = bus->read(bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
- if (reg != MV_IDENT_VALUE)
- return false;
-
- /*
- * Now that we've established that the switch actually exists, let's
- * get rid of the competition :)
- */
- for (i = 0; i < 31; i++) {
- if (!bus->phy_map[i])
- continue;
-
- device_unregister(&bus->phy_map[i]->dev);
- kfree(bus->phy_map[i]);
- bus->phy_map[i] = NULL;
- }
-
- return true;
-}
-
static int
mvswitch_probe(struct phy_device *pdev)
{
return 0;
}
+static int
+mvswitch_fixup(struct phy_device *dev)
+{
+ u16 reg;
+
+ if (dev->addr != 0x10)
+ return 0;
+
+ reg = dev->bus->read(dev->bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
+ if (reg != MV_IDENT_VALUE)
+ return 0;
+
+ dev->phy_id = MVSWITCH_MAGIC;
+ return 0;
+}
+
static struct phy_driver mvswitch_driver = {
.name = "Marvell 88E6060",
+ .phy_id = MVSWITCH_MAGIC,
+ .phy_id_mask = 0xffffffff,
.features = PHY_BASIC_FEATURES,
- .detect = &mvswitch_detect,
.probe = &mvswitch_probe,
.remove = &mvswitch_remove,
.config_init = &mvswitch_config_init,
static int __init
mvswitch_init(void)
{
+ phy_register_fixup_for_id(PHY_ANY_ID, mvswitch_fixup);
return phy_driver_register(&mvswitch_driver);
}