netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver
@ 2011-06-10 10:51 Russell King
  2011-06-10 10:51 ` [PATCH 1/3] NET: am79c961: ensure asm() statements are marked volatile Russell King - ARM Linux
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Russell King @ 2011-06-10 10:51 UTC (permalink / raw)
  To: netdev

This series of patches fix some of the more serious issues discovered
with GCC 4 and the ARM EBSA110 am79c961 ethernet driver last weekend
while upgrading my firewall to 2.6.39.

-- 
Russell King

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] NET: am79c961: ensure asm() statements are marked volatile
  2011-06-10 10:51 [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver Russell King
@ 2011-06-10 10:51 ` Russell King - ARM Linux
  2011-06-10 10:52 ` [PATCH 2/3] NET: am79c961: ensure multicast filter is correctly set at open Russell King - ARM Linux
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Russell King - ARM Linux @ 2011-06-10 10:51 UTC (permalink / raw)
  To: netdev

Without this the compiler can (and does) optimize register reads away
from within loops, and other such optimizations.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/net/arm/am79c961a.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 0c9217f..084b67f 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -50,7 +50,7 @@ static const char version[] =
 #ifdef __arm__
 static void write_rreg(u_long base, u_int reg, u_int val)
 {
-	__asm__(
+	asm volatile(
 	"str%?h	%1, [%2]	@ NET_RAP\n\t"
 	"str%?h	%0, [%2, #-4]	@ NET_RDP"
 	:
@@ -60,7 +60,7 @@ static void write_rreg(u_long base, u_int reg, u_int val)
 static inline unsigned short read_rreg(u_long base_addr, u_int reg)
 {
 	unsigned short v;
-	__asm__(
+	asm volatile(
 	"str%?h	%1, [%2]	@ NET_RAP\n\t"
 	"ldr%?h	%0, [%2, #-4]	@ NET_RDP"
 	: "=r" (v)
@@ -70,7 +70,7 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg)
 
 static inline void write_ireg(u_long base, u_int reg, u_int val)
 {
-	__asm__(
+	asm volatile(
 	"str%?h	%1, [%2]	@ NET_RAP\n\t"
 	"str%?h	%0, [%2, #8]	@ NET_IDP"
 	:
@@ -80,7 +80,7 @@ static inline void write_ireg(u_long base, u_int reg, u_int val)
 static inline unsigned short read_ireg(u_long base_addr, u_int reg)
 {
 	u_short v;
-	__asm__(
+	asm volatile(
 	"str%?h	%1, [%2]	@ NAT_RAP\n\t"
 	"ldr%?h	%0, [%2, #8]	@ NET_IDP\n\t"
 	: "=r" (v)
@@ -131,7 +131,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
 	length = (length + 1) & ~1;
 	if ((int)buf & 2) {
 		unsigned int tmp;
-		__asm__ __volatile__(
+		asm volatile(
 			"ldr%?h	%2, [%0], #4\n\t"
 			"str%?b	%2, [%1], #1\n\t"
 			"mov%?	%2, %2, lsr #8\n\t"
@@ -141,7 +141,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
 	}
 	while (length > 8) {
 		unsigned int tmp, tmp2, tmp3;
-		__asm__ __volatile__(
+		asm volatile(
 			"ldr%?h	%2, [%0], #4\n\t"
 			"ldr%?h	%3, [%0], #4\n\t"
 			"orr%?	%2, %2, %3, lsl #16\n\t"
@@ -155,7 +155,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
 	}
 	while (length > 0) {
 		unsigned int tmp;
-		__asm__ __volatile__(
+		asm volatile(
 			"ldr%?h	%2, [%0], #4\n\t"
 			"str%?b	%2, [%1], #1\n\t"
 			"mov%?	%2, %2, lsr #8\n\t"
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] NET: am79c961: ensure multicast filter is correctly set at open
  2011-06-10 10:51 [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver Russell King
  2011-06-10 10:51 ` [PATCH 1/3] NET: am79c961: ensure asm() statements are marked volatile Russell King - ARM Linux
