Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] ipv6: RTAX_FEATURE_ALLFRAG causes inefficient TCP segment sizing
From: Tore Anderson @ 2012-04-26 10:32 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Maciej Żenczykowski, David Miller, netdev, Tom Herbert
In-Reply-To: <1335350667.3274.53.camel@edumazet-glaptop>

* Eric Dumazet

> Yes, in fact we are going to keep the allfrag feature, and arm it if 
> we
> receive an mtu < 512.

One thing to think about if you go down this path is to keep track of 
the PMTU received in the ICMPv6 PTB. If you activate the allfrag feature 
on a destination because you received a PTB with PMTU=400, it's not 
useful to include the Fragmentation header in packets <400 bytes in 
size, for example.

With the current code, even tiny packets without any L4 payload (e.g. 
TCP SYN/ACK) will have the Fragmentation header added. That's not 
optimal, but necessary since the current code does not keep track of the 
actual PMTU if it is <1280 as far as I can tell (instead it discards the 
received PMTU value, clamps the effective PMTU to 1280, and enables 
allfrag).

Tore

^ permalink raw reply

* Re: [GIT PULL] net/at91: at91_ether fixes for 3.4-rc
From: Nicolas Ferre @ 2012-04-26 10:31 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-arm-kernel, linux-kernel, avictor.za, plagnioj
In-Reply-To: <20120426.061212.570213998793556907.davem@davemloft.net>

On 04/26/2012 12:12 PM, David Miller :
> From: Nicolas Ferre <nicolas.ferre@atmel.com>
> Date: Thu, 26 Apr 2012 12:07:41 +0200
> 
>> So, should I repost both of them as patch series?
> 
> Yes, with a leading "[PATCH 0/N] " posting as I asked.

Ok, done!

Thanks, bye,
-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH 1/2] AT91: Remove fixed mapping for AT91RM9200 ethernet
From: Nicolas Ferre @ 2012-04-26 10:30 UTC (permalink / raw)
  To: netdev, linux-arm-kernel, davem
  Cc: linux-kernel, avictor.za, plagnioj, Nicolas Ferre

From: Andrew Victor <avictor.za@gmail.com>

The AT91RM9200 Ethernet controller still has a fixed IO mapping.
So:
* Remove the fixed IO mapping and AT91_VA_BASE_EMAC definition.
* Pass the physical base-address via platform-resources to the driver.
* Convert at91_ether.c driver to perform an ioremap().
* Ethernet PHY detection needs to be performed during the driver
initialization process, it can no longer be done first.

Signed-off-by: Andrew Victor <linux@maxim.org.za>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 arch/arm/mach-at91/at91rm9200.c            |   10 -
 arch/arm/mach-at91/at91rm9200_devices.c    |    4 +-
 arch/arm/mach-at91/include/mach/hardware.h |    1 -
 drivers/net/ethernet/cadence/at91_ether.c  |  527 +++++++++++++++-------------
 drivers/net/ethernet/cadence/at91_ether.h  |    1 +
 5 files changed, 287 insertions(+), 256 deletions(-)

diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 364c193..8910679 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -26,15 +26,6 @@
 #include "clock.h"
 #include "sam9_smc.h"
 
-static struct map_desc at91rm9200_io_desc[] __initdata = {
-	{
-		.virtual	= AT91_VA_BASE_EMAC,
-		.pfn		= __phys_to_pfn(AT91RM9200_BASE_EMAC),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	},
-};
-
 /* --------------------------------------------------------------------
  *  Clocks
  * -------------------------------------------------------------------- */
@@ -315,7 +306,6 @@ static void __init at91rm9200_map_io(void)
 {
 	/* Map peripherals */
 	at91_init_sram(0, AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE);
-	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 }
 
 static void __init at91rm9200_ioremap_registers(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 05774e5..60c4728 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -140,8 +140,8 @@ static struct macb_platform_data eth_data;
 
 static struct resource eth_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_EMAC,
-		.end	= AT91_VA_BASE_EMAC + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_EMAC,
+		.end	= AT91RM9200_BASE_EMAC + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
index e9e29a6..01db372 100644
--- a/arch/arm/mach-at91/include/mach/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -94,7 +94,6 @@
  * Virtual to Physical Address mapping for IO devices.
  */
 #define AT91_VA_BASE_SYS	AT91_IO_P2V(AT91_BASE_SYS)
-#define AT91_VA_BASE_EMAC	AT91_IO_P2V(AT91RM9200_BASE_EMAC)
 
  /* Internal SRAM is mapped below the IO devices */
 #define AT91_SRAM_MAX		SZ_1M
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 9061170..62761e1 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -30,6 +30,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/gfp.h>
+#include <linux/phy.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -51,21 +52,17 @@
 /*
  * Read from a EMAC register.
  */
-static inline unsigned long at91_emac_read(unsigned int reg)
+static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
 {
-	void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
-	return __raw_readl(emac_base + reg);
+	return __raw_readl(lp->emac_base + reg);
 }
 
 /*
  * Write to a EMAC register.
  */
-static inline void at91_emac_write(unsigned int reg, unsigned long value)
+static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
 {
-	void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
-	__raw_writel(value, emac_base + reg);
+	__raw_writel(value, lp->emac_base + reg);
 }
 
 /* ........................... PHY INTERFACE ........................... */
@@ -75,32 +72,33 @@ static inline void at91_emac_write(unsigned int reg, unsigned long value)
  * When not called from an interrupt-handler, access to the PHY must be
  *  protected by a spinlock.
  */
-static void enable_mdi(void)
+static void enable_mdi(struct at91_private *lp)
 {
 	unsigned long ctl;
 
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);	/* enable management port */
+	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+	at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);	/* enable management port */
 }
 
 /*
  * Disable the MDIO bit in the MAC control register
  */
-static void disable_mdi(void)
+static void disable_mdi(struct at91_private *lp)
 {
 	unsigned long ctl;
 
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);	/* disable management port */
+	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+	at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);	/* disable management port */
 }
 
 /*
  * Wait until the PHY operation is complete.
  */
-static inline void at91_phy_wait(void) {
+static inline void at91_phy_wait(struct at91_private *lp)
+{
 	unsigned long timeout = jiffies + 2;
 
-	while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
+	while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
 		if (time_after(jiffies, timeout)) {
 			printk("at91_ether: MIO timeout\n");
 			break;
@@ -113,28 +111,28 @@ static inline void at91_phy_wait(void) {
  * Write value to the a PHY register
  * Note: MDI interface is assumed to already have been enabled.
  */
-static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value)
+static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
 {
-	at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
+	at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
 		| ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
 
 	/* Wait until IDLE bit in Network Status register is cleared */
-	at91_phy_wait();
+	at91_phy_wait(lp);
 }
 
 /*
  * Read value stored in a PHY register.
  * Note: MDI interface is assumed to already have been enabled.
  */
-static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value)
+static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
 {
-	at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
+	at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
 		| ((phy_addr & 0x1f) << 23) | (address << 18));
 
 	/* Wait until IDLE bit in Network Status register is cleared */
-	at91_phy_wait();
+	at91_phy_wait(lp);
 
-	*value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
+	*value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
 }
 
 /* ........................... PHY MANAGEMENT .......................... */
@@ -158,13 +156,13 @@ static void update_linkspeed(struct net_device *dev, int silent)
 	}
 
 	/* Link up, or auto-negotiation still in progress */
-	read_phy(lp->phy_address, MII_BMSR, &bmsr);
-	read_phy(lp->phy_address, MII_BMCR, &bmcr);
+	read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
+	read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
 	if (bmcr & BMCR_ANENABLE) {				/* AutoNegotiation is enabled */
 		if (!(bmsr & BMSR_ANEGCOMPLETE))
 			return;			/* Do nothing - another interrupt generated when negotiation complete */
 
-		read_phy(lp->phy_address, MII_LPA, &lpa);
+		read_phy(lp, lp->phy_address, MII_LPA, &lpa);
 		if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
 		else speed = SPEED_10;
 		if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
@@ -175,7 +173,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
 	}
 
 	/* Update the MAC */
-	mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
+	mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
 	if (speed == SPEED_100) {
 		if (duplex == DUPLEX_FULL)		/* 100 Full Duplex */
 			mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
@@ -186,7 +184,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
 			mac_cfg |= AT91_EMAC_FD;
 		else {}					/* 10 Half Duplex */
 	}
-	at91_emac_write(AT91_EMAC_CFG, mac_cfg);
+	at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
 
 	if (!silent)
 		printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
@@ -207,34 +205,34 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
 	 * level-triggering.  We therefore have to check if the PHY actually has
 	 * an IRQ pending.
 	 */
-	enable_mdi();
+	enable_mdi(lp);
 	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-		read_phy(lp->phy_address, MII_DSINTR_REG, &phy);	/* ack interrupt in Davicom PHY */
+		read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy);	/* ack interrupt in Davicom PHY */
 		if (!(phy & (1 << 0)))
 			goto done;
 	}
 	else if (lp->phy_type == MII_LXT971A_ID) {
-		read_phy(lp->phy_address, MII_ISINTS_REG, &phy);	/* ack interrupt in Intel PHY */
+		read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy);	/* ack interrupt in Intel PHY */
 		if (!(phy & (1 << 2)))
 			goto done;
 	}
 	else if (lp->phy_type == MII_BCM5221_ID) {
-		read_phy(lp->phy_address, MII_BCMINTR_REG, &phy);	/* ack interrupt in Broadcom PHY */
+		read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy);	/* ack interrupt in Broadcom PHY */
 		if (!(phy & (1 << 0)))
 			goto done;
 	}
 	else if (lp->phy_type == MII_KS8721_ID) {
-		read_phy(lp->phy_address, MII_TPISTATUS, &phy);		/* ack interrupt in Micrel PHY */
+		read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy);		/* ack interrupt in Micrel PHY */
 		if (!(phy & ((1 << 2) | 1)))
 			goto done;
 	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {			/* ack interrupt in Teridian PHY */
-		read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy);
+	else if (lp->phy_type == MII_T78Q21x3_ID) {					/* ack interrupt in Teridian PHY */
+		read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
 		if (!(phy & ((1 << 2) | 1)))
 			goto done;
 	}
 	else if (lp->phy_type == MII_DP83848_ID) {
-		read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy);	/* ack interrupt in DP83848 PHY */
+		read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy);	/* ack interrupt in DP83848 PHY */
 		if (!(phy & (1 << 7)))
 			goto done;
 	}
@@ -242,7 +240,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
 	update_linkspeed(dev, 0);
 
 done:
-	disable_mdi();
+	disable_mdi(lp);
 
 	return IRQ_HANDLED;
 }
@@ -273,41 +271,41 @@ static void enable_phyirq(struct net_device *dev)
 	}
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 
 	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {	/* for Davicom PHY */
-		read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
 		dsintr = dsintr & ~0xf00;		/* clear bits 8..11 */
-		write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_LXT971A_ID) {	/* for Intel PHY */
-		read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
 		dsintr = dsintr | 0xf2;			/* set bits 1, 4..7 */
-		write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_BCM5221_ID) {	/* for Broadcom PHY */
 		dsintr = (1 << 15) | ( 1 << 14);
-		write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_KS8721_ID) {	/* for Micrel PHY */
 		dsintr = (1 << 10) | ( 1 << 8);
-		write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
+		write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
 	}
 	else if (lp->phy_type == MII_T78Q21x3_ID) {	/* for Teridian PHY */
-		read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
 		dsintr = dsintr | 0x500;		/* set bits 8, 10 */
-		write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_DP83848_ID) {	/* National Semiconductor DP83848 PHY */
-		read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
 		dsintr = dsintr | 0x3c;			/* set bits 2..5 */
-		write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
-		read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
+		write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
+		read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
 		dsintr = dsintr | 0x3;			/* set bits 0,1 */
-		write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
 	}
 
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 }
 
@@ -326,43 +324,43 @@ static void disable_phyirq(struct net_device *dev)
 	}
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 
 	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {	/* for Davicom PHY */
-		read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
 		dsintr = dsintr | 0xf00;			/* set bits 8..11 */
-		write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_LXT971A_ID) {	/* for Intel PHY */
-		read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
 		dsintr = dsintr & ~0xf2;			/* clear bits 1, 4..7 */
-		write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_BCM5221_ID) {	/* for Broadcom PHY */
-		read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
 		dsintr = ~(1 << 14);
-		write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_KS8721_ID) {	/* for Micrel PHY */
-		read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
+		read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
 		dsintr = ~((1 << 10) | (1 << 8));
-		write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
+		write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
 	}
 	else if (lp->phy_type == MII_T78Q21x3_ID) {	/* for Teridian PHY */
-		read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
 		dsintr = dsintr & ~0x500;			/* clear bits 8, 10 */
-		write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
 	}
 	else if (lp->phy_type == MII_DP83848_ID) {	/* National Semiconductor DP83848 PHY */
-		read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
+		read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
 		dsintr = dsintr & ~0x3;				/* clear bits 0, 1 */
-		write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
-		read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
+		write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
+		read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
 		dsintr = dsintr & ~0x3c;			/* clear bits 2..5 */
-		write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
+		write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
 	}
 
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
 	irq_number = lp->board_data.phy_irq_pin;
@@ -379,17 +377,17 @@ static void reset_phy(struct net_device *dev)
 	unsigned int bmcr;
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 
 	/* Perform PHY reset */
-	write_phy(lp->phy_address, MII_BMCR, BMCR_RESET);
+	write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
 
 	/* Wait until PHY reset is complete */
 	do {
-		read_phy(lp->phy_address, MII_BMCR, &bmcr);
+		read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
 	} while (!(bmcr & BMCR_RESET));
 
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 }
 #endif
@@ -399,13 +397,37 @@ static void at91ether_check_link(unsigned long dev_id)
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct at91_private *lp = netdev_priv(dev);
 
-	enable_mdi();
+	enable_mdi(lp);
 	update_linkspeed(dev, 1);
-	disable_mdi();
+	disable_mdi(lp);
 
 	mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
 }
 
+/*
+ * Perform any PHY-specific initialization.
+ */
+static void __init initialize_phy(struct at91_private *lp)
+{
+	unsigned int val;
+
+	spin_lock_irq(&lp->lock);
+	enable_mdi(lp);
+
+	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
+		read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
+		if ((val & (1 << 10)) == 0)			/* DSCR bit 10 is 0 -- fiber mode */
+			lp->phy_media = PORT_FIBRE;
+	} else if (machine_is_csb337()) {
+		/* mix link activity status into LED2 link state */
+		write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
+	} else if (machine_is_ecbat91())
+		write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
+
+	disable_mdi(lp);
+	spin_unlock_irq(&lp->lock);
+}
+
 /* ......................... ADDRESS MANAGEMENT ........................ */
 
 /*
@@ -454,17 +476,19 @@ static short __init unpack_mac_address(struct net_device *dev, unsigned int hi,
  */
 static void __init get_mac_address(struct net_device *dev)
 {
+	struct at91_private *lp = netdev_priv(dev);
+
 	/* Check Specific-Address 1 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L)))
+	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
 		return;
 	/* Check Specific-Address 2 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L)))
+	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
 		return;
 	/* Check Specific-Address 3 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L)))
+	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
 		return;
 	/* Check Specific-Address 4 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L)))
+	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
 		return;
 
 	printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
@@ -475,11 +499,13 @@ static void __init get_mac_address(struct net_device *dev)
  */
 static void update_mac_address(struct net_device *dev)
 {
-	at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-	at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
+	struct at91_private *lp = netdev_priv(dev);
 
-	at91_emac_write(AT91_EMAC_SA2L, 0);
-	at91_emac_write(AT91_EMAC_SA2H, 0);
+	at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
+	at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
+
+	at91_emac_write(lp, AT91_EMAC_SA2L, 0);
+	at91_emac_write(lp, AT91_EMAC_SA2H, 0);
 }
 
 /*
@@ -559,6 +585,7 @@ static int hash_get_index(__u8 *addr)
  */
 static void at91ether_sethashtable(struct net_device *dev)
 {
+	struct at91_private *lp = netdev_priv(dev);
 	struct netdev_hw_addr *ha;
 	unsigned long mc_filter[2];
 	unsigned int bitnr;
@@ -570,8 +597,8 @@ static void at91ether_sethashtable(struct net_device *dev)
 		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
 	}
 
-	at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
-	at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
+	at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
+	at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
 }
 
 /*
@@ -579,9 +606,10 @@ static void at91ether_sethashtable(struct net_device *dev)
  */
 static void at91ether_set_multicast_list(struct net_device *dev)
 {
+	struct at91_private *lp = netdev_priv(dev);
 	unsigned long cfg;
 
-	cfg = at91_emac_read(AT91_EMAC_CFG);
+	cfg = at91_emac_read(lp, AT91_EMAC_CFG);
 
 	if (dev->flags & IFF_PROMISC)			/* Enable promiscuous mode */
 		cfg |= AT91_EMAC_CAF;
@@ -589,34 +617,37 @@ static void at91ether_set_multicast_list(struct net_device *dev)
 		cfg &= ~AT91_EMAC_CAF;
 
 	if (dev->flags & IFF_ALLMULTI) {		/* Enable all multicast mode */
-		at91_emac_write(AT91_EMAC_HSH, -1);
-		at91_emac_write(AT91_EMAC_HSL, -1);
+		at91_emac_write(lp, AT91_EMAC_HSH, -1);
+		at91_emac_write(lp, AT91_EMAC_HSL, -1);
 		cfg |= AT91_EMAC_MTI;
 	} else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
 		at91ether_sethashtable(dev);
 		cfg |= AT91_EMAC_MTI;
 	} else if (dev->flags & (~IFF_ALLMULTI)) {	/* Disable all multicast mode */
-		at91_emac_write(AT91_EMAC_HSH, 0);
-		at91_emac_write(AT91_EMAC_HSL, 0);
+		at91_emac_write(lp, AT91_EMAC_HSH, 0);
+		at91_emac_write(lp, AT91_EMAC_HSL, 0);
 		cfg &= ~AT91_EMAC_MTI;
 	}
 
-	at91_emac_write(AT91_EMAC_CFG, cfg);
+	at91_emac_write(lp, AT91_EMAC_CFG, cfg);
 }
 
 /* ......................... ETHTOOL SUPPORT ........................... */
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
+	struct at91_private *lp = netdev_priv(dev);
 	unsigned int value;
 
-	read_phy(phy_id, location, &value);
+	read_phy(lp, phy_id, location, &value);
 	return value;
 }
 
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
-	write_phy(phy_id, location, value);
+	struct at91_private *lp = netdev_priv(dev);
+
+	write_phy(lp, phy_id, location, value);
 }
 
 static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -625,11 +656,11 @@ static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cm
 	int ret;
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 
 	ret = mii_ethtool_gset(&lp->mii, cmd);
 
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
 	if (lp->phy_media == PORT_FIBRE) {		/* override media type since mii.c doesn't know */
@@ -646,11 +677,11 @@ static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cm
 	int ret;
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 
 	ret = mii_ethtool_sset(&lp->mii, cmd);
 
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
 	return ret;
@@ -662,11 +693,11 @@ static int at91ether_nwayreset(struct net_device *dev)
 	int ret;
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 
 	ret = mii_nway_restart(&lp->mii);
 
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
 	return ret;
@@ -696,9 +727,9 @@ static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		return -EINVAL;
 
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 	res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
 	return res;
@@ -731,11 +762,11 @@ static void at91ether_start(struct net_device *dev)
 	lp->rxBuffIndex = 0;
 
 	/* Program address of descriptor list in Rx Buffer Queue register */
-	at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+	at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
 
 	/* Enable Receive and Transmit */
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+	at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
 }
 
 /*
@@ -752,8 +783,8 @@ static int at91ether_open(struct net_device *dev)
 	clk_enable(lp->ether_clk);		/* Re-enable Peripheral clock */
 
 	/* Clear internal statistics */
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+	at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
 
 	/* Update the MAC address (incase user has changed it) */
 	update_mac_address(dev);
@@ -762,15 +793,15 @@ static int at91ether_open(struct net_device *dev)
 	enable_phyirq(dev);
 
 	/* Enable MAC interrupts */
-	at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
+	at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
 				| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
 				| AT91_EMAC_ROVR | AT91_EMAC_ABT);
 
 	/* Determine current link speed */
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 	update_linkspeed(dev, 0);
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
 	at91ether_start(dev);
@@ -787,14 +818,14 @@ static int at91ether_close(struct net_device *dev)
 	unsigned long ctl;
 
 	/* Disable Receiver and Transmitter */
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
+	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+	at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
 
 	/* Disable PHY interrupt */
 	disable_phyirq(dev);
 
 	/* Disable MAC interrupts */
-	at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
+	at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
 				| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
 				| AT91_EMAC_ROVR | AT91_EMAC_ABT);
 
@@ -812,7 +843,7 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct at91_private *lp = netdev_priv(dev);
 
-	if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+	if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
 		netif_stop_queue(dev);
 
 		/* Store packet information (to free when Tx completed) */
@@ -822,9 +853,9 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		dev->stats.tx_bytes += skb->len;
 
 		/* Set address of the data in the Transmit Address register */
-		at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
+		at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
 		/* Set length of the packet in the Transmit Control register */
-		at91_emac_write(AT91_EMAC_TCR, skb->len);
+		at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
 
 	} else {
 		printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
@@ -841,31 +872,32 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
  */
 static struct net_device_stats *at91ether_stats(struct net_device *dev)
 {
+	struct at91_private *lp = netdev_priv(dev);
 	int ale, lenerr, seqe, lcol, ecol;
 
 	if (netif_running(dev)) {
-		dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK);		/* Good frames received */
-		ale = at91_emac_read(AT91_EMAC_ALE);
+		dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK);	/* Good frames received */
+		ale = at91_emac_read(lp, AT91_EMAC_ALE);
 		dev->stats.rx_frame_errors += ale;				/* Alignment errors */
-		lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
+		lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
 		dev->stats.rx_length_errors += lenerr;				/* Excessive Length or Undersize Frame error */
-		seqe = at91_emac_read(AT91_EMAC_SEQE);
+		seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
 		dev->stats.rx_crc_errors += seqe;				/* CRC error */
-		dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC);	/* Receive buffer not available */
+		dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
 		dev->stats.rx_errors += (ale + lenerr + seqe
-			+ at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
+			+ at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
 
-		dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA);		/* Frames successfully transmitted */
-		dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE);	/* Transmit FIFO underruns */
-		dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE);	/* Carrier Sense errors */
-		dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
+		dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA);	/* Frames successfully transmitted */
+		dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE);	/* Transmit FIFO underruns */
+		dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE);	/* Carrier Sense errors */
+		dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
 
-		lcol = at91_emac_read(AT91_EMAC_LCOL);
-		ecol = at91_emac_read(AT91_EMAC_ECOL);
+		lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
+		ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
 		dev->stats.tx_window_errors += lcol;			/* Late collisions */
 		dev->stats.tx_aborted_errors += ecol;			/* 16 collisions */
 
-		dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
+		dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
 	}
 	return &dev->stats;
 }
@@ -922,7 +954,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 
 	/* MAC Interrupt Status register indicates what interrupts are pending.
 	   It is automatically cleared once read. */
-	intstatus = at91_emac_read(AT91_EMAC_ISR);
+	intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
 
 	if (intstatus & AT91_EMAC_RCOM)		/* Receive complete */
 		at91ether_rx(dev);
@@ -942,9 +974,9 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 
 	/* Work-around for Errata #11 */
 	if (intstatus & AT91_EMAC_RBNA) {
-		ctl = at91_emac_read(AT91_EMAC_CTL);
-		at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-		at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+		ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+		at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
+		at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
 	}
 
 	if (intstatus & AT91_EMAC_ROVR)
@@ -980,189 +1012,199 @@ static const struct net_device_ops at91ether_netdev_ops = {
 };
 
 /*
- * Initialize the ethernet interface
+ * Detect the PHY type, and its address.
  */
-static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
-			struct platform_device *pdev, struct clk *ether_clk)
+static int __init at91ether_phy_detect(struct at91_private *lp)
+{
+	unsigned int phyid1, phyid2;
+	unsigned long phy_id;
+	unsigned short phy_address = 0;
+
+	while (phy_address < PHY_MAX_ADDR) {
+		/* Read the PHY ID registers */
+		enable_mdi(lp);
+		read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
+		read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
+		disable_mdi(lp);
+
+		phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
+		switch (phy_id) {
+			case MII_DM9161_ID:		/* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
+			case MII_DM9161A_ID:		/* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
+			case MII_LXT971A_ID:		/* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
+			case MII_RTL8201_ID:		/* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
+			case MII_BCM5221_ID:		/* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
+			case MII_DP83847_ID:		/* National Semiconductor DP83847:  */
+			case MII_DP83848_ID:		/* National Semiconductor DP83848:  */
+			case MII_AC101L_ID:		/* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
+			case MII_KS8721_ID:		/* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
+			case MII_T78Q21x3_ID:		/* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
+			case MII_LAN83C185_ID:		/* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
+				/* store detected values */
+				lp->phy_type = phy_id;		/* Type of PHY connected */
+				lp->phy_address = phy_address;	/* MDI address of PHY */
+				return 1;
+		}
+
+		phy_address++;
+	}
+
+	return 0;		/* not detected */
+}
+
+
+/*
+ * Detect MAC & PHY and perform ethernet interface initialization
+ */
+static int __init at91ether_probe(struct platform_device *pdev)
 {
 	struct macb_platform_data *board_data = pdev->dev.platform_data;
+	struct resource *regs;
 	struct net_device *dev;
 	struct at91_private *lp;
-	unsigned int val;
 	int res;
 
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENOENT;
+
 	dev = alloc_etherdev(sizeof(struct at91_private));
 	if (!dev)
 		return -ENOMEM;
 
-	dev->base_addr = AT91_VA_BASE_EMAC;
-	dev->irq = AT91RM9200_ID_EMAC;
+	lp = netdev_priv(dev);
+	lp->board_data = *board_data;
+	spin_lock_init(&lp->lock);
+
+	dev->base_addr = regs->start;		/* physical base address */
+	lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!lp->emac_base) {
+		res = -ENOMEM;
+		goto err_free_dev;
+	}
+
+	/* Clock */
+	lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
+	if (IS_ERR(lp->ether_clk)) {
+		res = -ENODEV;
+		goto err_ioumap;
+	}
+	clk_enable(lp->ether_clk);
 
 	/* Install the interrupt handler */
+	dev->irq = platform_get_irq(pdev, 0);
 	if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
-		free_netdev(dev);
-		return -EBUSY;
+		res = -EBUSY;
+		goto err_disable_clock;
 	}
 
 	/* Allocate memory for DMA Receive descriptors */
-	lp = netdev_priv(dev);
 	lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
 	if (lp->dlist == NULL) {
-		free_irq(dev->irq, dev);
-		free_netdev(dev);
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto err_free_irq;
 	}
-	lp->board_data = *board_data;
-	lp->ether_clk = ether_clk;
-	platform_set_drvdata(pdev, dev);
-
-	spin_lock_init(&lp->lock);
 
 	ether_setup(dev);
 	dev->netdev_ops = &at91ether_netdev_ops;
 	dev->ethtool_ops = &at91ether_ethtool_ops;
-
+	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	get_mac_address(dev);		/* Get ethernet address and store it in dev->dev_addr */
 	update_mac_address(dev);	/* Program ethernet address into MAC */
 
-	at91_emac_write(AT91_EMAC_CTL, 0);
+	at91_emac_write(lp, AT91_EMAC_CTL, 0);
 
-	if (lp->board_data.is_rmii)
-		at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
+	if (board_data->is_rmii)
+		at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
 	else
-		at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
+		at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
 
-	/* Perform PHY-specific initialization */
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-	if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-		read_phy(phy_address, MII_DSCR_REG, &val);
-		if ((val & (1 << 10)) == 0)			/* DSCR bit 10 is 0 -- fiber mode */
-			lp->phy_media = PORT_FIBRE;
-	} else if (machine_is_csb337()) {
-		/* mix link activity status into LED2 link state */
-		write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
-	} else if (machine_is_ecbat91())
-		write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
+	/* Detect PHY */
+	if (!at91ether_phy_detect(lp)) {
+		printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
+		res = -ENODEV;
+		goto err_free_dmamem;
+	}
 
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
+	initialize_phy(lp);
 
 	lp->mii.dev = dev;		/* Support for ethtool */
 	lp->mii.mdio_read = mdio_read;
 	lp->mii.mdio_write = mdio_write;
-	lp->mii.phy_id = phy_address;
+	lp->mii.phy_id = lp->phy_address;
 	lp->mii.phy_id_mask = 0x1f;
 	lp->mii.reg_num_mask = 0x1f;
 
-	lp->phy_type = phy_type;	/* Type of PHY connected */
-	lp->phy_address = phy_address;	/* MDI address of PHY */
-
 	/* Register the network interface */
 	res = register_netdev(dev);
-	if (res) {
-		free_irq(dev->irq, dev);
-		free_netdev(dev);
-		dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-		return res;
-	}
+	if (res)
+		goto err_free_dmamem;
 
 	/* Determine current link speed */
 	spin_lock_irq(&lp->lock);
-	enable_mdi();
+	enable_mdi(lp);
 	update_linkspeed(dev, 0);
-	disable_mdi();
+	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 	netif_carrier_off(dev);		/* will be enabled in open() */
 
 	/* If board has no PHY IRQ, use a timer to poll the PHY */
-	if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
+	if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
+		gpio_request(board_data->phy_irq_pin, "ethernet_phy");
+	} else {
+		/* If board has no PHY IRQ, use a timer to poll the PHY */
 		init_timer(&lp->check_timer);
 		lp->check_timer.data = (unsigned long)dev;
 		lp->check_timer.function = at91ether_check_link;
-	} else if (lp->board_data.phy_irq_pin >= 32)
-		gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy");
+	}
 
 	/* Display ethernet banner */
 	printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
 	       dev->name, (uint) dev->base_addr, dev->irq,
-	       at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-	       at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
+	       at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
+	       at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
 	       dev->dev_addr);
-	if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
+	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
 		printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-	else if (phy_type == MII_LXT971A_ID)
+	else if (lp->phy_type == MII_LXT971A_ID)
 		printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-	else if (phy_type == MII_RTL8201_ID)
+	else if (lp->phy_type == MII_RTL8201_ID)
 		printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-	else if (phy_type == MII_BCM5221_ID)
+	else if (lp->phy_type == MII_BCM5221_ID)
 		printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-	else if (phy_type == MII_DP83847_ID)
+	else if (lp->phy_type == MII_DP83847_ID)
 		printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
-	else if (phy_type == MII_DP83848_ID)
+	else if (lp->phy_type == MII_DP83848_ID)
 		printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
-	else if (phy_type == MII_AC101L_ID)
+	else if (lp->phy_type == MII_AC101L_ID)
 		printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-	else if (phy_type == MII_KS8721_ID)
+	else if (lp->phy_type == MII_KS8721_ID)
 		printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
-	else if (phy_type == MII_T78Q21x3_ID)
+	else if (lp->phy_type == MII_T78Q21x3_ID)
 		printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
-	else if (phy_type == MII_LAN83C185_ID)
+	else if (lp->phy_type == MII_LAN83C185_ID)
 		printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
 
-	return 0;
-}
-
-/*
- * Detect MAC and PHY and perform initialization
- */
-static int __init at91ether_probe(struct platform_device *pdev)
-{
-	unsigned int phyid1, phyid2;
-	int detected = -1;
-	unsigned long phy_id;
-	unsigned short phy_address = 0;
-	struct clk *ether_clk;
-
-	ether_clk = clk_get(&pdev->dev, "ether_clk");
-	if (IS_ERR(ether_clk)) {
-		printk(KERN_ERR "at91_ether: no clock defined\n");
-		return -ENODEV;
-	}
-	clk_enable(ether_clk);					/* Enable Peripheral clock */
-
-	while ((detected != 0) && (phy_address < 32)) {
-		/* Read the PHY ID registers */
-		enable_mdi();
-		read_phy(phy_address, MII_PHYSID1, &phyid1);
-		read_phy(phy_address, MII_PHYSID2, &phyid2);
-		disable_mdi();
-
-		phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-		switch (phy_id) {
-			case MII_DM9161_ID:		/* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-			case MII_DM9161A_ID:		/* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-			case MII_LXT971A_ID:		/* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-			case MII_RTL8201_ID:		/* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-			case MII_BCM5221_ID:		/* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-			case MII_DP83847_ID:		/* National Semiconductor DP83847:  */
-			case MII_DP83848_ID:		/* National Semiconductor DP83848:  */
-			case MII_AC101L_ID:		/* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-			case MII_KS8721_ID:		/* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-			case MII_T78Q21x3_ID:		/* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-			case MII_LAN83C185_ID:		/* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-				detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
-				break;
-		}
+	clk_disable(lp->ether_clk);					/* Disable Peripheral clock */
 
-		phy_address++;
-	}
+	return 0;
 
-	clk_disable(ether_clk);					/* Disable Peripheral clock */
 
-	return detected;
+err_free_dmamem:
+	platform_set_drvdata(pdev, NULL);
+	dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_disable_clock:
+	clk_disable(lp->ether_clk);
+	clk_put(lp->ether_clk);
+err_ioumap:
+	iounmap(lp->emac_base);
+err_free_dev:
+	free_netdev(dev);
+	return res;
 }
 
 static int __devexit at91ether_remove(struct platform_device *pdev)
@@ -1170,8 +1212,7 @@ static int __devexit at91ether_remove(struct platform_device *pdev)
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct at91_private *lp = netdev_priv(dev);
 
-	if (gpio_is_valid(lp->board_data.phy_irq_pin) &&
-	    lp->board_data.phy_irq_pin >= 32)
+	if (gpio_is_valid(lp->board_data.phy_irq_pin))
 		gpio_free(lp->board_data.phy_irq_pin);
 
 	unregister_netdev(dev);
diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
index 3725fbb0..0ef6328 100644
--- a/drivers/net/ethernet/cadence/at91_ether.h
+++ b/drivers/net/ethernet/cadence/at91_ether.h
@@ -88,6 +88,7 @@ struct at91_private
 	struct macb_platform_data board_data;	/* board-specific
 						 * configuration (shared with
 						 * macb for common data */
+	void __iomem *emac_base;		/* base register address */
 	struct clk *ether_clk;			/* clock */
 
 	/* PHY */
-- 
1.7.10

^ permalink raw reply related

* [PATCH 2/2] net/at91_ether: use gpio_to_irq for phy IRQ line
From: Nicolas Ferre @ 2012-04-26 10:30 UTC (permalink / raw)
  To: netdev, linux-arm-kernel, davem
  Cc: linux-kernel, avictor.za, plagnioj, Nicolas Ferre
In-Reply-To: <3ad9b1273c4f30d42dcc3bdf6d03470111246f14.1335435759.git.nicolas.ferre@atmel.com>

Use the gpio_to_irq() function to retrieve the phy IRQ line
from the GPIO pin specification.
This fix is needed now that we have moved to irqdomains on AT91.

Reported-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Andrew Victor <avictor.za@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/cadence/at91_ether.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 62761e1..7788419 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -263,7 +263,7 @@ static void enable_phyirq(struct net_device *dev)
 		return;
 	}
 
-	irq_number = lp->board_data.phy_irq_pin;
+	irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
 	status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
 	if (status) {
 		printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
@@ -363,7 +363,7 @@ static void disable_phyirq(struct net_device *dev)
 	disable_mdi(lp);
 	spin_unlock_irq(&lp->lock);
 
-	irq_number = lp->board_data.phy_irq_pin;
+	irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
 	free_irq(irq_number, dev);			/* Free interrupt handler */
 }
 
@@ -1234,7 +1234,7 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 
 	if (netif_running(net_dev)) {
 		if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-			int phy_irq = lp->board_data.phy_irq_pin;
+			int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
 			disable_irq(phy_irq);
 		}
 
@@ -1258,7 +1258,7 @@ static int at91ether_resume(struct platform_device *pdev)
 		netif_start_queue(net_dev);
 
 		if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-			int phy_irq = lp->board_data.phy_irq_pin;
+			int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
 			enable_irq(phy_irq);
 		}
 	}
-- 
1.7.10

^ permalink raw reply related

* Re: [PATCH iproute2] pedit action: add mask for changing bits.
From: Jamal Hadi Salim @ 2012-04-26 10:21 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Anton 'EvilMan' Danilov, netdev
In-Reply-To: <20120425131532.79ad7e6b@nehalam.linuxnetplumber.net>

On Wed, 2012-04-25 at 13:15 -0700, Stephen Hemminger wrote:

> Did you come to a conclusion, should it be applied as is?

No, dont apply it as is please. 
EvilMan should have a new version when he gets to it.

cheers,
jamal

^ permalink raw reply

* [PATCH] tcp repair: Fix unaligned access when repairing options (v2)
From: Pavel Emelyanov @ 2012-04-26  8:50 UTC (permalink / raw)
  To: David Miller, Linux Netdev List; +Cc: David Laight

Don't pick __u8/__u16 values directly from raw pointers, but instead use
an array of structures of code:value pairs. This is OK, since the buffer
we take options from is not an skb memory, but a user-to-kernel one.

For those options which don't require any value now, require this to be
zero (for potential future extension of this API).

