diff options
Diffstat (limited to 'target/linux')
10 files changed, 37 insertions, 2313 deletions
| diff --git a/target/linux/generic-2.6/files-2.6.30/drivers/net/phy/ar8216.c b/target/linux/generic-2.6/files-2.6.30/drivers/net/phy/ar8216.c deleted file mode 100644 index 93e4b33d9..000000000 --- a/target/linux/generic-2.6/files-2.6.30/drivers/net/phy/ar8216.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * ar8216.c: AR8216 switch driver - * - * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/if.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/if_ether.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/netlink.h> -#include <linux/bitops.h> -#include <net/genetlink.h> -#include <linux/switch.h> -#include <linux/delay.h> -#include <linux/phy.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include "ar8216.h" - - -struct ar8216_priv { -	struct switch_dev dev; -	struct phy_device *phy; -	u32 (*read)(struct ar8216_priv *priv, int reg); -	void (*write)(struct ar8216_priv *priv, int reg, u32 val); -	const struct net_device_ops *ndo_old; -	struct net_device_ops ndo; - -	/* all fields below are cleared on reset */ -	bool vlan; -	u8 vlan_id[AR8216_NUM_VLANS]; -	u8 vlan_table[AR8216_NUM_VLANS]; -	u8 vlan_tagged; -	u16 pvid[AR8216_NUM_PORTS]; -}; -static struct switch_dev athdev; - -#define to_ar8216(_dev) container_of(_dev, struct ar8216_priv, dev) - -static inline void -split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -{ -	regaddr >>= 1; -	*r1 = regaddr & 0x1e; - -	regaddr >>= 5; -	*r2 = regaddr & 0x7; - -	regaddr >>= 3; -	*page = regaddr & 0x1ff; -} - -static u32 -ar8216_mii_read(struct ar8216_priv *priv, int reg) -{ -	struct phy_device *phy = priv->phy; -	u16 r1, r2, page; -	u16 lo, hi; - -	split_addr((u32) reg, &r1, &r2, &page); -	phy->bus->write(phy->bus, 0x18, 0, page); -	msleep(1); /* wait for the page switch to propagate */ -	lo = phy->bus->read(phy->bus, 0x10 | r2, r1); -	hi = phy->bus->read(phy->bus, 0x10 | r2, r1 + 1); - -	return (hi << 16) | lo; -} - -static void -ar8216_mii_write(struct ar8216_priv *priv, int reg, u32 val) -{ -	struct phy_device *phy = priv->phy; -	u16 r1, r2, r3; -	u16 lo, hi; - -	split_addr((u32) reg, &r1, &r2, &r3); -	phy->bus->write(phy->bus, 0x18, 0, r3); -	msleep(1); /* wait for the page switch to propagate */ - -	lo = val & 0xffff; -	hi = (u16) (val >> 16); -	phy->bus->write(phy->bus, 0x10 | r2, r1 + 1, hi); -	phy->bus->write(phy->bus, 0x10 | r2, r1, lo); -} - -static u32 -ar8216_rmw(struct ar8216_priv *priv, int reg, u32 mask, u32 val) -{ -	u32 v; - -	v = priv->read(priv, reg); -	v &= ~mask; -	v |= val; -	priv->write(priv, reg, v); - -	return v; -} - -static int -ar8216_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	priv->vlan = !!val->value.i; -	return 0; -} - -static int -ar8216_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	val->value.i = priv->vlan; -	return 0; -} - - -static int -ar8216_set_pvid(struct switch_dev *dev, int port, int vlan) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	priv->pvid[port] = vlan; -	return 0; -} - -static int -ar8216_get_pvid(struct switch_dev *dev, int port, int *vlan) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	*vlan = priv->pvid[port]; -	return 0; -} - -static int -ar8216_set_vid(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	priv->vlan_id[val->port_vlan] = val->value.i; -	return 0; -} - -static int -ar8216_get_vid(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	val->value.i = priv->vlan_id[val->port_vlan]; -	return 0; -} - - -static int -ar8216_mangle_tx(struct sk_buff *skb, struct net_device *dev) -{ -	struct ar8216_priv *priv = dev->phy_ptr; -	unsigned char *buf; - -    if (unlikely(!priv)) -        goto error; - -	if (!priv->vlan) -		goto send; - -	if (unlikely(skb_headroom(skb) < 2)) { -		if (pskb_expand_head(skb, 2, 0, GFP_ATOMIC) < 0) -			goto error; -	} - -	buf = skb_push(skb, 2); -	buf[0] = 0x10; -	buf[1] = 0x80; - -send: -	return priv->ndo_old->ndo_start_xmit(skb, dev); - -error: -	dev_kfree_skb_any(skb); -	return 0; -} - -static int -ar8216_mangle_rx(struct sk_buff *skb, int napi) -{ -	struct ar8216_priv *priv; -	struct net_device *dev; -	unsigned char *buf; -	int port, vlan; - -	dev = skb->dev; -	if (!dev) -		goto error; - -	priv = dev->phy_ptr; -	if (!priv) -		goto error; - -	/* don't strip the header if vlan mode is disabled */ -	if (!priv->vlan) -		goto recv; - -	/* strip header, get vlan id */ -	buf = skb->data; -	skb_pull(skb, 2); - -	/* check for vlan header presence */ -	if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00)) -		goto recv; - -	port = buf[0] & 0xf; - -	/* no need to fix up packets coming from a tagged source */ -	if (priv->vlan_tagged & (1 << port)) -		goto recv; - -	/* lookup port vid from local table, the switch passes an invalid vlan id */ -	vlan = priv->pvid[port]; - -	buf[14 + 2] &= 0xf0; -	buf[14 + 2] |= vlan >> 8; -	buf[15 + 2] = vlan & 0xff; - -recv: -	skb->protocol = eth_type_trans(skb, skb->dev); - -	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; -} - -static int -ar8216_netif_rx(struct sk_buff *skb) -{ -	return ar8216_mangle_rx(skb, 0); -} - -static int -ar8216_netif_receive_skb(struct sk_buff *skb) -{ -	return ar8216_mangle_rx(skb, 1); -} - - -static struct switch_attr ar8216_globals[] = { -	{ -		.type = SWITCH_TYPE_INT, -		.name = "enable_vlan", -		.description = "Enable VLAN mode", -		.set = ar8216_set_vlan, -		.get = ar8216_get_vlan, -		.max = 1 -	}, -}; - -static struct switch_attr ar8216_port[] = { -}; - -static struct switch_attr ar8216_vlan[] = { -	{ -		.type = SWITCH_TYPE_INT, -		.name = "pvid", -		.description = "VLAN ID", -		.set = ar8216_set_vid, -		.get = ar8216_get_vid, -		.max = 4095, -	}, -}; - - -static int -ar8216_get_ports(struct switch_dev *dev, struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	u8 ports = priv->vlan_table[val->port_vlan]; -	int i; - -	val->len = 0; -	for (i = 0; i < AR8216_NUM_PORTS; i++) { -		struct switch_port *p; - -		if (!(ports & (1 << i))) -			continue; - -		p = &val->value.ports[val->len++]; -		p->id = i; -		if (priv->vlan_tagged & (1 << i)) -			p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); -		else -			p->flags = 0; -	} -	return 0; -} - -static int -ar8216_set_ports(struct switch_dev *dev, struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	u8 *vt = &priv->vlan_table[val->port_vlan]; -	int i, j; - -	*vt = 0; -	for (i = 0; i < val->len; i++) { -		struct switch_port *p = &val->value.ports[i]; - -		if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) -			priv->vlan_tagged |= (1 << p->id); -		else { -			priv->vlan_tagged &= ~(1 << p->id); -			priv->pvid[p->id] = val->port_vlan; - -			/* make sure that an untagged port does not -			 * appear in other vlans */ -			for (j = 0; j < AR8216_NUM_VLANS; j++) { -				if (j == val->port_vlan) -					continue; -				priv->vlan_table[j] &= ~(1 << p->id); -			} -		} - -		*vt |= 1 << p->id; -	} -	return 0; -} - -static int -ar8216_wait_bit(struct ar8216_priv *priv, int reg, u32 mask, u32 val) -{ -	int timeout = 20; - -	while ((priv->read(priv, reg) & mask) != val) { -		if (timeout-- <= 0) { -			printk(KERN_ERR "ar8216: timeout waiting for operation to complete\n"); -			return 1; -		} -	} -	return 0; -} - -static void -ar8216_vtu_op(struct ar8216_priv *priv, u32 op, u32 val) -{ -	if (ar8216_wait_bit(priv, AR8216_REG_VTU, AR8216_VTU_ACTIVE, 0)) -		return; -	if ((op & AR8216_VTU_OP) == AR8216_VTU_OP_LOAD) { -		val &= AR8216_VTUDATA_MEMBER; -		val |= AR8216_VTUDATA_VALID; -		priv->write(priv, AR8216_REG_VTU_DATA, val); -	} -	op |= AR8216_VTU_ACTIVE; -	priv->write(priv, AR8216_REG_VTU, op); -} - -static int -ar8216_hw_apply(struct switch_dev *dev) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	u8 portmask[AR8216_NUM_PORTS]; -	int i, j; - -	/* flush all vlan translation unit entries */ -	ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); - -	memset(portmask, 0, sizeof(portmask)); -	if (priv->vlan) { -		/* calculate the port destination masks and load vlans -		 * into the vlan translation unit */ -		for (j = 0; j < AR8216_NUM_VLANS; j++) { -			u8 vp = priv->vlan_table[j]; - -			if (!vp) -				continue; - -			for (i = 0; i < AR8216_NUM_PORTS; i++) { -				u8 mask = (1 << i); -				if (vp & mask) -					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), -				priv->vlan_table[j]); -		} -	} else { -		/* vlan disabled: -		 * isolate all ports, but connect them to the cpu port */ -		for (i = 0; i < AR8216_NUM_PORTS; i++) { -			if (i == AR8216_PORT_CPU) -				continue; - -			portmask[i] = 1 << AR8216_PORT_CPU; -			portmask[AR8216_PORT_CPU] |= (1 << i); -		} -	} - -	/* update the port destination mask registers and tag settings */ -	for (i = 0; i < AR8216_NUM_PORTS; i++) { -		int egress, ingress; -		int pvid; - -		if (priv->vlan) { -			pvid = priv->vlan_id[priv->pvid[i]]; -		} else { -			pvid = i; -		} - -		if (priv->vlan && (priv->vlan_tagged & (1 << i))) { -			egress = AR8216_OUT_ADD_VLAN; -		} else { -			egress = AR8216_OUT_STRIP_VLAN; -		} -		ingress = AR8216_IN_SECURE; - -		ar8216_rmw(priv, AR8216_REG_PORT_CTRL(i), -			AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | -			AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | -			AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK, -			AR8216_PORT_CTRL_LEARN | -			  (priv->vlan && i == AR8216_PORT_CPU ? -			   AR8216_PORT_CTRL_HEADER : 0) | -			  (egress << AR8216_PORT_CTRL_VLAN_MODE_S) | -			  (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); - -		ar8216_rmw(priv, AR8216_REG_PORT_VLAN(i), -			AR8216_PORT_VLAN_DEST_PORTS | AR8216_PORT_VLAN_MODE | -			  AR8216_PORT_VLAN_DEFAULT_ID, -			(portmask[i] << AR8216_PORT_VLAN_DEST_PORTS_S) | -			  (ingress << AR8216_PORT_VLAN_MODE_S) | -			  (pvid << AR8216_PORT_VLAN_DEFAULT_ID_S)); -	} - -	return 0; -} - -static int -ar8216_reset_switch(struct switch_dev *dev) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	int i; - -	memset(&priv->vlan, 0, sizeof(struct ar8216_priv) - -		offsetof(struct ar8216_priv, vlan)); -	for (i = 0; i < AR8216_NUM_VLANS; i++) { -		priv->vlan_id[i] = i; -	} -	for (i = 0; i < AR8216_NUM_PORTS; i++) { -		/* Enable port learning and tx */ -		priv->write(priv, AR8216_REG_PORT_CTRL(i), -			AR8216_PORT_CTRL_LEARN | -			(4 << AR8216_PORT_CTRL_STATE_S)); - -		priv->write(priv, AR8216_REG_PORT_VLAN(i), 0); - -		/* Configure all PHYs */ -		if (i == AR8216_PORT_CPU) { -			priv->write(priv, AR8216_REG_PORT_STATUS(i), -				AR8216_PORT_STATUS_LINK_UP | -				AR8216_PORT_STATUS_SPEED | -				AR8216_PORT_STATUS_TXMAC | -				AR8216_PORT_STATUS_RXMAC | -				AR8216_PORT_STATUS_DUPLEX); -		} else { -			priv->write(priv, AR8216_REG_PORT_STATUS(i), -				AR8216_PORT_STATUS_LINK_AUTO); -		} -	} -	/* XXX: undocumented magic from atheros, required! */ -	priv->write(priv, 0x38, 0xc000050e); - -	ar8216_rmw(priv, AR8216_REG_GLOBAL_CTRL, -		AR8216_GCTRL_MTU, 1518 + 8 + 2); - -	return ar8216_hw_apply(dev); -} - -static int -ar8216_config_init(struct phy_device *pdev) -{ -	struct ar8216_priv *priv; -	struct net_device *dev = pdev->attached_dev; -	int ret; - -	printk("%s: AR8216 PHY driver attached.\n", pdev->attached_dev->name); -	pdev->supported = ADVERTISED_100baseT_Full; -	pdev->advertising = ADVERTISED_100baseT_Full; - -	priv = kzalloc(sizeof(struct ar8216_priv), GFP_KERNEL); -	if (priv == NULL) -		return -ENOMEM; - -	priv->phy = pdev; -	priv->read = ar8216_mii_read; -	priv->write = ar8216_mii_write; -	memcpy(&priv->dev, &athdev, sizeof(struct switch_dev)); -	pdev->priv = priv; -	if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) { -		kfree(priv); -		goto done; -	} - -	ret = ar8216_reset_switch(&priv->dev); -	if (ret) -		goto done; - -	dev->phy_ptr = priv; -	pdev->pkt_align = 2; -	pdev->netif_receive_skb = ar8216_netif_receive_skb; -	pdev->netif_rx = ar8216_netif_rx; - -	priv->ndo_old = dev->netdev_ops; -	memcpy(&priv->ndo, priv->ndo_old, sizeof(struct net_device_ops)); -	priv->ndo.ndo_start_xmit = ar8216_mangle_tx; -	dev->netdev_ops = &priv->ndo; - -done: -	return ret; -} - -static int -ar8216_read_status(struct phy_device *phydev) -{ -	struct ar8216_priv *priv = phydev->priv; - -	phydev->speed = SPEED_100; -	phydev->duplex = DUPLEX_FULL; -	phydev->state = PHY_UP; - -	/* flush the address translation unit */ -	if (ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0)) -		return -ETIMEDOUT; - -	priv->write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH); - -	return 0; -} - -static int -ar8216_config_aneg(struct phy_device *phydev) -{ -	return 0; -} - -static int -ar8216_probe(struct phy_device *pdev) -{ -	struct ar8216_priv priv; - -	u8 id, rev; -	u32 val; - -	priv.phy = pdev; -	val = ar8216_mii_read(&priv, AR8216_REG_CTRL); -	rev = val & 0xff; -	id = (val >> 8) & 0xff; -	if ((id != 1) || (rev != 1)) -		return -ENODEV; - -	return 0; -} - -static void -ar8216_remove(struct phy_device *pdev) -{ -	struct ar8216_priv *priv = pdev->priv; -	struct net_device *dev = pdev->attached_dev; - -	if (!priv) -		return; - -	if (priv->ndo_old && dev) -		dev->netdev_ops = priv->ndo_old; -	unregister_switch(&priv->dev); -	kfree(priv); -} - -/* template */ -static struct switch_dev athdev = { -	.name = "Atheros AR8216", -	.cpu_port = AR8216_PORT_CPU, -	.ports = AR8216_NUM_PORTS, -	.vlans = AR8216_NUM_VLANS, -	.attr_global = { -		.attr = ar8216_globals, -		.n_attr = ARRAY_SIZE(ar8216_globals), -	}, -	.attr_port = { -		.attr = ar8216_port, -		.n_attr = ARRAY_SIZE(ar8216_port), -	}, -	.attr_vlan = { -		.attr = ar8216_vlan, -		.n_attr = ARRAY_SIZE(ar8216_vlan), -	}, -	.get_port_pvid = ar8216_get_pvid, -	.set_port_pvid = ar8216_set_pvid, -	.get_vlan_ports = ar8216_get_ports, -	.set_vlan_ports = ar8216_set_ports, -	.apply_config = ar8216_hw_apply, -	.reset_switch = ar8216_reset_switch, -}; - -static struct phy_driver ar8216_driver = { -	.name		= "Atheros AR8216", -	.features	= PHY_BASIC_FEATURES, -	.probe		= ar8216_probe, -	.remove		= ar8216_remove, -	.config_init	= &ar8216_config_init, -	.config_aneg	= &ar8216_config_aneg, -	.read_status	= &ar8216_read_status, -	.driver		= { .owner = THIS_MODULE }, -}; - -int __init -ar8216_init(void) -{ -	return phy_driver_register(&ar8216_driver); -} - -void __exit -ar8216_exit(void) -{ -	phy_driver_unregister(&ar8216_driver); -} - -module_init(ar8216_init); -module_exit(ar8216_exit); -MODULE_LICENSE("GPL"); - diff --git a/target/linux/generic-2.6/files-2.6.30/drivers/net/phy/mvswitch.c b/target/linux/generic-2.6/files-2.6.30/drivers/net/phy/mvswitch.c deleted file mode 100644 index 77899e082..000000000 --- a/target/linux/generic-2.6/files-2.6.30/drivers/net/phy/mvswitch.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Marvell 88E6060 switch driver - * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org> - * - * 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 - * Free Software Foundation - */ -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/unistd.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/phy.h> -#include <linux/if_vlan.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include "mvswitch.h" - -/* Undefine this to use trailer mode instead. - * I don't know if header mode works with all chips */ -#define HEADER_MODE	1 - -MODULE_DESCRIPTION("Marvell 88E6060 Switch driver"); -MODULE_AUTHOR("Felix Fietkau"); -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; -	u8 vlans[16]; -}; - -#define to_mvsw(_phy) ((struct mvswitch_priv *) (_phy)->priv) - -static inline u16 -r16(struct phy_device *phydev, int addr, int reg) -{ -	return phydev->bus->read(phydev->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); -} - - -static int -mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev) -{ -	struct mvswitch_priv *priv; -	char *buf = NULL; -	u16 vid; - -	priv = dev->phy_ptr; -	if (unlikely(!priv)) -		goto error; - -	if (unlikely(skb->len < 16)) -		goto error; - -#ifdef HEADER_MODE -	if (__vlan_hwaccel_get_tag(skb, &vid)) -		goto error; - -	if (skb_cloned(skb) || (skb->len <= 62) || (skb_headroom(skb) < MV_HEADER_SIZE)) { -		if (pskb_expand_head(skb, MV_HEADER_SIZE, (skb->len < 62 ? 62 - skb->len : 0), GFP_ATOMIC)) -			goto error_expand; -		if (skb->len < 62) -			skb->len = 62; -	} -	buf = skb_push(skb, MV_HEADER_SIZE); -#else -	if (__vlan_get_tag(skb, &vid)) -		goto error; - -	if (unlikely((vid > 15 || !priv->vlans[vid]))) -		goto error; - -	if (skb->len <= 64) { -		if (pskb_expand_head(skb, 0, 64 + MV_TRAILER_SIZE - skb->len, GFP_ATOMIC)) -			goto error_expand; - -		buf = skb->data + 64; -		skb->len = 64 + MV_TRAILER_SIZE; -	} else { -		if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) { -			if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC)) -				goto error_expand; -		} -		buf = skb_put(skb, 4); -	} - -	/* move the ethernet header 4 bytes forward, overwriting the vlan tag */ -	memmove(skb->data + 4, skb->data, 12); -	skb->data += 4; -	skb->len -= 4; -	skb->mac_header += 4; -#endif - -	if (!buf) -		goto error; - - -#ifdef HEADER_MODE -	/* prepend the tag */ -	*((__be16 *) buf) = cpu_to_be16( -		((vid << MV_HEADER_VLAN_S) & MV_HEADER_VLAN_M) | -		((priv->vlans[vid] << MV_HEADER_PORTS_S) & MV_HEADER_PORTS_M) -	); -#else -	/* append the tag */ -	*((__be32 *) buf) = cpu_to_be32(( -		(MV_TRAILER_OVERRIDE << MV_TRAILER_FLAGS_S) | -		((priv->vlans[vid] & MV_TRAILER_PORTS_M) << MV_TRAILER_PORTS_S) -	)); -#endif - -	return priv->ndo_old->ndo_start_xmit(skb, dev); - -error_expand: -	if (net_ratelimit()) -		printk("%s: failed to expand/update skb for the switch\n", dev->name); - -error: -	/* any errors? drop the packet! */ -	dev_kfree_skb_any(skb); -	return 0; -} - -static int -mvswitch_mangle_rx(struct sk_buff *skb, int napi) -{ -	struct mvswitch_priv *priv; -	struct net_device *dev; -	int vlan = -1; -	unsigned char *buf; -	int i; - -	dev = skb->dev; -	if (!dev) -		goto error; - -	priv = dev->phy_ptr; -	if (!priv) -		goto error; - -	if (!priv->grp) -		goto error; - -#ifdef HEADER_MODE -	buf = skb->data; -	skb_pull(skb, MV_HEADER_SIZE); -#else -	buf = skb->data + skb->len - MV_TRAILER_SIZE; -	if (buf[0] != 0x80) -		goto error; -#endif - -	/* look for the vlan matching the incoming port */ -	for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) { -		if ((1 << buf[1]) & priv->vlans[i]) -			vlan = i; -	} - -	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); - -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; -} - - -static int -mvswitch_wait_mask(struct phy_device *pdev, int addr, int reg, u16 mask, u16 val) -{ -	int i = 100; -	u16 r; - -	do { -		r = r16(pdev, addr, reg) & mask; -		if (r == val) -			return 0; -	} while(--i > 0); -	return -ETIMEDOUT; -} - -static int -mvswitch_config_init(struct phy_device *pdev) -{ -	struct mvswitch_priv *priv = to_mvsw(pdev); -	struct net_device *dev = pdev->attached_dev; -	u8 vlmap = 0; -	int i; - -	if (!dev) -		return -EINVAL; - -	printk("%s: Marvell 88E6060 PHY driver attached.\n", dev->name); -	pdev->supported = ADVERTISED_100baseT_Full; -	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 ? 2 : 1)] |= (1 << i); - -	/* before entering reset, disable all ports */ -	for (i = 0; i < MV_PORTS; i++) -		w16(pdev, MV_PORTREG(CONTROL, i), 0x00); - -	msleep(2); /* wait for the status change to settle in */ - -	/* put the ATU in reset */ -	w16(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET); - -	i = mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET, 0); -	if (i < 0) { -		printk("%s: Timeout waiting for the switch to reset.\n", dev->name); -		return i; -	} - -	/* set the ATU flags */ -	w16(pdev, MV_SWITCHREG(ATU_CTRL), -		MV_ATUCTL_NO_LEARN | -		MV_ATUCTL_ATU_1K | -		MV_ATUCTL_AGETIME(MV_ATUCTL_AGETIME_MIN) /* minimum without disabling ageing */ -	); - -	/* initialize the cpu port */ -	w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT), -#ifdef HEADER_MODE -		MV_PORTCTRL_HEADER | -#else -		MV_PORTCTRL_RXTR | -		MV_PORTCTRL_TXTR | -#endif -		MV_PORTCTRL_ENABLED -	); -	/* wait for the phy change to settle in */ -	msleep(2); -	for (i = 0; i < MV_PORTS; i++) { -		u8 pvid = 0; -		int j; - -		vlmap = 0; - -		/* look for the matching vlan */ -		for (j = 0; j < ARRAY_SIZE(priv->vlans); j++) { -			if (priv->vlans[j] & (1 << i)) { -				vlmap = priv->vlans[j]; -				pvid = j; -			} -		} -		/* leave port unconfigured if it's not part of a vlan */ -		if (!vlmap) -			continue; - -		/* add the cpu port to the allowed destinations list */ -		vlmap |= (1 << MV_CPUPORT); - -		/* take port out of its own vlan destination map */ -		vlmap &= ~(1 << i); - -		/* apply vlan settings */ -		w16(pdev, MV_PORTREG(VLANMAP, i), -			MV_PORTVLAN_PORTS(vlmap) | -			MV_PORTVLAN_ID(i) -		); - -		/* re-enable port */ -		w16(pdev, MV_PORTREG(CONTROL, i), -			MV_PORTCTRL_ENABLED -		); -	} - -	w16(pdev, MV_PORTREG(VLANMAP, MV_CPUPORT), -		MV_PORTVLAN_ID(MV_CPUPORT) -	); - -	/* set the port association vector */ -	for (i = 0; i <= MV_PORTS; i++) { -		w16(pdev, MV_PORTREG(ASSOC, i), -			MV_PORTASSOC_PORTS(1 << i) -		); -	} - -	/* init switch control */ -	w16(pdev, MV_SWITCHREG(CTRL), -		MV_SWITCHCTL_MSIZE | -		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; - -	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; -#else -	dev->features |= NETIF_F_HW_VLAN_RX; -#endif - -	return 0; -} - -static int -mvswitch_read_status(struct phy_device *pdev) -{ -	pdev->speed = SPEED_100; -	pdev->duplex = DUPLEX_FULL; -	pdev->state = PHY_UP; - -	/* XXX ugly workaround: we can't force the switch -	 * to gracefully handle hosts moving from one port to another, -	 * so we have to regularly clear the ATU database */ - -	/* wait for the ATU to become available */ -	mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0); - -	/* flush the ATU */ -	w16(pdev, MV_SWITCHREG(ATU_OP), -		MV_ATUOP_INPROGRESS | -		MV_ATUOP_FLUSH_ALL -	); - -	/* wait for operation to complete */ -	mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0); - -	return 0; -} - -static int -mvswitch_config_aneg(struct phy_device *phydev) -{ -	return 0; -} - -static void -mvswitch_remove(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; -	dev->vlan_rx_register = NULL; -	dev->vlan_rx_kill_vid = NULL; -	dev->phy_ptr = NULL; -	dev->features &= ~NETIF_F_HW_VLAN_RX; -	kfree(priv); -} - -static int -mvswitch_probe(struct phy_device *pdev) -{ -	struct mvswitch_priv *priv; - -	priv = kzalloc(sizeof(struct mvswitch_priv), GFP_KERNEL); -	if (priv == NULL) -		return -ENOMEM; - -	pdev->priv = priv; - -	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, -	.probe		= &mvswitch_probe, -	.remove		= &mvswitch_remove, -	.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); -} - -static void __exit -mvswitch_exit(void) -{ -	phy_driver_unregister(&mvswitch_driver); -} - -module_init(mvswitch_init); -module_exit(mvswitch_exit); diff --git a/target/linux/generic-2.6/files-2.6.31/drivers/net/phy/ar8216.c b/target/linux/generic-2.6/files-2.6.31/drivers/net/phy/ar8216.c deleted file mode 100644 index 93e4b33d9..000000000 --- a/target/linux/generic-2.6/files-2.6.31/drivers/net/phy/ar8216.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * ar8216.c: AR8216 switch driver - * - * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/if.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/if_ether.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/netlink.h> -#include <linux/bitops.h> -#include <net/genetlink.h> -#include <linux/switch.h> -#include <linux/delay.h> -#include <linux/phy.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include "ar8216.h" - - -struct ar8216_priv { -	struct switch_dev dev; -	struct phy_device *phy; -	u32 (*read)(struct ar8216_priv *priv, int reg); -	void (*write)(struct ar8216_priv *priv, int reg, u32 val); -	const struct net_device_ops *ndo_old; -	struct net_device_ops ndo; - -	/* all fields below are cleared on reset */ -	bool vlan; -	u8 vlan_id[AR8216_NUM_VLANS]; -	u8 vlan_table[AR8216_NUM_VLANS]; -	u8 vlan_tagged; -	u16 pvid[AR8216_NUM_PORTS]; -}; -static struct switch_dev athdev; - -#define to_ar8216(_dev) container_of(_dev, struct ar8216_priv, dev) - -static inline void -split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -{ -	regaddr >>= 1; -	*r1 = regaddr & 0x1e; - -	regaddr >>= 5; -	*r2 = regaddr & 0x7; - -	regaddr >>= 3; -	*page = regaddr & 0x1ff; -} - -static u32 -ar8216_mii_read(struct ar8216_priv *priv, int reg) -{ -	struct phy_device *phy = priv->phy; -	u16 r1, r2, page; -	u16 lo, hi; - -	split_addr((u32) reg, &r1, &r2, &page); -	phy->bus->write(phy->bus, 0x18, 0, page); -	msleep(1); /* wait for the page switch to propagate */ -	lo = phy->bus->read(phy->bus, 0x10 | r2, r1); -	hi = phy->bus->read(phy->bus, 0x10 | r2, r1 + 1); - -	return (hi << 16) | lo; -} - -static void -ar8216_mii_write(struct ar8216_priv *priv, int reg, u32 val) -{ -	struct phy_device *phy = priv->phy; -	u16 r1, r2, r3; -	u16 lo, hi; - -	split_addr((u32) reg, &r1, &r2, &r3); -	phy->bus->write(phy->bus, 0x18, 0, r3); -	msleep(1); /* wait for the page switch to propagate */ - -	lo = val & 0xffff; -	hi = (u16) (val >> 16); -	phy->bus->write(phy->bus, 0x10 | r2, r1 + 1, hi); -	phy->bus->write(phy->bus, 0x10 | r2, r1, lo); -} - -static u32 -ar8216_rmw(struct ar8216_priv *priv, int reg, u32 mask, u32 val) -{ -	u32 v; - -	v = priv->read(priv, reg); -	v &= ~mask; -	v |= val; -	priv->write(priv, reg, v); - -	return v; -} - -static int -ar8216_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	priv->vlan = !!val->value.i; -	return 0; -} - -static int -ar8216_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	val->value.i = priv->vlan; -	return 0; -} - - -static int -ar8216_set_pvid(struct switch_dev *dev, int port, int vlan) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	priv->pvid[port] = vlan; -	return 0; -} - -static int -ar8216_get_pvid(struct switch_dev *dev, int port, int *vlan) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	*vlan = priv->pvid[port]; -	return 0; -} - -static int -ar8216_set_vid(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	priv->vlan_id[val->port_vlan] = val->value.i; -	return 0; -} - -static int -ar8216_get_vid(struct switch_dev *dev, const struct switch_attr *attr, -                struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	val->value.i = priv->vlan_id[val->port_vlan]; -	return 0; -} - - -static int -ar8216_mangle_tx(struct sk_buff *skb, struct net_device *dev) -{ -	struct ar8216_priv *priv = dev->phy_ptr; -	unsigned char *buf; - -    if (unlikely(!priv)) -        goto error; - -	if (!priv->vlan) -		goto send; - -	if (unlikely(skb_headroom(skb) < 2)) { -		if (pskb_expand_head(skb, 2, 0, GFP_ATOMIC) < 0) -			goto error; -	} - -	buf = skb_push(skb, 2); -	buf[0] = 0x10; -	buf[1] = 0x80; - -send: -	return priv->ndo_old->ndo_start_xmit(skb, dev); - -error: -	dev_kfree_skb_any(skb); -	return 0; -} - -static int -ar8216_mangle_rx(struct sk_buff *skb, int napi) -{ -	struct ar8216_priv *priv; -	struct net_device *dev; -	unsigned char *buf; -	int port, vlan; - -	dev = skb->dev; -	if (!dev) -		goto error; - -	priv = dev->phy_ptr; -	if (!priv) -		goto error; - -	/* don't strip the header if vlan mode is disabled */ -	if (!priv->vlan) -		goto recv; - -	/* strip header, get vlan id */ -	buf = skb->data; -	skb_pull(skb, 2); - -	/* check for vlan header presence */ -	if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00)) -		goto recv; - -	port = buf[0] & 0xf; - -	/* no need to fix up packets coming from a tagged source */ -	if (priv->vlan_tagged & (1 << port)) -		goto recv; - -	/* lookup port vid from local table, the switch passes an invalid vlan id */ -	vlan = priv->pvid[port]; - -	buf[14 + 2] &= 0xf0; -	buf[14 + 2] |= vlan >> 8; -	buf[15 + 2] = vlan & 0xff; - -recv: -	skb->protocol = eth_type_trans(skb, skb->dev); - -	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; -} - -static int -ar8216_netif_rx(struct sk_buff *skb) -{ -	return ar8216_mangle_rx(skb, 0); -} - -static int -ar8216_netif_receive_skb(struct sk_buff *skb) -{ -	return ar8216_mangle_rx(skb, 1); -} - - -static struct switch_attr ar8216_globals[] = { -	{ -		.type = SWITCH_TYPE_INT, -		.name = "enable_vlan", -		.description = "Enable VLAN mode", -		.set = ar8216_set_vlan, -		.get = ar8216_get_vlan, -		.max = 1 -	}, -}; - -static struct switch_attr ar8216_port[] = { -}; - -static struct switch_attr ar8216_vlan[] = { -	{ -		.type = SWITCH_TYPE_INT, -		.name = "pvid", -		.description = "VLAN ID", -		.set = ar8216_set_vid, -		.get = ar8216_get_vid, -		.max = 4095, -	}, -}; - - -static int -ar8216_get_ports(struct switch_dev *dev, struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	u8 ports = priv->vlan_table[val->port_vlan]; -	int i; - -	val->len = 0; -	for (i = 0; i < AR8216_NUM_PORTS; i++) { -		struct switch_port *p; - -		if (!(ports & (1 << i))) -			continue; - -		p = &val->value.ports[val->len++]; -		p->id = i; -		if (priv->vlan_tagged & (1 << i)) -			p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); -		else -			p->flags = 0; -	} -	return 0; -} - -static int -ar8216_set_ports(struct switch_dev *dev, struct switch_val *val) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	u8 *vt = &priv->vlan_table[val->port_vlan]; -	int i, j; - -	*vt = 0; -	for (i = 0; i < val->len; i++) { -		struct switch_port *p = &val->value.ports[i]; - -		if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) -			priv->vlan_tagged |= (1 << p->id); -		else { -			priv->vlan_tagged &= ~(1 << p->id); -			priv->pvid[p->id] = val->port_vlan; - -			/* make sure that an untagged port does not -			 * appear in other vlans */ -			for (j = 0; j < AR8216_NUM_VLANS; j++) { -				if (j == val->port_vlan) -					continue; -				priv->vlan_table[j] &= ~(1 << p->id); -			} -		} - -		*vt |= 1 << p->id; -	} -	return 0; -} - -static int -ar8216_wait_bit(struct ar8216_priv *priv, int reg, u32 mask, u32 val) -{ -	int timeout = 20; - -	while ((priv->read(priv, reg) & mask) != val) { -		if (timeout-- <= 0) { -			printk(KERN_ERR "ar8216: timeout waiting for operation to complete\n"); -			return 1; -		} -	} -	return 0; -} - -static void -ar8216_vtu_op(struct ar8216_priv *priv, u32 op, u32 val) -{ -	if (ar8216_wait_bit(priv, AR8216_REG_VTU, AR8216_VTU_ACTIVE, 0)) -		return; -	if ((op & AR8216_VTU_OP) == AR8216_VTU_OP_LOAD) { -		val &= AR8216_VTUDATA_MEMBER; -		val |= AR8216_VTUDATA_VALID; -		priv->write(priv, AR8216_REG_VTU_DATA, val); -	} -	op |= AR8216_VTU_ACTIVE; -	priv->write(priv, AR8216_REG_VTU, op); -} - -static int -ar8216_hw_apply(struct switch_dev *dev) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	u8 portmask[AR8216_NUM_PORTS]; -	int i, j; - -	/* flush all vlan translation unit entries */ -	ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); - -	memset(portmask, 0, sizeof(portmask)); -	if (priv->vlan) { -		/* calculate the port destination masks and load vlans -		 * into the vlan translation unit */ -		for (j = 0; j < AR8216_NUM_VLANS; j++) { -			u8 vp = priv->vlan_table[j]; - -			if (!vp) -				continue; - -			for (i = 0; i < AR8216_NUM_PORTS; i++) { -				u8 mask = (1 << i); -				if (vp & mask) -					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), -				priv->vlan_table[j]); -		} -	} else { -		/* vlan disabled: -		 * isolate all ports, but connect them to the cpu port */ -		for (i = 0; i < AR8216_NUM_PORTS; i++) { -			if (i == AR8216_PORT_CPU) -				continue; - -			portmask[i] = 1 << AR8216_PORT_CPU; -			portmask[AR8216_PORT_CPU] |= (1 << i); -		} -	} - -	/* update the port destination mask registers and tag settings */ -	for (i = 0; i < AR8216_NUM_PORTS; i++) { -		int egress, ingress; -		int pvid; - -		if (priv->vlan) { -			pvid = priv->vlan_id[priv->pvid[i]]; -		} else { -			pvid = i; -		} - -		if (priv->vlan && (priv->vlan_tagged & (1 << i))) { -			egress = AR8216_OUT_ADD_VLAN; -		} else { -			egress = AR8216_OUT_STRIP_VLAN; -		} -		ingress = AR8216_IN_SECURE; - -		ar8216_rmw(priv, AR8216_REG_PORT_CTRL(i), -			AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | -			AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | -			AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK, -			AR8216_PORT_CTRL_LEARN | -			  (priv->vlan && i == AR8216_PORT_CPU ? -			   AR8216_PORT_CTRL_HEADER : 0) | -			  (egress << AR8216_PORT_CTRL_VLAN_MODE_S) | -			  (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); - -		ar8216_rmw(priv, AR8216_REG_PORT_VLAN(i), -			AR8216_PORT_VLAN_DEST_PORTS | AR8216_PORT_VLAN_MODE | -			  AR8216_PORT_VLAN_DEFAULT_ID, -			(portmask[i] << AR8216_PORT_VLAN_DEST_PORTS_S) | -			  (ingress << AR8216_PORT_VLAN_MODE_S) | -			  (pvid << AR8216_PORT_VLAN_DEFAULT_ID_S)); -	} - -	return 0; -} - -static int -ar8216_reset_switch(struct switch_dev *dev) -{ -	struct ar8216_priv *priv = to_ar8216(dev); -	int i; - -	memset(&priv->vlan, 0, sizeof(struct ar8216_priv) - -		offsetof(struct ar8216_priv, vlan)); -	for (i = 0; i < AR8216_NUM_VLANS; i++) { -		priv->vlan_id[i] = i; -	} -	for (i = 0; i < AR8216_NUM_PORTS; i++) { -		/* Enable port learning and tx */ -		priv->write(priv, AR8216_REG_PORT_CTRL(i), -			AR8216_PORT_CTRL_LEARN | -			(4 << AR8216_PORT_CTRL_STATE_S)); - -		priv->write(priv, AR8216_REG_PORT_VLAN(i), 0); - -		/* Configure all PHYs */ -		if (i == AR8216_PORT_CPU) { -			priv->write(priv, AR8216_REG_PORT_STATUS(i), -				AR8216_PORT_STATUS_LINK_UP | -				AR8216_PORT_STATUS_SPEED | -				AR8216_PORT_STATUS_TXMAC | -				AR8216_PORT_STATUS_RXMAC | -				AR8216_PORT_STATUS_DUPLEX); -		} else { -			priv->write(priv, AR8216_REG_PORT_STATUS(i), -				AR8216_PORT_STATUS_LINK_AUTO); -		} -	} -	/* XXX: undocumented magic from atheros, required! */ -	priv->write(priv, 0x38, 0xc000050e); - -	ar8216_rmw(priv, AR8216_REG_GLOBAL_CTRL, -		AR8216_GCTRL_MTU, 1518 + 8 + 2); - -	return ar8216_hw_apply(dev); -} - -static int -ar8216_config_init(struct phy_device *pdev) -{ -	struct ar8216_priv *priv; -	struct net_device *dev = pdev->attached_dev; -	int ret; - -	printk("%s: AR8216 PHY driver attached.\n", pdev->attached_dev->name); -	pdev->supported = ADVERTISED_100baseT_Full; -	pdev->advertising = ADVERTISED_100baseT_Full; - -	priv = kzalloc(sizeof(struct ar8216_priv), GFP_KERNEL); -	if (priv == NULL) -		return -ENOMEM; - -	priv->phy = pdev; -	priv->read = ar8216_mii_read; -	priv->write = ar8216_mii_write; -	memcpy(&priv->dev, &athdev, sizeof(struct switch_dev)); -	pdev->priv = priv; -	if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) { -		kfree(priv); -		goto done; -	} - -	ret = ar8216_reset_switch(&priv->dev); -	if (ret) -		goto done; - -	dev->phy_ptr = priv; -	pdev->pkt_align = 2; -	pdev->netif_receive_skb = ar8216_netif_receive_skb; -	pdev->netif_rx = ar8216_netif_rx; - -	priv->ndo_old = dev->netdev_ops; -	memcpy(&priv->ndo, priv->ndo_old, sizeof(struct net_device_ops)); -	priv->ndo.ndo_start_xmit = ar8216_mangle_tx; -	dev->netdev_ops = &priv->ndo; - -done: -	return ret; -} - -static int -ar8216_read_status(struct phy_device *phydev) -{ -	struct ar8216_priv *priv = phydev->priv; - -	phydev->speed = SPEED_100; -	phydev->duplex = DUPLEX_FULL; -	phydev->state = PHY_UP; - -	/* flush the address translation unit */ -	if (ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0)) -		return -ETIMEDOUT; - -	priv->write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH); - -	return 0; -} - -static int -ar8216_config_aneg(struct phy_device *phydev) -{ -	return 0; -} - -static int -ar8216_probe(struct phy_device *pdev) -{ -	struct ar8216_priv priv; - -	u8 id, rev; -	u32 val; - -	priv.phy = pdev; -	val = ar8216_mii_read(&priv, AR8216_REG_CTRL); -	rev = val & 0xff; -	id = (val >> 8) & 0xff; -	if ((id != 1) || (rev != 1)) -		return -ENODEV; - -	return 0; -} - -static void -ar8216_remove(struct phy_device *pdev) -{ -	struct ar8216_priv *priv = pdev->priv; -	struct net_device *dev = pdev->attached_dev; - -	if (!priv) -		return; - -	if (priv->ndo_old && dev) -		dev->netdev_ops = priv->ndo_old; -	unregister_switch(&priv->dev); -	kfree(priv); -} - -/* template */ -static struct switch_dev athdev = { -	.name = "Atheros AR8216", -	.cpu_port = AR8216_PORT_CPU, -	.ports = AR8216_NUM_PORTS, -	.vlans = AR8216_NUM_VLANS, -	.attr_global = { -		.attr = ar8216_globals, -		.n_attr = ARRAY_SIZE(ar8216_globals), -	}, -	.attr_port = { -		.attr = ar8216_port, -		.n_attr = ARRAY_SIZE(ar8216_port), -	}, -	.attr_vlan = { -		.attr = ar8216_vlan, -		.n_attr = ARRAY_SIZE(ar8216_vlan), -	}, -	.get_port_pvid = ar8216_get_pvid, -	.set_port_pvid = ar8216_set_pvid, -	.get_vlan_ports = ar8216_get_ports, -	.set_vlan_ports = ar8216_set_ports, -	.apply_config = ar8216_hw_apply, -	.reset_switch = ar8216_reset_switch, -}; - -static struct phy_driver ar8216_driver = { -	.name		= "Atheros AR8216", -	.features	= PHY_BASIC_FEATURES, -	.probe		= ar8216_probe, -	.remove		= ar8216_remove, -	.config_init	= &ar8216_config_init, -	.config_aneg	= &ar8216_config_aneg, -	.read_status	= &ar8216_read_status, -	.driver		= { .owner = THIS_MODULE }, -}; - -int __init -ar8216_init(void) -{ -	return phy_driver_register(&ar8216_driver); -} - -void __exit -ar8216_exit(void) -{ -	phy_driver_unregister(&ar8216_driver); -} - -module_init(ar8216_init); -module_exit(ar8216_exit); -MODULE_LICENSE("GPL"); - diff --git a/target/linux/generic-2.6/files-2.6.31/drivers/net/phy/mvswitch.c b/target/linux/generic-2.6/files-2.6.31/drivers/net/phy/mvswitch.c deleted file mode 100644 index 7aed70d47..000000000 --- a/target/linux/generic-2.6/files-2.6.31/drivers/net/phy/mvswitch.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Marvell 88E6060 switch driver - * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org> - * - * 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 - * Free Software Foundation - */ -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/unistd.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/phy.h> -#include <linux/if_vlan.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include "mvswitch.h" - -/* Undefine this to use trailer mode instead. - * I don't know if header mode works with all chips */ -#define HEADER_MODE	1 - -MODULE_DESCRIPTION("Marvell 88E6060 Switch driver"); -MODULE_AUTHOR("Felix Fietkau"); -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; -	u8 vlans[16]; -}; - -#define to_mvsw(_phy) ((struct mvswitch_priv *) (_phy)->priv) - -static inline u16 -r16(struct phy_device *phydev, int addr, int reg) -{ -	return phydev->bus->read(phydev->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); -} - - -static int -mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev) -{ -	struct mvswitch_priv *priv; -	char *buf = NULL; -	u16 vid; - -	priv = dev->phy_ptr; -	if (unlikely(!priv)) -		goto error; - -	if (unlikely(skb->len < 16)) -		goto error; - -#ifdef HEADER_MODE -	if (__vlan_hwaccel_get_tag(skb, &vid)) -		goto error; - -	if (skb_cloned(skb) || (skb->len <= 62) || (skb_headroom(skb) < MV_HEADER_SIZE)) { -		if (pskb_expand_head(skb, MV_HEADER_SIZE, (skb->len < 62 ? 62 - skb->len : 0), GFP_ATOMIC)) -			goto error_expand; -		if (skb->len < 62) -			skb->len = 62; -	} -	buf = skb_push(skb, MV_HEADER_SIZE); -#else -	if (__vlan_get_tag(skb, &vid)) -		goto error; - -	if (unlikely((vid > 15 || !priv->vlans[vid]))) -		goto error; - -	if (skb->len <= 64) { -		if (pskb_expand_head(skb, 0, 64 + MV_TRAILER_SIZE - skb->len, GFP_ATOMIC)) -			goto error_expand; - -		buf = skb->data + 64; -		skb->len = 64 + MV_TRAILER_SIZE; -	} else { -		if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) { -			if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC)) -				goto error_expand; -		} -		buf = skb_put(skb, 4); -	} - -	/* move the ethernet header 4 bytes forward, overwriting the vlan tag */ -	memmove(skb->data + 4, skb->data, 12); -	skb->data += 4; -	skb->len -= 4; -	skb->mac_header += 4; -#endif - -	if (!buf) -		goto error; - - -#ifdef HEADER_MODE -	/* prepend the tag */ -	*((__be16 *) buf) = cpu_to_be16( -		((vid << MV_HEADER_VLAN_S) & MV_HEADER_VLAN_M) | -		((priv->vlans[vid] << MV_HEADER_PORTS_S) & MV_HEADER_PORTS_M) -	); -#else -	/* append the tag */ -	*((__be32 *) buf) = cpu_to_be32(( -		(MV_TRAILER_OVERRIDE << MV_TRAILER_FLAGS_S) | -		((priv->vlans[vid] & MV_TRAILER_PORTS_M) << MV_TRAILER_PORTS_S) -	)); -#endif - -	return priv->ndo_old->ndo_start_xmit(skb, dev); - -error_expand: -	if (net_ratelimit()) -		printk("%s: failed to expand/update skb for the switch\n", dev->name); - -error: -	/* any errors? drop the packet! */ -	dev_kfree_skb_any(skb); -	return 0; -} - -static int -mvswitch_mangle_rx(struct sk_buff *skb, int napi) -{ -	struct mvswitch_priv *priv; -	struct net_device *dev; -	int vlan = -1; -	unsigned char *buf; -	int i; - -	dev = skb->dev; -	if (!dev) -		goto error; - -	priv = dev->phy_ptr; -	if (!priv) -		goto error; - -	if (!priv->grp) -		goto error; - -#ifdef HEADER_MODE -	buf = skb->data; -	skb_pull(skb, MV_HEADER_SIZE); -#else -	buf = skb->data + skb->len - MV_TRAILER_SIZE; -	if (buf[0] != 0x80) -		goto error; -#endif - -	/* look for the vlan matching the incoming port */ -	for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) { -		if ((1 << buf[1]) & priv->vlans[i]) -			vlan = i; -	} - -	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); - -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; -} - - -static int -mvswitch_wait_mask(struct phy_device *pdev, int addr, int reg, u16 mask, u16 val) -{ -	int i = 100; -	u16 r; - -	do { -		r = r16(pdev, addr, reg) & mask; -		if (r == val) -			return 0; -	} while(--i > 0); -	return -ETIMEDOUT; -} - -static int -mvswitch_config_init(struct phy_device *pdev) -{ -	struct mvswitch_priv *priv = to_mvsw(pdev); -	struct net_device *dev = pdev->attached_dev; -	u8 vlmap = 0; -	int i; - -	if (!dev) -		return -EINVAL; - -	printk("%s: Marvell 88E6060 PHY driver attached.\n", dev->name); -	pdev->supported = ADVERTISED_100baseT_Full; -	pdev->advertising = ADVERTISED_100baseT_Full; -	dev->phy_ptr = priv; -	dev->irq = PHY_POLL; - -	/* initialize default vlans */ -	for (i = 0; i < MV_PORTS; i++) -		priv->vlans[(i == MV_WANPORT ? 2 : 1)] |= (1 << i); - -	/* before entering reset, disable all ports */ -	for (i = 0; i < MV_PORTS; i++) -		w16(pdev, MV_PORTREG(CONTROL, i), 0x00); - -	msleep(2); /* wait for the status change to settle in */ - -	/* put the ATU in reset */ -	w16(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET); - -	i = mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET, 0); -	if (i < 0) { -		printk("%s: Timeout waiting for the switch to reset.\n", dev->name); -		return i; -	} - -	/* set the ATU flags */ -	w16(pdev, MV_SWITCHREG(ATU_CTRL), -		MV_ATUCTL_NO_LEARN | -		MV_ATUCTL_ATU_1K | -		MV_ATUCTL_AGETIME(MV_ATUCTL_AGETIME_MIN) /* minimum without disabling ageing */ -	); - -	/* initialize the cpu port */ -	w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT), -#ifdef HEADER_MODE -		MV_PORTCTRL_HEADER | -#else -		MV_PORTCTRL_RXTR | -		MV_PORTCTRL_TXTR | -#endif -		MV_PORTCTRL_ENABLED -	); -	/* wait for the phy change to settle in */ -	msleep(2); -	for (i = 0; i < MV_PORTS; i++) { -		u8 pvid = 0; -		int j; - -		vlmap = 0; - -		/* look for the matching vlan */ -		for (j = 0; j < ARRAY_SIZE(priv->vlans); j++) { -			if (priv->vlans[j] & (1 << i)) { -				vlmap = priv->vlans[j]; -				pvid = j; -			} -		} -		/* leave port unconfigured if it's not part of a vlan */ -		if (!vlmap) -			continue; - -		/* add the cpu port to the allowed destinations list */ -		vlmap |= (1 << MV_CPUPORT); - -		/* take port out of its own vlan destination map */ -		vlmap &= ~(1 << i); - -		/* apply vlan settings */ -		w16(pdev, MV_PORTREG(VLANMAP, i), -			MV_PORTVLAN_PORTS(vlmap) | -			MV_PORTVLAN_ID(i) -		); - -		/* re-enable port */ -		w16(pdev, MV_PORTREG(CONTROL, i), -			MV_PORTCTRL_ENABLED -		); -	} - -	w16(pdev, MV_PORTREG(VLANMAP, MV_CPUPORT), -		MV_PORTVLAN_ID(MV_CPUPORT) -	); - -	/* set the port association vector */ -	for (i = 0; i <= MV_PORTS; i++) { -		w16(pdev, MV_PORTREG(ASSOC, i), -			MV_PORTASSOC_PORTS(1 << i) -		); -	} - -	/* init switch control */ -	w16(pdev, MV_SWITCHREG(CTRL), -		MV_SWITCHCTL_MSIZE | -		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; - -	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; -#else -	dev->features |= NETIF_F_HW_VLAN_RX; -#endif - -	return 0; -} - -static int -mvswitch_read_status(struct phy_device *pdev) -{ -	pdev->speed = SPEED_100; -	pdev->duplex = DUPLEX_FULL; -	pdev->state = PHY_UP; - -	/* XXX ugly workaround: we can't force the switch -	 * to gracefully handle hosts moving from one port to another, -	 * so we have to regularly clear the ATU database */ - -	/* wait for the ATU to become available */ -	mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0); - -	/* flush the ATU */ -	w16(pdev, MV_SWITCHREG(ATU_OP), -		MV_ATUOP_INPROGRESS | -		MV_ATUOP_FLUSH_ALL -	); - -	/* wait for operation to complete */ -	mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0); - -	return 0; -} - -static int -mvswitch_config_aneg(struct phy_device *phydev) -{ -	return 0; -} - -static void -mvswitch_remove(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; -	dev->vlan_rx_register = NULL; -	dev->vlan_rx_kill_vid = NULL; -	dev->phy_ptr = NULL; -	dev->features &= ~NETIF_F_HW_VLAN_RX; -	kfree(priv); -} - -static int -mvswitch_probe(struct phy_device *pdev) -{ -	struct mvswitch_priv *priv; - -	priv = kzalloc(sizeof(struct mvswitch_priv), GFP_KERNEL); -	if (priv == NULL) -		return -ENOMEM; - -	pdev->priv = priv; - -	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, -	.probe		= &mvswitch_probe, -	.remove		= &mvswitch_remove, -	.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); -} - -static void __exit -mvswitch_exit(void) -{ -	phy_driver_unregister(&mvswitch_driver); -} - -module_init(mvswitch_init); -module_exit(mvswitch_exit); 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 3100b92de..93e4b33d9 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 @@ -33,12 +33,12 @@  struct ar8216_priv { -	int (*hardstart)(struct sk_buff *skb, struct net_device *dev); -  	struct switch_dev dev;  	struct phy_device *phy;  	u32 (*read)(struct ar8216_priv *priv, int reg);  	void (*write)(struct ar8216_priv *priv, int reg, u32 val); +	const struct net_device_ops *ndo_old; +	struct net_device_ops ndo;  	/* all fields below are cleared on reset */  	bool vlan; @@ -186,7 +186,7 @@ ar8216_mangle_tx(struct sk_buff *skb, struct net_device *dev)  	buf[1] = 0x80;  send: -	return priv->hardstart(skb, dev); +	return priv->ndo_old->ndo_start_xmit(skb, dev);  error:  	dev_kfree_skb_any(skb); @@ -439,7 +439,8 @@ ar8216_hw_apply(struct switch_dev *dev)  			AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE |  			AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK,  			AR8216_PORT_CTRL_LEARN | -			  (i == AR8216_PORT_CPU ? AR8216_PORT_CTRL_HEADER : 0) | +			  (priv->vlan && i == AR8216_PORT_CPU ? +			   AR8216_PORT_CTRL_HEADER : 0) |  			  (egress << AR8216_PORT_CTRL_VLAN_MODE_S) |  			  (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); @@ -526,10 +527,13 @@ ar8216_config_init(struct phy_device *pdev)  	dev->phy_ptr = priv;  	pdev->pkt_align = 2; -	priv->hardstart = dev->hard_start_xmit;  	pdev->netif_receive_skb = ar8216_netif_receive_skb;  	pdev->netif_rx = ar8216_netif_rx; -	dev->hard_start_xmit = ar8216_mangle_tx; + +	priv->ndo_old = dev->netdev_ops; +	memcpy(&priv->ndo, priv->ndo_old, sizeof(struct net_device_ops)); +	priv->ndo.ndo_start_xmit = ar8216_mangle_tx; +	dev->netdev_ops = &priv->ndo;  done:  	return ret; @@ -586,8 +590,8 @@ ar8216_remove(struct phy_device *pdev)  	if (!priv)  		return; -	if (priv->hardstart && dev) -		dev->hard_start_xmit = priv->hardstart; +	if (priv->ndo_old && dev) +		dev->netdev_ops = priv->ndo_old;  	unregister_switch(&priv->dev);  	kfree(priv);  } diff --git a/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c b/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c index b98699e17..3ae8899c2 100644 --- a/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c +++ b/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c @@ -41,8 +41,8 @@ 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];  }; @@ -133,7 +133,7 @@ mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)  	));  #endif -	return priv->hardstart(skb, dev); +	return priv->ndo_old->ndo_start_xmit(skb, dev);  error_expand:  	if (net_ratelimit()) @@ -248,6 +248,9 @@ mvswitch_config_init(struct phy_device *pdev)  	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++) @@ -340,12 +343,15 @@ mvswitch_config_init(struct phy_device *pdev)  	);  	/* 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; +  	pdev->pkt_align = 2; -	priv->hardstart = dev->hard_start_xmit;  	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 @@ -393,11 +399,9 @@ mvswitch_remove(struct phy_device *pdev)  	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); diff --git a/target/linux/generic-2.6/patches-2.6.28/660-phy_mvswitch.patch b/target/linux/generic-2.6/patches-2.6.28/660-phy_mvswitch.patch deleted file mode 100644 index 29b9c31f0..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/660-phy_mvswitch.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -77,6 +77,9 @@ config ADM6996_PHY - 	---help--- - 	  Currently supports the ADM6996F switch -  -+config MVSWITCH_PHY -+	tristate "Driver for Marvell 88E6060 switches" -+ - config FIXED_PHY - 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" - 	depends on PHYLIB=y ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o - obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o - obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o - obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o -+obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o - obj-$(CONFIG_REALTEK_PHY)	+= realtek.o - obj-$(CONFIG_FIXED_PHY)		+= fixed.o - obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o diff --git a/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch b/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch index 380d18d4e..02a5947aa 100644 --- a/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch +++ b/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch @@ -1,8 +1,8 @@  --- a/drivers/net/phy/Kconfig  +++ b/drivers/net/phy/Kconfig -@@ -80,6 +80,10 @@ config ADM6996_PHY - config MVSWITCH_PHY - 	tristate "Driver for Marvell 88E6060 switches" +@@ -77,6 +77,10 @@ config ADM6996_PHY + 	---help--- + 	  Currently supports the ADM6996F switch  +config IP175C_PHY  +	tristate "Driver for IC+ IP175C/IP178C switches" @@ -13,10 +13,10 @@   	depends on PHYLIB=y  --- a/drivers/net/phy/Makefile  +++ b/drivers/net/phy/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o +@@ -14,6 +14,7 @@ obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o + obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o   obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o   obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o - obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o  +obj-$(CONFIG_IP175C_PHY)	+= ip175c.o   obj-$(CONFIG_REALTEK_PHY)	+= realtek.o   obj-$(CONFIG_FIXED_PHY)		+= fixed.o diff --git a/target/linux/generic-2.6/patches-2.6.28/680-phy_ar8216.patch b/target/linux/generic-2.6/patches-2.6.28/680-phy_ar8216.patch deleted file mode 100644 index 2e9bab10e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/680-phy_ar8216.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -84,6 +84,10 @@ config IP175C_PHY - 	tristate "Driver for IC+ IP175C/IP178C switches" - 	select SWCONFIG -  -+config AR8216_PHY -+	tristate "Driver for Atheros AR8216 switches" -+	select SWCONFIG -+ - config FIXED_PHY - 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" - 	depends on PHYLIB=y ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o - obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o - obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o - obj-$(CONFIG_IP175C_PHY)	+= ip175c.o -+obj-$(CONFIG_AR8216_PHY)	+= ar8216.o - obj-$(CONFIG_REALTEK_PHY)	+= realtek.o - obj-$(CONFIG_FIXED_PHY)		+= fixed.o - obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o diff --git a/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch b/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch index e88db1664..b56d55b45 100644 --- a/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch +++ b/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch @@ -1,7 +1,7 @@  --- a/drivers/net/phy/Kconfig  +++ b/drivers/net/phy/Kconfig -@@ -88,6 +88,10 @@ config AR8216_PHY - 	tristate "Driver for Atheros AR8216 switches" +@@ -81,6 +81,10 @@ config IP175C_PHY + 	tristate "Driver for IC+ IP175C/IP178C switches"   	select SWCONFIG  +config RTL8306_PHY @@ -13,10 +13,10 @@   	depends on PHYLIB=y  --- a/drivers/net/phy/Makefile  +++ b/drivers/net/phy/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o - obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o +@@ -15,6 +15,7 @@ obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o + obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o + obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o   obj-$(CONFIG_IP175C_PHY)	+= ip175c.o - obj-$(CONFIG_AR8216_PHY)	+= ar8216.o  +obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o   obj-$(CONFIG_REALTEK_PHY)	+= realtek.o   obj-$(CONFIG_FIXED_PHY)		+= fixed.o | 