@ 2011-06-10 10:52 ` Russell King - ARM Linux
  2011-06-10 10:52 ` [PATCH 3/3] NET: am79c961: fix assembler warnings Russell King - ARM Linux
  2011-06-11 22:56 ` [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: Russell King - ARM Linux @ 2011-06-10 10:52 UTC (permalink / raw)
  To: netdev

We were clearing out the multicast filter whenever the interface was
upped, and not setting the mode bits correctly.  This can cause
problems if there are any multicast addresses already set at this
point, or if ALLMULTI was set.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/net/arm/am79c961a.c |   77 ++++++++++++++++++++++--------------------
 1 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 084b67f..79d88a0 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -196,6 +196,42 @@ am79c961_ramtest(struct net_device *dev, unsigned int val)
 	return errorcount;
 }
 
+static void am79c961_mc_hash(char *addr, u16 *hash)
+{
+	if (addr[0] & 0x01) {
+		int idx, bit;
+		u32 crc;
+
+		crc = ether_crc_le(ETH_ALEN, addr);
+
+		idx = crc >> 30;
+		bit = (crc >> 26) & 15;
+
+		hash[idx] |= 1 << bit;
+	}
+}
+
+static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
+{
+	unsigned int mode = MODE_PORT_10BT;
+
+	if (dev->flags & IFF_PROMISC) {
+		mode |= MODE_PROMISC;
+		memset(hash, 0xff, 4 * sizeof(*hash));
+	} else if (dev->flags & IFF_ALLMULTI) {
+		memset(hash, 0xff, 4 * sizeof(*hash));
+	} else {
+		struct netdev_hw_addr *ha;
+
+		memset(hash, 0, 4 * sizeof(*hash));
+
+		netdev_for_each_mc_addr(ha, dev)
+			am79c961_mc_hash(ha->addr, hash);
+	}
+
+	return mode;
+}
+
 static void
 am79c961_init_for_open(struct net_device *dev)
 {
@@ -203,6 +239,7 @@ am79c961_init_for_open(struct net_device *dev)
 	unsigned long flags;
 	unsigned char *p;
 	u_int hdr_addr, first_free_addr;
+	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
 	int i;
 
 	/*
@@ -218,16 +255,12 @@ am79c961_init_for_open(struct net_device *dev)
 	write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */
 
 	for (i = LADRL; i <= LADRH; i++)
-		write_rreg (dev->base_addr, i, 0);
+		write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);
 
 	for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
 		write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
 
-	i = MODE_PORT_10BT;
-	if (dev->flags & IFF_PROMISC)
-		i |= MODE_PROMISC;
-
-	write_rreg (dev->base_addr, MODE, i);
+	write_rreg (dev->base_addr, MODE, mode);
 	write_rreg (dev->base_addr, POLLINT, 0);
 	write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
 	write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
@@ -340,21 +373,6 @@ am79c961_close(struct net_device *dev)
 	return 0;
 }
 
-static void am79c961_mc_hash(char *addr, unsigned short *hash)
-{
-	if (addr[0] & 0x01) {
-		int idx, bit;
-		u32 crc;
-
-		crc = ether_crc_le(ETH_ALEN, addr);
-
-		idx = crc >> 30;
-		bit = (crc >> 26) & 15;
-
-		hash[idx] |= 1 << bit;
-	}
-}
-
 /*
  * Set or clear promiscuous/multicast mode filter for this adapter.
  */
@@ -362,24 +380,9 @@ static void am79c961_setmulticastlist (struct net_device *dev)
 {
 	struct dev_priv *priv = netdev_priv(dev);
 	unsigned long flags;
-	unsigned short multi_hash[4], mode;
+	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
 	int i, stopped;
 
-	mode = MODE_PORT_10BT;
-
-	if (dev->flags & IFF_PROMISC) {
-		mode |= MODE_PROMISC;
-	} else if (dev->flags & IFF_ALLMULTI) {
-		memset(multi_hash, 0xff, sizeof(multi_hash));
-	} else {
-		struct netdev_hw_addr *ha;
-
-		memset(multi_hash, 0x00, sizeof(multi_hash));
-
-		netdev_for_each_mc_addr(ha, dev)
-			am79c961_mc_hash(ha->addr, multi_hash);
-	}
-
 	spin_lock_irqsave(&priv->chip_lock, flags);
 
 	stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] NET: am79c961: fix assembler warnings
  2011-06-10 10:51 [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver Russell King
  2011-06-10 10:51 ` [PATCH 1/3] NET: am79c961: ensure asm() statements are marked volatile Russell King - ARM Linux
  2011-06-10 10:52 ` [PATCH 2/3] NET: am79c961: ensure multicast filter is correctly set at open Russell King - ARM Linux
@ 2011-06-10 10:52 ` Russell King - ARM Linux
  2011-06-11 22:56 ` [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: Russell King - ARM Linux @ 2011-06-10 10:52 UTC (permalink / raw)
  To: netdev

Fix:
/tmp/ccvoZ6h8.s: Assembler messages:
/tmp/ccvoZ6h8.s:284: Warning: register range not in ascending order
/tmp/ccvoZ6h8.s:881: Warning: register range not in ascending order
/tmp/ccvoZ6h8.s:1087: Warning: register range not in ascending order

by ensuring that we have temporary variables placed into specific
registers.  Reorder the code a bit to allow the resulting assembly
to be slightly more optimal.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/net/arm/am79c961a.c |   35 ++++++++++++++++++-----------------
 1 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 79d88a0..7b3e23f 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -91,40 +91,41 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg)
 #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
 #define am_readword(dev,off)      __raw_readw(ISAMEM_BASE + ((off) << 1))
 
-static inline void
+static void
 am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
 {
 	offset = ISAMEM_BASE + (offset << 1);
 	length = (length + 1) & ~1;
 	if ((int)buf & 2) {
-		__asm__ __volatile__("str%?h	%2, [%0], #4"
+		asm volatile("str%?h	%2, [%0], #4"
 		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
 		buf += 2;
 		length -= 2;
 	}
 	while (length > 8) {
-		unsigned int tmp, tmp2;
-		__asm__ __volatile__(
-			"ldm%?ia	%1!, {%2, %3}\n\t"
+		register unsigned int tmp asm("r2"), tmp2 asm("r3");
+		asm volatile(
+			"ldm%?ia	%0!, {%1, %2}"
+			: "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
+		length -= 8;
+		asm volatile(
+			"str%?h	%1, [%0], #4\n\t"
+			"mov%?	%1, %1, lsr #16\n\t"
+			"str%?h	%1, [%0], #4\n\t"
 			"str%?h	%2, [%0], #4\n\t"
 			"mov%?	%2, %2, lsr #16\n\t"
-			"str%?h	%2, [%0], #4\n\t"
-			"str%?h	%3, [%0], #4\n\t"
-			"mov%?	%3, %3, lsr #16\n\t"
-			"str%?h	%3, [%0], #4"
-		: "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
-		: "0" (offset), "1" (buf));
-		length -= 8;
+			"str%?h	%2, [%0], #4"
+		: "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
 	}
 	while (length > 0) {
-		__asm__ __volatile__("str%?h	%2, [%0], #4"
+		asm volatile("str%?h	%2, [%0], #4"
 		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
 		buf += 2;
 		length -= 2;
 	}
 }
 
-static inline void
+static void
 am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
 {
 	offset = ISAMEM_BASE + (offset << 1);
@@ -140,12 +141,12 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
 		length -= 2;
 	}
 	while (length > 8) {
-		unsigned int tmp, tmp2, tmp3;
+		register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
 		asm volatile(
 			"ldr%?h	%2, [%0], #4\n\t"
+			"ldr%?h	%4, [%0], #4\n\t"
 			"ldr%?h	%3, [%0], #4\n\t"
-			"orr%?	%2, %2, %3, lsl #16\n\t"
-			"ldr%?h	%3, [%0], #4\n\t"
+			"orr%?	%2, %2, %4, lsl #16\n\t"
 			"ldr%?h	%4, [%0], #4\n\t"
 			"orr%?	%3, %3, %4, lsl #16\n\t"
 			"stm%?ia	%1!, {%2, %3}"
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver
  2011-06-10 10:51 [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver Russell King
                   ` (2 preceding siblings ...)
  2011-06-10 10:52 ` [PATCH 3/3] NET: am79c961: fix assembler warnings Russell King - ARM Linux
@ 2011-06-11 22:56 ` David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2011-06-11 22:56 UTC (permalink / raw)
  To: rmk; +Cc: netdev

From: Russell King <rmk@arm.linux.org.uk>
Date: Fri, 10 Jun 2011 11:51:22 +0100

> This series of patches fix some of the more serious issues discovered
> with GCC 4 and the ARM EBSA110 am79c961 ethernet driver last weekend
> while upgrading my firewall to 2.6.39.

All applied to net-2.6, thanks Russell.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-06-11 22:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-10 10:51 [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver Russell King
2011-06-10 10:51 ` [PATCH 1/3] NET: am79c961: ensure asm() statements are marked volatile Russell King - ARM Linux
2011-06-10 10:52 ` [PATCH 2/3] NET: am79c961: ensure multicast filter is correctly set at open Russell King - ARM Linux
2011-06-10 10:52 ` [PATCH 3/3] NET: am79c961: fix assembler warnings Russell King - ARM Linux
2011-06-11 22:56 ` [PATCH 0/3] Fixes for ARM/ebsa110 am79c961 driver David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).