v2: Changed tcp_repair_opt to use two __u32-s as spotted by David Laight.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/tcp.h |    5 ++++
 net/ipv4/tcp.c      |   60 +++++++++++++++++---------------------------------
 2 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 9865936..d0401d9 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -111,6 +111,11 @@ enum {
 #define TCP_QUEUE_SEQ		21
 #define TCP_REPAIR_OPTIONS	22
 
+struct tcp_repair_opt {
+	__u32	opt_code;
+	__u32	opt_val;
+};
+
 enum {
 	TCP_NO_QUEUE,
 	TCP_RECV_QUEUE,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index de6a238..9670af3 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2283,60 +2283,40 @@ static inline int tcp_can_repair_sock(struct sock *sk)
 		((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
 }
 
-static int tcp_repair_options_est(struct tcp_sock *tp, char __user *optbuf, unsigned int len)
+static int tcp_repair_options_est(struct tcp_sock *tp,
+		struct tcp_repair_opt __user *optbuf, unsigned int len)
 {
-	/*
-	 * Options are stored in CODE:VALUE form where CODE is 8bit and VALUE
-	 * fits the respective TCPOLEN_ size
-	 */
+	struct tcp_repair_opt opt;
 
-	while (len > 0) {
-		u8 opcode;
-
-		if (get_user(opcode, optbuf))
+	while (len >= sizeof(opt)) {
+		if (copy_from_user(&opt, optbuf, sizeof(opt)))
 			return -EFAULT;
 
 		optbuf++;
-		len--;
-
-		switch (opcode) {
-		case TCPOPT_MSS: {
-			u16 in_mss;
+		len -= sizeof(opt);
 
-			if (len < sizeof(in_mss))
-				return -ENODATA;
-			if (get_user(in_mss, optbuf))
-				return -EFAULT;
-
-			tp->rx_opt.mss_clamp = in_mss;
-
-			optbuf += sizeof(in_mss);
-			len -= sizeof(in_mss);
+		switch (opt.opt_code) {
+		case TCPOPT_MSS:
+			tp->rx_opt.mss_clamp = opt.opt_val;
 			break;
-		}
-		case TCPOPT_WINDOW: {
-			u8 wscale;
-
-			if (len < sizeof(wscale))
-				return -ENODATA;
-			if (get_user(wscale, optbuf))
-				return -EFAULT;
-
-			if (wscale > 14)
+		case TCPOPT_WINDOW:
+			if (opt.opt_val > 14)
 				return -EFBIG;
 
-			tp->rx_opt.snd_wscale = wscale;
-
-			optbuf += sizeof(wscale);
-			len -= sizeof(wscale);
+			tp->rx_opt.snd_wscale = opt.opt_val;
 			break;
-		}
 		case TCPOPT_SACK_PERM:
+			if (opt.opt_val != 0)
+				return -EINVAL;
+
 			tp->rx_opt.sack_ok |= TCP_SACK_SEEN;
 			if (sysctl_tcp_fack)
 				tcp_enable_fack(tp);
 			break;
 		case TCPOPT_TIMESTAMP:
+			if (opt.opt_val != 0)
+				return -EINVAL;
+
 			tp->rx_opt.tstamp_ok = 1;
 			break;
 		}
@@ -2557,7 +2537,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		if (!tp->repair)
 			err = -EINVAL;
 		else if (sk->sk_state == TCP_ESTABLISHED)
-			err = tcp_repair_options_est(tp, optval, optlen);
+			err = tcp_repair_options_est(tp,
+					(struct tcp_repair_opt __user *)optval,
+					optlen);
 		else
 			err = -EPERM;
 		break;
-- 
1.5.5.6

^ permalink raw reply related

* Re: [PATCH] tcp repair: Fix unaligned access when repairing options (v2)
From: David Miller @ 2012-04-26 10:14 UTC (permalink / raw)
  To: xemul, xemul; +Cc: netdev
In-Reply-To: <4F9918A8.20100@sacred.ru>

From: Pavel Emelyanov <xemul@sacred.ru>
Date: Thu, 26 Apr 2012 13:43:04 +0400

> From: Pavel Emelyanov <xemul@parallels.com>
> 
> Don't pick __u8/__u16 values directly from raw pointers, but instead use
> an array of structures of code:value pairs. This is OK, since the buffer
> we take options from is not an skb memory, but a user-to-kernel one.
> 
> For those options which don't require any value now, require this to be
> zero (for potential future extension of this API).
> 
> v2: Changed tcp_repair_opt to use two __u32-s as spotted by David Laight.
> 
> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

Seems to have worked this time, applied :-)

^ permalink raw reply

* Re: [GIT PULL] net/at91: at91_ether fixes for 3.4-rc
From: David Miller @ 2012-04-26 10:12 UTC (permalink / raw)
  To: nicolas.ferre
  Cc: netdev, avictor.za, plagnioj, linux-kernel, linux-arm-kernel
In-Reply-To: <4F991E6D.4020303@atmel.com>

From: Nicolas Ferre <nicolas.ferre@atmel.com>
Date: Thu, 26 Apr 2012 12:07:41 +0200

> So, should I repost both of them as patch series?

Yes, with a leading "[PATCH 0/N] " posting as I asked.

^ permalink raw reply

* Re: [RFC] allow skb->head to point/alias to first skb frag
From: Maciej Żenczykowski @ 2012-04-26 10:09 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, ilpo.jarvinen, rick.jones2, netdev, therbert,
	ncardwell, ycheng
In-Reply-To: <1335432147.2775.27.camel@edumazet-glaptop>

it would be very useful if there was an api for freeing skb->head memory...

I've fooled around with a single memory buffer for both the head and
the data and seen huge performance wins under heavy packet load (half
the amount of malloc/free), but could never quite get it to be 100%
stable.

On Thu, Apr 26, 2012 at 2:22 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Thu, 2012-04-26 at 05:18 -0400, David Miller wrote:
>> From: Eric Dumazet <eric.dumazet@gmail.com>
>> Date: Thu, 26 Apr 2012 11:10:02 +0200
>>
>> > The 'frag' would have a known size : 2048 bytes
>> >
>> > But the end of it would be used by struct skb_shared_info
>> >
>> > so data_len would be 0 in fact.
>> >
>> > This would look like a regular linear skb.
>> >
>> > Just a bit set in skb to say : Warning, skb->head was not kmalloced :
>> > replace kfree(head) by put_page(...)
>> >
>> > And this bit would be tested in GRO or tcp merge to 'upgrade' this
>> > skb->head to proper page/frag
>>
>> And what happens if this ends up in a piece of code which wants to
>> append a page frag?
>>
>> Or a piece of code which copies an SKB, including page frag parts?
>>
>> All I'm saying is that the number of tests necessary to make this work
>> properly might become prohibitive.
>
> I'll cook a patch, I believe not so many parts assume skb->head can be
> kmalloc()/kfree(). This should be contained in net/core/skbuff.c only.
>
> Elsewhere we use skb->head as a pointer to memory. It will stay the
> same.
>
>
>



-- 
Maciej A. Żenczykowski
Kernel Networking Developer @ Google
1600 Amphitheatre Parkway, Mountain View, CA 94043
tel: +1 (650) 253-0062

^ permalink raw reply

* [PATCH] tcp repair: Fix unaligned access when repairing options (v2)
From: Pavel Emelyanov @ 2012-04-26  9:43 UTC (permalink / raw)
  To: Linux Netdev List

From: Pavel Emelyanov <xemul@parallels.com>

Don't pick __u8/__u16 values directly from raw pointers, but instead use
an array of structures of code:value pairs. This is OK, since the buffer
we take options from is not an skb memory, but a user-to-kernel one.

For those options which don't require any value now, require this to be
zero (for potential future extension of this API).

v2: Changed tcp_repair_opt to use two __u32-s as spotted by David Laight.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/tcp.h |    5 ++++
 net/ipv4/tcp.c      |   60 +++++++++++++++++---------------------------------
 2 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 9865936..d0401d9 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -111,6 +111,11 @@ enum {
 #define TCP_QUEUE_SEQ		21
 #define TCP_REPAIR_OPTIONS	22
 
+struct tcp_repair_opt {
+	__u32	opt_code;
+	__u32	opt_val;
+};
+
 enum {
 	TCP_NO_QUEUE,
 	TCP_RECV_QUEUE,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index de6a238..9670af3 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2283,60 +2283,40 @@ static inline int tcp_can_repair_sock(struct sock *sk)
 		((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
 }
 
-static int tcp_repair_options_est(struct tcp_sock *tp, char __user *optbuf, unsigned int len)
+static int tcp_repair_options_est(struct tcp_sock *tp,
+		struct tcp_repair_opt __user *optbuf, unsigned int len)
 {
-	/*
-	 * Options are stored in CODE:VALUE form where CODE is 8bit and VALUE
-	 * fits the respective TCPOLEN_ size
-	 */
+	struct tcp_repair_opt opt;
 
-	while (len > 0) {
-		u8 opcode;
-
-		if (get_user(opcode, optbuf))
+	while (len >= sizeof(opt)) {
+		if (copy_from_user(&opt, optbuf, sizeof(opt)))
 			return -EFAULT;
 
 		optbuf++;
-		len--;
-
-		switch (opcode) {
-		case TCPOPT_MSS: {
-			u16 in_mss;
+		len -= sizeof(opt);
 
-			if (len < sizeof(in_mss))
-				return -ENODATA;
-			if (get_user(in_mss, optbuf))
-				return -EFAULT;
-
-			tp->rx_opt.mss_clamp = in_mss;
-
-			optbuf += sizeof(in_mss);
-			len -= sizeof(in_mss);
+		switch (opt.opt_code) {
+		case TCPOPT_MSS:
+			tp->rx_opt.mss_clamp = opt.opt_val;
 			break;
-		}
-		case TCPOPT_WINDOW: {
-			u8 wscale;
-
-			if (len < sizeof(wscale))
-				return -ENODATA;
-			if (get_user(wscale, optbuf))
-				return -EFAULT;
-
-			if (wscale > 14)
+		case TCPOPT_WINDOW:
+			if (opt.opt_val > 14)
 				return -EFBIG;
 
-			tp->rx_opt.snd_wscale = wscale;
-
-			optbuf += sizeof(wscale);
-			len -= sizeof(wscale);
+			tp->rx_opt.snd_wscale = opt.opt_val;
 			break;
-		}
 		case TCPOPT_SACK_PERM:
+			if (opt.opt_val != 0)
+				return -EINVAL;
+
 			tp->rx_opt.sack_ok |= TCP_SACK_SEEN;
 			if (sysctl_tcp_fack)
 				tcp_enable_fack(tp);
 			break;
 		case TCPOPT_TIMESTAMP:
+			if (opt.opt_val != 0)
+				return -EINVAL;
+
 			tp->rx_opt.tstamp_ok = 1;
 			break;
 		}
@@ -2557,7 +2537,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		if (!tp->repair)
 			err = -EINVAL;
 		else if (sk->sk_state == TCP_ESTABLISHED)
-			err = tcp_repair_options_est(tp, optval, optlen);
+			err = tcp_repair_options_est(tp,
+					(struct tcp_repair_opt __user *)optval,
+					optlen);
 		else
 			err = -EPERM;
 		break;

^ permalink raw reply related

* Re: [GIT PULL] net/at91: at91_ether fixes for 3.4-rc
From: Nicolas Ferre @ 2012-04-26 10:07 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, avictor.za, plagnioj, linux-kernel, linux-arm-kernel
In-Reply-To: <20120426.052006.1832921763623188173.davem@davemloft.net>

On 04/26/2012 11:20 AM, David Miller :
> From: Nicolas Ferre <nicolas.ferre@atmel.com>
> Date: Thu, 26 Apr 2012 11:14:56 +0200
> 
>> Can you please pull those fixes for 3.4-rc? The ARM/AT91 part
>> of modifications is pretty small and bounded to a single SoC so
>> it will not mess with arm-soc git tree.
> 
> Please post the patches themselves to netdev.
> 
> You can give me pull requests, but those go into the "[PATCH 0/N] ..."
> email, it doesn't preclude you're still having to post the actual
> patches.
> 
> Otherwise nobody can review your work.

Both patches have been posted on netdev (but independently):

First has been posted on February 13th:
http://www.spinics.net/lists/netdev/msg188868.html
With a question from myself a few days ago:
http://www.spinics.net/lists/netdev/msg196183.html
And I can find ancestors back in May 2011...

Second one has been posted on April 23rd:
http://www.spinics.net/lists/netdev/msg196002.html

So, should I repost both of them as patch series?

Best regards,
-- 
Nicolas Ferre

^ permalink raw reply

* Re: [PATCH net-next 0/2][6lowpan] code improvements and refactorings
From: David Miller @ 2012-04-26 10:02 UTC (permalink / raw)
  To: alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1335432951-17340-1-git-send-email-alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

From: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Thu, 26 Apr 2012 13:35:49 +0400

> The following patches contains 6lowpan code improvements.

Both applied, thanks.

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

^ permalink raw reply

* Re: [PATCH v2] smsc95xx: mark link down on startup and let PHY interrupt deal with carrier changes
From: David Miller @ 2012-04-26  9:56 UTC (permalink / raw)
  To: steve; +Cc: fillods, paolo.pisati, netdev
In-Reply-To: <CAKh2mn6YM=Jmpmfr7ErM0cRjsMc97DzoBLcA45gh9yzSpQDRJg@mail.gmail.com>

From: Steve Glendinning <steve@shawell.net>
Date: Thu, 26 Apr 2012 10:41:33 +0100

> Hi all,
> 
> On 24 April 2012 16:45, Steve Glendinning <steve@shawell.net> wrote:
>> Hi all,
>>
>> On 24 April 2012 05:42, David Miller <davem@davemloft.net> wrote:
>>>
>>> Steve, please send a maintainers etc. update and please provide
>>> feedback on this link status fix.
> 
> Good catch Paolo, this patch fixes reporting of link status when the
> device is first connected with no ethernet cable plugged in.
> 
> I'll prepare the same patch for smsc75xx as it also suffers from the same issue.
> 
> Acked-by: Steve Glendinning <steve.glendinning@shawell.net>

Applied.

^ permalink raw reply

* Re: [PATCH] net: usb: smsc95xx: fix mtu
From: Steve Glendinning @ 2012-04-26  9:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, fillods
In-Reply-To: <20120426.053850.929602823670004153.davem@davemloft.net>

On 26 April 2012 10:38, David Miller <davem@davemloft.net> wrote:
>
> This is already in the 'net' tree for nearly a week:

Doh!  Sorry David, I missed this.

-- 
Steve Glendinning

^ permalink raw reply

* Re: [PATCH v2] smsc95xx: mark link down on startup and let PHY interrupt deal with carrier changes
From: Steve Glendinning @ 2012-04-26  9:41 UTC (permalink / raw)
  To: David Miller; +Cc: fillods, paolo.pisati, netdev
In-Reply-To: <CAKh2mn4JLm8f036d7vNimLdA2wCP+Db7xhgUgfsg760yhs3Yjw@mail.gmail.com>

Hi all,

On 24 April 2012 16:45, Steve Glendinning <steve@shawell.net> wrote:
> Hi all,
>
> On 24 April 2012 05:42, David Miller <davem@davemloft.net> wrote:
>>
>> Steve, please send a maintainers etc. update and please provide
>> feedback on this link status fix.

Good catch Paolo, this patch fixes reporting of link status when the
device is first connected with no ethernet cable plugged in.

I'll prepare the same patch for smsc75xx as it also suffers from the same issue.

Acked-by: Steve Glendinning <steve.glendinning@shawell.net>

-- 
Steve Glendinning

^ permalink raw reply

* Re: [PATCH] tcp repair: Fix unaligned access when repairing options (v2)
From: Pavel Emelyanov @ 2012-04-26  9:41 UTC (permalink / raw)
  To: David Miller; +Cc: netdev@vger.kernel.org, David.Laight@ACULAB.COM
In-Reply-To: <20120426.052336.664675835426476301.davem@davemloft.net>

On 04/26/2012 01:23 PM, David Miller wrote:
> From: Pavel Emelyanov <xemul@parallels.com>
> Date: Thu, 26 Apr 2012 12:50:57 +0400
> 
>> Don't pick __u8/__u16 values directly from raw pointers, but instead use
>> an array of structures of code:value pairs. This is OK, since the buffer
>> we take options from is not an skb memory, but a user-to-kernel one.
>>
>> For those options which don't require any value now, require this to be
>> zero (for potential future extension of this API).
>>
>> v2: Changed tcp_repair_opt to use two __u32-s as spotted by David Laight.
>>
>> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
> 
> Hmmm, this didn't show up on netdev, I wonder why?

So do I :( I haven't received any mail with errors from netdev, neither
Parallels mail server reported any problems.

I will resubmit this one again.

Thanks,
Pavel

^ permalink raw reply

* Re: [PATCH] dl2k: Clean up rio_ioctl
From: David Miller @ 2012-04-26  9:38 UTC (permalink / raw)
  To: jeffm; +Cc: netdev
In-Reply-To: <4F989789.9040405@suse.com>

From: Jeff Mahoney <jeffm@suse.com>
Date: Wed, 25 Apr 2012 20:32:09 -0400

> The dl2k driver's rio_ioctl call has a few issues:
> - No permissions checking
> - Implements SIOCGMIIREG and SIOCGMIIREG using the SIOCDEVPRIVATE numbers
> - Has a few ioctls that may have been used for debugging at one point
>   but have no place in the kernel proper.
> 
> This patch removes all but the MII ioctls, renumbers them to use the
> standard ones, and adds the proper permission check for SIOCSMIIREG.
> 
> We can also get rid of the dl2k-specific struct mii_data in favor of
> the generic struct mii_ioctl_data.
> 
> Since we have the phyid on hand, we can add the SIOCGMIIPHY ioctl too.
> 
> Most of the MII code for the driver could probably be converted to use
> the generic MII library but I don't have a device to test the results.
> 
> Reported-by: Stephan Mueller <stephan.mueller@atsec.com>
> Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] net: usb: smsc95xx: fix mtu
From: David Miller @ 2012-04-26  9:38 UTC (permalink / raw)
  To: steve.glendinning; +Cc: netdev, fillods
In-Reply-To: <1335430964-1018-1-git-send-email-steve.glendinning@shawell.net>


This is already in the 'net' tree for nearly a week:

commit 9bbf56609d304e8aae2076610d938206453035de
Author: Stephane Fillod <fillods@users.sf.net>
Date:   Fri Apr 20 09:39:23 2012 +0000

    net: usb: smsc95xx: fix mtu
    
    Make smsc95xx recalculate the hard_mtu after adjusting the
    hard_header_len.
    
    Without this, usbnet adjusts the MTU down to 1488 bytes, and the host is
    unable to receive standard 1500-byte frames from the device.
    
    Inspired by same fix on cdc_eem 78fb72f7936c01d5b426c03a691eca082b03f2b9.
    
    Tested on ARM/Beagle.
    
    Signed-off-by: Stephane Fillod <fillods@users.sf.net>
    Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* [PATCH net-next 2/2] 6lowpan: duplicate definition of IEEE802154_ALEN
From: Alexander Smirnov @ 2012-04-26  9:35 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1335432951-17340-1-git-send-email-alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

The same macros is defined in 'include/net/af_ieee802154.h' and is called
IEEE802154_ADDR_LEN. No need another one, so remove it.

Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 net/ieee802154/6lowpan.c |    4 ++--
 net/ieee802154/6lowpan.h |    3 ---
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index f406ac8..32eb417 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -196,7 +196,7 @@ lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
 static void
 lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr)
 {
-	memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ALEN);
+	memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ADDR_LEN);
 	/* second bit-flip (Universe/Local) is done according RFC2464 */
 	ipaddr->s6_addr[8] ^= 0x02;
 }
@@ -221,7 +221,7 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
 
 	if (lladdr)
 		lowpan_raw_dump_inline(__func__, "linklocal address",
-						lladdr,	IEEE802154_ALEN);
+						lladdr,	IEEE802154_ADDR_LEN);
 	if (prefcount > 0)
 		memcpy(ipaddr, prefix, prefcount);
 
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index aeff3f3..8c2251f 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -53,9 +53,6 @@
 #ifndef __6LOWPAN_H__
 #define __6LOWPAN_H__
 
-/* need to know address length to manipulate with it */
-#define IEEE802154_ALEN		8
-
 #define UIP_802154_SHORTADDR_LEN	2  /* compressed ipv6 address length */
 #define UIP_IPH_LEN			40 /* ipv6 fixed header size */
 #define UIP_PROTO_UDP			17 /* ipv6 next header value for UDP */
-- 
1.7.2.3


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

^ permalink raw reply related

* [PATCH net-next 1/2] 6lowpan: move frame allocation code to a separate function
From: Alexander Smirnov @ 2012-04-26  9:35 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1335432951-17340-1-git-send-email-alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Separate frame allocation routine from data processing function.
This makes code more human readable and easier for understanding.

Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 net/ieee802154/6lowpan.c |   81 +++++++++++++++++++++++++++-------------------
 1 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index b570dbf..f406ac8 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -650,6 +650,53 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
 	kfree(entry);
 }
 
+static struct lowpan_fragment *
+lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 len, u8 tag)
+{
+	struct lowpan_fragment *frame;
+
+	frame = kzalloc(sizeof(struct lowpan_fragment),
+			GFP_ATOMIC);
+	if (!frame)
+		goto frame_err;
+
+	INIT_LIST_HEAD(&frame->list);
+
+	frame->length = (iphc0 & 7) | (len << 3);
+	frame->tag = tag;
+
+	/* allocate buffer for frame assembling */
+	frame->skb = alloc_skb(frame->length +
+			       sizeof(struct ipv6hdr), GFP_ATOMIC);
+
+	if (!frame->skb)
+		goto skb_err;
+
+	frame->skb->priority = skb->priority;
+	frame->skb->dev = skb->dev;
+
+	/* reserve headroom for uncompressed ipv6 header */
+	skb_reserve(frame->skb, sizeof(struct ipv6hdr));
+	skb_put(frame->skb, frame->length);
+
+	init_timer(&frame->timer);
+	/* time out is the same as for ipv6 - 60 sec */
+	frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT;
+	frame->timer.data = (unsigned long)frame;
+	frame->timer.function = lowpan_fragment_timer_expired;
+
+	add_timer(&frame->timer);
+
+	list_add_tail(&frame->list, &lowpan_fragments);
+
+	return frame;
+
+skb_err:
+	kfree(frame);
+frame_err:
+	return NULL;
+}
+
 static int
 lowpan_process_data(struct sk_buff *skb)
 {
@@ -692,41 +739,9 @@ lowpan_process_data(struct sk_buff *skb)
 
 		/* alloc new frame structure */
 		if (!found) {
-			frame = kzalloc(sizeof(struct lowpan_fragment),
-								GFP_ATOMIC);
+			frame = lowpan_alloc_new_frame(skb, iphc0, len, tag);
 			if (!frame)
 				goto unlock_and_drop;
-
-			INIT_LIST_HEAD(&frame->list);
-
-			frame->length = (iphc0 & 7) | (len << 3);
-			frame->tag = tag;
-
-			/* allocate buffer for frame assembling */
-			frame->skb = alloc_skb(frame->length +
-					sizeof(struct ipv6hdr), GFP_ATOMIC);
-
-			if (!frame->skb) {
-				kfree(frame);
-				goto unlock_and_drop;
-			}
-
-			frame->skb->priority = skb->priority;
-			frame->skb->dev = skb->dev;
-
-			/* reserve headroom for uncompressed ipv6 header */
-			skb_reserve(frame->skb, sizeof(struct ipv6hdr));
-			skb_put(frame->skb, frame->length);
-
-			init_timer(&frame->timer);
-			/* time out is the same as for ipv6 - 60 sec */
-			frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT;
-			frame->timer.data = (unsigned long)frame;
-			frame->timer.function = lowpan_fragment_timer_expired;
-
-			add_timer(&frame->timer);
-
-			list_add_tail(&frame->list, &lowpan_fragments);
 		}
 
 		if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)
-- 
1.7.2.3


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

^ permalink raw reply related

* [PATCH net-next 0/2][6lowpan] code improvements and refactorings
From: Alexander Smirnov @ 2012-04-26  9:35 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

The following patches contains 6lowpan code improvements.

With best regards,
Alex

8<--

The following changes since commit b89f01c8dab2b2d07729e1e6525272568bca54e0:

  6lowpan: add missing spin_lock_init() (2012-04-26 11:35:28 +0400)

are available in the git repository at:
  6lowpan_dev ..BRANCH.NOT.VERIFIED..

Alexander Smirnov (2):
      6lowpan: move frame allocation code to a separate function
      6lowpan: duplicate definition of IEEE802154_ALEN

 net/ieee802154/6lowpan.c |   85 +++++++++++++++++++++++++++-------------------
 net/ieee802154/6lowpan.h |    3 --
 2 files changed, 50 insertions(+), 38 deletions(-)

From: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: [PATCH net-next 0/2][6lowpan] code improvements and refactorings
In-Reply-To: 


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

^ permalink raw reply

* Re: [PATCH net 0/3][6lowpan] fixes for 6lowpan
From: David Miller @ 2012-04-26  9:33 UTC (permalink / raw)
  To: alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1335432298-17161-1-git-send-email-alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

From: Alexander Smirnov <alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Thu, 26 Apr 2012 13:24:55 +0400

> The following patch set contains several fixes for the 6lowpan holes which lead
> to unpredictable module state.

All applied, thanks.

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

^ permalink raw reply

* Re: [PATCH 0/4] mISDN Fix and enhancements for the HFC 4S/8S/E1 driver
From: David Miller @ 2012-04-26  9:32 UTC (permalink / raw)
  To: kkeil; +Cc: netdev
In-Reply-To: <1335336734-25181-1-git-send-email-kkeil@linux-pingi.de>

From: Karsten Keil <kkeil@linux-pingi.de>
Date: Wed, 25 Apr 2012 08:52:10 +0200

> For net-next.
> 
> Patchset contains fixes for issues fond in long time testing.
> The LED support now works as proposed by the card documentation.
> For special cases you can now split a E1 line into independ logical
> instances.

All applied, thanks Karsten.

^ permalink raw reply

* [PATCH net 3/3] 6lowpan: add missing spin_lock_init()
From: Alexander Smirnov @ 2012-04-26  9:24 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-zigbee-devel, Alexander Smirnov
In-Reply-To: <1335432298-17161-1-git-send-email-alex.bluesman.smirnov@gmail.com>

Add missing spin_lock_init() for frames list lock.

Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
---
 net/ieee802154/6lowpan.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index a21ca6e..b570dbf 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1168,6 +1168,8 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 	list_add_tail(&entry->list, &lowpan_devices);
 	mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
 
+	spin_lock_init(&flist_lock);
+
 	register_netdevice(dev);
 
 	return 0;
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH net 2/3] 6lowpan: clean up fragments list if module unloaded
From: Alexander Smirnov @ 2012-04-26  9:24 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-zigbee-devel, Alexander Smirnov
In-Reply-To: <1335432298-17161-1-git-send-email-alex.bluesman.smirnov@gmail.com>

Clean all the pending fragments and relative timers if 6lowpan link
is going to be deleted.

Signed-off-by: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
---
 net/ieee802154/6lowpan.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 7ce508f..a21ca6e 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1177,11 +1177,20 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
 	struct net_device *real_dev = lowpan_dev->real_dev;
-	struct lowpan_dev_record *entry;
-	struct lowpan_dev_record *tmp;
+	struct lowpan_dev_record *entry, *tmp;
+	struct lowpan_fragment *frame, *tframe;
 
 	ASSERT_RTNL();
 
+	spin_lock(&flist_lock);
+	list_for_each_entry_safe(frame, tframe, &lowpan_fragments, list) {
+		del_timer(&frame->timer);
+		list_del(&frame->list);
+		dev_kfree_skb(frame->skb);
+		kfree(frame);
+	}
+	spin_unlock(&flist_lock);
+
 	mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
 	list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
 		if (entry->ldev == dev) {
-- 
1.7.2.3

^ permalink raw reply related


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