Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 4/5] ethtool: Explicitly state the exit condition for interrupt coalescing
From: Ben Hutchings @ 2011-08-16  0:08 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Eli Cohen
In-Reply-To: <1313453180.2731.57.camel@bwh-desktop>

Also explicitly state how to disable interrupt coalescing.

Remove the now-redundant text from field descriptions.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 include/linux/ethtool.h |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 18059ca..42378b3 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -121,20 +121,18 @@ struct ethtool_eeprom {
  * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates
  * @cmd: ETHTOOL_{G,S}COALESCE
  * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
- *	a packet arrives.  If 0, only @rx_max_coalesced_frames is used.
+ *	a packet arrives.
  * @rx_max_coalesced_frames: Maximum number of packets to receive
- *	before an RX interrupt.  If 0, only @rx_coalesce_usecs is used.
+ *	before an RX interrupt.
  * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that
  *	this value applies while an IRQ is being serviced by the host.
  * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames,
  *	except that this value applies while an IRQ is being serviced
  *	by the host.
  * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after
- *	a packet is sent.  If 0, only @tx_max_coalesced_frames
- *	is used.
+ *	a packet is sent.
  * @tx_max_coalesced_frames: Maximum number of packets to be sent
- *	before a TX interrupt.  If 0, only @tx_coalesce_usecs is
- *     used.
+ *	before a TX interrupt.
  * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that
  *	this value applies while an IRQ is being serviced by the host.
  * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames,
@@ -167,8 +165,13 @@ struct ethtool_eeprom {
  * @rate_sample_interval: How often to do adaptive coalescing packet rate
  *	sampling, measured in seconds.  Must not be zero.
  *
- * It is illegal to set both usecs and max frames to zero as this
- * would cause interrupts to never be generated.
+ * Each pair of (usecs, max_frames) fields specifies this exit
+ * condition for interrupt coalescing:
+ *	(usecs > 0 && time_since_first_completion >= usecs) ||
+ *	(max_frames > 0 && completed_frames >= max_frames)
+ * It is illegal to set both usecs and max_frames to zero as this
+ * would cause interrupts to never be generated.  To disable
+ * coalescing, set usecs = 0 and max_frames = 1.
  *
  * Adaptive RX/TX coalescing is an algorithm implemented by some
  * drivers to improve latency under low packet rates and improve
-- 
1.7.4.4



-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* [PATCH net-next 5/5] ethtool: Note common alternate exit condition for interrupt coalescing
From: Ben Hutchings @ 2011-08-16  0:09 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Eli Cohen
In-Reply-To: <1313453180.2731.57.camel@bwh-desktop>

Many implementations ignore the value of max_frames and do not
treat usecs == 0 as special.  Document this as deprecated.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 include/linux/ethtool.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 42378b3..3829712 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -173,6 +173,12 @@ struct ethtool_eeprom {
  * would cause interrupts to never be generated.  To disable
  * coalescing, set usecs = 0 and max_frames = 1.
  *
+ * Some implementations ignore the value of max_frames and use the
+ * condition:
+ *	time_since_first_completion >= usecs
+ * This is deprecated.  Drivers for hardware that does not support
+ * counting completions should validate that max_frames == !rx_usecs.
+ *
  * Adaptive RX/TX coalescing is an algorithm implemented by some
  * drivers to improve latency under low packet rates and improve
  * throughput under high packet rates.  Some drivers only implement
-- 
1.7.4.4


-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* [PATCH net-2.6 V2] bonding:reset backup and inactive flag of slave
From: Weiping Pan @ 2011-08-16  1:57 UTC (permalink / raw)
  To: netdev; +Cc: Weiping Pan
In-Reply-To: <j2bgs2$pf5$1@dough.gmane.org>

Eduard Sinelnikov (eduard.sinelnikov@gmail.com) found that if we change
bonding mode from active backup to round robin, some slaves are still keeping
"backup", and won't transmit packets.

As Jay Vosburgh(fubar@us.ibm.com) pointed out that we can work around that by
removing the bond_is_active_slave() check, because the "backup" flag is only
meaningful for active backup mode.

But if we just simply ignore the bond_is_active_slave() check,
the transmission will work fine, but we can't maintain the correct value of
"backup" flag for each slaves, though it is meaningless for other mode than
active backup.

I'd like to reset "backup" and "inactive" flag in bond_open,
thus we can keep the correct value of them.

As for bond_is_active_slave(), I'd like to prepare another patch to handle it.

V2:
Use C style comment.
Move read_lock(&bond->curr_slave_lock).
Replace restore with reset, for active backup mode, it means "restore",
but for other modes, it means "reset".

Signed-off-by: Weiping Pan <panweiping3@gmail.com>
---
 drivers/net/bonding/bond_main.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 38a83ac..43f2ea5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3419,9 +3419,27 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
 static int bond_open(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct slave *slave;
+	int i;
 
 	bond->kill_timers = 0;
 
+	/* reset slave->backup and slave->inactive */
+	read_lock(&bond->lock);
+	if (bond->slave_cnt > 0) {
+		read_lock(&bond->curr_slave_lock);
+		bond_for_each_slave(bond, slave, i) {
+			if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+				&& (slave != bond->curr_active_slave)) {
+				bond_set_slave_inactive_flags(slave);
+			} else {
+				bond_set_slave_active_flags(slave);
+			}
+		}
+		read_unlock(&bond->curr_slave_lock);
+	}
+	read_unlock(&bond->lock);
+
 	INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
 
 	if (bond_is_lb(bond)) {
-- 
1.7.4.4


^ permalink raw reply related

* linux-next: build failure after merge of the net tree
From: Stephen Rothwell @ 2011-08-16  3:26 UTC (permalink / raw)
  To: David Miller, netdev; +Cc: linux-next, linux-kernel

Hi all,

After merging the net tree, today's linux-next build (x86_64 allmodconfig)
failed like this:

drivers/net/ethernet/sun/sungem_phy.c:36:24: fatal error: sungem_phy.h: No such file or directory

Caused by commit 2bb698412d8a ("net: Move sungem_phy.h under
include/linux").

I applied this patch for today:

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 13:22:24 +1000
Subject: [PATCH] sungem: sungem_phy.h moved

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 drivers/net/ethernet/sun/sungem_phy.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/sun/sungem_phy.c b/drivers/net/ethernet/sun/sungem_phy.c
index d16880d..db99c22 100644
--- a/drivers/net/ethernet/sun/sungem_phy.c
+++ b/drivers/net/ethernet/sun/sungem_phy.c
@@ -33,7 +33,7 @@
 #include <asm/prom.h>
 #endif
 
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
 
 /* Link modes of the BCM5400 PHY */
 static const int phy_BCM5400_link_table[8][3] = {
-- 
1.7.5.4

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

^ permalink raw reply related

* Re: linux-next: build failure after merge of the net tree
From: David Miller @ 2011-08-16  4:03 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linux-next, linux-kernel
In-Reply-To: <20110816132659.7719837bd136aa520c5814ac@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 13:26:59 +1000

> I applied this patch for today:
> 
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Tue, 16 Aug 2011 13:22:24 +1000
> Subject: [PATCH] sungem: sungem_phy.h moved
> 
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>

Sigh, applied, sorry about this.

^ permalink raw reply

* Re: linux-next: build failure after merge of the final tree (net tree related)
From: Stephen Rothwell @ 2011-08-16  5:28 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110814.225610.2264854100578866902.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 467 bytes --]

Hi Dave,

On Sun, 14 Aug 2011 22:56:10 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>
> This should fix the include problem, but I suspect this thing won't
> link.

Yep, indeed, today I get:

make[5]: *** No rule to make target `drivers/net/ethernet/toshiba/ethernet/sun/sungem_phy.o', needed by `drivers/net/ethernet/toshiba/built-in.o'.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* Re: linux-next: build failure after merge of the final tree (net tree related)
From: David Miller @ 2011-08-16  6:11 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110816152815.911f15937efa2ebf58a2795d@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 15:28:15 +1000

> Hi Dave,
> 
> On Sun, 14 Aug 2011 22:56:10 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>>
>> This should fix the include problem, but I suspect this thing won't
>> link.
> 
> Yep, indeed, today I get:
> 
> make[5]: *** No rule to make target `drivers/net/ethernet/toshiba/ethernet/sun/sungem_phy.o', needed by `drivers/net/ethernet/toshiba/built-in.o'.

Please test this patch:

--------------------
net: Fix sungem_phy sharing.

Since sungem_phy is used by multiple, unrelated, drivers make it
build as a real module under drivers/net.

depmod will pick up the symbol dependency and make sure sungem_phy.ko
gets loaded any time sungem.ko or spider_net.ko is loaded.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/Kconfig                       |    3 +
 drivers/net/Makefile                      |    2 +
 drivers/net/ethernet/sun/Makefile         |    1 -
 drivers/net/ethernet/sun/sungem.c         |    2 +-
 drivers/net/ethernet/sun/sungem_phy.c     | 1200 -----------------------------
 drivers/net/ethernet/toshiba/Makefile     |    2 +-
 drivers/net/ethernet/toshiba/spider_net.c |    4 +-
 drivers/net/sungem_phy.c                  | 1199 ++++++++++++++++++++++++++++
 include/linux/sungem_phy.h                |    2 +-
 9 files changed, 1209 insertions(+), 1206 deletions(-)
 delete mode 100644 drivers/net/ethernet/sun/sungem_phy.c
 create mode 100644 drivers/net/sungem_phy.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 31d8792..ef6b6be 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -186,6 +186,9 @@ config MII
 
 source "drivers/net/phy/Kconfig"
 
+config SUNGEM_PHY
+	tristate
+
 #
 #	Ethernet
 #
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 9cb47bb..c33009b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -75,3 +75,5 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
 
 obj-$(CONFIG_WIMAX) += wimax/
 obj-$(CONFIG_CAIF) += caif/
+
+obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
diff --git a/drivers/net/ethernet/sun/Makefile b/drivers/net/ethernet/sun/Makefile
index 6e25dad..1e620ff 100644
--- a/drivers/net/ethernet/sun/Makefile
+++ b/drivers/net/ethernet/sun/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
 obj-$(CONFIG_SUNQE) += sunqe.o
 obj-$(CONFIG_SUNBMAC) += sunbmac.o
 obj-$(CONFIG_SUNGEM) += sungem.o
-obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
 obj-$(CONFIG_CASSINI) += cassini.o
 obj-$(CONFIG_SUNVNET) += sunvnet.o
 obj-$(CONFIG_NIU) += niu.o
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 0f13c5d..fb9885d 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -1721,7 +1721,7 @@ static void gem_init_phy(struct gem *gp)
 	if (gp->phy_type == phy_mii_mdio0 ||
 	    gp->phy_type == phy_mii_mdio1) {
 		/* Reset and detect MII PHY */
-		mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
+		sungem_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
 
 		/* Init PHY */
 		if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
diff --git a/drivers/net/ethernet/sun/sungem_phy.c b/drivers/net/ethernet/sun/sungem_phy.c
deleted file mode 100644
index db99c22..0000000
--- a/drivers/net/ethernet/sun/sungem_phy.c
+++ /dev/null
@@ -1,1200 +0,0 @@
-/*
- * PHY drivers for the sungem ethernet driver.
- *
- * This file could be shared with other drivers.
- *
- * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org)
- *
- * TODO:
- *  - Add support for PHYs that provide an IRQ line
- *  - Eventually moved the entire polling state machine in
- *    there (out of the eth driver), so that it can easily be
- *    skipped on PHYs that implement it in hardware.
- *  - On LXT971 & BCM5201, Apple uses some chip specific regs
- *    to read the link status. Figure out why and if it makes
- *    sense to do the same (magic aneg ?)
- *  - Apple has some additional power management code for some
- *    Broadcom PHYs that they "hide" from the OpenSource version
- *    of darwin, still need to reverse engineer that
- */
-
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/prom.h>
-#endif
-
-#include <linux/sungem_phy.h>
-
-/* Link modes of the BCM5400 PHY */
-static const int phy_BCM5400_link_table[8][3] = {
-	{ 0, 0, 0 },	/* No link */
-	{ 0, 0, 0 },	/* 10BT Half Duplex */
-	{ 1, 0, 0 },	/* 10BT Full Duplex */
-	{ 0, 1, 0 },	/* 100BT Half Duplex */
-	{ 0, 1, 0 },	/* 100BT Half Duplex */
-	{ 1, 1, 0 },	/* 100BT Full Duplex*/
-	{ 1, 0, 1 },	/* 1000BT */
-	{ 1, 0, 1 },	/* 1000BT */
-};
-
-static inline int __phy_read(struct mii_phy* phy, int id, int reg)
-{
-	return phy->mdio_read(phy->dev, id, reg);
-}
-
-static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
-{
-	phy->mdio_write(phy->dev, id, reg, val);
-}
-
-static inline int phy_read(struct mii_phy* phy, int reg)
-{
-	return phy->mdio_read(phy->dev, phy->mii_id, reg);
-}
-
-static inline void phy_write(struct mii_phy* phy, int reg, int val)
-{
-	phy->mdio_write(phy->dev, phy->mii_id, reg, val);
-}
-
-static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
-{
-	u16 val;
-	int limit = 10000;
-
-	val = __phy_read(phy, phy_id, MII_BMCR);
-	val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
-	val |= BMCR_RESET;
-	__phy_write(phy, phy_id, MII_BMCR, val);
-
-	udelay(100);
-
-	while (--limit) {
-		val = __phy_read(phy, phy_id, MII_BMCR);
-		if ((val & BMCR_RESET) == 0)
-			break;
-		udelay(10);
-	}
-	if ((val & BMCR_ISOLATE) && limit > 0)
-		__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
-
-	return limit <= 0;
-}
-
-static int bcm5201_init(struct mii_phy* phy)
-{
-	u16 data;
-
-	data = phy_read(phy, MII_BCM5201_MULTIPHY);
-	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
-	phy_write(phy, MII_BCM5201_MULTIPHY, data);
-
-	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
-
-	return 0;
-}
-
-static int bcm5201_suspend(struct mii_phy* phy)
-{
-	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
-	phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
-
-	return 0;
-}
-
-static int bcm5221_init(struct mii_phy* phy)
-{
-	u16 data;
-
-	data = phy_read(phy, MII_BCM5221_TEST);
-	phy_write(phy, MII_BCM5221_TEST,
-		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
-	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
-	phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
-		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
-
-	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
-	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
-		data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
-
-	data = phy_read(phy, MII_BCM5221_TEST);
-	phy_write(phy, MII_BCM5221_TEST,
-		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
-
-	return 0;
-}
-
-static int bcm5221_suspend(struct mii_phy* phy)
-{
-	u16 data;
-
-	data = phy_read(phy, MII_BCM5221_TEST);
-	phy_write(phy, MII_BCM5221_TEST,
-		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
-	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
-	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
-		  data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
-
-	return 0;
-}
-
-static int bcm5241_init(struct mii_phy* phy)
-{
-	u16 data;
-
-	data = phy_read(phy, MII_BCM5221_TEST);
-	phy_write(phy, MII_BCM5221_TEST,
-		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
-	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
-	phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
-		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
-
-	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
-	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
-		data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
-
-	data = phy_read(phy, MII_BCM5221_TEST);
-	phy_write(phy, MII_BCM5221_TEST,
-		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
-
-	return 0;
-}
-
-static int bcm5241_suspend(struct mii_phy* phy)
-{
-	u16 data;
-
-	data = phy_read(phy, MII_BCM5221_TEST);
-	phy_write(phy, MII_BCM5221_TEST,
-		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
-
-	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
-	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
-		  data | MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
-
-	return 0;
-}
-
-static int bcm5400_init(struct mii_phy* phy)
-{
-	u16 data;
-
-	/* Configure for gigabit full duplex */
-	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
-	data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
-	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
-
-	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
-	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
-	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
-
-	udelay(100);
-
-	/* Reset and configure cascaded 10/100 PHY */
-	(void)reset_one_mii_phy(phy, 0x1f);
-
-	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
-	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
-	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
-
-	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
-	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
-	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
-
-	return 0;
-}
-
-static int bcm5400_suspend(struct mii_phy* phy)
-{
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
-	phy_write(phy, MII_BMCR, BMCR_PDOWN);
-#endif
-	return 0;
-}
-
-static int bcm5401_init(struct mii_phy* phy)
-{
-	u16 data;
-	int rev;
-
-	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
-	if (rev == 0 || rev == 3) {
-		/* Some revisions of 5401 appear to need this
-		 * initialisation sequence to disable, according
-		 * to OF, "tap power management"
-		 *
-		 * WARNING ! OF and Darwin don't agree on the
-		 * register addresses. OF seem to interpret the
-		 * register numbers below as decimal
-		 *
-		 * Note: This should (and does) match tg3_init_5401phy_dsp
-		 *       in the tg3.c driver. -DaveM
-		 */
-		phy_write(phy, 0x18, 0x0c20);
-		phy_write(phy, 0x17, 0x0012);
-		phy_write(phy, 0x15, 0x1804);
-		phy_write(phy, 0x17, 0x0013);
-		phy_write(phy, 0x15, 0x1204);
-		phy_write(phy, 0x17, 0x8006);
-		phy_write(phy, 0x15, 0x0132);
-		phy_write(phy, 0x17, 0x8006);
-		phy_write(phy, 0x15, 0x0232);
-		phy_write(phy, 0x17, 0x201f);
-		phy_write(phy, 0x15, 0x0a20);
-	}
-
-	/* Configure for gigabit full duplex */
-	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
-	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
-	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
-
-	udelay(10);
-
-	/* Reset and configure cascaded 10/100 PHY */
-	(void)reset_one_mii_phy(phy, 0x1f);
-
-	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
-	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
-	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
-
-	return 0;
-}
-
-static int bcm5401_suspend(struct mii_phy* phy)
-{
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
-	phy_write(phy, MII_BMCR, BMCR_PDOWN);
-#endif
-	return 0;
-}
-
-static int bcm5411_init(struct mii_phy* phy)
-{
-	u16 data;
-
-	/* Here's some more Apple black magic to setup
-	 * some voltage stuffs.
-	 */
-	phy_write(phy, 0x1c, 0x8c23);
-	phy_write(phy, 0x1c, 0x8ca3);
-	phy_write(phy, 0x1c, 0x8c23);
-
-	/* Here, Apple seems to want to reset it, do
-	 * it as well
-	 */
-	phy_write(phy, MII_BMCR, BMCR_RESET);
-	phy_write(phy, MII_BMCR, 0x1340);
-
-	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
-	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
-	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
-
-	udelay(10);
-
-	/* Reset and configure cascaded 10/100 PHY */
-	(void)reset_one_mii_phy(phy, 0x1f);
-
-	return 0;
-}
-
-static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
-	u16 ctl, adv;
-
-	phy->autoneg = 1;
-	phy->speed = SPEED_10;
-	phy->duplex = DUPLEX_HALF;
-	phy->pause = 0;
-	phy->advertising = advertise;
-
-	/* Setup standard advertise */
-	adv = phy_read(phy, MII_ADVERTISE);
-	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	if (advertise & ADVERTISED_10baseT_Half)
-		adv |= ADVERTISE_10HALF;
-	if (advertise & ADVERTISED_10baseT_Full)
-		adv |= ADVERTISE_10FULL;
-	if (advertise & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	phy_write(phy, MII_ADVERTISE, adv);
-
-	/* Start/Restart aneg */
-	ctl = phy_read(phy, MII_BMCR);
-	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
-	u16 ctl;
-
-	phy->autoneg = 0;
-	phy->speed = speed;
-	phy->duplex = fd;
-	phy->pause = 0;
-
-	ctl = phy_read(phy, MII_BMCR);
-	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
-
-	/* First reset the PHY */
-	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
-
-	/* Select speed & duplex */
-	switch(speed) {
-	case SPEED_10:
-		break;
-	case SPEED_100:
-		ctl |= BMCR_SPEED100;
-		break;
-	case SPEED_1000:
-	default:
-		return -EINVAL;
-	}
-	if (fd == DUPLEX_FULL)
-		ctl |= BMCR_FULLDPLX;
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int genmii_poll_link(struct mii_phy *phy)
-{
-	u16 status;
-
-	(void)phy_read(phy, MII_BMSR);
-	status = phy_read(phy, MII_BMSR);
-	if ((status & BMSR_LSTATUS) == 0)
-		return 0;
-	if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
-		return 0;
-	return 1;
-}
-
-static int genmii_read_link(struct mii_phy *phy)
-{
-	u16 lpa;
-
-	if (phy->autoneg) {
-		lpa = phy_read(phy, MII_LPA);
-
-		if (lpa & (LPA_10FULL | LPA_100FULL))
-			phy->duplex = DUPLEX_FULL;
-		else
-			phy->duplex = DUPLEX_HALF;
-		if (lpa & (LPA_100FULL | LPA_100HALF))
-			phy->speed = SPEED_100;
-		else
-			phy->speed = SPEED_10;
-		phy->pause = 0;
-	}
-	/* On non-aneg, we assume what we put in BMCR is the speed,
-	 * though magic-aneg shouldn't prevent this case from occurring
-	 */
-
-	 return 0;
-}
-
-static int generic_suspend(struct mii_phy* phy)
-{
-	phy_write(phy, MII_BMCR, BMCR_PDOWN);
-
-	return 0;
-}
-
-static int bcm5421_init(struct mii_phy* phy)
-{
-	u16 data;
-	unsigned int id;
-
-	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
-
-	/* Revision 0 of 5421 needs some fixups */
-	if (id == 0x002060e0) {
-		/* This is borrowed from MacOS
-		 */
-		phy_write(phy, 0x18, 0x1007);
-		data = phy_read(phy, 0x18);
-		phy_write(phy, 0x18, data | 0x0400);
-		phy_write(phy, 0x18, 0x0007);
-		data = phy_read(phy, 0x18);
-		phy_write(phy, 0x18, data | 0x0800);
-		phy_write(phy, 0x17, 0x000a);
-		data = phy_read(phy, 0x15);
-		phy_write(phy, 0x15, data | 0x0200);
-	}
-
-	/* Pick up some init code from OF for K2 version */
-	if ((id & 0xfffffff0) == 0x002062e0) {
-		phy_write(phy, 4, 0x01e1);
-		phy_write(phy, 9, 0x0300);
-	}
-
-	/* Check if we can enable automatic low power */
-#ifdef CONFIG_PPC_PMAC
-	if (phy->platform_data) {
-		struct device_node *np = of_get_parent(phy->platform_data);
-		int can_low_power = 1;
-		if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
-			can_low_power = 0;
-		if (can_low_power) {
-			/* Enable automatic low-power */
-			phy_write(phy, 0x1c, 0x9002);
-			phy_write(phy, 0x1c, 0xa821);
-			phy_write(phy, 0x1c, 0x941d);
-		}
-	}
-#endif /* CONFIG_PPC_PMAC */
-
-	return 0;
-}
-
-static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
-	u16 ctl, adv;
-
-	phy->autoneg = 1;
-	phy->speed = SPEED_10;
-	phy->duplex = DUPLEX_HALF;
-	phy->pause = 0;
-	phy->advertising = advertise;
-
-	/* Setup standard advertise */
-	adv = phy_read(phy, MII_ADVERTISE);
-	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	if (advertise & ADVERTISED_10baseT_Half)
-		adv |= ADVERTISE_10HALF;
-	if (advertise & ADVERTISED_10baseT_Full)
-		adv |= ADVERTISE_10FULL;
-	if (advertise & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	if (advertise & ADVERTISED_Pause)
-		adv |= ADVERTISE_PAUSE_CAP;
-	if (advertise & ADVERTISED_Asym_Pause)
-		adv |= ADVERTISE_PAUSE_ASYM;
-	phy_write(phy, MII_ADVERTISE, adv);
-
-	/* Setup 1000BT advertise */
-	adv = phy_read(phy, MII_1000BASETCONTROL);
-	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
-	if (advertise & SUPPORTED_1000baseT_Half)
-		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
-	if (advertise & SUPPORTED_1000baseT_Full)
-		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
-	phy_write(phy, MII_1000BASETCONTROL, adv);
-
-	/* Start/Restart aneg */
-	ctl = phy_read(phy, MII_BMCR);
-	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
-	u16 ctl;
-
-	phy->autoneg = 0;
-	phy->speed = speed;
-	phy->duplex = fd;
-	phy->pause = 0;
-
-	ctl = phy_read(phy, MII_BMCR);
-	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
-
-	/* First reset the PHY */
-	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
-
-	/* Select speed & duplex */
-	switch(speed) {
-	case SPEED_10:
-		break;
-	case SPEED_100:
-		ctl |= BMCR_SPEED100;
-		break;
-	case SPEED_1000:
-		ctl |= BMCR_SPD2;
-	}
-	if (fd == DUPLEX_FULL)
-		ctl |= BMCR_FULLDPLX;
-
-	// XXX Should we set the sungem to GII now on 1000BT ?
-
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int bcm54xx_read_link(struct mii_phy *phy)
-{
-	int link_mode;
-	u16 val;
-
-	if (phy->autoneg) {
-	    	val = phy_read(phy, MII_BCM5400_AUXSTATUS);
-		link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
-			     MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
-		phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
-			DUPLEX_FULL : DUPLEX_HALF;
-		phy->speed = phy_BCM5400_link_table[link_mode][2] ?
-				SPEED_1000 :
-				(phy_BCM5400_link_table[link_mode][1] ?
-				 SPEED_100 : SPEED_10);
-		val = phy_read(phy, MII_LPA);
-		phy->pause = (phy->duplex == DUPLEX_FULL) &&
-			((val & LPA_PAUSE) != 0);
-	}
-	/* On non-aneg, we assume what we put in BMCR is the speed,
-	 * though magic-aneg shouldn't prevent this case from occurring
-	 */
-
-	return 0;
-}
-
-static int marvell88e1111_init(struct mii_phy* phy)
-{
-	u16 rev;
-
-	/* magic init sequence for rev 0 */
-	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
-	if (rev == 0) {
-		phy_write(phy, 0x1d, 0x000a);
-		phy_write(phy, 0x1e, 0x0821);
-
-		phy_write(phy, 0x1d, 0x0006);
-		phy_write(phy, 0x1e, 0x8600);
-
-		phy_write(phy, 0x1d, 0x000b);
-		phy_write(phy, 0x1e, 0x0100);
-
-		phy_write(phy, 0x1d, 0x0004);
-		phy_write(phy, 0x1e, 0x4850);
-	}
-	return 0;
-}
-
-#define BCM5421_MODE_MASK	(1 << 5)
-
-static int bcm5421_poll_link(struct mii_phy* phy)
-{
-	u32 phy_reg;
-	int mode;
-
-	/* find out in what mode we are */
-	phy_write(phy, MII_NCONFIG, 0x1000);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	mode = (phy_reg & BCM5421_MODE_MASK) >> 5;
-
-	if ( mode == BCM54XX_COPPER)
-		return genmii_poll_link(phy);
-
-	/* try to find out wether we have a link */
-	phy_write(phy, MII_NCONFIG, 0x2000);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	if (phy_reg & 0x0020)
-		return 0;
-	else
-		return 1;
-}
-
-static int bcm5421_read_link(struct mii_phy* phy)
-{
-	u32 phy_reg;
-	int mode;
-
-	/* find out in what mode we are */
-	phy_write(phy, MII_NCONFIG, 0x1000);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	mode = (phy_reg & BCM5421_MODE_MASK ) >> 5;
-
-	if ( mode == BCM54XX_COPPER)
-		return bcm54xx_read_link(phy);
-
-	phy->speed = SPEED_1000;
-
-	/* find out wether we are running half- or full duplex */
-	phy_write(phy, MII_NCONFIG, 0x2000);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	if ( (phy_reg & 0x0080) >> 7)
-		phy->duplex |=  DUPLEX_HALF;
-	else
-		phy->duplex |=  DUPLEX_FULL;
-
-	return 0;
-}
-
-static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
-{
-	/* enable fiber mode */
-	phy_write(phy, MII_NCONFIG, 0x9020);
-	/* LEDs active in both modes, autosense prio = fiber */
-	phy_write(phy, MII_NCONFIG, 0x945f);
-
-	if (!autoneg) {
-		/* switch off fibre autoneg */
-		phy_write(phy, MII_NCONFIG, 0xfc01);
-		phy_write(phy, 0x0b, 0x0004);
-	}
-
-	phy->autoneg = autoneg;
-
-	return 0;
-}
-
-#define BCM5461_FIBER_LINK	(1 << 2)
-#define BCM5461_MODE_MASK	(3 << 1)
-
-static int bcm5461_poll_link(struct mii_phy* phy)
-{
-	u32 phy_reg;
-	int mode;
-
-	/* find out in what mode we are */
-	phy_write(phy, MII_NCONFIG, 0x7c00);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
-
-	if ( mode == BCM54XX_COPPER)
-		return genmii_poll_link(phy);
-
-	/* find out wether we have a link */
-	phy_write(phy, MII_NCONFIG, 0x7000);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	if (phy_reg & BCM5461_FIBER_LINK)
-		return 1;
-	else
-		return 0;
-}
-
-#define BCM5461_FIBER_DUPLEX	(1 << 3)
-
-static int bcm5461_read_link(struct mii_phy* phy)
-{
-	u32 phy_reg;
-	int mode;
-
-	/* find out in what mode we are */
-	phy_write(phy, MII_NCONFIG, 0x7c00);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
-
-	if ( mode == BCM54XX_COPPER) {
-		return bcm54xx_read_link(phy);
-	}
-
-	phy->speed = SPEED_1000;
-
-	/* find out wether we are running half- or full duplex */
-	phy_write(phy, MII_NCONFIG, 0x7000);
-	phy_reg = phy_read(phy, MII_NCONFIG);
-
-	if (phy_reg & BCM5461_FIBER_DUPLEX)
-		phy->duplex |=  DUPLEX_FULL;
-	else
-		phy->duplex |=  DUPLEX_HALF;
-
-	return 0;
-}
-
-static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
-{
-	/* select fiber mode, enable 1000 base-X registers */
-	phy_write(phy, MII_NCONFIG, 0xfc0b);
-
-	if (autoneg) {
-		/* enable fiber with no autonegotiation */
-		phy_write(phy, MII_ADVERTISE, 0x01e0);
-		phy_write(phy, MII_BMCR, 0x1140);
-	} else {
-		/* enable fiber with autonegotiation */
-		phy_write(phy, MII_BMCR, 0x0140);
-	}
-
-	phy->autoneg = autoneg;
-
-	return 0;
-}
-
-static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
-	u16 ctl, adv;
-
-	phy->autoneg = 1;
-	phy->speed = SPEED_10;
-	phy->duplex = DUPLEX_HALF;
-	phy->pause = 0;
-	phy->advertising = advertise;
-
-	/* Setup standard advertise */
-	adv = phy_read(phy, MII_ADVERTISE);
-	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	if (advertise & ADVERTISED_10baseT_Half)
-		adv |= ADVERTISE_10HALF;
-	if (advertise & ADVERTISED_10baseT_Full)
-		adv |= ADVERTISE_10FULL;
-	if (advertise & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	if (advertise & ADVERTISED_Pause)
-		adv |= ADVERTISE_PAUSE_CAP;
-	if (advertise & ADVERTISED_Asym_Pause)
-		adv |= ADVERTISE_PAUSE_ASYM;
-	phy_write(phy, MII_ADVERTISE, adv);
-
-	/* Setup 1000BT advertise & enable crossover detect
-	 * XXX How do we advertise 1000BT ? Darwin source is
-	 * confusing here, they read from specific control and
-	 * write to control... Someone has specs for those
-	 * beasts ?
-	 */
-	adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
-	adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
-	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
-			MII_1000BASETCONTROL_HALFDUPLEXCAP);
-	if (advertise & SUPPORTED_1000baseT_Half)
-		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
-	if (advertise & SUPPORTED_1000baseT_Full)
-		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
-	phy_write(phy, MII_1000BASETCONTROL, adv);
-
-	/* Start/Restart aneg */
-	ctl = phy_read(phy, MII_BMCR);
-	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
-	u16 ctl, ctl2;
-
-	phy->autoneg = 0;
-	phy->speed = speed;
-	phy->duplex = fd;
-	phy->pause = 0;
-
-	ctl = phy_read(phy, MII_BMCR);
-	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
-	ctl |= BMCR_RESET;
-
-	/* Select speed & duplex */
-	switch(speed) {
-	case SPEED_10:
-		break;
-	case SPEED_100:
-		ctl |= BMCR_SPEED100;
-		break;
-	/* I'm not sure about the one below, again, Darwin source is
-	 * quite confusing and I lack chip specs
-	 */
-	case SPEED_1000:
-		ctl |= BMCR_SPD2;
-	}
-	if (fd == DUPLEX_FULL)
-		ctl |= BMCR_FULLDPLX;
-
-	/* Disable crossover. Again, the way Apple does it is strange,
-	 * though I don't assume they are wrong ;)
-	 */
-	ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
-	ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
-		MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
-		MII_1000BASETCONTROL_FULLDUPLEXCAP |
-		MII_1000BASETCONTROL_HALFDUPLEXCAP);
-	if (speed == SPEED_1000)
-		ctl2 |= (fd == DUPLEX_FULL) ?
-			MII_1000BASETCONTROL_FULLDUPLEXCAP :
-			MII_1000BASETCONTROL_HALFDUPLEXCAP;
-	phy_write(phy, MII_1000BASETCONTROL, ctl2);
-
-	// XXX Should we set the sungem to GII now on 1000BT ?
-
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int marvell_read_link(struct mii_phy *phy)
-{
-	u16 status, pmask;
-
-	if (phy->autoneg) {
-		status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
-		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
-			return -EAGAIN;
-		if (status & MII_M1011_PHY_SPEC_STATUS_1000)
-			phy->speed = SPEED_1000;
-		else if (status & MII_M1011_PHY_SPEC_STATUS_100)
-			phy->speed = SPEED_100;
-		else
-			phy->speed = SPEED_10;
-		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
-			phy->duplex = DUPLEX_FULL;
-		else
-			phy->duplex = DUPLEX_HALF;
-		pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE |
-			MII_M1011_PHY_SPEC_STATUS_RX_PAUSE;
-		phy->pause = (status & pmask) == pmask;
-	}
-	/* On non-aneg, we assume what we put in BMCR is the speed,
-	 * though magic-aneg shouldn't prevent this case from occurring
-	 */
-
-	return 0;
-}
-
-#define MII_BASIC_FEATURES \
-	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |	\
-	 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |	\
-	 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |	\
-	 SUPPORTED_Pause)
-
-/* On gigabit capable PHYs, we advertise Pause support but not asym pause
- * support for now as I'm not sure it's supported and Darwin doesn't do
- * it neither. --BenH.
- */
-#define MII_GBIT_FEATURES \
-	(MII_BASIC_FEATURES |	\
-	 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
-
-/* Broadcom BCM 5201 */
-static struct mii_phy_ops bcm5201_phy_ops = {
-	.init		= bcm5201_init,
-	.suspend	= bcm5201_suspend,
-	.setup_aneg	= genmii_setup_aneg,
-	.setup_forced	= genmii_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= genmii_read_link,
-};
-
-static struct mii_phy_def bcm5201_phy_def = {
-	.phy_id		= 0x00406210,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5201",
-	.features	= MII_BASIC_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5201_phy_ops
-};
-
-/* Broadcom BCM 5221 */
-static struct mii_phy_ops bcm5221_phy_ops = {
-	.suspend	= bcm5221_suspend,
-	.init		= bcm5221_init,
-	.setup_aneg	= genmii_setup_aneg,
-	.setup_forced	= genmii_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= genmii_read_link,
-};
-
-static struct mii_phy_def bcm5221_phy_def = {
-	.phy_id		= 0x004061e0,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5221",
-	.features	= MII_BASIC_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5221_phy_ops
-};
-
-/* Broadcom BCM 5241 */
-static struct mii_phy_ops bcm5241_phy_ops = {
-	.suspend	= bcm5241_suspend,
-	.init		= bcm5241_init,
-	.setup_aneg	= genmii_setup_aneg,
-	.setup_forced	= genmii_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= genmii_read_link,
-};
-static struct mii_phy_def bcm5241_phy_def = {
-	.phy_id		= 0x0143bc30,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5241",
-	.features	= MII_BASIC_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5241_phy_ops
-};
-
-/* Broadcom BCM 5400 */
-static struct mii_phy_ops bcm5400_phy_ops = {
-	.init		= bcm5400_init,
-	.suspend	= bcm5400_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5400_phy_def = {
-	.phy_id		= 0x00206040,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5400",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5400_phy_ops
-};
-
-/* Broadcom BCM 5401 */
-static struct mii_phy_ops bcm5401_phy_ops = {
-	.init		= bcm5401_init,
-	.suspend	= bcm5401_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5401_phy_def = {
-	.phy_id		= 0x00206050,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5401",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5401_phy_ops
-};
-
-/* Broadcom BCM 5411 */
-static struct mii_phy_ops bcm5411_phy_ops = {
-	.init		= bcm5411_init,
-	.suspend	= generic_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5411_phy_def = {
-	.phy_id		= 0x00206070,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5411",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5411_phy_ops
-};
-
-/* Broadcom BCM 5421 */
-static struct mii_phy_ops bcm5421_phy_ops = {
-	.init		= bcm5421_init,
-	.suspend	= generic_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= bcm5421_poll_link,
-	.read_link	= bcm5421_read_link,
-	.enable_fiber   = bcm5421_enable_fiber,
-};
-
-static struct mii_phy_def bcm5421_phy_def = {
-	.phy_id		= 0x002060e0,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5421",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5421_phy_ops
-};
-
-/* Broadcom BCM 5421 built-in K2 */
-static struct mii_phy_ops bcm5421k2_phy_ops = {
-	.init		= bcm5421_init,
-	.suspend	= generic_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5421k2_phy_def = {
-	.phy_id		= 0x002062e0,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5421-K2",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5421k2_phy_ops
-};
-
-static struct mii_phy_ops bcm5461_phy_ops = {
-	.init		= bcm5421_init,
-	.suspend	= generic_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= bcm5461_poll_link,
-	.read_link	= bcm5461_read_link,
-	.enable_fiber   = bcm5461_enable_fiber,
-};
-
-static struct mii_phy_def bcm5461_phy_def = {
-	.phy_id		= 0x002060c0,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5461",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5461_phy_ops
-};
-
-/* Broadcom BCM 5462 built-in Vesta */
-static struct mii_phy_ops bcm5462V_phy_ops = {
-	.init		= bcm5421_init,
-	.suspend	= generic_suspend,
-	.setup_aneg	= bcm54xx_setup_aneg,
-	.setup_forced	= bcm54xx_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= bcm54xx_read_link,
-};
-
-static struct mii_phy_def bcm5462V_phy_def = {
-	.phy_id		= 0x002060d0,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "BCM5462-Vesta",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &bcm5462V_phy_ops
-};
-
-/* Marvell 88E1101 amd 88E1111 */
-static struct mii_phy_ops marvell88e1101_phy_ops = {
-	.suspend	= generic_suspend,
-	.setup_aneg	= marvell_setup_aneg,
-	.setup_forced	= marvell_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= marvell_read_link
-};
-
-static struct mii_phy_ops marvell88e1111_phy_ops = {
-	.init		= marvell88e1111_init,
-	.suspend	= generic_suspend,
-	.setup_aneg	= marvell_setup_aneg,
-	.setup_forced	= marvell_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= marvell_read_link
-};
-
-/* two revs in darwin for the 88e1101 ... I could use a datasheet
- * to get the proper names...
- */
-static struct mii_phy_def marvell88e1101v1_phy_def = {
-	.phy_id		= 0x01410c20,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "Marvell 88E1101v1",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &marvell88e1101_phy_ops
-};
-static struct mii_phy_def marvell88e1101v2_phy_def = {
-	.phy_id		= 0x01410c60,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "Marvell 88E1101v2",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &marvell88e1101_phy_ops
-};
-static struct mii_phy_def marvell88e1111_phy_def = {
-	.phy_id		= 0x01410cc0,
-	.phy_id_mask	= 0xfffffff0,
-	.name		= "Marvell 88E1111",
-	.features	= MII_GBIT_FEATURES,
-	.magic_aneg	= 1,
-	.ops		= &marvell88e1111_phy_ops
-};
-
-/* Generic implementation for most 10/100 PHYs */
-static struct mii_phy_ops generic_phy_ops = {
-	.setup_aneg	= genmii_setup_aneg,
-	.setup_forced	= genmii_setup_forced,
-	.poll_link	= genmii_poll_link,
-	.read_link	= genmii_read_link
-};
-
-static struct mii_phy_def genmii_phy_def = {
-	.phy_id		= 0x00000000,
-	.phy_id_mask	= 0x00000000,
-	.name		= "Generic MII",
-	.features	= MII_BASIC_FEATURES,
-	.magic_aneg	= 0,
-	.ops		= &generic_phy_ops
-};
-
-static struct mii_phy_def* mii_phy_table[] = {
-	&bcm5201_phy_def,
-	&bcm5221_phy_def,
-	&bcm5241_phy_def,
-	&bcm5400_phy_def,
-	&bcm5401_phy_def,
-	&bcm5411_phy_def,
-	&bcm5421_phy_def,
-	&bcm5421k2_phy_def,
-	&bcm5461_phy_def,
-	&bcm5462V_phy_def,
-	&marvell88e1101v1_phy_def,
-	&marvell88e1101v2_phy_def,
-	&marvell88e1111_phy_def,
-	&genmii_phy_def,
-	NULL
-};
-
-int mii_phy_probe(struct mii_phy *phy, int mii_id)
-{
-	int rc;
-	u32 id;
-	struct mii_phy_def* def;
-	int i;
-
-	/* We do not reset the mii_phy structure as the driver
-	 * may re-probe the PHY regulary
-	 */
-	phy->mii_id = mii_id;
-
-	/* Take PHY out of isloate mode and reset it. */
-	rc = reset_one_mii_phy(phy, mii_id);
-	if (rc)
-		goto fail;
-
-	/* Read ID and find matching entry */
-	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
-	printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
-	       id, mii_id);
-	for (i=0; (def = mii_phy_table[i]) != NULL; i++)
-		if ((id & def->phy_id_mask) == def->phy_id)
-			break;
-	/* Should never be NULL (we have a generic entry), but... */
-	if (def == NULL)
-		goto fail;
-
-	phy->def = def;
-
-	return 0;
-fail:
-	phy->speed = 0;
-	phy->duplex = 0;
-	phy->pause = 0;
-	phy->advertising = 0;
-	return -ENODEV;
-}
-
-EXPORT_SYMBOL(mii_phy_probe);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/net/ethernet/toshiba/Makefile b/drivers/net/ethernet/toshiba/Makefile
index 71d861f..a506900 100644
--- a/drivers/net/ethernet/toshiba/Makefile
+++ b/drivers/net/ethernet/toshiba/Makefile
@@ -6,5 +6,5 @@ obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
 gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
 ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
 spidernet-y += spider_net.o spider_net_ethtool.o
-obj-$(CONFIG_SPIDER_NET) += spidernet.o ethernet/sun/sungem_phy.o
+obj-$(CONFIG_SPIDER_NET) += spidernet.o
 obj-$(CONFIG_TC35815) += tc35815.o
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 1ff3491c..af345db 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -196,7 +196,7 @@ spider_net_setup_aneg(struct spider_net_card *card)
 	if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
 		advertise |= SUPPORTED_1000baseT_Half;
 
-	mii_phy_probe(phy, phy->mii_id);
+	sungem_phy_probe(phy, phy->mii_id);
 	phy->def->ops->setup_aneg(phy, advertise);
 
 }
@@ -2120,7 +2120,7 @@ spider_net_setup_phy(struct spider_net_card *card)
 		unsigned short id;
 		id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
 		if (id != 0x0000 && id != 0xffff) {
-			if (!mii_phy_probe(phy, phy->mii_id)) {
+			if (!sungem_phy_probe(phy, phy->mii_id)) {
 				pr_info("Found %s.\n", phy->def->name);
 				break;
 			}
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
new file mode 100644
index 0000000..58f13ad
--- /dev/null
+++ b/drivers/net/sungem_phy.c
@@ -0,0 +1,1199 @@
+/*
+ * PHY drivers for the sungem ethernet driver.
+ *
+ * This file could be shared with other drivers.
+ *
+ * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ *
+ * TODO:
+ *  - Add support for PHYs that provide an IRQ line
+ *  - Eventually moved the entire polling state machine in
+ *    there (out of the eth driver), so that it can easily be
+ *    skipped on PHYs that implement it in hardware.
+ *  - On LXT971 & BCM5201, Apple uses some chip specific regs
+ *    to read the link status. Figure out why and if it makes
+ *    sense to do the same (magic aneg ?)
+ *  - Apple has some additional power management code for some
+ *    Broadcom PHYs that they "hide" from the OpenSource version
+ *    of darwin, still need to reverse engineer that
+ */
+
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/prom.h>
+#endif
+
+#include <linux/sungem_phy.h>
+
+/* Link modes of the BCM5400 PHY */
+static const int phy_BCM5400_link_table[8][3] = {
+	{ 0, 0, 0 },	/* No link */
+	{ 0, 0, 0 },	/* 10BT Half Duplex */
+	{ 1, 0, 0 },	/* 10BT Full Duplex */
+	{ 0, 1, 0 },	/* 100BT Half Duplex */
+	{ 0, 1, 0 },	/* 100BT Half Duplex */
+	{ 1, 1, 0 },	/* 100BT Full Duplex*/
+	{ 1, 0, 1 },	/* 1000BT */
+	{ 1, 0, 1 },	/* 1000BT */
+};
+
+static inline int __phy_read(struct mii_phy* phy, int id, int reg)
+{
+	return phy->mdio_read(phy->dev, id, reg);
+}
+
+static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
+{
+	phy->mdio_write(phy->dev, id, reg, val);
+}
+
+static inline int phy_read(struct mii_phy* phy, int reg)
+{
+	return phy->mdio_read(phy->dev, phy->mii_id, reg);
+}
+
+static inline void phy_write(struct mii_phy* phy, int reg, int val)
+{
+	phy->mdio_write(phy->dev, phy->mii_id, reg, val);
+}
+
+static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
+{
+	u16 val;
+	int limit = 10000;
+
+	val = __phy_read(phy, phy_id, MII_BMCR);
+	val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
+	val |= BMCR_RESET;
+	__phy_write(phy, phy_id, MII_BMCR, val);
+
+	udelay(100);
+
+	while (--limit) {
+		val = __phy_read(phy, phy_id, MII_BMCR);
+		if ((val & BMCR_RESET) == 0)
+			break;
+		udelay(10);
+	}
+	if ((val & BMCR_ISOLATE) && limit > 0)
+		__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
+
+	return limit <= 0;
+}
+
+static int bcm5201_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5201_MULTIPHY);
+	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
+	phy_write(phy, MII_BCM5201_MULTIPHY, data);
+
+	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+
+	return 0;
+}
+
+static int bcm5201_suspend(struct mii_phy* phy)
+{
+	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+	phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
+
+	return 0;
+}
+
+static int bcm5221_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
+		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+		data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	return 0;
+}
+
+static int bcm5221_suspend(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+		  data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
+
+	return 0;
+}
+
+static int bcm5241_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
+		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+		data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	return 0;
+}
+
+static int bcm5241_suspend(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+		  data | MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
+
+	return 0;
+}
+
+static int bcm5400_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	/* Configure for gigabit full duplex */
+	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
+	data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
+	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
+
+	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+	udelay(100);
+
+	/* Reset and configure cascaded 10/100 PHY */
+	(void)reset_one_mii_phy(phy, 0x1f);
+
+	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
+	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
+	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
+	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
+
+	return 0;
+}
+
+static int bcm5400_suspend(struct mii_phy* phy)
+{
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+	phy_write(phy, MII_BMCR, BMCR_PDOWN);
+#endif
+	return 0;
+}
+
+static int bcm5401_init(struct mii_phy* phy)
+{
+	u16 data;
+	int rev;
+
+	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+	if (rev == 0 || rev == 3) {
+		/* Some revisions of 5401 appear to need this
+		 * initialisation sequence to disable, according
+		 * to OF, "tap power management"
+		 *
+		 * WARNING ! OF and Darwin don't agree on the
+		 * register addresses. OF seem to interpret the
+		 * register numbers below as decimal
+		 *
+		 * Note: This should (and does) match tg3_init_5401phy_dsp
+		 *       in the tg3.c driver. -DaveM
+		 */
+		phy_write(phy, 0x18, 0x0c20);
+		phy_write(phy, 0x17, 0x0012);
+		phy_write(phy, 0x15, 0x1804);
+		phy_write(phy, 0x17, 0x0013);
+		phy_write(phy, 0x15, 0x1204);
+		phy_write(phy, 0x17, 0x8006);
+		phy_write(phy, 0x15, 0x0132);
+		phy_write(phy, 0x17, 0x8006);
+		phy_write(phy, 0x15, 0x0232);
+		phy_write(phy, 0x17, 0x201f);
+		phy_write(phy, 0x15, 0x0a20);
+	}
+
+	/* Configure for gigabit full duplex */
+	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+	udelay(10);
+
+	/* Reset and configure cascaded 10/100 PHY */
+	(void)reset_one_mii_phy(phy, 0x1f);
+
+	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
+	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+	return 0;
+}
+
+static int bcm5401_suspend(struct mii_phy* phy)
+{
+#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
+	phy_write(phy, MII_BMCR, BMCR_PDOWN);
+#endif
+	return 0;
+}
+
+static int bcm5411_init(struct mii_phy* phy)
+{
+	u16 data;
+
+	/* Here's some more Apple black magic to setup
+	 * some voltage stuffs.
+	 */
+	phy_write(phy, 0x1c, 0x8c23);
+	phy_write(phy, 0x1c, 0x8ca3);
+	phy_write(phy, 0x1c, 0x8c23);
+
+	/* Here, Apple seems to want to reset it, do
+	 * it as well
+	 */
+	phy_write(phy, MII_BMCR, BMCR_RESET);
+	phy_write(phy, MII_BMCR, 0x1340);
+
+	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
+
+	udelay(10);
+
+	/* Reset and configure cascaded 10/100 PHY */
+	(void)reset_one_mii_phy(phy, 0x1f);
+
+	return 0;
+}
+
+static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	u16 ctl, adv;
+
+	phy->autoneg = 1;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	u16 ctl;
+
+	phy->autoneg = 0;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
+
+	/* First reset the PHY */
+	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+	/* Select speed & duplex */
+	switch(speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	case SPEED_1000:
+	default:
+		return -EINVAL;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int genmii_poll_link(struct mii_phy *phy)
+{
+	u16 status;
+
+	(void)phy_read(phy, MII_BMSR);
+	status = phy_read(phy, MII_BMSR);
+	if ((status & BMSR_LSTATUS) == 0)
+		return 0;
+	if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
+		return 0;
+	return 1;
+}
+
+static int genmii_read_link(struct mii_phy *phy)
+{
+	u16 lpa;
+
+	if (phy->autoneg) {
+		lpa = phy_read(phy, MII_LPA);
+
+		if (lpa & (LPA_10FULL | LPA_100FULL))
+			phy->duplex = DUPLEX_FULL;
+		else
+			phy->duplex = DUPLEX_HALF;
+		if (lpa & (LPA_100FULL | LPA_100HALF))
+			phy->speed = SPEED_100;
+		else
+			phy->speed = SPEED_10;
+		phy->pause = 0;
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	 return 0;
+}
+
+static int generic_suspend(struct mii_phy* phy)
+{
+	phy_write(phy, MII_BMCR, BMCR_PDOWN);
+
+	return 0;
+}
+
+static int bcm5421_init(struct mii_phy* phy)
+{
+	u16 data;
+	unsigned int id;
+
+	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+
+	/* Revision 0 of 5421 needs some fixups */
+	if (id == 0x002060e0) {
+		/* This is borrowed from MacOS
+		 */
+		phy_write(phy, 0x18, 0x1007);
+		data = phy_read(phy, 0x18);
+		phy_write(phy, 0x18, data | 0x0400);
+		phy_write(phy, 0x18, 0x0007);
+		data = phy_read(phy, 0x18);
+		phy_write(phy, 0x18, data | 0x0800);
+		phy_write(phy, 0x17, 0x000a);
+		data = phy_read(phy, 0x15);
+		phy_write(phy, 0x15, data | 0x0200);
+	}
+
+	/* Pick up some init code from OF for K2 version */
+	if ((id & 0xfffffff0) == 0x002062e0) {
+		phy_write(phy, 4, 0x01e1);
+		phy_write(phy, 9, 0x0300);
+	}
+
+	/* Check if we can enable automatic low power */
+#ifdef CONFIG_PPC_PMAC
+	if (phy->platform_data) {
+		struct device_node *np = of_get_parent(phy->platform_data);
+		int can_low_power = 1;
+		if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
+			can_low_power = 0;
+		if (can_low_power) {
+			/* Enable automatic low-power */
+			phy_write(phy, 0x1c, 0x9002);
+			phy_write(phy, 0x1c, 0xa821);
+			phy_write(phy, 0x1c, 0x941d);
+		}
+	}
+#endif /* CONFIG_PPC_PMAC */
+
+	return 0;
+}
+
+static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	u16 ctl, adv;
+
+	phy->autoneg = 1;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	if (advertise & ADVERTISED_Pause)
+		adv |= ADVERTISE_PAUSE_CAP;
+	if (advertise & ADVERTISED_Asym_Pause)
+		adv |= ADVERTISE_PAUSE_ASYM;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	/* Setup 1000BT advertise */
+	adv = phy_read(phy, MII_1000BASETCONTROL);
+	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
+	if (advertise & SUPPORTED_1000baseT_Half)
+		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+	if (advertise & SUPPORTED_1000baseT_Full)
+		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_1000BASETCONTROL, adv);
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	u16 ctl;
+
+	phy->autoneg = 0;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
+
+	/* First reset the PHY */
+	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+	/* Select speed & duplex */
+	switch(speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	case SPEED_1000:
+		ctl |= BMCR_SPD2;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+
+	// XXX Should we set the sungem to GII now on 1000BT ?
+
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int bcm54xx_read_link(struct mii_phy *phy)
+{
+	int link_mode;
+	u16 val;
+
+	if (phy->autoneg) {
+	    	val = phy_read(phy, MII_BCM5400_AUXSTATUS);
+		link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
+			     MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
+		phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
+			DUPLEX_FULL : DUPLEX_HALF;
+		phy->speed = phy_BCM5400_link_table[link_mode][2] ?
+				SPEED_1000 :
+				(phy_BCM5400_link_table[link_mode][1] ?
+				 SPEED_100 : SPEED_10);
+		val = phy_read(phy, MII_LPA);
+		phy->pause = (phy->duplex == DUPLEX_FULL) &&
+			((val & LPA_PAUSE) != 0);
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	return 0;
+}
+
+static int marvell88e1111_init(struct mii_phy* phy)
+{
+	u16 rev;
+
+	/* magic init sequence for rev 0 */
+	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+	if (rev == 0) {
+		phy_write(phy, 0x1d, 0x000a);
+		phy_write(phy, 0x1e, 0x0821);
+
+		phy_write(phy, 0x1d, 0x0006);
+		phy_write(phy, 0x1e, 0x8600);
+
+		phy_write(phy, 0x1d, 0x000b);
+		phy_write(phy, 0x1e, 0x0100);
+
+		phy_write(phy, 0x1d, 0x0004);
+		phy_write(phy, 0x1e, 0x4850);
+	}
+	return 0;
+}
+
+#define BCM5421_MODE_MASK	(1 << 5)
+
+static int bcm5421_poll_link(struct mii_phy* phy)
+{
+	u32 phy_reg;
+	int mode;
+
+	/* find out in what mode we are */
+	phy_write(phy, MII_NCONFIG, 0x1000);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	mode = (phy_reg & BCM5421_MODE_MASK) >> 5;
+
+	if ( mode == BCM54XX_COPPER)
+		return genmii_poll_link(phy);
+
+	/* try to find out wether we have a link */
+	phy_write(phy, MII_NCONFIG, 0x2000);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	if (phy_reg & 0x0020)
+		return 0;
+	else
+		return 1;
+}
+
+static int bcm5421_read_link(struct mii_phy* phy)
+{
+	u32 phy_reg;
+	int mode;
+
+	/* find out in what mode we are */
+	phy_write(phy, MII_NCONFIG, 0x1000);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	mode = (phy_reg & BCM5421_MODE_MASK ) >> 5;
+
+	if ( mode == BCM54XX_COPPER)
+		return bcm54xx_read_link(phy);
+
+	phy->speed = SPEED_1000;
+
+	/* find out wether we are running half- or full duplex */
+	phy_write(phy, MII_NCONFIG, 0x2000);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	if ( (phy_reg & 0x0080) >> 7)
+		phy->duplex |=  DUPLEX_HALF;
+	else
+		phy->duplex |=  DUPLEX_FULL;
+
+	return 0;
+}
+
+static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
+{
+	/* enable fiber mode */
+	phy_write(phy, MII_NCONFIG, 0x9020);
+	/* LEDs active in both modes, autosense prio = fiber */
+	phy_write(phy, MII_NCONFIG, 0x945f);
+
+	if (!autoneg) {
+		/* switch off fibre autoneg */
+		phy_write(phy, MII_NCONFIG, 0xfc01);
+		phy_write(phy, 0x0b, 0x0004);
+	}
+
+	phy->autoneg = autoneg;
+
+	return 0;
+}
+
+#define BCM5461_FIBER_LINK	(1 << 2)
+#define BCM5461_MODE_MASK	(3 << 1)
+
+static int bcm5461_poll_link(struct mii_phy* phy)
+{
+	u32 phy_reg;
+	int mode;
+
+	/* find out in what mode we are */
+	phy_write(phy, MII_NCONFIG, 0x7c00);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
+
+	if ( mode == BCM54XX_COPPER)
+		return genmii_poll_link(phy);
+
+	/* find out wether we have a link */
+	phy_write(phy, MII_NCONFIG, 0x7000);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	if (phy_reg & BCM5461_FIBER_LINK)
+		return 1;
+	else
+		return 0;
+}
+
+#define BCM5461_FIBER_DUPLEX	(1 << 3)
+
+static int bcm5461_read_link(struct mii_phy* phy)
+{
+	u32 phy_reg;
+	int mode;
+
+	/* find out in what mode we are */
+	phy_write(phy, MII_NCONFIG, 0x7c00);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
+
+	if ( mode == BCM54XX_COPPER) {
+		return bcm54xx_read_link(phy);
+	}
+
+	phy->speed = SPEED_1000;
+
+	/* find out wether we are running half- or full duplex */
+	phy_write(phy, MII_NCONFIG, 0x7000);
+	phy_reg = phy_read(phy, MII_NCONFIG);
+
+	if (phy_reg & BCM5461_FIBER_DUPLEX)
+		phy->duplex |=  DUPLEX_FULL;
+	else
+		phy->duplex |=  DUPLEX_HALF;
+
+	return 0;
+}
+
+static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
+{
+	/* select fiber mode, enable 1000 base-X registers */
+	phy_write(phy, MII_NCONFIG, 0xfc0b);
+
+	if (autoneg) {
+		/* enable fiber with no autonegotiation */
+		phy_write(phy, MII_ADVERTISE, 0x01e0);
+		phy_write(phy, MII_BMCR, 0x1140);
+	} else {
+		/* enable fiber with autonegotiation */
+		phy_write(phy, MII_BMCR, 0x0140);
+	}
+
+	phy->autoneg = autoneg;
+
+	return 0;
+}
+
+static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	u16 ctl, adv;
+
+	phy->autoneg = 1;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	if (advertise & ADVERTISED_Pause)
+		adv |= ADVERTISE_PAUSE_CAP;
+	if (advertise & ADVERTISED_Asym_Pause)
+		adv |= ADVERTISE_PAUSE_ASYM;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	/* Setup 1000BT advertise & enable crossover detect
+	 * XXX How do we advertise 1000BT ? Darwin source is
+	 * confusing here, they read from specific control and
+	 * write to control... Someone has specs for those
+	 * beasts ?
+	 */
+	adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
+	adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
+	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+			MII_1000BASETCONTROL_HALFDUPLEXCAP);
+	if (advertise & SUPPORTED_1000baseT_Half)
+		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+	if (advertise & SUPPORTED_1000baseT_Full)
+		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+	phy_write(phy, MII_1000BASETCONTROL, adv);
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	u16 ctl, ctl2;
+
+	phy->autoneg = 0;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
+	ctl |= BMCR_RESET;
+
+	/* Select speed & duplex */
+	switch(speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	/* I'm not sure about the one below, again, Darwin source is
+	 * quite confusing and I lack chip specs
+	 */
+	case SPEED_1000:
+		ctl |= BMCR_SPD2;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+
+	/* Disable crossover. Again, the way Apple does it is strange,
+	 * though I don't assume they are wrong ;)
+	 */
+	ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
+	ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
+		MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
+		MII_1000BASETCONTROL_FULLDUPLEXCAP |
+		MII_1000BASETCONTROL_HALFDUPLEXCAP);
+	if (speed == SPEED_1000)
+		ctl2 |= (fd == DUPLEX_FULL) ?
+			MII_1000BASETCONTROL_FULLDUPLEXCAP :
+			MII_1000BASETCONTROL_HALFDUPLEXCAP;
+	phy_write(phy, MII_1000BASETCONTROL, ctl2);
+
+	// XXX Should we set the sungem to GII now on 1000BT ?
+
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int marvell_read_link(struct mii_phy *phy)
+{
+	u16 status, pmask;
+
+	if (phy->autoneg) {
+		status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
+		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
+			return -EAGAIN;
+		if (status & MII_M1011_PHY_SPEC_STATUS_1000)
+			phy->speed = SPEED_1000;
+		else if (status & MII_M1011_PHY_SPEC_STATUS_100)
+			phy->speed = SPEED_100;
+		else
+			phy->speed = SPEED_10;
+		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+			phy->duplex = DUPLEX_FULL;
+		else
+			phy->duplex = DUPLEX_HALF;
+		pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE |
+			MII_M1011_PHY_SPEC_STATUS_RX_PAUSE;
+		phy->pause = (status & pmask) == pmask;
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	return 0;
+}
+
+#define MII_BASIC_FEATURES \
+	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |	\
+	 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |	\
+	 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |	\
+	 SUPPORTED_Pause)
+
+/* On gigabit capable PHYs, we advertise Pause support but not asym pause
+ * support for now as I'm not sure it's supported and Darwin doesn't do
+ * it neither. --BenH.
+ */
+#define MII_GBIT_FEATURES \
+	(MII_BASIC_FEATURES |	\
+	 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
+
+/* Broadcom BCM 5201 */
+static struct mii_phy_ops bcm5201_phy_ops = {
+	.init		= bcm5201_init,
+	.suspend	= bcm5201_suspend,
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link,
+};
+
+static struct mii_phy_def bcm5201_phy_def = {
+	.phy_id		= 0x00406210,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5201",
+	.features	= MII_BASIC_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5201_phy_ops
+};
+
+/* Broadcom BCM 5221 */
+static struct mii_phy_ops bcm5221_phy_ops = {
+	.suspend	= bcm5221_suspend,
+	.init		= bcm5221_init,
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link,
+};
+
+static struct mii_phy_def bcm5221_phy_def = {
+	.phy_id		= 0x004061e0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5221",
+	.features	= MII_BASIC_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5221_phy_ops
+};
+
+/* Broadcom BCM 5241 */
+static struct mii_phy_ops bcm5241_phy_ops = {
+	.suspend	= bcm5241_suspend,
+	.init		= bcm5241_init,
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link,
+};
+static struct mii_phy_def bcm5241_phy_def = {
+	.phy_id		= 0x0143bc30,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5241",
+	.features	= MII_BASIC_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5241_phy_ops
+};
+
+/* Broadcom BCM 5400 */
+static struct mii_phy_ops bcm5400_phy_ops = {
+	.init		= bcm5400_init,
+	.suspend	= bcm5400_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5400_phy_def = {
+	.phy_id		= 0x00206040,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5400",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5400_phy_ops
+};
+
+/* Broadcom BCM 5401 */
+static struct mii_phy_ops bcm5401_phy_ops = {
+	.init		= bcm5401_init,
+	.suspend	= bcm5401_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5401_phy_def = {
+	.phy_id		= 0x00206050,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5401",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5401_phy_ops
+};
+
+/* Broadcom BCM 5411 */
+static struct mii_phy_ops bcm5411_phy_ops = {
+	.init		= bcm5411_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5411_phy_def = {
+	.phy_id		= 0x00206070,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5411",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5411_phy_ops
+};
+
+/* Broadcom BCM 5421 */
+static struct mii_phy_ops bcm5421_phy_ops = {
+	.init		= bcm5421_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= bcm5421_poll_link,
+	.read_link	= bcm5421_read_link,
+	.enable_fiber   = bcm5421_enable_fiber,
+};
+
+static struct mii_phy_def bcm5421_phy_def = {
+	.phy_id		= 0x002060e0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5421",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5421_phy_ops
+};
+
+/* Broadcom BCM 5421 built-in K2 */
+static struct mii_phy_ops bcm5421k2_phy_ops = {
+	.init		= bcm5421_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5421k2_phy_def = {
+	.phy_id		= 0x002062e0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5421-K2",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5421k2_phy_ops
+};
+
+static struct mii_phy_ops bcm5461_phy_ops = {
+	.init		= bcm5421_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= bcm5461_poll_link,
+	.read_link	= bcm5461_read_link,
+	.enable_fiber   = bcm5461_enable_fiber,
+};
+
+static struct mii_phy_def bcm5461_phy_def = {
+	.phy_id		= 0x002060c0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5461",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5461_phy_ops
+};
+
+/* Broadcom BCM 5462 built-in Vesta */
+static struct mii_phy_ops bcm5462V_phy_ops = {
+	.init		= bcm5421_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= bcm54xx_setup_aneg,
+	.setup_forced	= bcm54xx_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5462V_phy_def = {
+	.phy_id		= 0x002060d0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "BCM5462-Vesta",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &bcm5462V_phy_ops
+};
+
+/* Marvell 88E1101 amd 88E1111 */
+static struct mii_phy_ops marvell88e1101_phy_ops = {
+	.suspend	= generic_suspend,
+	.setup_aneg	= marvell_setup_aneg,
+	.setup_forced	= marvell_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= marvell_read_link
+};
+
+static struct mii_phy_ops marvell88e1111_phy_ops = {
+	.init		= marvell88e1111_init,
+	.suspend	= generic_suspend,
+	.setup_aneg	= marvell_setup_aneg,
+	.setup_forced	= marvell_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= marvell_read_link
+};
+
+/* two revs in darwin for the 88e1101 ... I could use a datasheet
+ * to get the proper names...
+ */
+static struct mii_phy_def marvell88e1101v1_phy_def = {
+	.phy_id		= 0x01410c20,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Marvell 88E1101v1",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &marvell88e1101_phy_ops
+};
+static struct mii_phy_def marvell88e1101v2_phy_def = {
+	.phy_id		= 0x01410c60,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Marvell 88E1101v2",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &marvell88e1101_phy_ops
+};
+static struct mii_phy_def marvell88e1111_phy_def = {
+	.phy_id		= 0x01410cc0,
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "Marvell 88E1111",
+	.features	= MII_GBIT_FEATURES,
+	.magic_aneg	= 1,
+	.ops		= &marvell88e1111_phy_ops
+};
+
+/* Generic implementation for most 10/100 PHYs */
+static struct mii_phy_ops generic_phy_ops = {
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link
+};
+
+static struct mii_phy_def genmii_phy_def = {
+	.phy_id		= 0x00000000,
+	.phy_id_mask	= 0x00000000,
+	.name		= "Generic MII",
+	.features	= MII_BASIC_FEATURES,
+	.magic_aneg	= 0,
+	.ops		= &generic_phy_ops
+};
+
+static struct mii_phy_def* mii_phy_table[] = {
+	&bcm5201_phy_def,
+	&bcm5221_phy_def,
+	&bcm5241_phy_def,
+	&bcm5400_phy_def,
+	&bcm5401_phy_def,
+	&bcm5411_phy_def,
+	&bcm5421_phy_def,
+	&bcm5421k2_phy_def,
+	&bcm5461_phy_def,
+	&bcm5462V_phy_def,
+	&marvell88e1101v1_phy_def,
+	&marvell88e1101v2_phy_def,
+	&marvell88e1111_phy_def,
+	&genmii_phy_def,
+	NULL
+};
+
+int sungem_phy_probe(struct mii_phy *phy, int mii_id)
+{
+	int rc;
+	u32 id;
+	struct mii_phy_def* def;
+	int i;
+
+	/* We do not reset the mii_phy structure as the driver
+	 * may re-probe the PHY regulary
+	 */
+	phy->mii_id = mii_id;
+
+	/* Take PHY out of isloate mode and reset it. */
+	rc = reset_one_mii_phy(phy, mii_id);
+	if (rc)
+		goto fail;
+
+	/* Read ID and find matching entry */
+	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+	printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
+	       id, mii_id);
+	for (i=0; (def = mii_phy_table[i]) != NULL; i++)
+		if ((id & def->phy_id_mask) == def->phy_id)
+			break;
+	/* Should never be NULL (we have a generic entry), but... */
+	if (def == NULL)
+		goto fail;
+
+	phy->def = def;
+
+	return 0;
+fail:
+	phy->speed = 0;
+	phy->duplex = 0;
+	phy->pause = 0;
+	phy->advertising = 0;
+	return -ENODEV;
+}
+
+EXPORT_SYMBOL(sungem_phy_probe);
+MODULE_LICENSE("GPL");
diff --git a/include/linux/sungem_phy.h b/include/linux/sungem_phy.h
index af02f94..bd9be9f 100644
--- a/include/linux/sungem_phy.h
+++ b/include/linux/sungem_phy.h
@@ -61,7 +61,7 @@ struct mii_phy
 /* Pass in a struct mii_phy with dev, mdio_read and mdio_write
  * filled, the remaining fields will be filled on return
  */
-extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
+extern int sungem_phy_probe(struct mii_phy *phy, int mii_id);
 
 
 /* MII definitions missing from mii.h */
-- 
1.7.6

^ permalink raw reply related

* Re: linux-next: build failure after merge of the final tree (net tree related)
From: Stephen Rothwell @ 2011-08-16  6:57 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110815.231116.1728582609642497613.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 428 bytes --]

Hi Dave,

On Mon, 15 Aug 2011 23:11:16 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>
> Please test this patch:
> 
> --------------------
> net: Fix sungem_phy sharing.

This fixes my allyesconfig build (and doesn't break any of the others :-)).

Tested-by: Stephen Rothwell <sfr@canb.auug.org.au>

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* Re: linux-next: build failure after merge of the final tree (net tree related)
From: David Miller @ 2011-08-16  7:17 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linux-next, linux-kernel, jeffrey.t.kirsher
In-Reply-To: <20110816165744.5c069b0c9f2e329e48ecd7d0@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 16 Aug 2011 16:57:44 +1000

> Hi Dave,
> 
> On Mon, 15 Aug 2011 23:11:16 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>>
>> Please test this patch:
>> 
>> --------------------
>> net: Fix sungem_phy sharing.
> 
> This fixes my allyesconfig build (and doesn't break any of the others :-)).
> 
> Tested-by: Stephen Rothwell <sfr@canb.auug.org.au>

Thanks a lot for testing.

^ permalink raw reply

* [patch net-2.6] via-velocity: remove non-tagged packet filtering
From: Jiri Pirko @ 2011-08-16  8:33 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger, romieu, stephan.baerwolf

It's undesired to filter untagged packets at any time. So simply remove this.

Reported-by: Stephan Bärwolf <stephan.baerwolf@tu-ilmenau.de>
Tested-by: Stephan Bärwolf <stephan.baerwolf@tu-ilmenau.de>
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 drivers/net/via-velocity.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index deb1eca..7c5336c 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -515,10 +515,6 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
 	mac_set_cam_mask(regs, vptr->mCAMmask);
 
 	/* Enable VCAMs */
-
-	if (test_bit(0, vptr->active_vlans))
-		WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
-
 	for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
 		mac_set_vlan_cam(regs, i, (u8 *) &vid);
 		vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
-- 
1.7.6


^ permalink raw reply related

* get_random_int() should use hash[1]
From: George Spelvin @ 2011-08-16  9:07 UTC (permalink / raw)
  To: davem; +Cc: linux, netdev

Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea

As long as you're using MD5, you should know that each round only
modifies one word of the state.  The order is [0], [3], [2], [1],
repeating 64 times.  Thus, on output, word [1] is the "most hashed"
word.  If you really wanted word [0], you could just skip the last
3 rounds.

It's not really critical, but as long as you're performing the
rounds, you might as well use them...

--- drivers/char/random.c.1	2011-08-16 05:02:09.000000000 -0400
+++ drivers/char/random.c.2	2011-08-16 05:02:43.000000000 -0400
@@ -1323,7 +1323,7 @@
 
 	hash[0] += current->pid + jiffies + get_cycles();
 	md5_transform(hash, random_int_secret);
-	ret = hash[0];
+	ret = hash[1];
 	put_cpu_var(get_random_int_hash);
 
 	return ret;

Me, I'd also put jiffies and get_cycles into different words
just on general principles, but that's up to you:

- 	hash[0] += current->pid + jiffies + get_cycles();
+ 	hash[1] += current->pid + jiffies;
+ 	hash[2] += get_cycles();

^ permalink raw reply

* Re: get_random_int() should use hash[1]
From: David Miller @ 2011-08-16  9:09 UTC (permalink / raw)
  To: linux; +Cc: netdev
In-Reply-To: <20110816090723.18492.qmail@science.horizon.com>

From: "George Spelvin" <linux@horizon.com>
Date: 16 Aug 2011 05:07:23 -0400

> Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea
> 
> As long as you're using MD5, you should know that each round only
> modifies one word of the state.  The order is [0], [3], [2], [1],
> repeating 64 times.  Thus, on output, word [1] is the "most hashed"
> word.  If you really wanted word [0], you could just skip the last
> 3 rounds.
> 
> It's not really critical, but as long as you're performing the
> rounds, you might as well use them...

Please provide a proper signoff with your change and properly
"-p1" base your patch.

Thanks.

^ permalink raw reply

* Re: get_random_int() should use hash[1]
From: David Miller @ 2011-08-16  9:10 UTC (permalink / raw)
  To: linux; +Cc: netdev
In-Reply-To: <20110816.020935.717525957035990843.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Tue, 16 Aug 2011 02:09:35 -0700 (PDT)

> From: "George Spelvin" <linux@horizon.com>
> Date: 16 Aug 2011 05:07:23 -0400
> 
>> Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea
>> 
>> As long as you're using MD5, you should know that each round only
>> modifies one word of the state.  The order is [0], [3], [2], [1],
>> repeating 64 times.  Thus, on output, word [1] is the "most hashed"
>> word.  If you really wanted word [0], you could just skip the last
>> 3 rounds.
>> 
>> It's not really critical, but as long as you're performing the
>> rounds, you might as well use them...
> 
> Please provide a proper signoff with your change and properly
> "-p1" base your patch.
> 
> Thanks.

Also this change is of interest to, and effects, folks outside of
networking.  So probably want to CC: linux-kernel when you respin
this.

^ permalink raw reply

* [patch net-next-2.6] bonding: use ndo_change_rx_flags callback
From: Jiri Pirko @ 2011-08-16  9:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, fubar, andy

Benefit from use of ndo_change_rx_flags in handling change of promisc
and allmulti. No need to store previous state locally.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 drivers/net/bonding/bond_main.c |   44 ++++++++++++--------------------------
 drivers/net/bonding/bonding.h   |    1 -
 2 files changed, 14 insertions(+), 31 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 854aa8d..731763a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3686,44 +3686,27 @@ static bool bond_addr_in_mc_list(unsigned char *addr,
 	return false;
 }
 
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_change_rx_flags(struct net_device *bond_dev, int change)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct netdev_hw_addr *ha;
-	bool found;
 
-	/*
-	 * Do promisc before checking multicast_mode
-	 */
-	if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
-		/*
-		 * FIXME: Need to handle the error when one of the multi-slaves
-		 * encounters error.
-		 */
-		bond_set_promiscuity(bond, 1);
-
-
-	if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
-		bond_set_promiscuity(bond, -1);
+	if (change & IFF_PROMISC)
+		bond_set_promiscuity(bond,
+				     bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
 
+	if (change & IFF_ALLMULTI)
+		bond_set_allmulti(bond,
+				  bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
 
-	/* set allmulti flag to slaves */
-	if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
-		/*
-		 * FIXME: Need to handle the error when one of the multi-slaves
-		 * encounters error.
-		 */
-		bond_set_allmulti(bond, 1);
-
-
-	if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
-		bond_set_allmulti(bond, -1);
-
+static void bond_set_multicast_list(struct net_device *bond_dev)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+	struct netdev_hw_addr *ha;
+	bool found;
 
 	read_lock(&bond->lock);
 
-	bond->flags = bond_dev->flags;
-
 	/* looking for addresses to add to slaves' mc list */
 	netdev_for_each_mc_addr(ha, bond_dev) {
 		found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
@@ -4282,6 +4265,7 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_select_queue	= bond_select_queue,
 	.ndo_get_stats64	= bond_get_stats,
 	.ndo_do_ioctl		= bond_do_ioctl,
+	.ndo_change_rx_flags	= bond_change_rx_flags,
 	.ndo_set_multicast_list	= bond_set_multicast_list,
 	.ndo_change_mtu		= bond_change_mtu,
 	.ndo_set_mac_address	= bond_set_mac_address,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 43526a2..e823366 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -234,7 +234,6 @@ struct bonding {
 	struct   netdev_hw_addr_list mc_list;
 	int      (*xmit_hash_policy)(struct sk_buff *, int);
 	__be32   master_ip;
-	u16      flags;
 	u16      rr_tx_counter;
 	struct   ad_bond_info ad_info;
 	struct   alb_bond_info alb_info;
-- 
1.7.6


^ permalink raw reply related

* Re: [patch net-next-2.6] bonding: use ndo_change_rx_flags callback
From: Michał Mirosław @ 2011-08-16 10:03 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, fubar, andy
In-Reply-To: <1313487050-4048-1-git-send-email-jpirko@redhat.com>

2011/8/16 Jiri Pirko <jpirko@redhat.com>:
> Benefit from use of ndo_change_rx_flags in handling change of promisc
> and allmulti. No need to store previous state locally.
[...]
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 854aa8d..731763a 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
[...]
> -static void bond_set_multicast_list(struct net_device *bond_dev)
> +static void bond_change_rx_flags(struct net_device *bond_dev, int change)
>  {
[...]
> +       if (change & IFF_PROMISC)
> +               bond_set_promiscuity(bond,
> +                                    bond_dev->flags & IFF_ALLMULTI ? 1 : -1);

Typo: flags & IFF_PROMISC ?

Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: get_random_int() should use hash[1]
From: George Spelvin @ 2011-08-16 10:30 UTC (permalink / raw)
  To: davem, linux, mpm; +Cc: linux-kernel, netdev
In-Reply-To: <20110816.021031.1778295949152117484.davem@davemloft.net>

>From davem@davemloft.net Tue Aug 16 09:10:35 2011
Date: Tue, 16 Aug 2011 02:10:31 -0700 (PDT)
To: linux@horizon.com
Cc: netdev@vger.kernel.org
Subject: Re: get_random_int() should use hash[1]
From: David Miller <davem@davemloft.net>
In-Reply-To: <20110816.020935.717525957035990843.davem@davemloft.net>
References: <20110816090723.18492.qmail@science.horizon.com>
	<20110816.020935.717525957035990843.davem@davemloft.net>
X-Mailer: Mew version 6.3 on Emacs 23.2 / Mule 6.0 (HANACHIRUSATO)
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (shards.monkeyblade.net [198.137.202.13]); Tue, 16 Aug 2011 02:10:33 -0700 (PDT)

From: David Miller <davem@davemloft.net>
Date: Tue, 16 Aug 2011 02:09:35 -0700 (PDT)

> From: "George Spelvin" <linux@horizon.com>
> Date: 16 Aug 2011 05:07:23 -0400
> 
>> Re: commit e997d47bff5a467262ef224b4cf8cbba2d3eceea
>> 
>> As long as you're using MD5, you should know that each round only
>> modifies one word of the state.  The order is [0], [3], [2], [1],
>> repeating 64 times.  Thus, on output, word [1] is the "most hashed"
>> word.  If you really wanted word [0], you could just skip the last
>> 3 rounds.
>> 
>> It's not really critical, but as long as you're performing the
>> rounds, you might as well use them...
> 
> Please provide a proper signoff with your change and properly
> "-p1" base your patch.

Not a problem.  This came up in the middle of a rebase operation so I
didn't have a tree immediately at hand to work with.

I'll also get the various uses in net/core/secure_seq.c.

One thing about that commit I'm becoming more concerneed by: I notice that
it eliminates the periodic reseeding of the secret.

While the reduction in the number of random bits was a tradeoff (and it
can be increased to 28 or so), it had two great advantages:
- The usefulness of an attack drops off sharply after 5 minutes (you
  can still attack connections established during the attack window,
  but then you have to guess how much data has been sent across them).
- An initial shortage of seed entropy does not become a persistent
  problem.  Note that late_initcall() is still before any device
  activity, much less entropy pool re-seeding from init scripts.

Put together, an attacker has the system uptime to try to guess
the low-entropy boot seed.  That's not clearly a security improvement.

What I *really* wonder is whether such a change is really -stable
material.  Cc: to Matt Mackall for comment.

It seems at least worth figuring out a way to defer seeding until
after /dev/random reseeding.  (E.g. until first non-loopback
connection is made.)

(There are also both better and faster algorithms than MD5 for
the job, but that's a separate issue.)


Just for example, as long as you're actually willing to spend more CPU
time, you could do *both*.  Compute both a fixed-secret 32-bit value and a
changing-secret 24-bit value and add them together.  Best of both worlds.

^ permalink raw reply

* Re: [Bug 41212] New: [regression] [3.1-git] ipoib causes kernel panic (NULL pointer dereference)
From: Bernd Schubert @ 2011-08-16 10:34 UTC (permalink / raw)
  To: Erez Shitrit
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAAk-MO8EToGY4OhmX1xPN01iAXR9WSsJXWxHG9EVyrSGYP3h5w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hello Erez,

are you sure? Commit 69cce1d1404968f78b177a0314f5822d5afdbbfb is not in 
3.0 yet and I also don't see how 3.0 should fail there, as it tests 
immediately for "if (likely(skb_dst(skb)"


Thanks,
Bernd

On 08/16/2011 10:06 AM, Erez Shitrit wrote:
> Hi,
> it happened in 3.0 also, if you take the git tag v3.0-rc7 and below it
> will work.
>
> Thanks, Erez
>
> On Mon, Aug 15, 2011 at 6:40 PM, <bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r@public.gmane.org
> <mailto:bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r@public.gmane.org>> wrote:
>
>     https://bugzilla.kernel.org/show_bug.cgi?id=41212
>
>                Summary: [regression] [3.1-git] ipoib causes kernel panic
>     (NULL
>                         pointer dereference)
>                Product: Networking
>                Version: 2.5
>         Kernel Version: 3.1-git
>               Platform: All
>             OS/Version: Linux
>                   Tree: Mainline
>                 Status: NEW
>               Severity: normal
>               Priority: P1
>              Component: Other
>             AssignedTo: acme-f8uhVLnGfZaxAyOMLChx1axOck334EZe@public.gmane.org
>     <mailto:acme-f8uhVLnGfZaxAyOMLChx1axOck334EZe@public.gmane.org>
>             ReportedBy: bernd.schubert-97jfqw80gc6171pxa8y+qA@public.gmane.org
>     <mailto:bernd.schubert-97jfqw80gc6171pxa8y+qA@public.gmane.org>
>                     CC: linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>     <mailto:linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
>             Regression: Yes
>
>
>     Each time when I start IPoIB with any 3.1-rcX git version I tested
>     so far I get
>     a kernel panic. This didn't happen in 3.0 yet.
>
>
>     fslab2 login: [  114.392408] EXT4-fs (sdc): barriers disabled
>     [  114.449737] EXT4-fs (sdc): mounted filesystem with writeback data
>     mode.
>     Opts: journal_async_commit,barrier=0,data=writeback
>     [  240.944030] BUG: unable to handle kernel NULL pointer dereference at
>     0000000000000040
>     [  240.948007] IP: [<ffffffffa0366ce9>] ipoib_start_xmit+0x39/0x280
>     [ib_ipoib]
>     [  240.948007] PGD 1f964f067 PUD 1f9bf2067 PMD 0
>     [  240.948007] Oops: 0000 [#1] SMP
>     [  240.948007] CPU 1
>     [  240.948007] Modules linked in: ext4 mbcache jbd2 crc16 nfsd
>     ib_umad rdma_ucm
>     rdma_cm iw_cm ib_addr ib_uverbs ib_ipoib sg ib_cm ib_sa ipv6 sd_mod
>     crc_t10dif
>     loop arcmsr md_mod pcspkr ib_mthca ib_mad ib_core 8250_pnp fuse
>     af_packet nfs
>     lockd fscache auth_rpcgss nfs_acl sunrpc btrfs lzo_decompress
>     lzo_compress
>     zlib_deflate crc32c libcrc32c crypto_hash crypto_algapi ata_generic
>     pata_acpi
>     e1000 pata_amd sata_nv libata scsi_mod unix [last unloaded:
>     scsi_wait_scan]
>     [  240.948007]
>     [  240.948007] Pid: 0, comm: kworker/0:0 Not tainted 3.1.0-rc2+ #29
>     Supermicro
>     H8DCE/H8DCE
>     [  240.948007] RIP: 0010:[<ffffffffa0366ce9>]  [<ffffffffa0366ce9>]
>     ipoib_start_xmit+0x39/0x280 [ib_ipoib]
>     [  240.948007] RSP: 0018:ffff8801ffc03c10  EFLAGS: 00010246
>     [  240.948007] RAX: 0000000000000000 RBX: ffff8801f99ea000 RCX:
>     0000000000004420
>     [  240.948007] RDX: 0000000000000000 RSI: ffff8801f99ea000 RDI:
>     ffff8801f9afd500
>     [  240.948007] RBP: ffff8801ffc03c40 R08: ffff8801f940d49c R09:
>     ffff8801f9852240
>     [  240.948007] R10: 0000000000000000 R11: 0000000000000020 R12:
>     ffff8801f9afd500
>     [  240.948007] R13: 0000000000000050 R14: ffff8801f99ea600 R15:
>     ffff8801f9852280
>     [  240.948007] FS:  00007f0b66016700(0000) GS:ffff8801ffc00000(0000)
>     knlGS:0000000000000000
>     [  240.948007] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
>     [  240.948007] CR2: 0000000000000040 CR3: 00000001f9a65000 CR4:
>     00000000000006e0
>     [  240.948007] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>     0000000000000000
>     [  240.948007] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
>     0000000000000400
>     [  240.948007] Process kworker/0:0 (pid: 0, threadinfo
>     ffff8800bfe82000, task
>     ffff8800bfe6f1a0)
>     [  240.948007] Stack:
>     [  240.948007]  0000000000000010 ffff8801f9afd500 0000000000004420
>     0000000000000050
>     [  240.948007]  ffff8801f99ea000 ffff8801f9852280 ffff8801ffc03ca0
>     ffffffff812cd5e0
>     [  240.948007]  0000000000000001 ffffffffa03721a0 ffffffff8131f680
>     ffff8801fa110540
>     [  240.948007] Call Trace:
>     [  240.948007] <IRQ>
>     [  240.948007]  [<ffffffff812cd5e0>] dev_hard_start_xmit+0x2a0/0x590
>     [  240.948007]  [<ffffffff8131f680>] ? arp_create+0x70/0x200
>     [  240.948007]  [<ffffffff812e8e1f>] sch_direct_xmit+0xef/0x1c0
>     [  240.948007]  [<ffffffff812cd9f9>] dev_queue_xmit+0x129/0x3b0
>     [  240.948007]  [<ffffffff8131f853>] arp_send+0x43/0x50
>     [  240.948007]  [<ffffffff8131f96b>] arp_solicit+0x10b/0x240
>
>     --
>     Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
>     ------- You are receiving this mail because: -------
>     You are on the CC list for the bug.
>     --
>     To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
>     the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>     <mailto:majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
>     More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 0/2] 3.1-git ipoib: fix NULL pointer dereference
From: Bernd Schubert @ 2011-08-16 10:56 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA

The following series  
- fixes a NULL pointer dereferences in ipoib_start_xmit()
- renames variable 'n' to 'dst_neigh' to make the code better readable

Question: I am unsure about the usage of likely() here, as I run into the else branch,
maybe it is not that unlikely and likely() should be removed?

---

Bernd Schubert (2):
      Fix possible Null pointer dereference in ipoib_start_xmit()
      Rename 'n' into a longer variable name.


 drivers/infiniband/ulp/ipoib/ipoib_main.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)

--
Bernd Schubert
Fraunhofer ITWM / FhGFS

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/2] Fix possible Null pointer dereference in ipoib_start_xmit()
From: Bernd Schubert @ 2011-08-16 10:56 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20110816105648.1805137.35191.stgit@fsdevel3>

This will fix https://bugzilla.kernel.org/show_bug.cgi?id=41212

fslab2 login: [  114.392408] EXT4-fs (sdc): barriers disabled
[  114.449737] EXT4-fs (sdc): mounted filesystem with writeback data mode.
Opts: journal_async_commit,barrier=0,data=writeback
[  240.944030] BUG: unable to handle kernel NULL pointer dereference at
0000000000000040
[  240.948007] IP: [<ffffffffa0366ce9>] ipoib_start_xmit+0x39/0x280 [ib_ipoib]
[...]
[  240.948007] Call Trace:
[  240.948007]  <IRQ>
[  240.948007]  [<ffffffff812cd5e0>] dev_hard_start_xmit+0x2a0/0x590
[  240.948007]  [<ffffffff8131f680>] ? arp_create+0x70/0x200
[  240.948007]  [<ffffffff812e8e1f>] sch_direct_xmit+0xef/0x1c0

Signed-off-by: Bernd Schubert <bernd.schubert-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 43f89ba..fe89c46 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -717,11 +717,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh;
-	struct neighbour *n;
+	struct neighbour *n = NULL;
 	unsigned long flags;
 
-	n = dst_get_neighbour(skb_dst(skb));
-	if (likely(skb_dst(skb) && n)) {
+	if (likely(skb_dst(skb)))
+		n = dst_get_neighbour(skb_dst(skb));
+
+	if (likely(n)) {
 		if (unlikely(!*to_ipoib_neigh(n))) {
 			ipoib_path_lookup(skb, dev);
 			return NETDEV_TX_OK;

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 2/2] Rename 'n' into a longer variable name.
From: Bernd Schubert @ 2011-08-16 10:56 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20110816105648.1805137.35191.stgit@fsdevel3>

When it comes to me variable names consisting of a single letter
should be forbidden by coding style guide lines, as it is rather
difficult to search for single letter, such as 'n'.

Rename struct neighbour *n to dst_neigh


Signed-off-by: Bernd Schubert <bernd.schubert-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fe89c46..189d4cb 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -717,22 +717,22 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh;
-	struct neighbour *n = NULL;
+	struct neighbour *dst_neigh = NULL;
 	unsigned long flags;
 
 	if (likely(skb_dst(skb)))
-		n = dst_get_neighbour(skb_dst(skb));
+		dst_neigh = dst_get_neighbour(skb_dst(skb));
 
-	if (likely(n)) {
-		if (unlikely(!*to_ipoib_neigh(n))) {
+	if (likely(dst_neigh)) {
+		if (unlikely(!*to_ipoib_neigh(dst_neigh))) {
 			ipoib_path_lookup(skb, dev);
 			return NETDEV_TX_OK;
 		}
 
-		neigh = *to_ipoib_neigh(n);
+		neigh = *to_ipoib_neigh(dst_neigh);
 
 		if (unlikely((memcmp(&neigh->dgid.raw,
-				     n->ha + 4,
+				     dst_neigh->ha + 4,
 				     sizeof(union ib_gid))) ||
 			     (neigh->dev != dev))) {
 			spin_lock_irqsave(&priv->lock, flags);
@@ -758,7 +758,8 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 				return NETDEV_TX_OK;
 			}
 		} else if (neigh->ah) {
-			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
+			ipoib_send(dev, skb, neigh->ah,
+				   IPOIB_QPN(dst_neigh->ha));
 			return NETDEV_TX_OK;
 		}
 

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH] bnx2x: suppress repeated error messages about Max BW
From: Michal Schmidt @ 2011-08-16 11:38 UTC (permalink / raw)
  To: eilong; +Cc: netdev@vger.kernel.org, Dmitry Kravkov, Vladislav Zolotarov
In-Reply-To: <1313434042.30399.0.camel@lb-tlvb-eilong.il.broadcom.com>

On 08/15/2011 08:47 PM, Eilon Greenstein wrote:
> On Mon, 2011-08-15 at 08:13 -0700, Michal Schmidt wrote:
>> A tester reported getting only these 4 messages with the patch applied:
>>
>> [bnx2x_extract_max_cfg:1074(eth4)]Illegal configuration detected for Max
>> BW on vn 2 - using 100 instead
>> [bnx2x_extract_max_cfg:1074(eth5)]Illegal configuration detected for Max
>> BW on vn 2 - using 100 instead
>> [bnx2x_extract_max_cfg:1074(eth6)]Illegal configuration detected for Max
>> BW on vn 3 - using 100 instead
>> [bnx2x_extract_max_cfg:1074(eth7)]Illegal configuration detected for Max
>> BW on vn 3 - using 100 instead
>>
>> This suggests that VNs 0 and 1 had non-zero Max BW configuration.
>
> Michal - this is a great point of data! It helped me finding a bug in
> that code - the code is not suitable for 4 port devices, it always
> assumes 4 VN per PCI function, while in 4 port devices there are only 2
> VN per PCI function. I assume that you are seeing this problem on a
> 57800 with 2x10G + 2x1G - and the 1G devices are in single function mode
> and therefore you are seeing this error message. I will send a patch to
> fix the problem on 4 port devices soon (after testing it for a while) -
> please confirm that you are seeing this issue on 2x10G+2x1G 57800
> device.

Eilon,
the tester is seeing this with BCM57711E. It's a HP-Blade bl460c-g6 with 
HP VirtualConnect. Quote from him:

   hp-agents reports 4 dual port nic's, Linux kernel reports 8 identical
   nic's but it's actual a blade with 2 LOM's (lan on motherboard) with
   each one port. Via VC we present max 4 FlexNic's per port, but for
   this server we present 2 FlexNic's per port.

   The fun with Linux is that it always sees all FlexNic's devices even
   if we configure 2 FlexNics via a VC profile on a port like on this
   server.

Michal

^ permalink raw reply

* Re: Linux ipsec and dynamic routing
From: Stephen Clark @ 2011-08-16 11:51 UTC (permalink / raw)
  To: hachi; +Cc: netdev
In-Reply-To: <2B8C0848-C5A1-4F19-AFDF-C7CB443789E0@kuiki.net>

On 08/14/2011 04:58 AM, hachi wrote:
> Hello heroes!
>
> I am after an eventual goal of dynamic routing (BGP) via the linux kernel using ipsec tunneling and no inner tunnel (gre or others). On the way to this goal I've done some light source diving of source and talked a little theory with others to hunt down as much as I could to get closer. I have a lot of questions here, so thanks for any answers or suggestions you may give.
>
> All of my testing is done using openswan, and debian stable (linux 2.6.32, iproute 20100519)
>
> * Are there any existing methods of implementing dynamic routed ipsec armored ip forwarding?
>
> I haven't been able to find anyone who has a working setup in this regard. My goal is very similar to the exposed routing setup of Amazon's VPC ipsec connections. I'm trying to implement one or both ends in linux successfully and haven't found any docs on the subject.
>
> * The ip xfrm policy selector syntax has a 'dev' argument that can be supplied. I was unable to figure out what the intention of this argument is via source, and I never found any docs or samples of its use. Can anyone enlighten me?
>
> * Are there any plans or generally accepted patches to expand the rules that may be used to select what frames are transformed?
>
> Currently the rules I can use are source address, destination address, and the mysterious 'dev' setting. I think the ultimate solution for me would be able to select frames for forwarding based on the gateway defined in the normal routing tables.
>
> * Do ip xfrm policy rules bypass normal routing policy?
>
> I'm relatively certain the answer to this is 'yes'. However I may not have the full story.
>
> I ran a simple test of two /24 exposed at either end of an ipsec tunnel. The left end is 10.24.2.0/24, the right is 10.24.3.0/24, and the transit is being done via 10.24.1.0/30. I configured this test using openswan and after setting up and checking to see if the boxes can pass frames I examined the policy list and the routing table.
>
> src 10.24.3.0/24 dst 10.24.2.0/24
> 	dir fwd priority 2344 ptype main
> 	tmpl src 10.24.1.2 dst 10.24.1.1
> 		proto esp reqid 16385 mode tunnel
>
> 10.24.1.0/30 dev eth1  proto kernel  scope link  src 10.24.1.1
> 10.24.2.0/24 dev eth0  proto kernel  scope link  src 10.24.2.2
> 172.16.3.0/24 dev eth0  proto kernel  scope link  src 172.16.3.16
> default via 172.16.3.1 dev eth0
>
> The opposite end is appropriately reversed, and there are two more policies for 'in' and 'out', but they are appropriately similar.
>
> What I notice is that despite not having a route for the exposed subnet on the other end of the tunnel linux happily forwards the frames and encodes them to the other end, and visa versa.
>
> I can watch the frames passing across eth1 and they are appropriately encrypted as specified, and if I turn the ipsec tunnel off on both sides the forwarding capability does indeed shut down. If I add routes for the opposing ends then the kernel starts forwarding frames as expected.
>
> * If I need to dive into this more to seek an implementation, does anyone know if the general theory should be the dynamic routing daemon in userspace should expand its code to update xfrm policies, or is the fact that xfrm policy is taking precedence over routing an oversight of the kernel code that should be fixed/updated/etc. ?
>
> * Is there any hope for policy routing table support to extend into this as well?
>
> I hope I'm reaching out to the proper group for this inquiry, please let me know if this was wrong :)
>
> --hachi--
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>    
Did you get any responses? I would certainly like to know the answers to 
some of the questions you posed.

-- 

"They that give up essential liberty to obtain temporary safety,
deserve neither liberty nor safety."  (Ben Franklin)

"The course of history shows that as a government grows, liberty
decreases."  (Thomas Jefferson)




^ permalink raw reply

* Re: [PATCH net-2.6 V2] bonding:reset backup and inactive flag of slave
From: WANG Cong @ 2011-08-16 12:30 UTC (permalink / raw)
  To: netdev
In-Reply-To: <8ed5a280dcc02566671810bcf7df83a05cb6a35d.1313459746.git.panweiping3@gmail.com>

On Tue, 16 Aug 2011 09:57:35 +0800, Weiping Pan wrote:

> Eduard Sinelnikov (eduard.sinelnikov@gmail.com) found that if we change
> bonding mode from active backup to round robin, some slaves are still
> keeping "backup", and won't transmit packets.
> 
> As Jay Vosburgh(fubar@us.ibm.com) pointed out that we can work around
> that by removing the bond_is_active_slave() check, because the "backup"
> flag is only meaningful for active backup mode.
> 
> But if we just simply ignore the bond_is_active_slave() check, the
> transmission will work fine, but we can't maintain the correct value of
> "backup" flag for each slaves, though it is meaningless for other mode
> than active backup.
> 
> I'd like to reset "backup" and "inactive" flag in bond_open, thus we can
> keep the correct value of them.
> 
> As for bond_is_active_slave(), I'd like to prepare another patch to
> handle it.
> 
> V2:
> Use C style comment.
> Move read_lock(&bond->curr_slave_lock). Replace restore with reset, for
> active backup mode, it means "restore", but for other modes, it means
> "reset".
> 
> Signed-off-by: Weiping Pan <panweiping3@gmail.com>

Reviewed-by: WANG Cong <xiyou.wangcong@gmail.com>

Thanks.


^ permalink raw reply

* Re: Transfer Offer
From: Song Li @ 2011-08-17  3:32 UTC (permalink / raw)
  To: Recipients

l am a Staff of Hang Seng Bank HongKong, I do not know if we can work
together in transferring $19,500,000.USD from my bank to you account.
Finally if you are interested I shall provide you with more details.
Email: songli1@w.cn

^ permalink raw reply

* Re: [PATCH] bnx2x: suppress repeated error messages about Max BW
From: Eilon Greenstein @ 2011-08-16 12:45 UTC (permalink / raw)
  To: Michal Schmidt
  Cc: netdev@vger.kernel.org, Dmitry Kravkov, Vladislav Zolotarov
In-Reply-To: <4E4A56C0.4030009@redhat.com>

On Tue, 2011-08-16 at 04:38 -0700, Michal Schmidt wrote:
> On 08/15/2011 08:47 PM, Eilon Greenstein wrote:
> > On Mon, 2011-08-15 at 08:13 -0700, Michal Schmidt wrote:
> >> A tester reported getting only these 4 messages with the patch applied:
> >>
> >> [bnx2x_extract_max_cfg:1074(eth4)]Illegal configuration detected for Max
> >> BW on vn 2 - using 100 instead
> >> [bnx2x_extract_max_cfg:1074(eth5)]Illegal configuration detected for Max
> >> BW on vn 2 - using 100 instead
> >> [bnx2x_extract_max_cfg:1074(eth6)]Illegal configuration detected for Max
> >> BW on vn 3 - using 100 instead
> >> [bnx2x_extract_max_cfg:1074(eth7)]Illegal configuration detected for Max
> >> BW on vn 3 - using 100 instead
> >>
> >> This suggests that VNs 0 and 1 had non-zero Max BW configuration.
> >
> > Michal - this is a great point of data! It helped me finding a bug in
> > that code - the code is not suitable for 4 port devices, it always
> > assumes 4 VN per PCI function, while in 4 port devices there are only 2
> > VN per PCI function. I assume that you are seeing this problem on a
> > 57800 with 2x10G + 2x1G - and the 1G devices are in single function mode
> > and therefore you are seeing this error message. I will send a patch to
> > fix the problem on 4 port devices soon (after testing it for a while) -
> > please confirm that you are seeing this issue on 2x10G+2x1G 57800
> > device.
> 
> Eilon,
> the tester is seeing this with BCM57711E. It's a HP-Blade bl460c-g6 with 
> HP VirtualConnect. Quote from him:
> 
>    hp-agents reports 4 dual port nic's, Linux kernel reports 8 identical
>    nic's but it's actual a blade with 2 LOM's (lan on motherboard) with
>    each one port. Via VC we present max 4 FlexNic's per port, but for
>    this server we present 2 FlexNic's per port.
> 
>    The fun with Linux is that it always sees all FlexNic's devices even
>    if we configure 2 FlexNics via a VC profile on a port like on this
>    server.
> 
> Michal

I see. This seems to be a valid VC configuration and therefore the
message should be reduced to debug level all together. At least we
resolved a 4 port configuration problem...

Eilon





^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox