Netdev List
 help / color / mirror / Atom feed
* [RFC 3/3] TCP: htcp - use measured rtt
From: Stephen Hemminger @ 2007-07-19  7:41 UTC (permalink / raw)
  To: David S. Miller; +Cc: Sangtae Ha, Luca De Cicco, Gavin McCullagh, netdev
In-Reply-To: <20070719074129.670215301@linux-foundation.org>

[-- Attachment #1: htcp-fix.patch --]
[-- Type: text/plain, Size: 1447 bytes --]

Change HTCP to use measured RTT rather than smooth RTT.
Srtt is computed using the TCP receive timestamp
options, so it is vulnerable to hostile receivers. To avoid any problems
this might cause use the measured RTT instead.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>

--- a/net/ipv4/tcp_htcp.c	2007-07-19 08:26:40.000000000 +0100
+++ b/net/ipv4/tcp_htcp.c	2007-07-19 08:28:07.000000000 +0100
@@ -76,12 +76,11 @@ static u32 htcp_cwnd_undo(struct sock *s
 	return max(tp->snd_cwnd, (tp->snd_ssthresh << 7) / ca->beta);
 }
 
-static inline void measure_rtt(struct sock *sk)
+static inline void measure_rtt(struct sock *sk, u32 srtt)
 {
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 	const struct tcp_sock *tp = tcp_sk(sk);
 	struct htcp *ca = inet_csk_ca(sk);
-	u32 srtt = tp->srtt >> 3;
 
 	/* keep track of minimum RTT seen so far, minRTT is zero at first */
 	if (ca->minRTT > srtt || !ca->minRTT)
@@ -108,6 +107,9 @@ static void measure_achieved_throughput(
 	if (icsk->icsk_ca_state == TCP_CA_Open)
 		ca->pkts_acked = pkts_acked;
 
+	if (rtt > 0)
+		measure_rtt(sk, usecs_to_jiffies(rtt));
+
 	if (!use_bandwidth_switch)
 		return;
 
@@ -237,8 +239,6 @@ static void htcp_cong_avoid(struct sock 
 	if (tp->snd_cwnd <= tp->snd_ssthresh)
 		tcp_slow_start(tp);
 	else {
-		measure_rtt(sk);
-
 		/* In dangerous area, increase slowly.
 		 * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd
 		 */

-- 


^ permalink raw reply

* [RFC 0/3] TCP congestion control RTT patches
From: Stephen Hemminger @ 2007-07-19  7:41 UTC (permalink / raw)
  To: David S. Miller; +Cc: Sangtae Ha, Luca De Cicco, Gavin McCullagh, netdev

These patches deal with issues brought up by Gavin McCullagh
about reactions of Cubic and HTCP to hostile receivers that return
bogus timestamp options. In a couple of places the timestamp value
is used in ways that could cause unfairness.

The solution in these patches is to only use local values to measure
RTT for congestion control.  The timestamp is still used as described
in RFC's to measure RTT used for retransmit timer.

This code is preliminary and not throughly tested yet. It could
be backported to 2.6.22 for stable kernels, but it would be hard to
go back to earlier kernels because it builds on the recent TCP congestion
control API changes.

-- 


^ permalink raw reply

* Re: [PATCH] net/, drivers/net/ , missing EXPERIMENTAL in menus
From: Robert P. J. Day @ 2007-07-19  7:33 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: Jeff Garzik, Randy Dunlap, Gabriel C, Linux Kernel Mailing List,
	netdev
In-Reply-To: <20070719054742.GN3801@stusta.de>

On Thu, 19 Jul 2007, Adrian Bunk wrote:

...
> I would consider it more ugly to special case this and that in the
> kconfig code when plain dependencies already offer exactly the same
> functionality...

well, this is the *third* time i've proposed adding this kind of
feature so, at this point, i've really given up caring about it.  if
someone wants to do this, have at it.  i have better things to do than
to keep suggesting it and getting nowhere with it.

rday
--
========================================================================
Robert P. J. Day Linux Consulting, Training and Annoying Kernel
Pedantry Waterloo, Ontario, CANADA

http://fsdev.net/wiki/index.php?title=Main_Page
========================================================================

^ permalink raw reply

* Re: Socket Buffers and Memory Managment
From: pradeep singh @ 2007-07-19  7:04 UTC (permalink / raw)
  To: vinay ravuri; +Cc: Stephen Hemminger, netdev
In-Reply-To: <261750.43078.qm@web82911.mail.mud.yahoo.com>

On 7/19/07, vinay ravuri <vinaynyc@yahoo.com> wrote:
> How about the following approach:
>
> I allocate an skb of 0 bytes and replace data element
> of skb struct (i.e. skb.data = addr_given_by_hw) when
> the h/w interrupts me with a packet.  I register for a
> destructor for this skb and when the kernel is ready
> to free the skb, I make sure that my free is invoked -
> Ofcourse this is assuming that their is a facility in
> linux socket buffers to be able to do destructors.  Is
> this approach a viable, if so, are any gottcha's?

I wonder if passing a zero size will work correctly with
alloc_skb/__alloc_skb as you still have just skb frag list to work
with in this case.
And as Stephen pointed out, if i understand correctly that would be
still a problem.

yes/no?

thanks
--pradeep
>
> -Vinay
>
>
> --- Stephen Hemminger
> <shemminger@linux-foundation.org> wrote:
>
> > On Tue, 17 Jul 2007 10:20:58 -0700 (PDT)
> > vinay ravuri <vinaynyc@yahoo.com> wrote:
> >
> > > Hi,
> > >
> > > I am fairly new to linux socket buffers and have
> > the
> > > following questions!
> > >
> > > I am working with a custom ethernet MAC that does
> > not
> > > allow me to specify a particular memory location
> > for
> > > the h/w to DMA the packet into (Rx side).
> > Instead, it
> > > has a pool of fixed size buffers with some h/w
> > > specific headers around each buffer that are
> > managed
> > > by h/w and will pick a free buffer and DMA the
> > packet.
> >
> > Sounds like sucky hardware...
> > You need to copy to a newly allocated skb, see
> > 8139too.c
> >
> > >  It appears dev_alloc_skb() actually allocates the
> > > physical memory and doesn't allow the user to
> > specify
> > > the skb.data to something specific to what I want
> > > which is a problem for me.  First is my assumption
> > > correct that I am cannot pick an arbitrary
> > skb.data
> > > location in struct sk_buff?  I want to avoid
> > copying
> > > the dma'ed data into a new socket buffer as it is
> > > expense.  Is there any ways around this problem?
> >
> > You could play tricks with skb frags but it would be
> > fragile
> > and not worth the trouble. The problem is that the
> > receive
> > skb can stay in the system for a really long time
> > (until the application
> > reads the data) so your fixed size buffer pool in
> > hardware
> > would get exhausted.
> >
> > > Also, if the h/w gives me a single packet in
> > multiple
> > > locations (i.e. non-contiguous chunks of memory),
> > can
> > > socket buffers handle chains of buffers?  I am
> > looking
> > > for a facility like mbuf's in netbsd where one can
> > > chain multiple buffers together to make construct
> > a
> > > single packet.
> >
> > Yes, skb frag list could be used for that but you
> > don't
> > want to do that. See above. Copy the data into an
> > new
> > skb and reserve any necessary bytes so IP header is
> > aligned.  I.e. if using ethernet header (14 bytes),
> > do
> > skb_reserve(skb, 2) before copying the data.
> >
>
>
>
>
> ____________________________________________________________________________________
> Looking for a deal? Find great prices on flights and hotels with Yahoo! FareChase.
> http://farechase.yahoo.com/
> -
> 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
>


-- 
Pradeep

^ permalink raw reply

* Re: Socket Buffers and Memory Managment
From: vinay ravuri @ 2007-07-19  6:51 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20070717204129.79e7fe0d@oldman>

How about the following approach:

I allocate an skb of 0 bytes and replace data element
of skb struct (i.e. skb.data = addr_given_by_hw) when
the h/w interrupts me with a packet.  I register for a
destructor for this skb and when the kernel is ready
to free the skb, I make sure that my free is invoked -
Ofcourse this is assuming that their is a facility in
linux socket buffers to be able to do destructors.  Is
this approach a viable, if so, are any gottcha's?

-Vinay


--- Stephen Hemminger
<shemminger@linux-foundation.org> wrote:

> On Tue, 17 Jul 2007 10:20:58 -0700 (PDT)
> vinay ravuri <vinaynyc@yahoo.com> wrote:
> 
> > Hi,
> > 
> > I am fairly new to linux socket buffers and have
> the
> > following questions!
> > 
> > I am working with a custom ethernet MAC that does
> not
> > allow me to specify a particular memory location
> for
> > the h/w to DMA the packet into (Rx side). 
> Instead, it
> > has a pool of fixed size buffers with some h/w
> > specific headers around each buffer that are
> managed
> > by h/w and will pick a free buffer and DMA the
> packet.
> 
> Sounds like sucky hardware...
> You need to copy to a newly allocated skb, see
> 8139too.c
> 
> >  It appears dev_alloc_skb() actually allocates the
> > physical memory and doesn't allow the user to
> specify
> > the skb.data to something specific to what I want
> > which is a problem for me.  First is my assumption
> > correct that I am cannot pick an arbitrary
> skb.data
> > location in struct sk_buff?  I want to avoid
> copying
> > the dma'ed data into a new socket buffer as it is
> > expense.  Is there any ways around this problem?
> 
> You could play tricks with skb frags but it would be
> fragile
> and not worth the trouble. The problem is that the
> receive
> skb can stay in the system for a really long time
> (until the application
> reads the data) so your fixed size buffer pool in
> hardware
> would get exhausted.
>  
> > Also, if the h/w gives me a single packet in
> multiple
> > locations (i.e. non-contiguous chunks of memory),
> can
> > socket buffers handle chains of buffers?  I am
> looking
> > for a facility like mbuf's in netbsd where one can
> > chain multiple buffers together to make construct
> a
> > single packet.
> 
> Yes, skb frag list could be used for that but you
> don't
> want to do that. See above. Copy the data into an
> new
> skb and reserve any necessary bytes so IP header is
> aligned.  I.e. if using ethernet header (14 bytes),
> do
> skb_reserve(skb, 2) before copying the data.
> 



       
____________________________________________________________________________________
Looking for a deal? Find great prices on flights and hotels with Yahoo! FareChase.
http://farechase.yahoo.com/

^ permalink raw reply

* Re: ~3 hours old git tree: Virtual device lo asks to queue packet!
From: Arkadiusz Miskiewicz @ 2007-07-19  6:19 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netdev
In-Reply-To: <469E9CF7.1040403@trash.net>

On Thursday 19 of July 2007, Patrick McHardy wrote:
> Arkadiusz Miskiewicz wrote:
> > I'm having problems with networking on recent git kernel.
> >
> > kernel logs tons of "Virtual device lo asks to queue packet!"
> > and networking stops working correctly:
> >
> > CONFIG_NETDEVICES_MULTIQUEUE=y
>
> Does it go away if you disable this option?

Yes, it goes away after disabling this.

-- 
Arkadiusz Miśkiewicz        PLD/Linux Team
arekm / maven.pl            http://ftp.pld-linux.org/

^ permalink raw reply

* Re: [PATCH] net/, drivers/net/ , missing EXPERIMENTAL in menus
From: Adrian Bunk @ 2007-07-19  5:47 UTC (permalink / raw)
  To: Robert P. J. Day
  Cc: Jeff Garzik, Randy Dunlap, Gabriel C, Linux Kernel Mailing List,
	netdev
In-Reply-To: <Pine.LNX.4.64.0707181712340.16513@localhost.localdomain>

On Wed, Jul 18, 2007 at 05:18:20PM -0400, Robert P. J. Day wrote:
> On Wed, 18 Jul 2007, Adrian Bunk wrote:
> 
> > On Wed, Jul 18, 2007 at 04:51:33PM -0400, Robert P. J. Day wrote:
> > > On Wed, 18 Jul 2007, Jeff Garzik wrote:
> > >
> > > > Randy Dunlap wrote:
> > > > > On Wed, 18 Jul 2007 16:23:09 -0400 (EDT) Robert P. J. Day wrote:
> > > > > > there's no point adding all that redundant content when it can all be
> > > > > > done automatically.
> > > > >
> > > > > I like it.  Are there any kconfig patches to support this plan?
> > > >
> > > > Speaking specifically to adding 'EXPERIMENTAL', I distinctly
> > > > remember at some point in the past the config system was smart
> > > > enough to print " (EXPERIMENTAL)" if that entry depended on
> > > > CONFIG_EXPERIMENTAL.
> > > >
> > > > We should head in that direction.
> > >
> > > there's one point i want to re-iterate.  i'd prefer to see
> > > EXPERIMENTAL stop being a dependency, as in:
> > >
> > >   depends on SNAFU && FUBAR && EXPERIMENTAL
> > >
> > > "EXPERIMENTAL" is not a dependency in the true sense of the word
> > > -- it is more of an attribute, and i think it would far more sense
> > > to see entries like:
> > >
> > >   depends on SNAFU && FUBAR
> > >   maturity EXPERIMENTAL
> >
> > Plus some special case in the kconfig code that you can somewhere
> > select the maturity levels you want to use (currently it's a normal
> > option kconfig doesn't have to know anything about).
> 
> i already described that here:
> 
> http://readlist.com/lists/vger.kernel.org/linux-kernel/66/334172.html
> 
> where the top-level config would look something like:
> 
> [*] Activate maturity attributes
>   [*] EXPERIMENTAL
>   [*] DEPRECATED
>   [*] OBSOLETE
>   [*] BROKEN

We already made the mistake of offering BROKEN as an option in the past, 
and the result was that people enabled it instead of reporting that a 
dependency on BROKEN was wrong.

> whereupon you could select any combination of the attributes you want
> displayed *beyond the regular ones* during the config process.
> 
> > Remind me, would there be any big advantage after such a change
> > besides being able to automatically print " (EXPERIMENTAL)" at the
> > end of the prompt?
> 
> defining a new Kconfig attribute means you can process it differently
> from regular dependencies.  and if it's added as a general feature, it
> can be used for other possible attributes beyond just a maturity
> level.
> 
> if you leave these maturity levels as regular dependencies, you're
> going to have to brute force and manually process them, and why make
> it that ugly?

I would consider it more ugly to special case this and that in the 
kconfig code when plain dependencies already offer exactly the same 
functionality...

> rday

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed


^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [1/8]
From: Steven J. Hill @ 2007-07-19  4:47 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 142 bytes --]

This first patch 642xx #defines to the 'include/linux/mv643xx.h' file.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 01-mv643xx-64260-linux-header.patch --]
[-- Type: text/x-patch; name="01-mv643xx-64260-linux-header.patch", Size: 9484 bytes --]

--- linux-2.6.22.1/include/linux/mv643xx.h	2007-05-10 15:16:24.000000000 -0500
+++ linux-2.6.22.1-rci/include/linux/mv643xx.h	2007-07-18 15:50:44.000000000 -0500
@@ -666,7 +666,11 @@
 #define MV643XX_ETH_SHARED_REGS_SIZE                                0x2000
 
 #define MV643XX_ETH_PHY_ADDR_REG                                    0x2000
+#ifdef CONFIG_GT64260
+#define MV643XX_ETH_SMI_REG                                         0x2010
+#else
 #define MV643XX_ETH_SMI_REG                                         0x2004
+#endif
 #define MV643XX_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
 #define MV643XX_ETH_UNIT_DEFAULTID_REG                              0x200c
 #define MV643XX_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
@@ -693,6 +697,21 @@
 #define MV643XX_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
 #define MV643XX_ETH_BASE_ADDR_ENABLE_REG                            0x2290
 #define MV643XX_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
+#ifdef CONFIG_GT64260
+#define MV643XX_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
+#define MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2408 + (port<<10))
+#define MV643XX_ETH_PORT_STATUS_REG(port)                          (0x2418 + (port<<10))
+#define GT64260_ETH_HASH_TABLE_POINTER_REG(port)                   (0x2428 + (port<<10))
+#define MV643XX_ETH_SDMA_CONFIG_REG(port)                          (0x2440 + (port<<10))
+#define MV643XX_ETH_SDMA_COMMAND_REG(port)                         (0x2448 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2450 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_MASK_REG(port)                       (0x2458 + (port<<10))
+#define MV643XX_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2470 + (port<<10))
+#define MV643XX_ETH_RX_FIRST_QUEUE_DESC_PTR_0(port)                (0x2480 + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x24a0 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x24e0 + (port<<10))
+#define MV643XX_ETH_MIB_COUNTERS_BASE(port)                        (0x2500 + (port<<7))
+#else
 #define MV643XX_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
 #define MV643XX_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
 #define MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
@@ -775,6 +794,7 @@
 #define MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
 #define MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
 #define MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
+#endif
 
 /*******************************************/
 /*          CUNIT  Registers               */
@@ -1094,6 +1114,45 @@
 };
 
 /* These macros describe Ethernet Port configuration reg (Px_cR) bits */
+#define GT64260_ETH_RECEIVE_BC			0
+#define GT64260_ETH_REJECT_BC			(1<<1)
+#define GT64260_ETH_REJECT_BAD_FRAMES		0
+#define GT64260_ETH_RECEIVE_BAD_FRAMES		(1<<2)
+#define GT64260_ETH_DISABLE			0
+#define GT64260_ETH_ENABLE			(1<<7)
+#define GT64260_ETH_CLR_INT_LOOPBACK		0
+#define GT64260_ETH_SET_INT_LOOPBACK		(1<<8)
+#define GT64260_ETH_CLR_EXT_LOOPBACK		0
+#define GT64260_ETH_SET_EXT_LOOPBACK		(1<<9)
+#define GT64260_ETH_DISABLE_FORCE_COLLISION	0
+#define GT64260_ETH_ENABLE_FORCE_COLLISION	(1<<10)
+#define GT64260_ETH_HASH_SIZE_HALFK		0
+#define GT64260_ETH_HASH_SIZE_8K		(1<<12)
+#define GT64260_ETH_HASH_SIZE_SHIFT		12
+#define GT64260_ETH_HASH_MODE_0			0
+#define GT64260_ETH_HASH_MODE_1			(1<<13)
+#define GT64260_ETH_HASH_MODE_SHIFT		13
+#define GT64260_ETH_HASH_DEFAULT_DISCARD	0
+#define GT64260_ETH_HASH_DEFAULT_PASS		(1<<14)
+#define GT64260_ETH_HASH_DEFAULT_SHIFT		14
+#define GT64260_ETH_SET_HALF_DUPLEX_MODE	0
+#define GT64260_ETH_SET_FULL_DUPLEX_MODE	(1<<15)
+#define GT64260_ETH_DISABLE_ACCEL_SLOT_TIME	0
+#define GT64260_ETH_ENABLE_ACCEL_SLOT_TIME	(1<<31)
+
+#define	GT64260_ETH_PORT_CONFIG_DEFAULT_VALUE			\
+		GT64260_ETH_RECEIVE_BC			|	\
+		GT64260_ETH_REJECT_BAD_FRAMES		|	\
+		GT64260_ETH_DISABLE			|	\
+		GT64260_ETH_CLR_INT_LOOPBACK		|	\
+		GT64260_ETH_CLR_EXT_LOOPBACK		|	\
+		GT64260_ETH_DISABLE_FORCE_COLLISION	|	\
+		GT64260_ETH_HASH_SIZE_HALFK		|	\
+		GT64260_ETH_HASH_MODE_0			|	\
+		GT64260_ETH_HASH_DEFAULT_DISCARD	|	\
+		GT64260_ETH_SET_FULL_DUPLEX_MODE	|	\
+		GT64260_ETH_DISABLE_ACCEL_SLOT_TIME
+
 #define MV643XX_ETH_UNICAST_NORMAL_MODE		0
 #define MV643XX_ETH_UNICAST_PROMISCUOUS_MODE	(1<<0)
 #define MV643XX_ETH_DEFAULT_RX_QUEUE_0		0
@@ -1162,6 +1221,59 @@
 		MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0
 
 /* These macros describe Ethernet Port configuration extend reg (Px_cXR) bits*/
+#define GT64260_ETH_IGMP_CAPTURE_ENABLE			0
+#define GT64260_ETH_IGMP_CAPTURE_DISABLE		(1<<0)
+#define GT64260_ETH_BPDU_PACKETS_AS_NORMAL		0
+#define GT64260_ETH_BPDU_PACKETS_TO_RX_QUEUE		(1<<1)
+#define GT64260_ETH_PARTITION_DISABLE			0
+#define GT64260_ETH_PARTITION_ENABLE			(1<<2)
+#define GT64260_ETH_PARTITION_DISABLE			0
+#define GT64260_ETH_TX_PRIORITY_1_HIGH_1_LOW		0
+#define GT64260_ETH_TX_PRIORITY_2_HIGH_1_LOW		(0x1<<3)
+#define GT64260_ETH_TX_PRIORITY_4_HIGH_1_LOW		(0x2<<3)
+#define GT64260_ETH_TX_PRIORITY_6_HIGH_1_LOW		(0x3<<3)
+#define GT64260_ETH_TX_PRIORITY_8_HIGH_1_LOW		(0x4<<3)
+#define GT64260_ETH_TX_PRIORITY_10_HIGH_1_LOW		(0x5<<3)
+#define GT64260_ETH_TX_PRIORITY_12_HIGH_1_LOW		(0x6<<3)
+#define GT64260_ETH_TX_PRIORITY_ALL_HIGH_0_LOW		(0x7<<3)
+#define GT64260_ETH_TX_PRIORITY_MASK			(0x7<<3)
+#define GT64260_ETH_RX_PRIORITY_LOWEST			0
+#define GT64260_ETH_RX_PRIORITY_HIGHEST			(0x3<<6)
+#define GT64260_ETH_RX_PRIORITY_OVERRIDE_DISABLE	0
+#define GT64260_ETH_RX_PRIORITY_OVERRIDE_ENABLE		(1<<8)
+#define GT64260_ETH_ENABLE_AUTO_NEG_FOR_DPLX		0
+#define GT64260_ETH_DISABLE_AUTO_NEG_FOR_DPLX		(1<<9)
+#define GT64260_ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL	0
+#define GT64260_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL	(1<<10)
+#define GT64260_ETH_FORCE_LINK_PASS			0
+#define GT64260_ETH_DO_NOT_FORCE_LINK_PASS		(1<<11)
+#define GT64260_ETH_DISABLE_FLOW_CTRL			0
+#define GT64260_ETH_ENABLE_FLOW_CTRL			(1<<12)
+/* Bit 13 is reserved. */
+#define GT64260_ETH_MAX_RX_PACKET_1518BYTE		0
+#define GT64260_ETH_MAX_RX_PACKET_1536BYTE		(0x1<<14)
+#define GT64260_ETH_MAX_RX_PACKET_2048BYTE		(0x2<<14)
+#define GT64260_ETH_MAX_RX_PACKET_64KBYTE		(0x3<<14)
+#define GT64260_ETH_MAX_RX_PACKET_MASK			(0x7<<14)
+#define GT64260_ETH_CLR_MIB_COUNTERS			0
+/* Bit 17 is undocumented. */
+#define GT64260_ETH_SET_SPEED_TO_10			0
+#define GT64260_ETH_SET_SPEED_TO_100			(1<<18)
+#define GT64260_ETH_ENABLE_AUTONEG_FOR_SPEED		0
+#define GT64260_ETH_DISABLE_AUTONEG_FOR_SPEED		(1<<19)
+#define GT64260_ETH_ENABLE_MII				0
+#define GT64260_ETH_ENABLE_RMII				(1<<20)
+#define GT64260_ETH_DISABLE_DSCP			0
+#define GT64260_ETH_ENABLE_DSCP				(1<<21)
+/* Bits 22 - 31 are reserved. */
+
+#define	GT64260_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE		\
+		GT64260_ETH_RX_PRIORITY_OVERRIDE_ENABLE	|	\
+		GT64260_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |	\
+		GT64260_ETH_DO_NOT_FORCE_LINK_PASS	|	\
+		GT64260_ETH_MAX_RX_PACKET_1536BYTE	|	\
+		GT64260_ETH_ENABLE_RMII
+
 #define MV643XX_ETH_CLASSIFY_EN				(1<<0)
 #define MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL		0
 #define MV643XX_ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7	(1<<1)
@@ -1173,6 +1285,23 @@
 		MV643XX_ETH_PARTITION_DISABLE
 
 /* These macros describe Ethernet Port Sdma configuration reg (SDCR) bits */
+#define GT64260_ETH_RETRANSMIT_COUNT_MASK		(0xf<<2)
+#define GT64260_ETH_BLM_RX_NO_SWAP			0
+#define GT64260_ETH_BLM_RX_BYTE_SWAP			(1<<6)
+#define GT64260_ETH_BLM_TX_NO_SWAP			0
+#define GT64260_ETH_BLM_TX_BYTE_SWAP			(1<<7)
+#define GT64260_ETH_PCI_OVERRIDE			(1<<8)
+#define GT64260_ETH_RIFB				(1<<9)
+#define GT64260_ETH_BURST_SIZE_1_64BIT			(0x0<<12)
+#define GT64260_ETH_BURST_SIZE_2_64BIT			(0x1<<12)
+#define GT64260_ETH_BURST_SIZE_4_64BIT			(0x2<<12)
+#define GT64260_ETH_BURST_SIZE_8_64BIT			(0x3<<12)
+
+#define	GT64260_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE		\
+		GT64260_ETH_RETRANSMIT_COUNT_MASK	|	\
+		GT64260_ETH_RIFB			|	\
+		GT64260_ETH_BURST_SIZE_4_64BIT
+
 #define MV643XX_ETH_RIFB			(1<<0)
 #define MV643XX_ETH_RX_BURST_SIZE_1_64BIT		0
 #define MV643XX_ETH_RX_BURST_SIZE_2_64BIT		(1<<1)
@@ -1198,6 +1327,13 @@
 		MV643XX_ETH_IPG_INT_RX(0)		|	\
 		MV643XX_ETH_TX_BURST_SIZE_4_64BIT
 
+/* These macros describe Ethernet Port Sdma command reg (SDCMR) bits */
+#define GT64260_ETH_ENABLE_RX_DMA			(1<<7)
+#define GT64260_ETH_ABORT_RX_DMA			(1<<15)
+#define GT64260_ETH_START_TX_HIGH			(1<<23)
+#define GT64260_ETH_START_TX_LOW			(1<<24)
+#define GT64260_ETH_ABORT_TX_DMA			(1<<31)
+
 /* These macros describe Ethernet Port serial control reg (PSCR) bits */
 #define MV643XX_ETH_SERIAL_PORT_DISABLE			0
 #define MV643XX_ETH_SERIAL_PORT_ENABLE			(1<<0)
@@ -1279,7 +1417,10 @@
 #define MV643XX_ETH_PORT_STATUS_TX_FIFO_EMPTY		(1<<10)
 /* PSR bits 11-31 are reserved */
 
+/* Default TX ring size is 800 descriptors */
 #define	MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE	800
+
+/* Default RX ring size is 400 descriptors */
 #define	MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE	400
 
 #define MV643XX_ETH_DESC_SIZE				64

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [2/8]
From: Steven J. Hill @ 2007-07-19  4:49 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 144 bytes --]

Add #defines for RGMII Discovery II/III in 'include/linux/mv643xx.h' file.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 02-mv643xx-add-rgmii-defines.patch --]
[-- Type: text/x-patch; name="02-mv643xx-add-rgmii-defines.patch", Size: 500 bytes --]

--- linux-2.6.22.1/include/linux/mv643xx.h	2007-05-10 15:16:24.000000000 -0500
+++ linux-2.6.22.1-rci/include/linux/mv643xx.h	2007-07-18 15:50:44.000000000 -0500
@@ -1243,6 +1379,8 @@
 #define MV643XX_ETH_SET_GMII_SPEED_TO_1000		(1<<23)
 #define MV643XX_ETH_SET_MII_SPEED_TO_10			0
 #define MV643XX_ETH_SET_MII_SPEED_TO_100		(1<<24)
+#define MV643XX_ETH_SET_RGMII_TX_DELAY			(1<<26)
+#define MV643XX_ETH_SET_RGMII_RX_DELAY			(1<<27)
 
 #define MV643XX_ETH_MAX_RX_PACKET_MASK			(0x7<<17)
 

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [3/8]
From: Steven J. Hill @ 2007-07-19  4:51 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 118 bytes --]

Add 642xx support to 'drivers/net/mv643xx_eth.h'

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 03-mv643xx-64260-driver-header.patch --]
[-- Type: text/x-patch; name="03-mv643xx-64260-driver-header.patch", Size: 10091 bytes --]

--- linux-2.6.22.1/drivers/net/mv643xx_eth.h	2007-07-11 08:53:06.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.h	2007-07-11 09:28:16.000000000 -0500
@@ -14,8 +14,13 @@
 /* Checksum offload for Tx works for most packets, but
  * fails if previous packet sent did not use hw csum
  */
+#ifdef CONFIG_GT64260
+#undef	MV643XX_CHECKSUM_OFFLOAD_TX
+#undef	MV643XX_NAPI
+#else
 #define	MV643XX_CHECKSUM_OFFLOAD_TX
 #define	MV643XX_NAPI
+#endif
 #define	MV643XX_TX_FAST_REFILL
 #undef	MV643XX_COAL
 
@@ -54,17 +59,31 @@
 #define ETH_RX_QUEUES_ENABLED	(1 << 0)	/* use only Q0 for receive */
 #define ETH_TX_QUEUES_ENABLED	(1 << 0)	/* use only Q0 for transmit */
 
+#ifdef CONFIG_GT64260
+#define ETH_INT_CAUSE_RX_DONE	(ETH_RX_QUEUES_ENABLED << 16)
+#define ETH_INT_CAUSE_RX_ERROR	(ETH_RX_QUEUES_ENABLED << 20)
+#define ETH_INT_CAUSE_RX	(ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
+#define ETH_INT_UNMASK_ALL	0x30ff010d
+#else
 #define ETH_INT_CAUSE_RX_DONE	(ETH_RX_QUEUES_ENABLED << 2)
 #define ETH_INT_CAUSE_RX_ERROR	(ETH_RX_QUEUES_ENABLED << 9)
 #define ETH_INT_CAUSE_RX	(ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
 #define ETH_INT_CAUSE_EXT	0x00000002
 #define ETH_INT_UNMASK_ALL	(ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT)
+#endif
 
+#ifdef CONFIG_GT64260
+#define ETH_INT_CAUSE_TX_DONE	(ETH_TX_QUEUES_ENABLED << 2)
+#define ETH_INT_CAUSE_TX_ERROR	(ETH_TX_QUEUES_ENABLED << 10)
+#define ETH_INT_CAUSE_TX	(ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
+#define ETH_INT_CAUSE_PHY	0x10000000
+#else
 #define ETH_INT_CAUSE_TX_DONE	(ETH_TX_QUEUES_ENABLED << 0)
 #define ETH_INT_CAUSE_TX_ERROR	(ETH_TX_QUEUES_ENABLED << 8)
 #define ETH_INT_CAUSE_TX	(ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
 #define ETH_INT_CAUSE_PHY	0x00010000
 #define ETH_INT_UNMASK_ALL_EXT	(ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY)
+#endif
 
 #define ETH_INT_MASK_ALL	0x00000000
 #define ETH_INT_MASK_ALL_EXT	0x00000000
@@ -73,11 +92,42 @@
 #define PHY_WAIT_MICRO_SECONDS	10
 
 /* Buffer offset from buffer pointer */
+#ifdef CONFIG_GT64260
+#define RX_BUF_OFFSET				0x4
+#else
 #define RX_BUF_OFFSET				0x2
+#endif
 
 /* Gigabit Ethernet Unit Global Registers */
 
 /* MIB Counters register definitions */
+#ifdef CONFIG_GT64260
+#define ETH_MIB_OCTETS_RECEIVED			0x0
+#define ETH_MIB_OCTETS_SENT			0x4
+#define ETH_MIB_FRAMES_RECEIVED			0x8
+#define ETH_MIB_FRAMES_SENT			0xc
+#define ETH_MIB_TOTAL_OCTETS_RECEIVED		0x10
+#define ETH_MIB_TOTAL_FRAMES_RECEIVED		0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED	0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED	0x1c
+#define ETH_MIB_BAD_CRC_EVENT			0x20
+#define ETH_MIB_OVERSIZE_RECEIVED		0x24
+#define ETH_MIB_FRAGMENTS_RECEIVED		0x28
+#define ETH_MIB_JABBER_RECEIVED			0x2c
+#define ETH_MIB_COLLISION			0x30
+#define ETH_MIB_LATE_COLLISION			0x34
+#define ETH_MIB_FRAMES_64_OCTETS		0x38
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS		0x3c
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS	0x40
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS	0x44
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS	0x48
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS	0x4c
+#define ETH_MIB_MAC_RECEIVE_ERROR		0x50
+#define ETH_MIB_DROPPED_FRAMES			0x54
+#define ETH_MIB_MULTICAST_FRAMES_SENT		0x58
+#define ETH_MIB_BROADCAST_FRAMES_SENT		0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED		0x60
+#else
 #define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW	0x0
 #define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH	0x4
 #define ETH_MIB_BAD_OCTETS_RECEIVED		0x8
@@ -110,6 +160,7 @@
 #define ETH_MIB_BAD_CRC_EVENT			0x74
 #define ETH_MIB_COLLISION			0x78
 #define ETH_MIB_LATE_COLLISION			0x7c
+#endif
 
 /* Port serial status reg (PSR) */
 #define ETH_INTERFACE_PCM			0x00000001
@@ -134,18 +185,35 @@
 /* SDMA command status fields macros */
 
 /* Tx & Rx descriptors status */
+#ifdef CONFIG_GT64260
+#define ETH_ERROR_SUMMARY			0x00008000
+#else
 #define ETH_ERROR_SUMMARY			0x00000001
+#endif
 
 /* Tx & Rx descriptors command */
 #define ETH_BUFFER_OWNED_BY_DMA			0x80000000
 
 /* Tx descriptors status */
+#ifdef CONFIG_GT64260
+#define ETH_LC_ERROR				0x00000020
+#define ETH_UR_ERROR				0x00000040
+#define ETH_RL_ERROR				0x00000100
+#else
 #define ETH_LC_ERROR				0
 #define ETH_UR_ERROR				0x00000002
 #define ETH_RL_ERROR				0x00000004
 #define ETH_LLC_SNAP_FORMAT			0x00000200
+#endif
 
 /* Rx descriptors status */
+#ifdef CONFIG_GT64260
+#define ETH_OVERRUN_ERROR			0x00000040
+#define ETH_MAX_FRAME_LENGTH_ERROR		0x00000080
+#define ETH_RX_LAST_DESC			0x00010000
+#define ETH_RX_FIRST_DESC			0x00020000
+#define ETH_RX_ENABLE_INTERRUPT			0x00800000
+#else
 #define ETH_OVERRUN_ERROR			0x00000002
 #define ETH_MAX_FRAME_LENGTH_ERROR		0x00000004
 #define ETH_RESOURCE_ERROR			0x00000006
@@ -161,11 +229,19 @@
 #define ETH_UNKNOWN_DESTINATION_ADDR		0x10000000
 #define ETH_RX_ENABLE_INTERRUPT			0x20000000
 #define ETH_LAYER_4_CHECKSUM_OK			0x40000000
+#endif
 
 /* Rx descriptors byte count */
 #define ETH_FRAME_FRAGMENTED			0x00000004
 
 /* Tx descriptors command */
+#ifdef CONFIG_GT64260
+#define ETH_ZERO_PADDING			0x00040000
+#define ETH_TX_LAST_DESC			0x00010000
+#define ETH_TX_FIRST_DESC			0x00020000
+#define ETH_GEN_CRC				0x00400000
+#define ETH_TX_ENABLE_INTERRUPT			0x00800000
+#else
 #define ETH_LAYER_4_CHECKSUM_FIRST_DESC		0x00000400
 #define ETH_FRAME_SET_TO_VLAN			0x00008000
 #define ETH_UDP_FRAME				0x00010000
@@ -177,6 +253,7 @@
 #define ETH_GEN_CRC				0x00400000
 #define ETH_TX_ENABLE_INTERRUPT			0x00800000
 #define ETH_AUTO_MODE				0x40000000
+#endif
 
 #define ETH_TX_IHL_SHIFT			11
 
@@ -204,11 +281,27 @@
  */
 #if defined(__BIG_ENDIAN)
 struct eth_rx_desc {
+# ifdef CONFIG_GT64260
+	u16 buf_size;		/* Buffer size				*/
+	u16 byte_cnt;		/* Descriptor buffer byte count		*/
+	u32 cmd_sts;		/* Descriptor command status		*/
+	u32 next_desc_ptr;	/* Next descriptor pointer		*/
+	u32 buf_ptr;		/* Descriptor buffer pointer		*/
+
+	/*
+	 * Force sizeof(gt64260enetDMAdescriptor) == sizeof(cacheline)
+	 * Not yet sure exactly why this is necessary but the GT64260-B
+	 * part apparently has (yet another) bug that shows itself without
+	 * this padding.  The symptom is that all Enet comms simply stop.
+	 */
+	u32 cachelineSizePadding[4];
+# else
 	u16 byte_cnt;		/* Descriptor buffer byte count		*/
 	u16 buf_size;		/* Buffer size				*/
 	u32 cmd_sts;		/* Descriptor command status		*/
 	u32 next_desc_ptr;	/* Next descriptor pointer		*/
 	u32 buf_ptr;		/* Descriptor buffer pointer		*/
+# endif
 };
 
 struct eth_tx_desc {
@@ -217,15 +310,32 @@
 	u32 cmd_sts;		/* Command/status field			*/
 	u32 next_desc_ptr;	/* Pointer to next descriptor		*/
 	u32 buf_ptr;		/* pointer to buffer for this descriptor*/
+# ifdef CONFIG_GT64260
+	/*
+	 * Force sizeof(gt64260enetDMAdescriptor) == sizeof(cacheline)
+	 * Not yet sure exactly why this is necessary but the GT64260-B
+	 * part apparently has (yet another) bug that shows itself without
+	 * this padding.  The symptom is that all Enet comms simply stop.
+	 */
+	u32 cachelineSizePadding[4];
+# endif
 };
 
 #elif defined(__LITTLE_ENDIAN)
 struct eth_rx_desc {
+# ifdef CONFIG_GT64260
+	u32 cmd_sts;		/* Descriptor command status		*/
+	u16 byte_cnt;		/* Descriptor buffer byte count		*/
+	u16 buf_size;		/* Buffer size				*/
+	u32 buf_ptr;		/* Descriptor buffer pointer		*/
+	u32 next_desc_ptr;	/* Next descriptor pointer		*/
+# else
 	u32 cmd_sts;		/* Descriptor command status		*/
 	u16 buf_size;		/* Buffer size				*/
 	u16 byte_cnt;		/* Descriptor buffer byte count		*/
 	u32 buf_ptr;		/* Descriptor buffer pointer		*/
 	u32 next_desc_ptr;	/* Next descriptor pointer		*/
+# endif
 };
 
 struct eth_tx_desc {
@@ -249,8 +359,53 @@
 	struct sk_buff *return_info;	/* User resource return information */
 };
 
+#ifdef CONFIG_GT64260
+struct eth_hash_table_entry {
+	u32 hi;
+	u32 lo;
+};
+
+#define MAC_ENTRY_SIZE	sizeof(struct eth_hash_table_entry)
+
+/* Cache helper macros */
+#define flush_dcache_addr_size(addr, length)			\
+	flush_dcache_range((u32) addr, (((u32) addr) + length))
+
+#define invalidate_dcache_addr_size(addr, length)			\
+	invalidate_dcache_range((u32) addr, (((u32) addr) + length))
+#endif
+
 /* Ethernet port specific information */
 
+#ifdef CONFIG_GT64260
+struct gt64260_mib_counters {
+	u32 good_octets_received;
+	u32 good_octets_sent;
+	u32 good_frames_received;
+	u32 good_frames_sent;
+	u32 total_octets_received;
+	u32 total_frames_received;
+	u32 broadcast_frames_received;
+	u32 multicast_frames_received;
+	u32 bad_crc_event;
+	u32 oversize_received;
+	u32 fragments_received;
+	u32 jabber_received;
+	u32 collision;
+	u32 late_collision;
+	u32 frames_64_octets;
+	u32 frames_65_to_127_octets;
+	u32 frames_128_to_255_octets;
+	u32 frames_256_to_511_octets;
+	u32 frames_512_to_1023_octets;
+	u32 frames_1024_to_max_octets;
+	u32 mac_receive_error;
+	u32 dropped_frames;
+	u32 multicast_frames_sent;
+	u32 broadcast_frames_sent;
+	u32 undersize_received;
+};
+#else
 struct mv643xx_mib_counters {
 	u64 good_octets_received;
 	u32 bad_octets_received;
@@ -283,6 +438,7 @@
 	u32 collision;
 	u32 late_collision;
 };
+#endif
 
 struct mv643xx_private {
 	int port_num;			/* User Ethernet port number	*/
@@ -294,7 +450,7 @@
 
 	int rx_resource_err;		/* Rx ring resource error flag */
 
-	/* Tx/Rx rings managment indexes fields. For driver use */
+	/* Tx/Rx rings management indexes fields. For driver use */
 
 	/* Next available and first returning Rx resource */
 	int rx_curr_desc_q, rx_used_desc_q;
@@ -319,7 +475,14 @@
 	struct work_struct tx_timeout_task;
 
 	struct net_device_stats stats;
+#ifdef CONFIG_GT64260
+	struct gt64260_mib_counters mib_counters;
+	struct eth_hash_table_entry *eth_hash_table;
+	dma_addr_t eth_hash_table_dma;
+	int eth_hash_table_size;
+#else
 	struct mv643xx_mib_counters mib_counters;
+#endif
 	spinlock_t lock;
 	/* Size of Tx Ring per queue */
 	int tx_ring_size;

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [8/8]
From: Steven J. Hill @ 2007-07-19  5:02 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 134 bytes --]

Fix long standing panic with regards to descriptors and locking.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 08-mv643xx-panic-lock-fix.patch --]
[-- Type: text/x-patch; name="08-mv643xx-panic-lock-fix.patch", Size: 1717 bytes --]

diff -ur linux-2.6.22.1/drivers/net/mv643xx_eth.c linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c
--- linux-2.6.22.1/drivers/net/mv643xx_eth.c	2007-07-18 22:55:11.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c	2007-07-18 22:39:37.000000000 -0500
@@ -350,13 +350,6 @@
 
 	while (mp->tx_desc_count > 0) {
 		spin_lock_irqsave(&mp->lock, flags);
-
-		/* tx_desc_count might have changed before acquiring the lock */
-		if (mp->tx_desc_count <= 0) {
-			spin_unlock_irqrestore(&mp->lock, flags);
-			return released;
-		}
-
 		tx_index = mp->tx_used_desc_q;
 		desc = &mp->p_tx_desc_area[tx_index];
 #ifdef CONFIG_GT64260
@@ -367,7 +360,7 @@
 
 		if (!force && (cmd_sts & ETH_BUFFER_OWNED_BY_DMA)) {
 			spin_unlock_irqrestore(&mp->lock, flags);
-			return released;
+			continue;
 		}
 
 		mp->tx_used_desc_q = (tx_index + 1) % mp->tx_ring_size;
@@ -1488,7 +1481,19 @@
 	BUG_ON(netif_queue_stopped(dev));
 	BUG_ON(skb == NULL);
 
-	if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+	if (mp->tx_ring_size - mp->tx_desc_count <= MAX_DESCS_PER_SKB) {
+		/*
+		 * We are completely out of TX descriptors, however,
+		 * if 'tx_used_desc_q' is zero, most likely the port
+		 * has been configured and is up, but there is no link.
+		 * We attempt to free a single descriptor to keep the
+		 * 'sendto' call and rest of the stack happy. If this
+		 * check is taken out, expect an error and kernel panic
+		 * from 'kernel/softirq.c:141' inside 'local_bh_enable'.
+		 */
+		if (mp->tx_used_desc_q == 0)
+			mv643xx_eth_free_all_tx_descs(dev);
+
 		printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
 		netif_stop_queue(dev);
 		return 1;

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [7/8]
From: Steven J. Hill @ 2007-07-19  4:56 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 101 bytes --]

Get rid of global PHY spinlock.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 07-mv643xx-remove-phy-spinlock.patch --]
[-- Type: text/x-patch; name="07-mv643xx-remove-phy-spinlock.patch", Size: 7997 bytes --]

diff -ur linux-2.6.22.1/drivers/net/mv643xx_eth.c linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c
--- linux-2.6.22.1/drivers/net/mv643xx_eth.c	2007-07-18 22:51:54.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c	2007-07-18 22:39:37.000000000 -0500
@@ -74,7 +74,7 @@
 #endif
 static int ethernet_phy_get(unsigned int eth_port_num);
 static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
-static int ethernet_phy_detect(unsigned int eth_port_num);
+static int ethernet_phy_detect(struct mv643xx_private *mp);
 static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location);
 static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val);
 static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -85,8 +85,6 @@
 
 static void __iomem *mv643xx_eth_shared_base;
 
-/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
-static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
 #ifdef CONFIG_GT64260
 extern struct mv64x60_handle bh;
 static u32 eth_hash_table_size[3] = { 1, 1, 1 };
@@ -936,11 +927,12 @@
 static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
+	unsigned long flags;
 	int err;
 
-	spin_lock_irq(&mp->lock);
+	spin_lock_irqsave(&mp->lock, flags);
 	err = mii_ethtool_sset(&mp->mii, cmd);
-	spin_unlock_irq(&mp->lock);
+	spin_unlock_irqrestore(&mp->lock, flags);
 
 	return err;
 }
@@ -948,11 +940,12 @@
 static int mv643xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
+	unsigned long flags;
 	int err;
 
-	spin_lock_irq(&mp->lock);
+	spin_lock_irqsave(&mp->lock, flags);
 	err = mii_ethtool_gset(&mp->mii, cmd);
-	spin_unlock_irq(&mp->lock);
+	spin_unlock_irqrestore(&mp->lock, flags);
 
 	/* The PHY may support 1000baseT_Half, but the mv643xx does not */
 	cmd->supported &= ~SUPPORTED_1000baseT_Half;
@@ -1594,12 +1599,12 @@
 static int mv643xx_eth_probe(struct platform_device *pdev)
 {
 	struct mv643xx_eth_platform_data *pd;
-	int port_num;
+	unsigned int port_num;
 	struct mv643xx_private *mp;
 	struct net_device *dev;
 	u8 *p;
 	struct resource *res;
-	int err;
+	int err = 0;
 	struct ethtool_cmd cmd;
 	int duplex = DUPLEX_HALF;
 	int speed = 0;			/* default to auto-negotiation */
@@ -1702,7 +1707,7 @@
 	mp->mii.phy_id_mask = 0x3f;
 	mp->mii.reg_num_mask = 0x1f;
 
-	err = ethernet_phy_detect(port_num);
+	err = ethernet_phy_detect(mp);
 	if (err) {
 		pr_debug("MV643xx ethernet port %d: "
 					"No PHY detected at addr %d\n",
@@ -1710,7 +1715,7 @@
 		goto out;
 	}
 
-	ethernet_phy_reset(port_num);
+	ethernet_phy_reset(mp);
 	mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii);
 	mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd);
 	mv643xx_eth_update_pscr(dev, &cmd);
@@ -2158,7 +2163,7 @@
 
 	/* save phy settings across reset */
 	mv643xx_get_settings(dev, &ethtool_cmd);
-	ethernet_phy_reset(mp->port_num);
+	ethernet_phy_reset(mp);
 	mv643xx_set_settings(dev, &ethtool_cmd);
 }
 
@@ -2761,22 +2766,22 @@
  *	-ENODEV on failure
  *
  */
-static int ethernet_phy_detect(unsigned int port_num)
+static int ethernet_phy_detect(struct mv643xx_private *mp)
 {
 	unsigned int phy_reg_data0;
 	int auto_neg;
 
-	eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
+	eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
 	auto_neg = phy_reg_data0 & 0x1000;
 	phy_reg_data0 ^= 0x1000;	/* invert auto_neg */
-	eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
+	eth_port_write_smi_reg(mp, 0, phy_reg_data0);
 
-	eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
+	eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
 	if ((phy_reg_data0 & 0x1000) == auto_neg)
 		return -ENODEV;				/* change didn't take */
 
 	phy_reg_data0 ^= 0x1000;
-	eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
+	eth_port_write_smi_reg(mp, 0, phy_reg_data0);
 	return 0;
 }
 
@@ -2849,19 +2854,19 @@
  *	None.
  *
  */
-static void ethernet_phy_reset(unsigned int eth_port_num)
+static void ethernet_phy_reset(struct mv643xx_private *mp)
 {
 	unsigned int phy_reg_data;
 
 	/* Reset the PHY */
-	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
+	eth_port_read_smi_reg(mp, 0, &phy_reg_data);
 	phy_reg_data |= 0x8000;	/* Set bit 15 to reset the PHY */
-	eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
+	eth_port_write_smi_reg(mp, 0, phy_reg_data);
 
 	/* wait for PHY to come out of reset */
 	do {
 		udelay(1);
-		eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
+		eth_port_read_smi_reg(mp, 0, &phy_reg_data);
 	} while (phy_reg_data & 0x8000);
 }
 
@@ -3033,15 +3038,18 @@
  *	true otherwise.
  *
  */
-static void eth_port_read_smi_reg(unsigned int port_num,
+static void eth_port_read_smi_reg(struct mv643xx_private *mp,
 				unsigned int phy_reg, unsigned int *value)
 {
-	int phy_addr = ethernet_phy_get(port_num);
+	int port_num = mp->port_num;
+	int phy_addr;
 	unsigned long flags;
 	int i;
 
+	phy_addr = ethernet_phy_get(port_num);
+
 	/* the SMI register is a shared resource */
-	spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
+	spin_lock_irqsave(&mp->lock, flags);
 
 	/* wait for the SMI register to become available */
 	for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
@@ -3066,7 +3074,7 @@
 
 	*value = mv_read(MV643XX_ETH_SMI_REG) & 0xffff;
 out:
-	spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
+	spin_unlock_irqrestore(&mp->lock, flags);
 }
 
 /*
@@ -3089,9 +3097,10 @@
  *	true otherwise.
  *
  */
-static void eth_port_write_smi_reg(unsigned int eth_port_num,
+static void eth_port_write_smi_reg(struct mv643xx_private *mp,
 				   unsigned int phy_reg, unsigned int value)
 {
+	int eth_port_num = mp->port_num;
 	int phy_addr;
 	int i;
 	unsigned long flags;
@@ -3099,7 +3108,7 @@
 	phy_addr = ethernet_phy_get(eth_port_num);
 
 	/* the SMI register is a shared resource */
-	spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
+	spin_lock_irqsave(&mp->lock, flags);
 
 	/* wait for the SMI register to become available */
 	for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
@@ -3114,7 +3123,7 @@
 	mv_write(MV643XX_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
 				ETH_SMI_OPCODE_WRITE | (value & 0xffff));
 out:
-	spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
+	spin_unlock_irqrestore(&mp->lock, flags);
 }
 
 /*
@@ -3125,14 +3134,14 @@
 	int val;
 	struct mv643xx_private *mp = netdev_priv(dev);
 
-	eth_port_read_smi_reg(mp->port_num, location, &val);
+	eth_port_read_smi_reg(mp, location, &val);
 	return val;
 }
 
 static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val)
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
-	eth_port_write_smi_reg(mp->port_num, location, val);
+	eth_port_write_smi_reg(mp, location, val);
 }
 
 /*
diff -ur linux-2.6.22.1/drivers/net/mv643xx_eth.h linux-2.6.22.1-rci/drivers/net/mv643xx_eth.h
--- linux-2.6.22.1/drivers/net/mv643xx_eth.h	2007-07-18 22:47:02.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.h	2007-07-11 09:28:16.000000000 -0500
@@ -510,12 +510,12 @@
 static void eth_port_start(struct net_device *dev);
 
 /* PHY and MIB routines */
-static void ethernet_phy_reset(unsigned int eth_port_num);
+static void ethernet_phy_reset(struct mv643xx_private *mp);
 
-static void eth_port_write_smi_reg(unsigned int eth_port_num,
+static void eth_port_write_smi_reg(struct mv643xx_private *mp,
 				   unsigned int phy_reg, unsigned int value);
 
-static void eth_port_read_smi_reg(unsigned int eth_port_num,
+static void eth_port_read_smi_reg(struct mv643xx_private *mp,
 				  unsigned int phy_reg, unsigned int *value);
 
 static void eth_clear_mib_counters(unsigned int eth_port_num);

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [6/8]
From: Steven J. Hill @ 2007-07-19  4:55 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 129 bytes --]

Fix the TX bytes statistics counter to, um, actually count.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 06-mv643xx-fix-tx-statistics.patch --]
[-- Type: text/x-patch; name="06-mv643xx-fix-tx-statistics.patch", Size: 396 bytes --]

--- linux-2.6.22.1/drivers/net/mv643xx_eth.c	2007-07-18 21:51:49.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c	2007-07-18 21:44:07.000000000 -0500
@@ -1506,7 +1511,7 @@
 	spin_lock_irqsave(&mp->lock, flags);
 
 	eth_tx_submit_descs_for_skb(mp, skb);
-	stats->tx_bytes = skb->len;
+	stats->tx_bytes += skb->len;
 	stats->tx_packets++;
 	dev->trans_start = jiffies;
 

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [5/8]
From: Steven J. Hill @ 2007-07-19  4:54 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 123 bytes --]

Fix 'mv643xx_eth_tx_timeout_task' function prototype.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 05-mv643xx-fix-function-prototype.patch --]
[-- Type: text/x-patch; name="05-mv643xx-fix-function-prototype.patch", Size: 662 bytes --]

--- linux-2.6.22.1/drivers/net/mv643xx_eth.c	2007-07-18 21:45:13.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c	2007-07-18 21:44:07.000000000 -0500
@@ -317,11 +315,9 @@
  *
  * Actual routine to reset the adapter when a timeout on Tx has occurred
  */
-static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
+static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
 {
-	struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private,
-						  tx_timeout_task);
-	struct net_device *dev = mp->mii.dev; /* yuck */
+	struct mv643xx_private *mp = netdev_priv(dev);
 
 	if (!netif_running(dev))
 		return;

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH] Merge GT/MV642xx Support into MV643xx Driver [4/8]
From: Steven J. Hill @ 2007-07-19  4:53 UTC (permalink / raw)
  To: netdev


[-- Attachment #1.1: Type: text/plain, Size: 131 bytes --]

Add main 642xx support to 'drivers/net/mv643xx_eth.c' file.

Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
---


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 04-mv643xx-64260-support.patch --]
[-- Type: text/x-patch; name="04-mv643xx-64260-support.patch", Size: 38873 bytes --]

--- linux-2.6.22.1/drivers/net/mv643xx_eth.c	2007-07-18 22:19:31.000000000 -0500
+++ linux-2.6.22.1-rci/drivers/net/mv643xx_eth.c	2007-07-18 22:22:04.000000000 -0500
@@ -13,8 +13,7 @@
  * Copyright (C) 2004-2006 MontaVista Software, Inc.
  *			   Dale Farnsworth <dale@farnsworth.org>
  *
- * Copyright (C) 2004 Steven J. Hill <sjhill1@rockwellcollins.com>
- *				     <sjhill@realitydiluted.com>
+ * Copyright (C) 2004-2007 Steven J. Hill <sjhill1@rockwellcollins.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -48,6 +47,11 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/delay.h>
+#ifdef CONFIG_GT64260
+# include <asm/cacheflush.h>
+# include <asm/tlbflush.h>
+# include <asm/mv64x60.h>
+#endif
 #include "mv643xx_eth.h"
 
 /* Static function declarations */
@@ -83,6 +87,14 @@
 
 /* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
 static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
+#ifdef CONFIG_GT64260
+extern struct mv64x60_handle bh;
+static u32 eth_hash_table_size[3] = { 1, 1, 1 };
+static u32 eth_hash_table_hash_mode[3] = { 0, 0, 0 };
+static u32 eth_hash_table_default_mode[3] = { 0, 0, 0 };
+static u32 eth_hash_table_vbase_addr[3];
+static const u32 eth_hash_length[2] = { 0x8000, 0x800 };
+#endif
 
 static inline u32 mv_read(int offset)
 {
@@ -102,7 +114,7 @@
 }
 
 /*
- * Changes MTU (maximum transfer unit) of the gigabit ethenret port
+ * Changes MTU (maximum transfer unit) of the gigabit ethernet port
  *
  * Input :	pointer to ethernet interface network device structure
  *		new mtu size
@@ -113,6 +125,29 @@
 	if ((new_mtu > 9500) || (new_mtu < 64))
 		return -EINVAL;
 
+#ifdef CONFIG_GT64260
+	/*
+	 * The 642XX needs the frame length to be set for certain MTU
+	 * sizes to avoid length overrun errors.
+	 */
+	{
+		struct mv643xx_private *mp = netdev_priv(dev);
+		unsigned int reg;
+
+		reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(mp->port_num));
+
+		if (new_mtu <= 1528)
+			reg &= ~(0x3 << 14);
+		else if (new_mtu <= 1536)
+			reg |= (0x1 << 14);
+		else if (new_mtu <= 2048)
+			reg |= (0x2 << 14);
+		else
+			reg |= (0x3 << 14);
+
+		mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(mp->port_num), reg);
+	}
+#endif
 	dev->mtu = new_mtu;
 	/*
 	 * Stop then re-open the interface. This will allocate RX skb's with
@@ -158,13 +193,18 @@
 		pkt_info.byte_cnt = ETH_RX_SKB_SIZE;
 		pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
 					ETH_RX_SKB_SIZE, DMA_FROM_DEVICE);
+#ifdef CONFIG_GT64260
+		invalidate_dcache_addr_size((u32) skb->data, dev->mtu);
+#endif
 		pkt_info.return_info = skb;
 		if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) {
 			printk(KERN_ERR
 				"%s: Error allocating RX Ring\n", dev->name);
 			break;
 		}
+#ifndef CONFIG_GT64260
 		skb_reserve(skb, ETH_HW_IP_ALIGN);
+#endif
 	}
 	/*
 	 * If RX ring is empty of SKB, set a timer to try allocating
@@ -323,6 +361,10 @@
 
 		tx_index = mp->tx_used_desc_q;
 		desc = &mp->p_tx_desc_area[tx_index];
+#ifdef CONFIG_GT64260
+		invalidate_dcache_addr_size((u32) desc, sizeof(struct eth_tx_desc));
+		mb();
+#endif
 		cmd_sts = desc->cmd_sts;
 
 		if (!force && (cmd_sts & ETH_BUFFER_OWNED_BY_DMA)) {
@@ -338,6 +380,10 @@
 		skb = mp->tx_skb[tx_index];
 		if (skb)
 			mp->tx_skb[tx_index] = NULL;
+#ifdef CONFIG_GT64260
+		flush_dcache_addr_size(skb, skb->len);
+		flush_dcache_addr_size((u32) desc, sizeof(struct eth_tx_desc));
+#endif
 
 		if (cmd_sts & ETH_ERROR_SUMMARY) {
 			printk("%s: Error in TX\n", dev->name);
@@ -381,7 +427,7 @@
  * queues toward kernel core or FastRoute them to another interface.
  *
  * Input :	dev - a pointer to the required interface
- *		max - maximum number to receive (0 means unlimted)
+ *		budget - maximum number to receive (0 means unlimited)
  *
  * Output :	number of served packets
  */
@@ -394,8 +440,10 @@
 	struct pkt_info pkt_info;
 
 	while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
+#ifndef CONFIG_GT64260
 		dma_unmap_single(NULL, pkt_info.buf_ptr, ETH_RX_SKB_SIZE,
 							DMA_FROM_DEVICE);
+#endif
 		mp->rx_desc_count--;
 		received_packets++;
 
@@ -429,6 +477,12 @@
 
 			dev_kfree_skb_irq(skb);
 		} else {
+#ifdef CONFIG_GT64260
+			skb_put(skb, pkt_info.byte_cnt);
+			skb->ip_summed = CHECKSUM_NONE;
+			skb->pkt_type = PACKET_HOST;
+			skb->dev = dev;
+#else
 			/*
 			 * The -4 is for the CRC in the trailer of the
 			 * received packet
@@ -440,6 +494,7 @@
 				skb->csum = htons(
 					(pkt_info.cmd_sts & 0x0007fff8) >> 3);
 			}
+#endif
 			skb->protocol = eth_type_trans(skb, dev);
 #ifdef MV643XX_NAPI
 			netif_receive_skb(skb);
@@ -460,6 +515,7 @@
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
 	int port_num = mp->port_num;
+#ifndef CONFIG_GT64260
 	u32 o_pscr, n_pscr;
 	unsigned int queues;
 
@@ -502,6 +558,52 @@
 				mv643xx_eth_port_enable_tx(port_num, queues);
 		}
 	}
+#else
+	u32 o_pcr, n_pcr;
+	u32 o_pcxr, n_pcxr;
+	unsigned int queues;
+
+	o_pcr = mv_read(MV643XX_ETH_PORT_CONFIG_REG(port_num));
+	n_pcr = o_pcr;
+	o_pcxr = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num));
+	n_pcxr = o_pcxr;
+
+	/* clear speed and duplex fields */
+	n_pcr &= ~(GT64260_ETH_SET_SPEED_TO_10 |
+		   GT64260_ETH_SET_SPEED_TO_100 |
+		   GT64260_ETH_SET_FULL_DUPLEX_MODE);
+	n_pcxr |= GT64260_ETH_DISABLE_AUTO_NEG_FOR_DPLX;
+
+	if (ecmd->duplex == DUPLEX_FULL)
+		n_pcr |= GT64260_ETH_SET_FULL_DUPLEX_MODE;
+
+	if (ecmd->speed == SPEED_100)
+		n_pcr |= GT64260_ETH_SET_SPEED_TO_100;
+
+	if (n_pcr != o_pcr) {
+		if ((o_pcr & GT64260_ETH_ENABLE) == 0)
+		{
+			mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), n_pcr);
+
+			mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
+				n_pcxr);
+		}
+		else
+		{
+			queues = mv643xx_eth_port_disable_tx(port_num);
+
+			n_pcr &= ~GT64260_ETH_ENABLE;
+
+			mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), n_pcr);
+
+			mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
+				n_pcxr);
+
+			if (queues)
+				mv643xx_eth_port_enable_tx(port_num, queues);
+		}
+	}
+#endif
 }
 
 /*
@@ -515,6 +617,80 @@
  * Output :	N/A
  */
 
+#ifdef CONFIG_GT64260
+static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct mv643xx_private *mp = netdev_priv(dev);
+	u32 eth_int_cause;
+	unsigned int port_num = mp->port_num;
+
+	/* Read interrupt cause registers */
+	eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+						ETH_INT_UNMASK_ALL;
+
+	/* Tx interrupt */
+	if (eth_int_cause & 0x000000cc) {
+		mv643xx_eth_free_completed_tx_descs(dev);
+		eth_int_cause &= ~0x000000cc;
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), eth_int_cause);
+	}
+
+	/* PHY status changed */
+	if (eth_int_cause & ETH_INT_CAUSE_PHY) {
+		struct ethtool_cmd cmd;
+
+		if (mii_link_ok(&mp->mii)) {
+			mv643xx_eth_update_pscr(dev, &cmd);
+			mv643xx_eth_port_enable_tx(port_num,
+						   ETH_TX_QUEUES_ENABLED);
+			if (!netif_carrier_ok(dev)) {
+				netif_carrier_on(dev);
+				if (mp->tx_ring_size - mp->tx_desc_count >=
+							MAX_DESCS_PER_SKB)
+					netif_wake_queue(dev);
+			}
+		} else if (netif_carrier_ok(dev)) {
+			netif_stop_queue(dev);
+			netif_carrier_off(dev);
+		}
+		eth_int_cause &= ~ETH_INT_CAUSE_PHY;
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), eth_int_cause);
+	}
+
+	/* Handle SMI completion */
+	if (eth_int_cause & 0x20000000) {
+		eth_int_cause &= ~0x20000000;
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), eth_int_cause);
+	}
+
+	/* Rx interrupt */
+#ifdef MV643XX_NAPI
+	if (eth_int_cause & 0x00110101) {
+		/* schedule the NAPI poll routine to maintain port */
+		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+							ETH_INT_MASK_ALL);
+		/* wait for previous write to complete */
+		mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+		netif_rx_schedule(dev);
+	}
+#else
+	if (eth_int_cause & 0x00ff0101) {
+		mv643xx_eth_receive_queue(dev, INT_MAX);
+		eth_int_cause &= ~0x00ff0101;
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), eth_int_cause);
+	}
+#endif
+	
+	if (eth_int_cause) {
+		printk("MV-643xx: port %d interrupts remaining = 0x%08x\n",
+				port_num, eth_int_cause);
+	}
+
+	return IRQ_HANDLED;
+}
+#else
 static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
@@ -580,6 +756,7 @@
 
 	return IRQ_HANDLED;
 }
+#endif
 
 #ifdef MV643XX_COAL
 
@@ -621,6 +798,7 @@
 }
 #endif
 
+#ifndef CONFIG_GT64260
 /*
  * eth_port_set_tx_coal - Sets coalescing interrupt mechanism on TX path
  *
@@ -654,6 +832,7 @@
 								coal << 4);
 	return coal;
 }
+#endif
 
 /*
  * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
@@ -690,6 +869,22 @@
 			((i + 1) % rx_desc_num) * sizeof(struct eth_rx_desc);
 	}
 
+#ifdef CONFIG_GT64260
+		/*
+		 * For the GT64260, we set the Enable Interrupt (EI) bit
+		 * to interrupt only on frames and not buffer boundaries.
+		 * It is also necessary to set the Receive Interrupt on
+		 * Frame Boundaries (RIFB) bit in the SDMA Configuration
+		 * Register (SDCR) of the Ethernet port. The RIFB bit is
+		 * set in the 'eth_port_start' function.
+		 *
+		 * These bits are documented on Pages 421 and 455 of the
+		 * Marvell GT64260B datasheet dated August 04, 2004.
+		 */
+		p_rx_desc[i].cmd_sts =
+			(ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT);
+#endif
+
 	/* Save Rx desc pointer to driver struct. */
 	mp->rx_curr_desc_q = 0;
 	mp->rx_used_desc_q = 0;
@@ -698,7 +893,7 @@
 }
 
 /*
- * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory.
+ * ether_init_tx_desc_ring - Carve a Tx chain desc list and buffer in memory.
  *
  * DESCRIPTION:
  *	This function prepares a Tx chained list of descriptors and packet
@@ -788,9 +983,11 @@
 
 	/* Clear any pending ethernet port interrupts */
 	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+#ifndef CONFIG_GT64260
 	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
 	/* wait for previous write to complete */
 	mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num));
+#endif
 
 	err = request_irq(dev->irq, mv643xx_eth_int_handler,
 			IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
@@ -800,6 +997,50 @@
 		return -EAGAIN;
 	}
 
+#ifdef CONFIG_GT64260
+	/*
+	 * Allocate and initialize hash table. We do this here so that
+	 * if the memory allocation fails, we can clean up and because
+	 * the table must be allocated before calling 'eth_port_init'.
+	 *
+	 * Hash mode	     - Hash mode 0 or Hash mode 1.
+	 * Hash size	     - Indicates number of table entries
+	 *		       (0 = 0x8000, 1 = 0x800)
+	 * Hash default mode - 0 = Discard addresses not found
+	 *		       1 = Pass addresses not found
+	 */
+	mp->eth_hash_table_size =
+		MAC_ENTRY_SIZE * eth_hash_length[eth_hash_table_size[port_num]];
+	mp->eth_hash_table = dma_alloc_coherent(NULL, mp->eth_hash_table_size,
+						&mp->eth_hash_table_dma,
+						GFP_KERNEL);
+	if (!mp->eth_hash_table) {
+		printk(KERN_ERR "%s: Cannot allocate hash table\n", dev->name);
+		err = -ENOMEM;
+		goto out_free_irq;
+	}
+	mv_write(GT64260_ETH_HASH_TABLE_POINTER_REG(port_num),
+			mp->eth_hash_table_dma);
+	eth_hash_table_vbase_addr[port_num] = (u32) mp->eth_hash_table;
+	invalidate_dcache_addr_size(mp->eth_hash_table, (MAC_ENTRY_SIZE *
+			eth_hash_length[eth_hash_table_size[port_num]]));
+
+	/* Set hash table parameters. */
+	{
+		u32 pcr = mv_read(MV643XX_ETH_PORT_CONFIG_REG(port_num));
+		pcr &= ~(GT64260_ETH_HASH_SIZE_8K |
+			 GT64260_ETH_HASH_MODE_1 |
+			 GT64260_ETH_HASH_DEFAULT_PASS);
+		pcr |= ((eth_hash_table_default_mode[port_num] <<
+				GT64260_ETH_HASH_DEFAULT_SHIFT)
+		     | (eth_hash_table_hash_mode[port_num] <<
+				GT64260_ETH_HASH_MODE_SHIFT)
+		     | (eth_hash_table_size[port_num] <<
+				GT64260_ETH_HASH_SIZE_SHIFT));
+		mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), pcr);
+	}
+#endif
+
 	eth_port_init(mp);
 
 	memset(&mp->timeout, 0, sizeof(struct timer_list));
@@ -807,12 +1048,24 @@
 	mp->timeout.data = (unsigned long)dev;
 
 	/* Allocate RX and TX skb rings */
+#ifdef CONFIG_GT64260
+	/* GT642XX needs page alignment for RX skb ring */
+	size = PAGE_SIZE;
+	while (size < (sizeof(*mp->rx_skb) * mp->rx_ring_size))
+		size += PAGE_SIZE;
+	mp->rx_skb = kmalloc(size, GFP_KERNEL);
+#else
 	mp->rx_skb = kmalloc(sizeof(*mp->rx_skb) * mp->rx_ring_size,
 								GFP_KERNEL);
+#endif
 	if (!mp->rx_skb) {
 		printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
 		err = -ENOMEM;
+#ifdef CONFIG_GT64260
+		goto out_free_hash_table;
+#else
 		goto out_free_irq;
+#endif
 	}
 	mp->tx_skb = kmalloc(sizeof(*mp->tx_skb) * mp->tx_ring_size,
 								GFP_KERNEL);
@@ -848,8 +1101,15 @@
 	ether_init_tx_desc_ring(mp);
 
 	/* Allocate RX ring */
+#ifdef CONFIG_GT64260
+	/* GT642XX needs page alignment for RX ring */
+	size = PAGE_SIZE;
+	while (size < (mp->rx_ring_size * sizeof(struct eth_rx_desc)))
+		size += PAGE_SIZE;
+#else
 	mp->rx_desc_count = 0;
 	size = mp->rx_ring_size * sizeof(struct eth_rx_desc);
+#endif
 	mp->rx_desc_area_size = size;
 
 	if (mp->rx_sram_size) {
@@ -889,12 +1149,14 @@
 		eth_port_set_rx_coal(port_num, 133000000, MV643XX_RX_COAL);
 #endif
 
+#ifndef CONFIG_GT64260
 	mp->tx_int_coal =
 		eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
 
 	/* Unmask phy and link status changes interrupts */
 	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
 						ETH_INT_UNMASK_ALL_EXT);
+#endif
 
 	/* Unmask RX buffer and TX end interrupt */
 	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
@@ -905,6 +1167,11 @@
 	kfree(mp->tx_skb);
 out_free_rx_skb:
 	kfree(mp->rx_skb);
+#ifdef CONFIG_GT64260
+out_free_hash_table:
+	dma_free_coherent(NULL, mp->eth_hash_table_size,
+			mp->eth_hash_table, mp->eth_hash_table_dma);
+#endif
 out_free_irq:
 	free_irq(dev->irq, dev);
 
@@ -1035,7 +1302,9 @@
 	if (done) {
 		netif_rx_complete(dev);
 		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+#ifndef CONFIG_GT64260
 		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+#endif
 		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
 						ETH_INT_UNMASK_ALL);
 	}
@@ -1090,6 +1359,9 @@
 static void eth_tx_fill_frag_descs(struct mv643xx_private *mp,
 				   struct sk_buff *skb)
 {
+#ifdef CONFIG_GT64260
+	printk("eth_tx_fill_frag_descs: Unable to handle fragments!\n");
+#else
 	int frag;
 	int tx_index;
 	struct eth_tx_desc *desc;
@@ -1108,7 +1380,7 @@
 					 ETH_TX_ENABLE_INTERRUPT;
 			mp->tx_skb[tx_index] = skb;
 		} else
-			mp->tx_skb[tx_index] = NULL;
+			mp->tx_skb[tx_index] = 0;
 
 		desc = &mp->p_tx_desc_area[tx_index];
 		desc->l4i_chk = 0;
@@ -1118,6 +1390,7 @@
 						this_frag->size,
 						DMA_TO_DEVICE);
 	}
+#endif
 }
 
 /**
@@ -1144,7 +1417,7 @@
 		eth_tx_fill_frag_descs(mp, skb);
 
 		length = skb_headlen(skb);
-		mp->tx_skb[tx_index] = NULL;
+		mp->tx_skb[tx_index] = 0;
 	} else {
 		cmd_sts |= ETH_ZERO_PADDING |
 			   ETH_TX_LAST_DESC |
@@ -1156,6 +1429,13 @@
 	desc->byte_cnt = length;
 	desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
 
+#ifdef CONFIG_GT64260
+	flush_dcache_addr_size(skb->data, length);
+	invalidate_dcache_addr_size(skb->data, length);
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
+		BUG();
+#else
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		BUG_ON(skb->protocol != ETH_P_IP);
 
@@ -1179,10 +1459,14 @@
 		cmd_sts |= 5 << ETH_TX_IHL_SHIFT;
 		desc->l4i_chk = 0;
 	}
+#endif
 
 	/* ensure all other descriptors are written before first cmd_sts */
 	wmb();
 	desc->cmd_sts = cmd_sts;
+#ifdef CONFIG_GT64260
+	flush_dcache_addr_size(desc, sizeof(struct eth_tx_desc));
+#endif
 
 	/* ensure all descriptors are written before poking hardware */
 	wmb();
@@ -1640,7 +1936,7 @@
  *		within the scope of this driver. Thus, the user is required to
  *		allocate memory for the descriptors ring and buffers. Those
  *		memory parameters are used by the Rx and Tx ring initialization
- *		routines in order to curve the descriptor linked list in a form
+ *		routines in order to carve the descriptor linked list in a form
  *		of a ring.
  *		Note: Pay special attention to alignment issues when using
  *		cached descriptors/buffers. In this phase the driver store
@@ -1716,7 +2012,12 @@
 static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
 
 /* Ethernet Port routines */
+#ifdef CONFIG_GT64260
+static void eth_port_set_filter_table_entry(unsigned int port,
+	unsigned char *p_addr, unsigned int rd, unsigned int skip);
+#else
 static void eth_port_set_filter_table_entry(int table, unsigned char entry);
+#endif
 
 /*
  * eth_port_init - Initialize the Ethernet port driver
@@ -1783,7 +2084,7 @@
 	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 	int tx_curr_desc, rx_curr_desc;
-	u32 pscr;
+	u32 reg;
 	struct ethtool_cmd ethtool_cmd;
 
 	/* Assignment of Tx CTRP of given queue */
@@ -1793,6 +2094,10 @@
 
 	/* Assignment of Rx CRDP of given queue */
 	rx_curr_desc = mp->rx_curr_desc_q;
+#ifdef CONFIG_GT64260
+	mv_write(MV643XX_ETH_RX_FIRST_QUEUE_DESC_PTR_0(port_num),
+		(u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
+#endif
 	mv_write(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
 		(u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
 
@@ -1800,27 +2105,57 @@
 	eth_port_uc_addr_set(port_num, dev->dev_addr);
 
 	/* Assign port configuration and command. */
+#ifdef CONFIG_GT64260
+	reg = GT64260_ETH_PORT_CONFIG_DEFAULT_VALUE;
+	reg |= ((eth_hash_table_default_mode[port_num] << GT64260_ETH_HASH_DEFAULT_SHIFT)
+	      | (eth_hash_table_hash_mode[port_num] << GT64260_ETH_HASH_MODE_SHIFT)
+	      | (eth_hash_table_size[port_num] << GT64260_ETH_HASH_SIZE_SHIFT));
+	mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), reg);
+
+	mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
+			GT64260_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE);
+
+	/* Assign port SDMA configuration */
+	mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
+			GT64260_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE);
+
+	/* Enable the interrupt for the port */
+	mv64x60_set_bits(&bh, GT64260_IC_CPU_INTR_MASK_HI, (1 << port_num));
+
+	/* Enable the actual Ethernet port */
+	reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num));
+	reg |= GT64260_ETH_ENABLE;
+	mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), reg);
+
+	/* Enable port Rx DMA */
+	mv643xx_eth_port_enable_rx(port_num, 0);
+
+	/* Disable port bandwidth limits by clearing MTU register */
+	reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(mp->port_num));
+	reg &= ~(0x3 << 14);
+	mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(mp->port_num), reg);
+#else
 	mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num),
 			  MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE);
 
 	mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
 			  MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE);
 
-	pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+	reg = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
 
-	pscr &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS);
-	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+	reg &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS);
+	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg);
 
-	pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
-		MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII    |
-		MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX     |
-		MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL	   |
-		MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED;
+	reg |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+	       MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII    |
+	       MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX     |
+	       MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL	   |
+	       MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED;
 
-	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg);
 
-	pscr |= MV643XX_ETH_SERIAL_PORT_ENABLE;
-	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+	reg |= MV643XX_ETH_SERIAL_PORT_ENABLE;
+	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg);
 
 	/* Assign port SDMA configuration */
 	mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
@@ -1831,6 +2166,7 @@
 
 	/* Disable port bandwidth limits by clearing MTU register */
 	mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
+#endif
 
 	/* save phy settings across reset */
 	mv643xx_get_settings(dev, &ethtool_cmd);
@@ -1839,10 +2175,27 @@
 }
 
 /*
- * eth_port_uc_addr_set - Write a MAC address into the port's hw registers
+ * eth_port_uc_addr_set - This function sets the port Unicast address.
+ *
+ * DESCRIPTION:
+ *		This function sets the port Ethernet MAC address.
+ *
+ * INPUT:
+ *	unsigned int	eth_port_num	Port number.
+ *	char *		p_addr		Address to be set
+ *
+ * OUTPUT:
+ *	Set MAC address low and high registers. also calls
+ *	eth_port_set_filter_table_entry() to set the unicast
+ *	table with the proper information.
+ *
+ * RETURN:
+ *	N/A.
+ *
  */
 static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
 {
+#ifndef CONFIG_GT64260
 	unsigned int mac_h;
 	unsigned int mac_l;
 	int table;
@@ -1854,13 +2207,31 @@
 	mv_write(MV643XX_ETH_MAC_ADDR_LOW(port_num), mac_l);
 	mv_write(MV643XX_ETH_MAC_ADDR_HIGH(port_num), mac_h);
 
-	/* Accept frames with this address */
+	/* Accept frames of this address */
 	table = MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port_num);
 	eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
+#else
+	eth_port_set_filter_table_entry(eth_port_num, p_addr, 1, 0);
+#endif
 }
 
 /*
- * eth_port_uc_addr_get - Read the MAC address from the port's hw registers
+ * eth_port_uc_addr_get - This function retrieves the port Unicast address
+ * (MAC address) from the ethernet hw registers.
+ *
+ * DESCRIPTION:
+ *		This function retrieves the port Ethernet MAC address.
+ *
+ * INPUT:
+ *	unsigned int	eth_port_num	Port number.
+ *	char		*MacAddr	pointer where the MAC address is stored
+ *
+ * OUTPUT:
+ *	Copy the MAC address to the location pointed to by MacAddr
+ *
+ * RETURN:
+ *	N/A.
+ *
  */
 static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
 {
@@ -1878,6 +2249,185 @@
 	p_addr[5] = mac_l & 0xff;
 }
 
+#ifdef CONFIG_GT64260
+# define HOP_NUMBER	12
+# define SKIP_BIT	1
+# define VALID		1
+# define _8K_TABLE	0
+
+# define NIBBLE_SWAPPING_32_BIT(X)			\
+	( (((X) & 0xf0f0f0f0) >> 4)			\
+	| (((X) & 0x0f0f0f0f) << 4) )
+
+# define NIBBLE_SWAPPING_16_BIT(X)			\
+	( (((X) & 0x0000f0f0) >> 4)			\
+	| (((X) & 0x00000f0f) << 4) )
+
+# define FLIP_4_BITS(X)					\
+	( (((X) & 0x01) << 3) | (((X) & 0x002) << 1)	\
+	| (((X) & 0x04) >> 1) | (((X) & 0x008) >> 3) )
+
+# define FLIP_6_BITS(X)					\
+	( (((X) & 0x01) << 5) | (((X) & 0x020) >> 5)	\
+	| (((X) & 0x02) << 3) | (((X) & 0x010) >> 3)	\
+	| (((X) & 0x04) << 1) | (((X) & 0x008) >> 1) )
+
+# define FLIP_9_BITS(X)					\
+	( (((X) & 0x01) << 8) | (((X) & 0x100) >> 8)	\
+	| (((X) & 0x02) << 6) | (((X) & 0x080) >> 6)	\
+	| (((X) & 0x04) << 4) | (((X) & 0x040) >> 4)	\
+	| ((X) & 0x10)	| (((X) & 0x08) << 2) | (((X) & 0x020) >> 2) )
+
+/*
+ * eth_hash_table_function - Calculates hash function of an address.
+ *
+ * Depends on the hash mode and hash size being initialized.
+ *
+ * Input :	macH - The 2 most significant bytes of the MAC address.
+ * 		macL - The 4 least significant bytes of the MAC address.
+ * 		hashMode - Hash mode 0 or hash mode 1.
+ * 		hashSizeSelector - Indicates number of hash table entries:
+ *				   (0 = 0x8000, 1 = 0x800)
+ *
+ * Output :	Calculated entry.
+ */
+static unsigned int
+eth_hash_table_function(unsigned int macH, unsigned int macL,
+		 unsigned int HashSize, unsigned int hash_mode)
+{
+	unsigned int hashResult;
+	unsigned int addrH;
+	unsigned int addrL;
+	unsigned int addr0;
+	unsigned int addr1;
+	unsigned int addr2;
+	unsigned int addr3;
+	unsigned int addrHSwapped;
+	unsigned int addrLSwapped;
+
+	addrH = NIBBLE_SWAPPING_16_BIT(macH);
+	addrL = NIBBLE_SWAPPING_32_BIT(macL);
+
+	addrHSwapped = FLIP_4_BITS(addrH & 0xf)
+	    + ((FLIP_4_BITS((addrH >> 4) & 0xf)) << 4)
+	    + ((FLIP_4_BITS((addrH >> 8) & 0xf)) << 8)
+	    + ((FLIP_4_BITS((addrH >> 12) & 0xf)) << 12);
+
+	addrLSwapped = FLIP_4_BITS(addrL & 0xf)
+	    + ((FLIP_4_BITS((addrL >> 4) & 0xf)) << 4)
+	    + ((FLIP_4_BITS((addrL >> 8) & 0xf)) << 8)
+	    + ((FLIP_4_BITS((addrL >> 12) & 0xf)) << 12)
+	    + ((FLIP_4_BITS((addrL >> 16) & 0xf)) << 16)
+	    + ((FLIP_4_BITS((addrL >> 20) & 0xf)) << 20)
+	    + ((FLIP_4_BITS((addrL >> 24) & 0xf)) << 24)
+	    + ((FLIP_4_BITS((addrL >> 28) & 0xf)) << 28);
+
+	addrH = addrHSwapped;
+	addrL = addrLSwapped;
+
+	if (hash_mode == 0) {
+		addr0 = (addrL >> 2) & 0x03f;
+		addr1 = (addrL & 0x003) | ((addrL >> 8) & 0x7f) << 2;
+		addr2 = (addrL >> 15) & 0x1ff;
+		addr3 = ((addrL >> 24) & 0x0ff) | ((addrH & 1) << 8);
+	} else {
+		addr0 = FLIP_6_BITS(addrL & 0x03f);
+		addr1 = FLIP_9_BITS(((addrL >> 6) & 0x1ff));
+		addr2 = FLIP_9_BITS((addrL >> 15) & 0x1ff);
+		addr3 =
+		    FLIP_9_BITS((((addrL >> 24) & 0x0ff) |
+				 ((addrH & 0x1) << 8)));
+	}
+
+	hashResult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3);
+
+	if (HashSize == _8K_TABLE) {
+		hashResult = hashResult & 0xffff;
+	} else {
+		hashResult = hashResult & 0x07ff;
+	}
+
+	return (hashResult);
+}
+
+/*
+ * eth_port_set_filter_table_entry - Add an entry to the hash address table.
+ *
+ * Depends on the hash mode and hash size being initialized.
+ *
+ * Input :	port - Ethernet port number.
+ * 		macH - The 2 most significant bytes of the MAC address.
+ * 		macL - The 4 least significant bytes of the MAC address.
+ * 		skip - If 1, skip this address.
+ * 		rd   - If 0, Discard packet upon match. If 1, receive packet.
+ *
+ * Output :	N/A
+ */
+static void eth_port_set_filter_table_entry(unsigned int port,
+		unsigned char *p_addr, unsigned int rd, unsigned int skip)
+{
+	struct eth_hash_table_entry *entry;
+	unsigned int newHi;
+	unsigned int newLo;
+	unsigned int macHi;
+	unsigned int macLo;
+	unsigned int i;
+
+	macHi = p_addr[0];
+	macHi = (macHi << 8) | p_addr[1];
+	macLo = p_addr[2];
+	macLo = (macLo << 8) | p_addr[3];
+	macLo = (macLo << 8) | p_addr[4];
+	macLo = (macLo << 8) | p_addr[5];
+
+	newLo = (((macHi >> 4) & 0xf) << 15)
+	    | (((macHi >> 0) & 0xf) << 11)
+	    | (((macHi >> 12) & 0xf) << 7)
+	    | (((macHi >> 8) & 0xf) << 3)
+	    | (((macLo >> 20) & 0x1) << 31)
+	    | (((macLo >> 16) & 0xf) << 27)
+	    | (((macLo >> 28) & 0xf) << 23)
+	    | (((macLo >> 24) & 0xf) << 19)
+	    | (skip << SKIP_BIT) | (rd << 2) | VALID;
+
+	newHi = (((macLo >> 4) & 0xf) << 15)
+	    | (((macLo >> 0) & 0xf) << 11)
+	    | (((macLo >> 12) & 0xf) << 7)
+	    | (((macLo >> 8) & 0xf) << 3)
+	    | (((macLo >> 21) & 0x7) << 0);
+
+	/*
+	 * Pick the appropriate table, start scanning for free/reusable
+	 * entries at the index obtained by hashing the specified MAC address
+	 */
+	entry = (struct eth_hash_table_entry *) eth_hash_table_vbase_addr[port];
+	entry += eth_hash_table_function(macHi, macLo,
+			eth_hash_table_size[port],
+			eth_hash_table_default_mode[port]);
+
+	for (i = 0; i < HOP_NUMBER; i++, entry++) {
+		if (!(entry->lo & VALID) /*|| (entry->lo & SKIP) */ ) {
+			break;
+		} else {	/* if same address put in same position */
+			if (((entry->lo & 0xfffffff8) == (newLo & 0xfffffff8))
+			    && (entry->hi == newHi)) {
+				break;
+			}
+		}
+	}
+
+	if (i == HOP_NUMBER) {
+		printk("eth_port_set_filter_table_entry: Hash table full!\n");
+	}
+
+	/*
+	 * Update the selected entry
+	 */
+	entry->hi = newHi;
+	entry->lo = newLo;
+	flush_dcache_addr_size(entry, MAC_ENTRY_SIZE);
+}
+#else
 /*
  * The entries in each table are indexed by a hash of a packet's MAC
  * address.  One bit in each entry determines whether the packet is
@@ -2005,13 +2555,13 @@
 	table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
 	eth_port_set_filter_table_entry(table, crc_result);
 }
+#endif
 
 /*
  * Set the entire multicast list based on dev->mc_list.
  */
 static void eth_port_set_multicast_list(struct net_device *dev)
 {
-
 	struct dev_mc_list	*mc_list;
 	int			i;
 	int			table_index;
@@ -2022,6 +2572,24 @@
 	 * we will fully populate both multicast tables with accept.
 	 * This is guaranteed to yield a match on all multicast addresses...
 	 */
+#ifdef CONFIG_GT64260
+	if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
+		struct eth_hash_table_entry *hash_table;
+
+		hash_table = (struct eth_hash_table_entry *) eth_hash_table_vbase_addr[eth_port_num];
+		for (table_index = 0; table_index <= eth_hash_table_size[eth_port_num]; table_index += 1) {
+			hash_table[table_index].lo |= VALID;
+		}
+		return;
+	}
+
+	/* Get pointer to net_device multicast list and add each one... */
+	for (i = 0, mc_list = dev->mc_list;
+			(i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+			i++, mc_list = mc_list->next)
+		if (mc_list->dmi_addrlen == 6)
+			eth_port_set_filter_table_entry(eth_port_num, mc_list->dmi_addr, 1, 0);
+#else
 	if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
 		for (table_index = 0; table_index <= 0xFC; table_index += 4) {
 			/* Set all entries in DA filter special multicast
@@ -2066,6 +2634,7 @@
 			i++, mc_list = mc_list->next)
 		if (mc_list->dmi_addrlen == 6)
 			eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
+#endif
 }
 
 /*
@@ -2086,6 +2655,12 @@
  */
 static void eth_port_init_mac_tables(unsigned int eth_port_num)
 {
+#ifdef CONFIG_GT64260
+	memset((void *) eth_hash_table_vbase_addr[eth_port_num], 0,
+		(eth_hash_table_size[eth_port_num] * MAC_ENTRY_SIZE));
+	flush_dcache_addr_size(eth_hash_table_vbase_addr[eth_port_num],
+		(eth_hash_table_size[eth_port_num] * MAC_ENTRY_SIZE));
+#else
 	int table_index;
 
 	/* Clear DA filter unicast table (Ex_dFUT) */
@@ -2101,6 +2676,7 @@
 		mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
 					(eth_port_num) + table_index, 0);
 	}
+#endif
 }
 
 /*
@@ -2125,8 +2701,13 @@
 	int i;
 
 	/* Perform dummy reads from MIB counters */
+#ifdef CONFIG_GT64260
+	for (i = ETH_MIB_OCTETS_RECEIVED; i < ETH_MIB_UNDERSIZE_RECEIVED;
+									i += 4)
+#else
 	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
 									i += 4)
+#endif
 		mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
 }
 
@@ -2137,6 +2718,19 @@
 
 static void eth_update_mib_counters(struct mv643xx_private *mp)
 {
+#ifdef CONFIG_GT64260
+	struct gt64260_mib_counters *p = &mp->mib_counters;
+	int offset;
+
+	p->good_octets_received +=
+		read_mib(mp, ETH_MIB_OCTETS_RECEIVED);
+
+	p->good_octets_sent += read_mib(mp, ETH_MIB_OCTETS_SENT);
+
+	for (offset = ETH_MIB_OCTETS_RECEIVED;
+			offset < ETH_MIB_UNDERSIZE_RECEIVED; offset += 4)
+		*(u32 *)((char *)p + offset) = read_mib(mp, offset);
+#else
 	struct mv643xx_mib_counters *p = &mp->mib_counters;
 	int offset;
 
@@ -2158,6 +2752,7 @@
 			offset <= ETH_MIB_LATE_COLLISION;
 			offset += 4)
 		*(u32 *)((char *)p + offset) += read_mib(mp, offset);
+#endif
 }
 
 /*
@@ -2285,19 +2880,49 @@
 static void mv643xx_eth_port_enable_tx(unsigned int port_num,
 					unsigned int queues)
 {
+#ifdef CONFIG_GT64260
+	mv64x60_set_bits(&bh, MV643XX_ETH_SDMA_COMMAND_REG(port_num),
+		(GT64260_ETH_START_TX_HIGH | GT64260_ETH_START_TX_LOW));
+#else
 	mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
+#endif
 }
 
 static void mv643xx_eth_port_enable_rx(unsigned int port_num,
 					unsigned int queues)
 {
+#ifdef CONFIG_GT64260
+	mv64x60_set_bits(&bh, MV643XX_ETH_SDMA_COMMAND_REG(port_num),
+		GT64260_ETH_ENABLE_RX_DMA);
+#else
 	mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
+#endif
 }
 
 static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
 {
 	u32 queues;
 
+#ifdef CONFIG_GT64260
+	u32 timeout = 100; 
+
+	queues = mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num))
+			& MV643XX_ETH_PORT_STATUS_TX_IN_PROGRESS;
+	if (queues) {
+		/* Stop Tx activity and wait until bit is set */
+		mv64x60_set_bits(&bh, MV643XX_ETH_SDMA_COMMAND_REG(port_num),
+				GT64260_ETH_ABORT_TX_DMA);
+		while ((mv_read(MV643XX_ETH_SDMA_COMMAND_REG(port_num))
+				& GT64260_ETH_ABORT_TX_DMA) && timeout)
+		{
+			udelay(PHY_WAIT_MICRO_SECONDS);
+			timeout--;
+		}
+
+		if (!timeout)
+			printk(KERN_WARNING "MV-643xx: port %d Disable Tx DMA timed out, no link?\n", port_num);
+	}
+#else
 	/* Stop Tx port activity. Check port Tx activity. */
 	queues = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
 							& 0xFF;
@@ -2317,6 +2942,7 @@
 							ETH_PORT_TX_FIFO_EMPTY)
 			udelay(PHY_WAIT_MICRO_SECONDS);
 	}
+#endif
 
 	return queues;
 }
@@ -2325,6 +2951,16 @@
 {
 	u32 queues;
 
+#ifdef CONFIG_GT64260
+	/* Stop Rx activity and wait until bit is set */
+	mv64x60_set_bits(&bh, MV643XX_ETH_SDMA_COMMAND_REG(port_num),
+			GT64260_ETH_ABORT_RX_DMA);
+	while (mv_read(MV643XX_ETH_SDMA_COMMAND_REG(port_num))
+			& GT64260_ETH_ABORT_RX_DMA)
+		udelay(PHY_WAIT_MICRO_SECONDS);
+
+	queues = 0;
+#else
 	/* Stop Rx port activity. Check port Rx activity. */
 	queues = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
 							& 0xFF;
@@ -2339,6 +2975,7 @@
 							& 0xFF)
 			udelay(PHY_WAIT_MICRO_SECONDS);
 	}
+#endif
 
 	return queues;
 }
@@ -2363,7 +3000,9 @@
  */
 static void eth_port_reset(unsigned int port_num)
 {
+#ifndef CONFIG_GT64260
 	unsigned int reg_data;
+#endif
 
 	mv643xx_eth_port_disable_tx(port_num);
 	mv643xx_eth_port_disable_rx(port_num);
@@ -2371,12 +3010,18 @@
 	/* Clear all MIB counters */
 	eth_clear_mib_counters(port_num);
 
+#ifdef CONFIG_GT64260
+	/* Mask main Ethernet interrupt */
+	mv64x60_clr_bits(&bh, GT64260_IC_CPU_INTR_MASK_HI,
+		(1 << port_num));
+#else
 	/* Reset the Enable bit in the Configuration Register */
 	reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
 	reg_data &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE		|
 			MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL	|
 			MV643XX_ETH_FORCE_LINK_PASS);
 	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
+#endif
 }
 
 
@@ -2544,6 +3189,10 @@
 	rx_used_desc = mp->rx_used_desc_q;
 
 	p_rx_desc = &mp->p_rx_desc_area[rx_curr_desc];
+#ifdef CONFIG_GT64260
+	flush_dcache_addr_size(p_rx_desc, sizeof(struct eth_rx_desc));
+	mb();
+#endif
 
 	/* The following parameters are used to save readings from memory */
 	command_status = p_rx_desc->cmd_sts;
@@ -2555,6 +3204,10 @@
 		return ETH_END_OF_JOB;
 	}
 
+#ifdef CONFIG_GT64260
+	invalidate_dcache_addr_size(p_rx_desc, sizeof(struct eth_rx_desc));
+	mb();
+#endif
 	p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
 	p_pkt_info->cmd_sts = command_status;
 	p_pkt_info->buf_ptr = (p_rx_desc->buf_ptr) + RX_BUF_OFFSET;
@@ -2623,6 +3276,9 @@
 	wmb();
 	p_used_rx_desc->cmd_sts =
 			ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+#ifdef CONFIG_GT64260
+	flush_dcache_addr_size(p_used_rx_desc, sizeof(struct eth_rx_desc));
+#endif
 	wmb();
 
 	/* Move the used descriptor pointer to the next descriptor */
@@ -2656,6 +3312,33 @@
 	{ "tx_errors", MV643XX_STAT(stats.tx_errors) },
 	{ "rx_dropped", MV643XX_STAT(stats.rx_dropped) },
 	{ "tx_dropped", MV643XX_STAT(stats.tx_dropped) },
+#ifdef CONFIG_GT64260
+	{ "good_octets_received", MV643XX_STAT(mib_counters.good_octets_received) },
+	{ "good_frames_received", MV643XX_STAT(mib_counters.good_frames_received) },
+	{ "broadcast_frames_received", MV643XX_STAT(mib_counters.broadcast_frames_received) },
+	{ "multicast_frames_received", MV643XX_STAT(mib_counters.multicast_frames_received) },
+	{ "total_octets_received", MV643XX_STAT(mib_counters.total_octets_received) },
+	{ "total_frames_received", MV643XX_STAT(mib_counters.total_frames_received) },
+	{ "frames_64_octets", MV643XX_STAT(mib_counters.frames_64_octets) },
+	{ "frames_65_to_127_octets", MV643XX_STAT(mib_counters.frames_65_to_127_octets) },
+	{ "frames_128_to_255_octets", MV643XX_STAT(mib_counters.frames_128_to_255_octets) },
+	{ "frames_256_to_511_octets", MV643XX_STAT(mib_counters.frames_256_to_511_octets) },
+	{ "frames_512_to_1023_octets", MV643XX_STAT(mib_counters.frames_512_to_1023_octets) },
+	{ "frames_1024_to_max_octets", MV643XX_STAT(mib_counters.frames_1024_to_max_octets) },
+	{ "good_octets_sent", MV643XX_STAT(mib_counters.good_octets_sent) },
+	{ "good_frames_sent", MV643XX_STAT(mib_counters.good_frames_sent) },
+	{ "multicast_frames_sent", MV643XX_STAT(mib_counters.multicast_frames_sent) },
+	{ "broadcast_frames_sent", MV643XX_STAT(mib_counters.broadcast_frames_sent) },
+	{ "dropped_frames", MV643XX_STAT(mib_counters.dropped_frames) },
+	{ "undersize_received", MV643XX_STAT(mib_counters.undersize_received) },
+	{ "fragments_received", MV643XX_STAT(mib_counters.fragments_received) },
+	{ "oversize_received", MV643XX_STAT(mib_counters.oversize_received) },
+	{ "jabber_received", MV643XX_STAT(mib_counters.jabber_received) },
+	{ "mac_receive_error", MV643XX_STAT(mib_counters.mac_receive_error) },
+	{ "bad_crc_event", MV643XX_STAT(mib_counters.bad_crc_event) },
+	{ "collision", MV643XX_STAT(mib_counters.collision) },
+	{ "late_collision", MV643XX_STAT(mib_counters.late_collision) },
+#else
 	{ "good_octets_received", MV643XX_STAT(mib_counters.good_octets_received) },
 	{ "bad_octets_received", MV643XX_STAT(mib_counters.bad_octets_received) },
 	{ "internal_mac_transmit_err", MV643XX_STAT(mib_counters.internal_mac_transmit_err) },
@@ -2686,6 +3369,7 @@
 	{ "bad_crc_event", MV643XX_STAT(mib_counters.bad_crc_event) },
 	{ "collision", MV643XX_STAT(mib_counters.collision) },
 	{ "late_collision", MV643XX_STAT(mib_counters.late_collision) },
+#endif
 };
 
 #define MV643XX_STATS_LEN	\

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* Re: [TG3]: Fix msi issue with kexec/kdump.
From: David Miller @ 2007-07-19  4:49 UTC (permalink / raw)
  To: mchan; +Cc: tina.yang, netdev
In-Reply-To: <1184816447.10854.30.camel@dell>

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jul 2007 20:40:47 -0700

> [TG3]: Fix msi issue with kexec/kdump.
> 
> Tina Yang <tina.yang@oracle.com> discovered an MSI related problem
> when doing kdump.  The problem is that the kexec kernel is booted
> without going through system reset, and as a result, MSI may already
> be enabled when tg3_init_one() is called.  tg3_init_one() calls
> pci_save_state() which will save the stale MSI state.  Later on in
> tg3_open(), we call pci_enable_msi() to reconfigure MSI on the chip
> before we reset the chip.  After chip reset, we call
> pci_restore_state() which will put the stale MSI address/data back
> onto the chip.
> 
> This is no longer a problem in the latest kernel because
> pci_restore_state() has been changed to restore MSI state from
> internal data structures which will guarantee restoring the proper
> MSI state.
> 
> But I think we should still fix it.  Our save and restore sequence
> can still cause very subtle problems down the road.  The fix is to
> have our own functions save and restore precisely what we need.  We
> also change it to save and restore state inside tg3_chip_reset() in a
> more straight forward way.
> 
> Thanks to Tina for helping to test and debug the problem.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>

Looks good, applied.

For good measure, I bumped the driver version and release date.

^ permalink raw reply

* Re: [GIT PULL] [NET]: Whitespace fixes
From: David Miller @ 2007-07-19  4:46 UTC (permalink / raw)
  To: yoshfuji; +Cc: netdev
In-Reply-To: <20070719.112133.94748123.yoshfuji@linux-ipv6.org>

From: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>
Date: Thu, 19 Jul 2007 11:21:33 +0900 (JST)

> Please consider pulling the following commits from
> 	net-2.6-20070719-whitespace-20070719
> branch at
> 	<git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-dev.git>.

Pulled, thanks a lot.

^ permalink raw reply

* Re: Realtek RTL8111B serious performance issues
From: Bill Fink @ 2007-07-19  4:44 UTC (permalink / raw)
  To: john; +Cc: Francois Romieu, netdev
In-Reply-To: <Pine.SOC.4.64.0707181516300.19789@katana>

Hi John,

On Wed, 18 Jul 2007, john@BlueSkyTours.com wrote:

> On Wed, 18 Jul 2007, Francois Romieu wrote:
> 
> > john@BlueSkyTours.com <john@BlueSkyTours.com> :
> > [...]
> >> Anyone have any suggestions for solving this problem?
> >
> > Try 2.6.23-rc1 when it is published or apply against 2.6.22 one of:
> > http://www.fr.zoreil.com/people/francois/misc/20070628-2.6.22-rc6-r8169-test.patch
> 
> Unfortunately, the 20070628 patch did not make any difference.
> 
> 
> > http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.22-rc6/r8169-20070628/
> 
> 
> I tried various patches from that directory (aren't most or all of them
> included in the 20070628 patch?), but none of them helped either.
> 
> 
> This problem could be very difficult to track down.  Like I said, it
> definately effects emacs and firefox being "drawn" on a remote computer.
> Ping times, however, are not that bad:
> 
> PING 192.168.26.150: 56 data bytes
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=0. time=0.287 ms
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=1. time=0.279 ms
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=2. time=0.196 ms
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=3. time=0.201 ms
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=4. time=0.159 ms
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=5. time=0.148 ms
> 64 bytes from dyn26-1.blueskytours.com (192.168.26.150): icmp_seq=6. time=0.150 ms
> 
> Also, wget gets good throughput when retrieving files.
> 
> It just seems to be X traffic which is extremely slow.  Using the old
> Linksys 10/100 PCI NIC, emacs comes up virtually instantaneously.  Using the
> integrated Realtek 8111B, emacs takes 10 seconds to draw.
> 
> Thank you very much for trying to help.

Any chance that the Realtek 8111B is sharing interrupts with another
device ("cat /proc/interrupts")?  Perhaps it is, and the Linksys isn't,
which could explain the difference in behavior.  Just something simple
to check and either rule in or out.

						-Bill

^ permalink raw reply

* [PATCH 2/2] ucc_geth: add support to netif message level
From: Li Yang @ 2007-07-19  3:48 UTC (permalink / raw)
  To: jeff; +Cc: netdev, Li Yang

Adds netif message level control to the ucc_geth driver.  The level can
be set by module parameter and ethtool.

Signed-off-by: Li Yang <leoli@freescale.com>
---
 drivers/net/ucc_geth.c |  315 +++++++++++++++++++++++++++++-------------------
 1 files changed, 190 insertions(+), 125 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 4a3fd62..12e01b2 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -60,11 +60,19 @@
 #else
 #define ugeth_vdbg(fmt, args...) do { } while (0)
 #endif				/* UGETH_VERBOSE_DEBUG */
+#define UGETH_MSG_DEFAULT	(NETIF_MSG_IFUP << 1 ) - 1
 
 void uec_set_ethtool_ops(struct net_device *netdev);
 	
 static DEFINE_SPINLOCK(ugeth_lock);
 
+static struct {
+	u32 msg_enable;
+} debug = { -1 };
+
+module_param_named(debug, debug.msg_enable, int, 0);
+MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)");
+
 static struct ucc_geth_info ugeth_primary_info = {
 	.uf_info = {
 		    .bd_mem_part = MEM_PART_SYSTEM,
@@ -282,7 +290,8 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
 
 	for (i = 0; i < num_entries; i++) {
 		if ((snum = qe_get_snum()) < 0) {
-			ugeth_err("fill_init_enet_entries: Can not get SNUM.");
+			if (netif_msg_ifup(ugeth))
+				ugeth_err("fill_init_enet_entries: Can not get SNUM.");
 			return snum;
 		}
 		if ((i == 0) && skip_page_for_first_entry)
@@ -292,8 +301,8 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
 			init_enet_offset =
 			    qe_muram_alloc(thread_size, thread_alignment);
 			if (IS_ERR_VALUE(init_enet_offset)) {
-				ugeth_err
-		("fill_init_enet_entries: Can not allocate DPRAM memory.");
+				if (netif_msg_ifup(ugeth))
+					ugeth_err("fill_init_enet_entries: Can not allocate DPRAM memory.");
 				qe_put_snum((u8) snum);
 				return -ENOMEM;
 			}
@@ -1487,9 +1496,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
 
 	ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
 	if (ret_val != 0) {
-		ugeth_err
-		    ("%s: Preamble length must be between 3 and 7 inclusive.",
-		     __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.",
+			     __FUNCTION__);
 		return ret_val;
 	}
 
@@ -1727,7 +1736,8 @@ static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
 
 	/* check if the UCC number is in range. */
 	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
-		ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -1755,7 +1765,8 @@ static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode)
 
 	/* check if the UCC number is in range. */
 	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
-		ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -2307,7 +2318,9 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
 
 	if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) ||
 	      (uf_info->bd_mem_part == MEM_PART_MURAM))) {
-		ugeth_err("%s: Bad memory partition value.", __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: Bad memory partition value.",
+					__FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -2316,9 +2329,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
 		if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
 		    (ug_info->bdRingLenRx[i] %
 		     UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
-			ugeth_err
-			    ("%s: Rx BD ring length must be multiple of 4,"
-				" no smaller than 8.", __FUNCTION__);
+			if (netif_msg_probe(ugeth))
+				ugeth_err
+				    ("%s: Rx BD ring length must be multiple of 4, no smaller than 8.",
+					__FUNCTION__);
 			return -EINVAL;
 		}
 	}
@@ -2326,9 +2340,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
 	/* Tx BD lengths */
 	for (i = 0; i < ug_info->numQueuesTx; i++) {
 		if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
-			ugeth_err
-			    ("%s: Tx BD ring length must be no smaller than 2.",
-			     __FUNCTION__);
+			if (netif_msg_probe(ugeth))
+				ugeth_err
+				    ("%s: Tx BD ring length must be no smaller than 2.",
+				     __FUNCTION__);
 			return -EINVAL;
 		}
 	}
@@ -2336,31 +2351,35 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
 	/* mrblr */
 	if ((uf_info->max_rx_buf_length == 0) ||
 	    (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
-		ugeth_err
-		    ("%s: max_rx_buf_length must be non-zero multiple of 128.",
-		     __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err
+			    ("%s: max_rx_buf_length must be non-zero multiple of 128.",
+			     __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* num Tx queues */
 	if (ug_info->numQueuesTx > NUM_TX_QUEUES) {
-		ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* num Rx queues */
 	if (ug_info->numQueuesRx > NUM_RX_QUEUES) {
-		ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* l2qt */
 	for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
 		if (ug_info->l2qt[i] >= ug_info->numQueuesRx) {
-			ugeth_err
-			    ("%s: VLAN priority table entry must not be"
-				" larger than number of Rx queues.",
-			     __FUNCTION__);
+			if (netif_msg_probe(ugeth))
+				ugeth_err
+				    ("%s: VLAN priority table entry must not be"
+					" larger than number of Rx queues.",
+				     __FUNCTION__);
 			return -EINVAL;
 		}
 	}
@@ -2368,26 +2387,29 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
 	/* l3qt */
 	for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
 		if (ug_info->l3qt[i] >= ug_info->numQueuesRx) {
-			ugeth_err
-			    ("%s: IP priority table entry must not be"
-				" larger than number of Rx queues.",
-			     __FUNCTION__);
+			if (netif_msg_probe(ugeth))
+				ugeth_err
+				    ("%s: IP priority table entry must not be"
+					" larger than number of Rx queues.",
+				     __FUNCTION__);
 			return -EINVAL;
 		}
 	}
 
 	if (ug_info->cam && !ug_info->ecamptr) {
-		ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
-			  __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
+				  __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if ((ug_info->numStationAddresses !=
 	     UCC_GETH_NUM_OF_STATION_ADDRESSES_1)
 	    && ug_info->rxExtendedFiltering) {
-		ugeth_err("%s: Number of station addresses greater than 1 "
-			  "not allowed in extended parsing mode.",
-			  __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: Number of station addresses greater than 1 "
+				  "not allowed in extended parsing mode.",
+				  __FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -2400,7 +2422,8 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
 		uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
 	/* Initialize the general fast UCC block. */
 	if (ucc_fast_init(uf_info, &ugeth->uccf)) {
-		ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -2453,7 +2476,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 		numThreadsRxNumerical = 8;
 		break;
 	default:
-		ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Bad number of Rx threads value.",
+				       	__FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -EINVAL;
 		break;
@@ -2476,7 +2501,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 		numThreadsTxNumerical = 8;
 		break;
 	default:
-		ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Bad number of Tx threads value.",
+				       	__FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -EINVAL;
 		break;
@@ -2528,8 +2555,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 					      ug_info->backToBackInterFrameGap,
 					      &ug_regs->ipgifg);
 	if (ret_val != 0) {
-		ugeth_err("%s: IPGIFG initialization parameter too large.",
-			  __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: IPGIFG initialization parameter too large.",
+				  __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return ret_val;
 	}
@@ -2545,7 +2573,8 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 					  ug_info->collisionWindow,
 					  &ug_regs->hafdup);
 	if (ret_val != 0) {
-		ugeth_err("%s: Half Duplex initialization parameter too large.",
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Half Duplex initialization parameter too large.",
 			  __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return ret_val;
@@ -2598,9 +2627,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 							 tx_bd_ring_offset[j]);
 		}
 		if (!ugeth->p_tx_bd_ring[j]) {
-			ugeth_err
-			    ("%s: Can not allocate memory for Tx bd rings.",
-			     __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err
+				    ("%s: Can not allocate memory for Tx bd rings.",
+				     __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2633,9 +2663,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 							 rx_bd_ring_offset[j]);
 		}
 		if (!ugeth->p_rx_bd_ring[j]) {
-			ugeth_err
-			    ("%s: Can not allocate memory for Rx bd rings.",
-			     __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err
+				    ("%s: Can not allocate memory for Rx bd rings.",
+				     __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2649,8 +2680,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 					      GFP_KERNEL);
 
 		if (ugeth->tx_skbuff[j] == NULL) {
-			ugeth_err("%s: Could not allocate tx_skbuff",
-				  __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err("%s: Could not allocate tx_skbuff",
+					  __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2680,8 +2712,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 					      GFP_KERNEL);
 
 		if (ugeth->rx_skbuff[j] == NULL) {
-			ugeth_err("%s: Could not allocate rx_skbuff",
-				  __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err("%s: Could not allocate rx_skbuff",
+					  __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2712,9 +2745,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	    qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram),
 			   UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -2734,9 +2768,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 			   32 * (numThreadsTxNumerical == 1),
 			   UCC_GETH_THREAD_DATA_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -2762,9 +2797,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 			   sizeof(struct ucc_geth_send_queue_qd),
 			   UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -2805,9 +2841,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 		    qe_muram_alloc(sizeof(struct ucc_geth_scheduler),
 				   UCC_GETH_SCHEDULER_ALIGNMENT);
 		if (IS_ERR_VALUE(ugeth->scheduler_offset)) {
-			ugeth_err
-			 ("%s: Can not allocate DPRAM memory for p_scheduler.",
-			     __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err
+				 ("%s: Can not allocate DPRAM memory for p_scheduler.",
+				     __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2853,9 +2890,11 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 				   (struct ucc_geth_tx_firmware_statistics_pram),
 				   UCC_GETH_TX_STATISTICS_ALIGNMENT);
 		if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) {
-			ugeth_err
-			    ("%s: Can not allocate DPRAM memory for"
-				" p_tx_fw_statistics_pram.", __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err
+				    ("%s: Can not allocate DPRAM memory for"
+					" p_tx_fw_statistics_pram.",
+				       	__FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2892,9 +2931,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	    qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram),
 			   UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -2913,9 +2953,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 			   sizeof(struct ucc_geth_thread_data_rx),
 			   UCC_GETH_THREAD_DATA_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -2936,9 +2977,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 				   (struct ucc_geth_rx_firmware_statistics_pram),
 				   UCC_GETH_RX_STATISTICS_ALIGNMENT);
 		if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) {
-			ugeth_err
-				("%s: Can not allocate DPRAM memory for"
-				" p_rx_fw_statistics_pram.", __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err
+					("%s: Can not allocate DPRAM memory for"
+					" p_rx_fw_statistics_pram.", __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -2958,9 +3000,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 			   sizeof(struct ucc_geth_rx_interrupt_coalescing_entry)
 			   + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for"
-			" p_rx_irq_coalescing_tbl.", __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for"
+				" p_rx_irq_coalescing_tbl.", __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -3026,9 +3069,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 			    sizeof(struct ucc_geth_rx_prefetched_bds)),
 			   UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
 	if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -3103,8 +3147,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	/* initialize extended filtering */
 	if (ug_info->rxExtendedFiltering) {
 		if (!ug_info->extendedFilteringChainPointer) {
-			ugeth_err("%s: Null Extended Filtering Chain Pointer.",
-				  __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err("%s: Null Extended Filtering Chain Pointer.",
+					  __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -EINVAL;
 		}
@@ -3115,9 +3160,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 		    qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram),
 		UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
 		if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) {
-			ugeth_err
-				("%s: Can not allocate DPRAM memory for"
-				" p_exf_glbl_param.", __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err
+					("%s: Can not allocate DPRAM memory for"
+					" p_exf_glbl_param.", __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return -ENOMEM;
 		}
@@ -3162,9 +3208,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	 */
 	if (!(ugeth->p_init_enet_param_shadow =
 	      kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) {
-		ugeth_err
-		    ("%s: Can not allocate memory for"
-			" p_UccInitEnetParamShadows.", __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate memory for"
+				" p_UccInitEnetParamShadows.", __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -3197,8 +3244,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 		QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
 	    && (ug_info->largestexternallookupkeysize !=
 		QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
-		ugeth_err("%s: Invalid largest External Lookup Key Size.",
-			  __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Invalid largest External Lookup Key Size.",
+				  __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -EINVAL;
 	}
@@ -3223,8 +3271,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 		/* Rx needs one extra for terminator */
 		, size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT,
 		ug_info->riscRx, 1)) != 0) {
-			ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
-				__FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+				ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+					__FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return ret_val;
 	}
@@ -3238,8 +3287,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 				    sizeof(struct ucc_geth_thread_tx_pram),
 				    UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
 				    ug_info->riscTx, 0)) != 0) {
-		ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
-			  __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+				  __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return ret_val;
 	}
@@ -3247,8 +3297,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	/* Load Rx bds with buffers */
 	for (i = 0; i < ug_info->numQueuesRx; i++) {
 		if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
-			ugeth_err("%s: Can not fill Rx bds with buffers.",
-				  __FUNCTION__);
+			if (netif_msg_ifup(ugeth))
+				ugeth_err("%s: Can not fill Rx bds with buffers.",
+					  __FUNCTION__);
 			ucc_geth_memclean(ugeth);
 			return ret_val;
 		}
@@ -3257,9 +3308,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	/* Allocate InitEnet command parameter structure */
 	init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4);
 	if (IS_ERR_VALUE(init_enet_pram_offset)) {
-		ugeth_err
-		    ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
-		     __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
+			     __FUNCTION__);
 		ucc_geth_memclean(ugeth);
 		return -ENOMEM;
 	}
@@ -3429,8 +3481,9 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
 		if (!skb ||
 		    (!(bd_status & (R_F | R_L))) ||
 		    (bd_status & R_ERRORS_FATAL)) {
-			ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x",
-				   __FUNCTION__, __LINE__, (u32) skb);
+			if (netif_msg_rx_err(ugeth))
+				ugeth_err("%s, %d: ERROR!!! skb - 0x%08x",
+					   __FUNCTION__, __LINE__, (u32) skb);
 			if (skb)
 				dev_kfree_skb_any(skb);
 
@@ -3459,7 +3512,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
 
 		skb = get_new_skb(ugeth, bd);
 		if (!skb) {
-			ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__);
+			if (netif_msg_rx_err(ugeth))
+				ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__);
 			ugeth->stats.rx_dropped++;
 			break;
 		}
@@ -3650,28 +3704,32 @@ static int ucc_geth_open(struct net_device *dev)
 
 	/* Test station address */
 	if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
-		ugeth_err("%s: Multicast address used for station address"
-			  " - is this what you wanted?", __FUNCTION__);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Multicast address used for station address"
+				  " - is this what you wanted?", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	err = ucc_struct_init(ugeth);
 	if (err) {
-		ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name);
 		return err;
 	}
 
 	err = ucc_geth_startup(ugeth);
 	if (err) {
-		ugeth_err("%s: Cannot configure net device, aborting.",
-			  dev->name);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Cannot configure net device, aborting.",
+				  dev->name);
 		return err;
 	}
 
 	err = adjust_enet_interface(ugeth);
 	if (err) {
-		ugeth_err("%s: Cannot configure net device, aborting.",
-			  dev->name);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Cannot configure net device, aborting.",
+				  dev->name);
 		return err;
 	}
 
@@ -3688,7 +3746,8 @@ static int ucc_geth_open(struct net_device *dev)
 
 	err = init_phy(dev);
 	if (err) {
-		ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name);
 		return err;
 	}
 
@@ -3698,15 +3757,17 @@ static int ucc_geth_open(struct net_device *dev)
 	    request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0,
 			"UCC Geth", dev);
 	if (err) {
-		ugeth_err("%s: Cannot get IRQ for net device, aborting.",
-			  dev->name);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Cannot get IRQ for net device, aborting.",
+				  dev->name);
 		ucc_geth_stop(ugeth);
 		return err;
 	}
 
 	err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
 	if (err) {
-		ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
+		if (netif_msg_ifup(ugeth))
+			ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
 		ucc_geth_stop(ugeth);
 		return err;
 	}
@@ -3789,6 +3850,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 		return -ENODEV;
 
 	ug_info = &ugeth_info[ucc_num];
+	if (ug_info == NULL) {
+		if (netif_msg_probe(&debug))
+			ugeth_err("%s: [%d] Missing additional data!",
+				       	__FUNCTION__, ucc_num);
+		return -ENODEV;
+	}
+
 	ug_info->uf_info.ucc_num = ucc_num;
 
 	prop = of_get_property(np, "rx-clock", NULL);
@@ -3867,15 +3935,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 
 	ug_info->mdio_bus = res.start;
 
-	printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n",
-		ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs,
-		ug_info->uf_info.irq);
-
-	if (ug_info == NULL) {
-		ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__,
-			  ucc_num);
-		return -ENODEV;
-	}
+	if (netif_msg_probe(&debug))
+		printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n",
+			ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs,
+			ug_info->uf_info.irq);
 
 	/* Create an ethernet device instance */
 	dev = alloc_etherdev(sizeof(*ugeth));
@@ -3910,14 +3973,15 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 	dev->mtu = 1500;
 	dev->set_multicast_list = ucc_geth_set_multi;
 
-	ugeth->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
+	ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT);
 	ugeth->phy_interface = phy_interface;
 	ugeth->max_speed = max_speed;
 
 	err = register_netdev(dev);
 	if (err) {
-		ugeth_err("%s: Cannot register net device, aborting.",
-			  dev->name);
+		if (netif_msg_probe(ugeth))
+			ugeth_err("%s: Cannot register net device, aborting.",
+				  dev->name);
 		free_netdev(dev);
 		return err;
 	}
@@ -3971,7 +4035,8 @@ static int __init ucc_geth_init(void)
 	if (ret)
 		return ret;
 
-	printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
+	if (netif_msg_drv(&debug))
+		printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
 	for (i = 0; i < 8; i++)
 		memcpy(&(ugeth_info[i]), &ugeth_primary_info,
 		       sizeof(ugeth_primary_info));
-- 
1.5.2.GIT


^ permalink raw reply related

* [PATCH 1/2] ucc_geth: add ethtool support
From: Li Yang @ 2007-07-19  3:47 UTC (permalink / raw)
  To: jeff; +Cc: netdev, Li Yang

The patch enables statistics in ucc_geth and adds ethtool support to
ucc_geth driver.

Signed-off-by: Li Yang <leoli@freescale.com>
---
 drivers/net/Makefile           |    2 +-
 drivers/net/ucc_geth.c         |   19 +-
 drivers/net/ucc_geth.h         |    6 +
 drivers/net/ucc_geth_ethtool.c |  388 ++++++++++++++++++++++++++++++++++++++++
 drivers/net/ucc_geth_mii.c     |    6 +-
 5 files changed, 407 insertions(+), 14 deletions(-)
 create mode 100644 drivers/net/ucc_geth_ethtool.c

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index eb41676..d69f07c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -18,7 +18,7 @@ gianfar_driver-objs := gianfar.o \
 		gianfar_sysfs.o
 
 obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
-ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o ucc_geth_ethtool.o
 
 #
 # link order important here
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index e4736a3..4a3fd62 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -43,10 +43,6 @@
 
 #undef DEBUG
 
-#define DRV_DESC "QE UCC Gigabit Ethernet Controller"
-#define DRV_NAME "ucc_geth"
-#define DRV_VERSION "1.1"
-
 #define ugeth_printk(level, format, arg...)  \
         printk(level format "\n", ## arg)
 
@@ -65,6 +61,8 @@
 #define ugeth_vdbg(fmt, args...) do { } while (0)
 #endif				/* UGETH_VERBOSE_DEBUG */
 
+void uec_set_ethtool_ops(struct net_device *netdev);
+	
 static DEFINE_SPINLOCK(ugeth_lock);
 
 static struct ucc_geth_info ugeth_primary_info = {
@@ -104,6 +102,7 @@ static struct ucc_geth_info ugeth_primary_info = {
 	.maxRetransmission = 0xf,
 	.collisionWindow = 0x37,
 	.receiveFlowControl = 1,
+	.transmitFlowControl = 1,
 	.maxGroupAddrInHash = 4,
 	.maxIndAddrInHash = 4,
 	.prel = 7,
@@ -139,7 +138,9 @@ static struct ucc_geth_info ugeth_primary_info = {
 	.numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
 	.largestexternallookupkeysize =
 	    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
-	.statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE,
+	.statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE |
+		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX |
+		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX,
 	.vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
 	.vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
 	.rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
@@ -1200,7 +1201,7 @@ static int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
 	return 0;
 }
 
-static int init_flow_control_params(u32 automatic_flow_control_mode,
+int init_flow_control_params(u32 automatic_flow_control_mode,
 				    int rx_flow_control_enable,
 				    int tx_flow_control_enable,
 				    u16 pause_period,
@@ -2507,7 +2508,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	/* For more details see the hardware spec.           */
 	init_flow_control_params(ug_info->aufc,
 				 ug_info->receiveFlowControl,
-				 1,
+				 ug_info->transmitFlowControl,
 				 ug_info->pausePeriod,
 				 ug_info->extensionField,
 				 &uf_regs->upsmr,
@@ -3732,8 +3733,6 @@ static int ucc_geth_close(struct net_device *dev)
 	return 0;
 }
 
-const struct ethtool_ops ucc_geth_ethtool_ops = { };
-
 static phy_interface_t to_phy_interface(const char *phy_connection_type)
 {
 	if (strcasecmp(phy_connection_type, "mii") == 0)
@@ -3896,6 +3895,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 	SET_NETDEV_DEV(dev, device);
 
 	/* Fill in the dev structure */
+	uec_set_ethtool_ops(dev);
 	dev->open = ucc_geth_open;
 	dev->hard_start_xmit = ucc_geth_start_xmit;
 	dev->tx_timeout = ucc_geth_timeout;
@@ -3909,7 +3909,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 //    dev->change_mtu = ucc_geth_change_mtu;
 	dev->mtu = 1500;
 	dev->set_multicast_list = ucc_geth_set_multi;
-	dev->ethtool_ops = &ucc_geth_ethtool_ops;
 
 	ugeth->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
 	ugeth->phy_interface = phy_interface;
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index a29e1c3..bb4dac8 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -30,6 +30,10 @@
 
 #include "ucc_geth_mii.h"
 
+#define DRV_DESC "QE UCC Gigabit Ethernet Controller"
+#define DRV_NAME "ucc_geth"
+#define DRV_VERSION "1.1"
+
 #define NUM_TX_QUEUES                   8
 #define NUM_RX_QUEUES                   8
 #define NUM_BDS_IN_PREFETCHED_BDS       4
@@ -896,6 +900,7 @@ struct ucc_geth_hardware_statistics {
 #define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX        8
 #define UCC_GETH_RX_BD_RING_SIZE_MIN            8
 #define UCC_GETH_TX_BD_RING_SIZE_MIN            2
+#define UCC_GETH_BD_RING_SIZE_MAX		0xffff
 
 #define UCC_GETH_SIZE_OF_BD                     QE_SIZEOF_BD
 
@@ -1135,6 +1140,7 @@ struct ucc_geth_info {
 	int bro;
 	int ecm;
 	int receiveFlowControl;
+	int transmitFlowControl;
 	u8 maxGroupAddrInHash;
 	u8 maxIndAddrInHash;
 	u8 prel;
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c
new file mode 100644
index 0000000..a8994c7
--- /dev/null
+++ b/drivers/net/ucc_geth_ethtool.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Description: QE UCC Gigabit Ethernet Ethtool API Set
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ *
+ * Limitation: 
+ * Can only get/set setttings of the first queue.
+ * Need to re-open the interface manually after changing some paramters.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_mii.h"
+
+static char hw_stat_gstrings[][ETH_GSTRING_LEN] = {
+	"tx-64-frames",
+	"tx-65-127-frames",
+	"tx-128-255-frames",
+	"rx-64-frames",
+	"rx-65-127-frames",
+	"rx-128-255-frames",
+	"tx-bytes-ok",
+	"tx-pause-frames",
+	"tx-multicast-frames",
+	"tx-broadcast-frames",
+	"rx-frames",
+	"rx-bytes-ok",
+	"rx-bytes-all",
+	"rx-multicast-frames",
+	"rx-broadcast-frames",
+	"stats-counter-carry",
+	"stats-counter-mask",
+	"rx-dropped-frames",
+};
+
+static char tx_fw_stat_gstrings[][ETH_GSTRING_LEN] = {
+	"tx-single-collision",
+	"tx-multiple-collision",
+	"tx-late-collsion",
+	"tx-aborted-frames",
+	"tx-lost-frames",
+	"tx-carrier-sense-errors",
+	"tx-frames-ok",
+	"tx-excessive-differ-frames",
+	"tx-256-511-frames",
+	"tx-1024-1518-frames",
+	"tx-jumbo-frames",
+};
+
+static char rx_fw_stat_gstrings[][ETH_GSTRING_LEN] = {
+	"rx-crc-errors",
+	"rx-alignment-errors",
+	"rx-in-range-length-errors",
+	"rx-out-of-range-length-errors",
+	"rx-too-long-frames",
+	"rx-runt",
+	"rx-very-long-event",
+	"rx-symbol-errors",
+	"rx-busy-drop-frames",
+	"reserved",
+	"reserved",
+	"rx-mismatch-drop-frames",
+	"rx-small-than-64",
+	"rx-256-511-frames",
+	"rx-512-1023-frames",
+	"rx-1024-1518-frames",
+	"rx-jumbo-frames",
+	"rx-mac-error-loss",
+	"rx-pause-frames",
+	"reserved",
+	"rx-vlan-removed",
+	"rx-vlan-replaced",
+	"rx-vlan-inserted",
+	"rx-ip-checksum-errors",
+};
+
+#define UEC_HW_STATS_LEN ARRAY_SIZE(hw_stat_gstrings)
+#define UEC_TX_FW_STATS_LEN ARRAY_SIZE(tx_fw_stat_gstrings)
+#define UEC_RX_FW_STATS_LEN ARRAY_SIZE(rx_fw_stat_gstrings)
+
+extern int init_flow_control_params(u32 automatic_flow_control_mode,
+		int rx_flow_control_enable,
+		int tx_flow_control_enable, u16 pause_period,
+		u16 extension_field, volatile u32 *upsmr_register,
+		volatile u32 *uempr_register, volatile u32 *maccfg1_register);
+
+static int
+uec_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	struct phy_device *phydev = ugeth->phydev;
+	struct ucc_geth_info *ug_info = ugeth->ug_info;
+
+	if (!phydev)
+		return -ENODEV;
+
+	ecmd->maxtxpkt = 1;
+	ecmd->maxrxpkt = ug_info->interruptcoalescingmaxvalue[0];
+
+	return phy_ethtool_gset(phydev, ecmd);
+}
+
+static int
+uec_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	struct phy_device *phydev = ugeth->phydev;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, ecmd);
+}
+
+static void
+uec_get_pauseparam(struct net_device *netdev,
+                     struct ethtool_pauseparam *pause)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+
+	pause->autoneg = ugeth->phydev->autoneg;
+
+	if (ugeth->ug_info->receiveFlowControl)
+		pause->rx_pause = 1;
+	if (ugeth->ug_info->transmitFlowControl)
+		pause->tx_pause = 1;
+}
+
+static int
+uec_set_pauseparam(struct net_device *netdev,
+                     struct ethtool_pauseparam *pause)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	int ret = 0;
+
+	ugeth->ug_info->receiveFlowControl = pause->rx_pause;
+	ugeth->ug_info->transmitFlowControl = pause->tx_pause;
+	
+	if (ugeth->phydev->autoneg) {
+		if (netif_running(netdev)) {
+			/* FIXME: automatically restart */
+			printk(KERN_INFO
+				"Please re-open the interface.\n");
+		}
+	} else {
+		struct ucc_geth_info *ug_info = ugeth->ug_info;
+
+		ret = init_flow_control_params(ug_info->aufc,
+					ug_info->receiveFlowControl,
+					ug_info->transmitFlowControl,
+					ug_info->pausePeriod,
+					ug_info->extensionField,
+					&ugeth->uccf->uf_regs->upsmr,
+					&ugeth->ug_regs->uempr,
+					&ugeth->ug_regs->maccfg1);
+	}
+
+	return ret;
+}
+
+static uint32_t
+uec_get_msglevel(struct net_device *netdev)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	return ugeth->msg_enable;
+}
+
+static void
+uec_set_msglevel(struct net_device *netdev, uint32_t data)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	ugeth->msg_enable = data;
+}
+
+static int
+uec_get_regs_len(struct net_device *netdev)
+{
+	return sizeof(struct ucc_geth);
+}
+
+static void
+uec_get_regs(struct net_device *netdev,
+               struct ethtool_regs *regs, void *p)
+{
+	int i;
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	u32 __iomem *ug_regs = (u32 __iomem *)ugeth->ug_regs;
+	u32 *buff = p;
+
+	for (i = 0; i < sizeof(struct ucc_geth) / sizeof(u32); i++)
+		buff[i] = in_be32(&ug_regs[i]);
+}
+
+static void
+uec_get_ringparam(struct net_device *netdev,
+                    struct ethtool_ringparam *ring)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	struct ucc_geth_info *ug_info = ugeth->ug_info;
+	int queue = 0;
+
+	ring->rx_max_pending = UCC_GETH_BD_RING_SIZE_MAX;
+	ring->rx_mini_max_pending = UCC_GETH_BD_RING_SIZE_MAX;
+	ring->rx_jumbo_max_pending = UCC_GETH_BD_RING_SIZE_MAX;
+	ring->tx_max_pending = UCC_GETH_BD_RING_SIZE_MAX;
+
+	ring->rx_pending = ug_info->bdRingLenRx[queue];
+	ring->rx_mini_pending = ug_info->bdRingLenRx[queue];
+	ring->rx_jumbo_pending = ug_info->bdRingLenRx[queue];
+	ring->tx_pending = ug_info->bdRingLenTx[queue];
+}
+
+static int
+uec_set_ringparam(struct net_device *netdev,
+                    struct ethtool_ringparam *ring)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	struct ucc_geth_info *ug_info = ugeth->ug_info;
+	int queue = 0, ret = 0;
+
+	if (ring->rx_pending < UCC_GETH_RX_BD_RING_SIZE_MIN) {
+		printk("%s: RxBD ring size must be no smaller than %d.\n",
+			       	netdev->name, UCC_GETH_RX_BD_RING_SIZE_MIN);
+		return -EINVAL;
+	}
+	if (ring->rx_pending % UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT) {
+		printk("%s: RxBD ring size must be multiple of %d.\n",
+			netdev->name, UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT);
+		return -EINVAL;
+	}
+	if (ring->tx_pending < UCC_GETH_TX_BD_RING_SIZE_MIN) {
+		printk("%s: TxBD ring size must be no smaller than %d.\n",
+				netdev->name, UCC_GETH_TX_BD_RING_SIZE_MIN);
+		return -EINVAL;
+	}
+
+	ug_info->bdRingLenRx[queue] = ring->rx_pending;
+	ug_info->bdRingLenTx[queue] = ring->tx_pending;
+
+	if (netif_running(netdev)) {
+		/* FIXME: restart automatically */
+		printk(KERN_INFO
+			"Please re-open the interface.\n");
+	}
+
+	return ret;
+}
+
+static int uec_get_stats_count(struct net_device *netdev)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	u32 stats_mode = ugeth->ug_info->statisticsMode;
+	int len = 0;
+
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE)
+		len += UEC_HW_STATS_LEN;
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX)
+		len += UEC_TX_FW_STATS_LEN;
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX)
+		len += UEC_RX_FW_STATS_LEN;
+
+	return len;
+}
+
+static void uec_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	u32 stats_mode = ugeth->ug_info->statisticsMode;
+
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
+		memcpy(buf, hw_stat_gstrings, UEC_HW_STATS_LEN *
+			       	ETH_GSTRING_LEN);
+		buf += UEC_HW_STATS_LEN * ETH_GSTRING_LEN;
+	}
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
+		memcpy(buf, tx_fw_stat_gstrings, UEC_TX_FW_STATS_LEN *
+			       	ETH_GSTRING_LEN);
+		buf += UEC_TX_FW_STATS_LEN * ETH_GSTRING_LEN;
+	}
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX)
+		memcpy(buf, tx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN *
+			       	ETH_GSTRING_LEN);
+}
+
+static void uec_get_ethtool_stats(struct net_device *netdev,
+		struct ethtool_stats *stats, uint64_t *data)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+	u32 stats_mode = ugeth->ug_info->statisticsMode;
+	u32 __iomem *base;
+	int i, j = 0;
+
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
+		base = (u32 __iomem *)&ugeth->ug_regs->tx64;
+		for (i = 0; i < UEC_HW_STATS_LEN; i++)
+			data[j++] = (u64)in_be32(&base[i]);
+	}
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
+		base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram;
+		for (i = 0; i < UEC_TX_FW_STATS_LEN; i++)
+			data[j++] = (u64)in_be32(&base[i]);
+	}
+	if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
+		base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram;
+		for (i = 0; i < UEC_RX_FW_STATS_LEN; i++)
+			data[j++] = (u64)in_be32(&base[i]);
+	}
+}
+
+static int uec_nway_reset(struct net_device *netdev)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(netdev);
+
+	return phy_start_aneg(ugeth->phydev);
+}
+
+/* Report driver information */
+static void
+uec_get_drvinfo(struct net_device *netdev,
+                       struct ethtool_drvinfo *drvinfo)
+{
+	strncpy(drvinfo->driver, DRV_NAME, 32);
+	strncpy(drvinfo->version, DRV_VERSION, 32);
+	strncpy(drvinfo->fw_version, "N/A", 32);
+	strncpy(drvinfo->bus_info, "QUICC ENGINE", 32);
+	drvinfo->n_stats = uec_get_stats_count(netdev);
+	drvinfo->testinfo_len = 0;
+	drvinfo->eedump_len = 0;
+	drvinfo->regdump_len = uec_get_regs_len(netdev);
+}
+
+static const struct ethtool_ops uec_ethtool_ops = {
+	.get_settings           = uec_get_settings,
+	.set_settings           = uec_set_settings,
+	.get_drvinfo            = uec_get_drvinfo,
+	.get_regs_len           = uec_get_regs_len,
+	.get_regs               = uec_get_regs,
+	.get_msglevel           = uec_get_msglevel,
+	.set_msglevel           = uec_set_msglevel,
+	.nway_reset             = uec_nway_reset,
+	.get_link               = ethtool_op_get_link,
+	.get_ringparam          = uec_get_ringparam,
+	.set_ringparam          = uec_set_ringparam,
+	.get_pauseparam         = uec_get_pauseparam,
+	.set_pauseparam         = uec_set_pauseparam,
+	.get_sg                 = ethtool_op_get_sg,
+	.set_sg                 = ethtool_op_set_sg,
+	.get_tso                = ethtool_op_get_tso,
+	.get_stats_count        = uec_get_stats_count,
+	.get_strings            = uec_get_strings,
+	.get_ethtool_stats      = uec_get_ethtool_stats,
+	.get_perm_addr          = ethtool_op_get_perm_addr,
+};
+
+void uec_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &uec_ethtool_ops);
+}
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index 7bcb82f..5f8c2d3 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -54,8 +54,8 @@
 #define vdbg(format, arg...) do {} while(0)
 #endif
 
-#define DRV_DESC "QE UCC Ethernet Controller MII Bus"
-#define DRV_NAME "fsl-uec_mdio"
+#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus"
+#define MII_DRV_NAME "fsl-uec_mdio"
 
 /* Write value to the PHY for this device to the register at regnum, */
 /* waiting until the write is done before it returns.  All PHY */
@@ -261,7 +261,7 @@ static struct of_device_id uec_mdio_match[] = {
 };
 
 static struct of_platform_driver uec_mdio_driver = {
-	.name	= DRV_NAME,
+	.name	= MII_DRV_NAME,
 	.probe	= uec_mdio_probe,
 	.remove	= uec_mdio_remove,
 	.match_table	= uec_mdio_match,
-- 
1.5.2.GIT


^ permalink raw reply related

* Re: ANNOUNCE: igb: Intel 82575 Gigabit Ethernet driver (PCI-Express)
From: Jeff Garzik @ 2007-07-19  3:00 UTC (permalink / raw)
  To: Kok, Auke; +Cc: NetDev, Arjan van de Ven, Ronciak, John, Mitch Williams
In-Reply-To: <46980ADA.5050104@intel.com>

Kok, Auke wrote:
> 
> 
> All,
> 
> We are pleased to announce a new Gigabit Ethernet product and its driver 
> to the
> linux community. This product is the Intel(R) 82575 Gigabit Ethernet 
> adapter
> family. Physical adapters will be available to the public soon. These 
> adapters
> come in 2- and 4-port versions (copper PHY) currently. Other variants 
> will be
> available later.
> 
> The 82575 chipset supports significantly different features that warrant 
> a new
> driver. The descriptor format is (just like the ixgbe driver) different. 
> The
> device can use multiple MSI-X vectors and multiple queues for both send and
> receive. This allows us to optimize some of the driver code specifically 
> as well
> compared to the e1000-supported devices.
> 
> This driver was forked from e1000 several months ago and extensively 
> reworked
> and cleaned up since. The driver was also tested on several platforms in 
> our
> validation labs.
> 
> Allthough some of the codebase is currently shared with the e1000 driver 
> (this
> igb driver has a copy of that code where needed), we realize that many 
> of the
> changes that we are discussing for e1000 (the pci-express adapters that 
> e1000
> supports particularly) will also apply to this driver. However, since 
> this is a
> completely new driver that is relatively free of all old NIC support, we 
> feel
> that it is currently the right time to post this driver.
> 
> Unfortunately, the patch to insert this driver is too large to send to 
> netdev. I
> have therefore posted the patch on http:
> 
>      http://foo-projects.org/~sofar/igb.patch       [558K]
>      http://foo-projects.org/~sofar/igb.patch.bz2   [98K]

Just took a look at this.

This has the same problem as in the other thread -- huge internal API -- 
except this time, the problem is emphasized by the fact that the 
majority of the API hooks only have a single user, making each hook and 
API entry point demonstrably useless overhead.

Please remove the useless internal API and resubmit.

PLEASE take a look at how bnx2 and tg3 are structured.

	Jeff




^ permalink raw reply

* [TG3]: Fix msi issue with kexec/kdump.
From: Michael Chan @ 2007-07-19  3:40 UTC (permalink / raw)
  To: davem; +Cc: tina.yang, netdev

[TG3]: Fix msi issue with kexec/kdump.

Tina Yang <tina.yang@oracle.com> discovered an MSI related problem
when doing kdump.  The problem is that the kexec kernel is booted
without going through system reset, and as a result, MSI may already
be enabled when tg3_init_one() is called.  tg3_init_one() calls
pci_save_state() which will save the stale MSI state.  Later on in
tg3_open(), we call pci_enable_msi() to reconfigure MSI on the chip
before we reset the chip.  After chip reset, we call
pci_restore_state() which will put the stale MSI address/data back
onto the chip.

This is no longer a problem in the latest kernel because
pci_restore_state() has been changed to restore MSI state from
internal data structures which will guarantee restoring the proper
MSI state.

But I think we should still fix it.  Our save and restore sequence
can still cause very subtle problems down the road.  The fix is to
have our own functions save and restore precisely what we need.  We
also change it to save and restore state inside tg3_chip_reset() in a
more straight forward way.

Thanks to Tina for helping to test and debug the problem.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5ee1476..7b362ed 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4847,6 +4847,59 @@ static int tg3_poll_fw(struct tg3 *tp)
 	return 0;
 }
 
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{
+	u32 val;
+
+	pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
+	tp->pci_cmd = val;
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{
+	u32 val;
+
+	/* Re-enable indirect register accesses. */
+	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+			       tp->misc_host_ctrl);
+
+	/* Set MAX PCI retry to zero. */
+	val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
+		val |= PCISTATE_RETRY_SAME_DMA;
+	pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+	pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+
+	/* Make sure PCI-X relaxed ordering bit is clear. */
+	pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
+	val &= ~PCIX_CAPS_RELAXED_ORDERING;
+	pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
+
+	if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+		u32 val;
+
+		/* Chip reset on 5780 will reset MSI enable bit,
+		 * so need to restore it.
+		 */
+		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+			u16 ctrl;
+
+			pci_read_config_word(tp->pdev,
+					     tp->msi_cap + PCI_MSI_FLAGS,
+					     &ctrl);
+			pci_write_config_word(tp->pdev,
+					      tp->msi_cap + PCI_MSI_FLAGS,
+					      ctrl | PCI_MSI_FLAGS_ENABLE);
+			val = tr32(MSGINT_MODE);
+			tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
+		}
+	}
+}
+
 static void tg3_stop_fw(struct tg3 *);
 
 /* tp->lock is held. */
@@ -4863,6 +4916,12 @@ static int tg3_chip_reset(struct tg3 *tp)
 	 */
 	tp->nvram_lock_cnt = 0;
 
+	/* GRC_MISC_CFG core clock reset will clear the memory
+	 * enable bit in PCI register 4 and the MSI enable bit
+	 * on some chips, so we save relevant registers here.
+	 */
+	tg3_save_pci_state(tp);
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
@@ -4961,50 +5020,14 @@ static int tg3_chip_reset(struct tg3 *tp)
 		pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
 	}
 
-	/* Re-enable indirect register accesses. */
-	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-			       tp->misc_host_ctrl);
-
-	/* Set MAX PCI retry to zero. */
-	val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
-	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
-	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
-		val |= PCISTATE_RETRY_SAME_DMA;
-	pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
-
-	pci_restore_state(tp->pdev);
+	tg3_restore_pci_state(tp);
 
 	tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
 
-	/* Make sure PCI-X relaxed ordering bit is clear. */
-	pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
-	val &= ~PCIX_CAPS_RELAXED_ORDERING;
-	pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
-
-	if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
-		u32 val;
-
-		/* Chip reset on 5780 will reset MSI enable bit,
-		 * so need to restore it.
-		 */
-		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-			u16 ctrl;
-
-			pci_read_config_word(tp->pdev,
-					     tp->msi_cap + PCI_MSI_FLAGS,
-					     &ctrl);
-			pci_write_config_word(tp->pdev,
-					      tp->msi_cap + PCI_MSI_FLAGS,
-					      ctrl | PCI_MSI_FLAGS_ENABLE);
-			val = tr32(MSGINT_MODE);
-			tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
-		}
-
+	val = 0;
+	if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
 		val = tr32(MEMARB_MODE);
-		tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
-
-	} else
-		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+	tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
 		tg3_stop_fw(tp);
@@ -11978,7 +12001,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	 */
 	if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
 	    (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
-		pci_save_state(tp->pdev);
 		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
 		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 	}
@@ -12007,12 +12029,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
 	tg3_init_coal(tp);
 
-	/* Now that we have fully setup the chip, save away a snapshot
-	 * of the PCI config space.  We need to restore this after
-	 * GRC_MISC_CFG core clock resets and some resume events.
-	 */
-	pci_save_state(tp->pdev);
-
 	pci_set_drvdata(pdev, dev);
 
 	err = register_netdev(dev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d84e75e..5c21f49 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2345,6 +2345,7 @@ struct tg3 {
 #define PHY_REV_BCM5411_X0		0x1 /* Found on Netgear GA302T */
 
 	u32				led_ctrl;
+	u32				pci_cmd;
 
 	char				board_part_number[24];
 	char				fw_ver[16];



^ permalink raw reply related

* [GIT PULL] [NET]: Whitespace fixes
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2007-07-19  2:21 UTC (permalink / raw)
  To: davem; +Cc: netdev, yoshfuji

Dave,

Please consider pulling the following commits from
	net-2.6-20070719-whitespace-20070719
branch at
	<git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-dev.git>.

Thanks.

HEADLINES
---------

    [NET] AX25: Fix whitespace errors.
    [NET] BLUETOOTH: Fix whitespace errors.
    [NET] CORE: Fix whitespace errors.
    [NET] DCCP: Fix whitespace errors.
    [NET] IPV4: Fix whitespace errors.
    [NET] NETFILTER: Fix whitespace errors.
    [NET] NETROM: Fix whitespace errors.
    [NET] PACKET: Fix whitespace errors.
    [NET] RFKILL: Fix whitespace errors.
    [NET] ROSE: Fix whitespace errors.
    [NET] RXRPC: Fix whitespace errors.
    [NET] SCTP: Fix whitespace errors.
    [NET] SUNRPC: Fix whitespace errors.
    [NET] TIPC: Fix whitespace errors.
    [NET] XFRM: Fix whitespace errors.

DIFFSTAT
--------

 net/ax25/af_ax25.c                      |    2 +-
 net/bluetooth/hci_core.c                |    2 +-
 net/core/dev.c                          |    2 +-
 net/core/rtnetlink.c                    |    2 +-
 net/core/sock.c                         |    2 +-
 net/dccp/ccids/lib/loss_interval.c      |    2 +-
 net/ipv4/fib_frontend.c                 |    2 +-
 net/ipv4/ip_forward.c                   |    2 +-
 net/ipv4/tcp_output.c                   |    2 +-
 net/netfilter/nf_conntrack_standalone.c |    2 +-
 net/netfilter/nf_log.c                  |    2 +-
 net/netrom/af_netrom.c                  |    2 +-
 net/packet/af_packet.c                  |    2 +-
 net/rfkill/rfkill-input.c               |    2 +-
 net/rose/af_rose.c                      |    2 +-
 net/rxrpc/af_rxrpc.c                    |   10 +++++-----
 net/sctp/sm_statefuns.c                 |    2 +-
 net/sctp/socket.c                       |    4 ++--
 net/sunrpc/auth_gss/gss_krb5_crypto.c   |    2 +-
 net/tipc/socket.c                       |   12 ++++++------
 net/xfrm/xfrm_policy.c                  |    2 +-
 net/xfrm/xfrm_state.c                   |    2 +-
 22 files changed, 32 insertions(+), 32 deletions(-)

CHANGESETS
----------

commit bd3b071b91a8acfe93b01567f556c879db049f99
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:43:13 2007 +0900

    [NET] AX25: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index c83cf84..dae2a42 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1262,7 +1262,7 @@ static int __must_check ax25_connect(struct socket *sock,
 
 		for (;;) {
 			prepare_to_wait(sk->sk_sleep, &wait,
-			                TASK_INTERRUPTIBLE);
+					TASK_INTERRUPTIBLE);
 			if (sk->sk_state != TCP_SYN_SENT)
 				break;
 			if (!signal_pending(current)) {

---
commit 00ae02f31519e8d6e374424bbdf0c7381489e416
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:43:16 2007 +0900

    [NET] BLUETOOTH: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f6d867e..63caa41 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -982,7 +982,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
 
 			skb->dev = (void *) hdev;
 			bt_cb(skb)->pkt_type = type;
-	
+
 			__reassembly(hdev, type) = skb;
 
 			scb = (void *) skb->cb;

---
commit 40b77c943468236c6dfad3e7b94348fe70c70331
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:43:23 2007 +0900

    [NET] CORE: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/core/dev.c b/net/core/dev.c
index 6357f54..38212c3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2629,7 +2629,7 @@ void __dev_set_rx_mode(struct net_device *dev)
 		return;
 
 	if (!netif_device_present(dev))
-	        return;
+		return;
 
 	if (dev->set_rx_mode)
 		dev->set_rx_mode(dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 864cbdf..06eccca 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -98,7 +98,7 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
 }
 
 int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
-			         struct rtattr *rta, int len)
+				 struct rtattr *rta, int len)
 {
 	if (RTA_PAYLOAD(rta) < len)
 		return -1;
diff --git a/net/core/sock.c b/net/core/sock.c
index 091032a..1d55fbd 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -217,7 +217,7 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
 			warned++;
 			printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) "
 			       "tries to set negative timeout\n",
-			        current->comm, current->pid);
+				current->comm, current->pid);
 		return 0;
 	}
 	*timeo_p = MAX_SCHEDULE_TIMEOUT;

---
commit 23248005fbe5fa32a3f6d00cdec1ecfb115d28eb
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:43:28 2007 +0900

    [NET] DCCP: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 515225f..dd0fc99 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -227,7 +227,7 @@ void dccp_li_update_li(struct sock *sk,
 		       struct list_head *li_hist_list,
 		       struct list_head *hist_list,
 		       struct timeval *last_feedback, u16 s, u32 bytes_recv,
-                       u32 previous_x_recv, u64 seq_loss, u8 win_loss)
+		       u32 previous_x_recv, u64 seq_loss, u8 win_loss)
 {
 	struct dccp_li_hist_entry *head;
 	u64 seq_temp;

---
commit 9c681b43fae1e402e39d157feaa5df454b9e4f1f
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:43:47 2007 +0900

    [NET] IPV4: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 2eb909b..eff6bce 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -817,7 +817,7 @@ static void nl_fib_input(struct sock *sk, int len)
 static void nl_fib_lookup_init(void)
 {
       netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, NULL,
-      			    THIS_MODULE);
+			    THIS_MODULE);
 }
 
 static void fib_disable_ip(struct net_device *dev, int force)
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 9cb04df..8c95cf0 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -86,7 +86,7 @@ int ip_forward(struct sk_buff *skb)
 		goto sr_failed;
 
 	if (unlikely(skb->len > dst_mtu(&rt->u.dst) &&
-	             (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
+		     (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
 		IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
 			  htonl(dst_mtu(&rt->u.dst)));
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 20aea15..666d8a5 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1615,7 +1615,7 @@ u32 __tcp_select_window(struct sock *sk)
 		if (window <= free_space - mss || window > free_space)
 			window = (free_space/mss)*mss;
 		else if (mss == full_space &&
-		         free_space > window + full_space/2)
+			 free_space > window + full_space/2)
 			window = free_space;
 	}
 

---
commit a5d292646ebf2ee51086f59899a377c85e5d50b2
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:21 2007 +0900

    [NET] NETFILTER: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index ffb6ff8..f752293 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -181,7 +181,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
 
 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return -ENOSPC;
-	
+
 	return 0;
 }
 
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 9498579..d67c4fb 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -9,7 +9,7 @@
 
 #include "nf_internals.h"
 
-/* Internal logging interface, which relies on the real 
+/* Internal logging interface, which relies on the real
    LOG target modules */
 
 #define NF_LOG_PREFIXLEN		128

---
commit 639fc4c381456df0564b23540e0f60b0af83093b
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:32 2007 +0900

    [NET] NETROM: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 5d66490..dc92732 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -720,7 +720,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
 
 		for (;;) {
 			prepare_to_wait(sk->sk_sleep, &wait,
-			                TASK_INTERRUPTIBLE);
+					TASK_INTERRUPTIBLE);
 			if (sk->sk_state != TCP_SYN_SENT)
 				break;
 			if (!signal_pending(current)) {

---
commit db0c58f998eeb552fb47b82915005259a83613ae
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:35 2007 +0900

    [NET] PACKET: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 7c27bd3..1322d62 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -108,7 +108,7 @@ Outgoing, dev->hard_header!=NULL
 Incoming, dev->hard_header==NULL
    mac_header -> UNKNOWN position. It is very likely, that it points to ll
 		 header.  PPP makes it, that is wrong, because introduce
-                 assymetry between rx and tx paths.
+		 assymetry between rx and tx paths.
    data       -> data
 
 Outgoing, dev->hard_header==NULL

---
commit 2b81bff416c4413333b19af627e11fddc620bd84
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:38 2007 +0900

    [NET] RFKILL: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index 230e35c..9f746be 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -83,7 +83,7 @@ static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
 static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH);
 
 static void rfkill_event(struct input_handle *handle, unsigned int type,
-		        unsigned int code, int down)
+			unsigned int code, int down)
 {
 	if (type == EV_KEY && down == 1) {
 		switch (code) {

---
commit 6140efb536e7758cd300461981634ebfd4f51efa
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:40 2007 +0900

    [NET] ROSE: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index f4d3aba..976c3cc 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -816,7 +816,7 @@ rose_try_next_neigh:
 
 		for (;;) {
 			prepare_to_wait(sk->sk_sleep, &wait,
-			                TASK_INTERRUPTIBLE);
+					TASK_INTERRUPTIBLE);
 			if (sk->sk_state != TCP_SYN_SENT)
 				break;
 			if (!signal_pending(current)) {

---
commit 1c899641acd18b8d9d8a61dcb5dd8826fc6c87ea
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:44 2007 +0900

    [NET] RXRPC: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 2c57df9..46f6d57 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -805,26 +805,26 @@ static int __init af_rxrpc_init(void)
 	}
 
 	ret = proto_register(&rxrpc_proto, 1);
-        if (ret < 0) {
-                printk(KERN_CRIT "RxRPC: Cannot register protocol\n");
+	if (ret < 0) {
+		printk(KERN_CRIT "RxRPC: Cannot register protocol\n");
 		goto error_proto;
 	}
 
 	ret = sock_register(&rxrpc_family_ops);
 	if (ret < 0) {
-                printk(KERN_CRIT "RxRPC: Cannot register socket family\n");
+		printk(KERN_CRIT "RxRPC: Cannot register socket family\n");
 		goto error_sock;
 	}
 
 	ret = register_key_type(&key_type_rxrpc);
 	if (ret < 0) {
-                printk(KERN_CRIT "RxRPC: Cannot register client key type\n");
+		printk(KERN_CRIT "RxRPC: Cannot register client key type\n");
 		goto error_key_type;
 	}
 
 	ret = register_key_type(&key_type_rxrpc_s);
 	if (ret < 0) {
-                printk(KERN_CRIT "RxRPC: Cannot register server key type\n");
+		printk(KERN_CRIT "RxRPC: Cannot register server key type\n");
 		goto error_key_type_s;
 	}
 

---
commit 9cbcbf4e010ec253df686257f99c819da9b895da
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:50 2007 +0900

    [NET] SCTP: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f02ce3d..fd2dfdd 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1779,7 +1779,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
 					     SCTP_COMM_UP, 0,
 					     asoc->c.sinit_num_ostreams,
 					     asoc->c.sinit_max_instreams,
-                                             NULL, GFP_ATOMIC);
+					     NULL, GFP_ATOMIC);
 		if (!ev)
 			goto nomem;
 
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b1917f6..ee88f2e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4803,7 +4803,7 @@ static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len,
 						  char __user *optval,
 						  int __user *optlen)
 {
-        u32 val;
+	u32 val;
 
 	if (len < sizeof(u32))
 		return -EINVAL;
@@ -4827,7 +4827,7 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
 				    char __user *optval,
 				    int __user *optlen)
 {
-        int val;
+	int val;
 
 	if (len < sizeof(int))
 		return -EINVAL;

---
commit fb1416a59b070d2dea280bfac3313bf3b8a17cd2
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:53 2007 +0900

    [NET] SUNRPC: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index f441aa0..bfb6a29 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -67,7 +67,7 @@ krb5_encrypt(
 
 	if (crypto_blkcipher_ivsize(tfm) > 16) {
 		dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
-		         crypto_blkcipher_ivsize(tfm));
+			 crypto_blkcipher_ivsize(tfm));
 		goto out;
 	}
 

---
commit 8238745a39606738c1d8d39f2052959b3e594b04
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:44:56 2007 +0900

    [NET] TIPC: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 4a8f37f..8411017 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1629,8 +1629,8 @@ static struct proto_ops msg_ops = {
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_msg,
 	.recvmsg	= recv_msg,
-        .mmap		= sock_no_mmap,
-        .sendpage	= sock_no_sendpage
+	.mmap		= sock_no_mmap,
+	.sendpage	= sock_no_sendpage
 };
 
 static struct proto_ops packet_ops = {
@@ -1650,8 +1650,8 @@ static struct proto_ops packet_ops = {
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_packet,
 	.recvmsg	= recv_msg,
-        .mmap		= sock_no_mmap,
-        .sendpage	= sock_no_sendpage
+	.mmap		= sock_no_mmap,
+	.sendpage	= sock_no_sendpage
 };
 
 static struct proto_ops stream_ops = {
@@ -1671,8 +1671,8 @@ static struct proto_ops stream_ops = {
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_stream,
 	.recvmsg	= recv_stream,
-        .mmap		= sock_no_mmap,
-        .sendpage	= sock_no_sendpage
+	.mmap		= sock_no_mmap,
+	.sendpage	= sock_no_sendpage
 };
 
 static struct net_proto_family tipc_family_ops = {

---
commit 7dc12d6dd6cc1aa489c6f3e34a75e8023c945da8
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date:   Thu Jul 19 10:45:15 2007 +0900

    [NET] XFRM: Fix whitespace errors.
    
    Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b48f06f..cfaf17c 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -857,7 +857,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
 					       pol, NULL);
 				return err;
 			}
-                }
+		}
 		for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
 			hlist_for_each_entry(pol, entry,
 					     xfrm_policy_bydst[dir].table + i,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index e070c3f..38f90ca 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -407,7 +407,7 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
 				xfrm_audit_log(audit_info->loginuid,
 					       audit_info->secid,
 					       AUDIT_MAC_IPSEC_DELSA,
-                                               0, NULL, x);
+					       0, NULL, x);
 
 				return err;
 			}

---

-- 
YOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@linux-ipv6.org>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

^ permalink raw reply related

* Re: Please pull 'upstream-davem' branch of wireless-2.6
From: David Miller @ 2007-07-19  1:21 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev
In-Reply-To: <20070719004510.GA5618@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 18 Jul 2007 20:45:10 -0400

> On Wed, Jul 18, 2007 at 03:32:48PM -0700, David Miller wrote:
> > From: "John W. Linville" <linville@tuxdriver.com>
> > Date: Wed, 18 Jul 2007 11:34:49 -0400
> > 
> > > On Tue, Jul 17, 2007 at 08:17:16PM -0700, David Miller wrote:
> > > > From: "John W. Linville" <linville@tuxdriver.com>
> > > > Date: Tue, 17 Jul 2007 22:16:07 -0400
> > > > 
> > > > > A few more for 2.6.23...individual patches available here:
> > > > > 
> > > > >   http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/upstream-davem
> > > > 
> > > > What about this warning which I reported to you right after the last
> > > > merge?  Did this get fixed?
> > > > 
> > > > net/mac80211/ieee80211.c:4989: warning: comparison of distinct pointer types lacks a cast
> > > > 
> > > > Please fix that up first, then I'll pull from your tree.
> > > 
> > > Fair enough! :-)
> > 
> > As I pointed out to Jiri, you need to spell out the complete type
> > warning fix, rather than just "unsigned".
> 
> I went ahead and made that change, including the mysterious space after
> "unsigned int " that seems to be common practice.  I had considered
> asking for this before...oh well, it's there now! :-)
> 
> BTW, I also included an extra patch from Michael Wu which helps to
> avoid some possible deadlocks when shutting down an interface.

Pulled, thanks John.

^ permalink raw reply

* Re: [PATCH 2.6.22-git5] via-rhine: Disable rx_copybreak on archs that don't allow unaligned DMA access
From: Andrew Morton @ 2007-07-19  1:19 UTC (permalink / raw)
  To: Dustin Marquess
  Cc: Francois Romieu, Jeff Garzik, Ivan Kokshaysky, netdev, linux-arch
In-Reply-To: <46991FBC.5070705@alcatraz.fdf.net>


(mailing lsits and cc's added - I trust that's OK)

(Please always cc mailing list(s) on patches)

On Sat, 14 Jul 2007 14:10:52 -0500
Dustin Marquess <jailbird@alcatraz.dnsalias.net> wrote:

> From: Dustin Marquess <jailbird@alcatraz.fdf.net>
> 
> Patch to disable the rx_copybreak feature on hardware architectures that
> don't allow unaligned DMA access.
> 
> #ifdef code taken from tulip_core.c.  Problem pointed out by Ivan
> Kokshaysky.
> 
> Signed-off-by: Dustin Marquess <jailbird@alcatraz.fdf.net>
> ---
> 
> diff -uprN a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
> --- a/drivers/net/via-rhine.c   2007-07-14 13:51:18.475341321 -0500
> +++ b/drivers/net/via-rhine.c   2007-07-14 13:56:40.684678999 -0500
> @@ -42,7 +42,13 @@ static int max_interrupt_work = 20;
> 
>   /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
>      Setting to > 1518 effectively disables this feature. */
> +#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
> +       || defined(CONFIG_SPARC) || defined(__ia64__) \
> +       || defined(__sh__) || defined(__mips__)
> +static int rx_copybreak = 1518;
> +#else
>   static int rx_copybreak;
> +#endif

I guess the patch makes sense, but boy that conditional does suck.

It would be much better to go into each of those architecture's
arch/foo/Kconfig and define a new CONFIG_NO_UNALIGNED_DMA or whatever, and
to then use that config variable here, in tulip_core.c and wherever else
we're doing this.


^ 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