LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 1/2] [POWERPC] MPC832x_RDB: update dts to use spi, register mmc_spi stub
From: Segher Boessenkool @ 2007-08-10 20:42 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20070810010217.GA17370@localhost.localdomain>

>>> We should co-ordinate better on this, if it's to become a
>>> convention...
>>
>> That means we shouldn't coordinate on this, right?
>
> Heh.  Either one is kind of ugly, I'll grant you.
>
> But, many SoCs do have a notion of device "number", which is relevant
> for programming other general control registers in places.  We need to
> encode it somehow, and it would be good to have a consistent way of
> doing it.

I'm not convinced there isn't a more direct way to represent
the relevant relationships.

Either way, we don't have enough experience with this stuff
yet to know what works well and what doesn't (at least, I
don't, and I haven't seen any evidence that others do); so
I'd prefer to keep this in per-device bindings for now; it
should be there anyhow, but once we do have experience with
it we could do some recommendation.


Segher

^ permalink raw reply

* Re: Device tree aware EMAC driver
From: Segher Boessenkool @ 2007-08-10 20:39 UTC (permalink / raw)
  To: Tony Breeds; +Cc: LinuxPPC-dev, David Gibson
In-Reply-To: <20070808031643.GK10345@bakeyournoodle.com>

>  * In drivers/net/ibm_newemac/Makefile, I think the preferred method is
>    to use ibm_newemac-y rather than ibm_newemac-objs.

I thought it was the other way around, so I checked with the
Kbuild maintainer, and indeed you are correct.


Segher

^ permalink raw reply

* Re: some questions about XUP and the generation of ace file
From: Grant Likely @ 2007-08-10 20:19 UTC (permalink / raw)
  To: windstorm; +Cc: linuxppc-embedded
In-Reply-To: <c46c91d0708100937h50fb37fcgff2f66db6207e025@mail.gmail.com>

On 8/10/07, windstorm <likunarmstrong@gmail.com> wrote:
> 1 it's strange. the ns16550.c do exist in the arch/ppc/boot/
> directory, not arch/ppc/boot/common. I just download the source
> yesterday.
>
> 2 Can you show me some reference about the "small bootloader"? Or any
> web material about it?

Sorry, I don't have anything I can publish.  I just grabbed some elf
decoding code from CFE (Common firmware environment which uses a BSD
style license) and bound it up with the Xilinx FAT driver.  It wasn't
very hard to do.

g.

>
> 2007/8/10, Grant Likely <grant.likely@secretlab.ca>:
> > On 8/10/07, windstorm <likunarmstrong@gmail.com> wrote:
> > > Hello all:
> > >
> > > I am trying to transfer the Linux onto XUP board. The kernel source I
> > > used is from the git trees from andrei konovalov or grant likely. But
> > > I encounter two questions now.
> > >
> > > 1 Generally, I should correct the kernel source file
> > > arch/ppc/boot/common/ns16550.c, In that file, changing SERIAL_BAUD
> > > from 9600 to 38400  makes the bootloader talk at 38400. I always do it
> > > when I use standard kernel source. But this time I found out that the
> > > ns16550.c's path is arch/ppc/boot/, not arch/ppc/boot/common/, and
> > > there was no "SERIAL_BAUD" string any more. So, how can I control the
> > > baud rate?
> >
> > ???
> >
> > I don't know what you're referring to.  ns16550.c is in
> > arch/ppc/boot/common on my tree, and it still contains the SERIAL_BAUD
> > #define.
> >
> > >
> > > 2 I have compiled the kernel and obtained a Image.elf whose size is
> > > 1.7MB, and then it's time for creating a system.ace file which I can
> > > put onto a compact flash card.  I Changed the file xupGenace.opt like
> > > the follow:
> >
> > You can do this, but I don't think it's a particularly good idea.
> > Binding the kernel image into an ACE file results in a *very* large
> > ace file, and it's slow.  Consider the fact that doing it that way
> > means that you're transferring the entire 1.7MB image via JTAG.
> >
> > I've also seem problems where DDR isn't fully initialized before the
> > SystemACE tries to transfer the image which results in a non-booting
> > system.
> >
> > What I do, is I've got a small bootloader that lives in BRAM and is
> > just smart enough to load an elf file off of the CF card.  If I can
> > get permission to do so, I'll publish the source for my utility.
> >
> > >
> > > -jprog
> > > -board user
> > > -target ppc_hw
> > > -hw ./implementation/download.bit
> > > -elf zImage.elf
> > > -configdevice devicenr 1 idcode 0x1127e093 irlength 14 partname xc2vp30
> > > -debugdevice devicenr 1 cpunr 1
> > > -ace system.ace
> > >
> > > and executed the command: xmd -tcl genace.tcl -opt genace.opt
> > >
> > > and the result I saw is:  Using GenACE option file : genace.opt
> > > Error: Executable zImage.elf does not contain start address..
> > >
> > > I examine the information by google, some said that it's the bug of
> > > development tools without sp, but both my ISE and EDK was patched.
> > > Others said that it's because of the "mb-objdump", we should chage it
> > > into "powerpc-eaci-objdump", and actually I had done this correction.
> > > BUT, the error still here.
> > >
> > > Could anyone please to help me about this question? I will be very grateful.
> >
> > Very odd.  I haven't seen this problem myself so I can't be much help. sorry.
> >
> > >
> > > BTW, could any kind person send any basic config file, which had been
> > > proved that the kernel compiled based on it could work good on XUP
> > > board?
> >
> > I don't have that board, sorry
> >
> > g.
> >
> > --
> > Grant Likely, B.Sc., P.Eng.
> > Secret Lab Technologies Ltd.
> > grant.likely@secretlab.ca
> > (403) 399-0195
> >
>
>
> --
> web: http://www.forwind.cn
> msn: likunarmstrong at hotmail.com
>


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH 1/2] pseries: device node status can be "ok" or "okay"
From: Segher Boessenkool @ 2007-08-10 20:17 UTC (permalink / raw)
  To: Matt Sealey; +Cc: ppc-dev, Paul Mackerras
In-Reply-To: <46BCBB2C.2040408@genesi-usa.com>

>>> It seems that some versions of firmware will report a device
>>> node status as the string "okay". As we are not expecting this
>>> string, the device node will be ignored by the EEH subsystem.
>>> Which means EEH will not be enabled.
>>>
>>> When EEH is not enabled, PCI errors will be converted into
>>> Machine Check exceptions, and we'll have a very unhappy system.
>>> -	if (status && strcmp(status, "ok") != 0)
>>> +	if (status && strncmp(status, "ok", 2) != 0)
>>>  		return NULL;	/* ignore devices with bad status */
>> Shouldn't you check for the two literal strings, instead of
>> only matching the common prefix?  Seems safer.
>
> What are the chances that the status string is "oklahoma" or
> "okeechobee" or "okinawa"?

What does it matter what the chances are?  The code is either
correct or not ;-)

Besides, that's only part of the problem -- what if the
property is empty, or contains an empty string only, or
a single non-zero byte?


Segher

^ permalink raw reply

* [PATCH 5/6] ibmveth: Remove dead frag processing code
From: Brian King @ 2007-08-10 19:29 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev
In-Reply-To: <11867741331983-patch-mail.ibm.com>


Removes dead frag processing code from ibmveth. Since NETIF_F_SG was
not set, this code was never executed. Also, since the ibmveth
interface can only handle 6 fragments, core networking code would need
to be modified in order to efficiently enable this support.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |  100 +++++---------------------------
 linux-2.6-bjking1/drivers/net/ibmveth.h |    5 -
 2 files changed, 17 insertions(+), 88 deletions(-)

diff -puN drivers/net/ibmveth.c~ibmveth_remove_frag drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_remove_frag	2007-08-09 15:15:18.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-09 15:15:18.000000000 -0500
@@ -28,7 +28,6 @@
 /**************************************************************************/
 /*
   TODO:
-  - remove frag processing code - no longer needed
   - add support for sysfs
   - possibly remove procfs support
 */
@@ -127,9 +126,6 @@ struct ibmveth_stat ibmveth_stats[] = {
 	{ "replenish_add_buff_success", IBMVETH_STAT_OFF(replenish_add_buff_success) },
 	{ "rx_invalid_buffer", IBMVETH_STAT_OFF(rx_invalid_buffer) },
 	{ "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) },
-	{ "tx_multidesc_send", IBMVETH_STAT_OFF(tx_multidesc_send) },
-	{ "tx_linearized", IBMVETH_STAT_OFF(tx_linearized) },
-	{ "tx_linearize_failed", IBMVETH_STAT_OFF(tx_linearize_failed) },
 	{ "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) },
 	{ "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) },
 };
@@ -832,9 +828,8 @@ static int ibmveth_ioctl(struct net_devi
 static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct ibmveth_adapter *adapter = netdev->priv;
-	union ibmveth_buf_desc desc[IbmVethMaxSendFrags];
+	union ibmveth_buf_desc desc;
 	unsigned long lpar_rc;
-	int nfrags = 0, curfrag;
 	unsigned long correlator;
 	unsigned long flags;
 	unsigned int retry_count;
@@ -844,25 +839,11 @@ static int ibmveth_start_xmit(struct sk_
 	unsigned int tx_send_failed = 0;
 	unsigned int tx_map_failed = 0;
 
-
-	if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) {
-		tx_dropped++;
-		goto out;
-	}
-
-	memset(&desc, 0, sizeof(desc));
-
-	/* nfrags = number of frags after the initial fragment */
-	nfrags = skb_shinfo(skb)->nr_frags;
-
-	if(nfrags)
-		adapter->tx_multidesc_send++;
-
-	/* map the initial fragment */
-	desc[0].fields.length  = nfrags ? skb->len - skb->data_len : skb->len;
-	desc[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
-					desc[0].fields.length, DMA_TO_DEVICE);
-	desc[0].fields.valid   = 1;
+	desc.desc = 0;
+	desc.fields.length  = skb->len;
+	desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
+					     desc.fields.length, DMA_TO_DEVICE);
+	desc.fields.valid   = 1;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
 	    ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
@@ -874,75 +855,34 @@ static int ibmveth_start_xmit(struct sk_
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
 
-		desc[0].fields.no_csum = 1;
-		desc[0].fields.csum_good = 1;
+		desc.fields.no_csum = 1;
+		desc.fields.csum_good = 1;
 
 		/* Need to zero out the checksum */
 		buf[0] = 0;
 		buf[1] = 0;
 	}
 
-	if(dma_mapping_error(desc[0].fields.address)) {
-		ibmveth_error_printk("tx: unable to map initial fragment\n");
+	if (dma_mapping_error(desc.fields.address)) {
+		ibmveth_error_printk("tx: unable to map xmit buffer\n");
 		tx_map_failed++;
 		tx_dropped++;
 		goto out;
 	}
 
-	curfrag = nfrags;
-
-	/* map fragments past the initial portion if there are any */
-	while(curfrag--) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[curfrag];
-		desc[curfrag+1].fields.address
-			= dma_map_single(&adapter->vdev->dev,
-				page_address(frag->page) + frag->page_offset,
-				frag->size, DMA_TO_DEVICE);
-		desc[curfrag+1].fields.length = frag->size;
-		desc[curfrag+1].fields.valid  = 1;
-		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			desc[curfrag+1].fields.no_csum = 1;
-			desc[curfrag+1].fields.csum_good = 1;
-		}
-
-		if(dma_mapping_error(desc[curfrag+1].fields.address)) {
-			ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag);
-			tx_map_failed++;
-			tx_dropped++;
-			/* Free all the mappings we just created */
-			while(curfrag < nfrags) {
-				dma_unmap_single(&adapter->vdev->dev,
-						 desc[curfrag+1].fields.address,
-						 desc[curfrag+1].fields.length,
-						 DMA_TO_DEVICE);
-				curfrag++;
-			}
-			goto out;
-		}
-	}
-
 	/* send the frame. Arbitrarily set retrycount to 1024 */
 	correlator = 0;
 	retry_count = 1024;
 	do {
 		lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
-					     desc[0].desc,
-					     desc[1].desc,
-					     desc[2].desc,
-					     desc[3].desc,
-					     desc[4].desc,
-					     desc[5].desc,
-					     correlator,
-					     &correlator);
+					     desc.desc, 0, 0, 0, 0, 0,
+					     correlator, &correlator);
 	} while ((lpar_rc == H_BUSY) && (retry_count--));
 
 	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
-		int i;
 		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
-		for(i = 0; i < 6; i++) {
-			ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i,
-					     desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address);
-		}
+		ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
+				     desc.fields.valid, desc.fields.length, desc.fields.address);
 		tx_send_failed++;
 		tx_dropped++;
 	} else {
@@ -951,11 +891,8 @@ static int ibmveth_start_xmit(struct sk_
 		netdev->trans_start = jiffies;
 	}
 
-	do {
-		dma_unmap_single(&adapter->vdev->dev,
-				desc[nfrags].fields.address,
-				desc[nfrags].fields.length, DMA_TO_DEVICE);
-	} while(--nfrags >= 0);
+	dma_unmap_single(&adapter->vdev->dev, desc.fields.address,
+			 desc.fields.length, DMA_TO_DEVICE);
 
 out:	spin_lock_irqsave(&adapter->stats_lock, flags);
 	adapter->stats.tx_dropped += tx_dropped;
@@ -1366,10 +1303,7 @@ static int ibmveth_seq_show(struct seq_f
 		   firmware_mac[3], firmware_mac[4], firmware_mac[5]);
 
 	seq_printf(seq, "\nAdapter Statistics:\n");
-	seq_printf(seq, "  TX:  skbuffs linearized:          %ld\n", adapter->tx_linearized);
-	seq_printf(seq, "       multi-descriptor sends:      %ld\n", adapter->tx_multidesc_send);
-	seq_printf(seq, "       skb_linearize failures:      %ld\n", adapter->tx_linearize_failed);
-	seq_printf(seq, "       vio_map_single failres:      %ld\n", adapter->tx_map_failed);
+	seq_printf(seq, "  TX:  vio_map_single failres:      %ld\n", adapter->tx_map_failed);
 	seq_printf(seq, "       send failures:               %ld\n", adapter->tx_send_failed);
 	seq_printf(seq, "  RX:  replenish task cycles:       %ld\n", adapter->replenish_task_cycles);
 	seq_printf(seq, "       alloc_skb_failures:          %ld\n", adapter->replenish_no_mem);
diff -puN drivers/net/ibmveth.h~ibmveth_remove_frag drivers/net/ibmveth.h
--- linux-2.6/drivers/net/ibmveth.h~ibmveth_remove_frag	2007-08-09 15:15:18.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.h	2007-08-09 15:15:18.000000000 -0500
@@ -25,8 +25,6 @@
 #ifndef _IBMVETH_H
 #define _IBMVETH_H
 
-#define IbmVethMaxSendFrags 6
-
 /* constants for H_MULTICAST_CTRL */
 #define IbmVethMcastReceptionModifyBit     0x80000UL
 #define IbmVethMcastReceptionEnableBit     0x20000UL
@@ -146,9 +144,6 @@ struct ibmveth_adapter {
     u64 replenish_add_buff_success;
     u64 rx_invalid_buffer;
     u64 rx_no_buffer;
-    u64 tx_multidesc_send;
-    u64 tx_linearized;
-    u64 tx_linearize_failed;
     u64 tx_map_failed;
     u64 tx_send_failed;
     spinlock_t stats_lock;
_

^ permalink raw reply

* [PATCH 6/6] ibmveth: Remove use of bitfields
From: Brian King @ 2007-08-10 19:29 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev
In-Reply-To: <11867741331983-patch-mail.ibm.com>


Removes the use of bitfields from the ibmveth driver. This results
in slightly smaller object code.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |   90 ++++++++++++++++----------------
 linux-2.6-bjking1/drivers/net/ibmveth.h |   56 ++++++++-----------
 2 files changed, 68 insertions(+), 78 deletions(-)

diff -puN drivers/net/ibmveth.h~ibmveth_nobitfields drivers/net/ibmveth.h
--- linux-2.6/drivers/net/ibmveth.h~ibmveth_nobitfields	2007-08-09 15:15:27.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.h	2007-08-09 15:15:27.000000000 -0500
@@ -39,6 +39,12 @@
 #define IbmVethMcastRemoveFilter     0x2UL
 #define IbmVethMcastClearFilterTable 0x3UL
 
+#define IBMVETH_ILLAN_PADDED_PKT_CSUM	0x0000000000002000ULL
+#define IBMVETH_ILLAN_TRUNK_PRI_MASK	0x0000000000000F00ULL
+#define IBMVETH_ILLAN_IPV6_TCP_CSUM		0x0000000000000004ULL
+#define IBMVETH_ILLAN_IPV4_TCP_CSUM		0x0000000000000002ULL
+#define IBMVETH_ILLAN_ACTIVE_TRUNK		0x0000000000000001ULL
+
 /* hcall macros */
 #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
   plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac)
@@ -150,13 +156,13 @@ struct ibmveth_adapter {
 };
 
 struct ibmveth_buf_desc_fields {
-    u32 valid : 1;
-    u32 toggle : 1;
-    u32 reserved : 4;
-    u32 no_csum : 1;
-    u32 csum_good : 1;
-    u32 length : 24;
-    u32 address;
+	u32 flags_len;
+#define IBMVETH_BUF_VALID	0x80000000
+#define IBMVETH_BUF_TOGGLE	0x40000000
+#define IBMVETH_BUF_NO_CSUM	0x02000000
+#define IBMVETH_BUF_CSUM_GOOD	0x01000000
+#define IBMVETH_BUF_LEN_MASK	0x00FFFFFF
+	u32 address;
 };
 
 union ibmveth_buf_desc {
@@ -164,33 +170,17 @@ union ibmveth_buf_desc {
     struct ibmveth_buf_desc_fields fields;
 };
 
-struct ibmveth_illan_attributes_fields {
-	u32 reserved;
-	u32 reserved2 : 18;
-	u32 csum_offload_padded_pkt_support : 1;
-	u32 reserved3 : 1;
-	u32 trunk_priority : 4;
-	u32 reserved4 : 5;
-	u32 tcp_csum_offload_ipv6 : 1;
-	u32 tcp_csum_offload_ipv4 : 1;
-	u32 active_trunk : 1;
-};
-
-union ibmveth_illan_attributes {
-	u64 desc;
-	struct ibmveth_illan_attributes_fields fields;
-};
-
 struct ibmveth_rx_q_entry {
-    u16 toggle : 1;
-    u16 valid : 1;
-    u16 reserved : 4;
-    u16 no_csum : 1;
-    u16 csum_good : 1;
-    u16 reserved2 : 8;
-    u16 offset;
-    u32 length;
-    u64 correlator;
+	u32 flags_off;
+#define IBMVETH_RXQ_TOGGLE		0x80000000
+#define IBMVETH_RXQ_TOGGLE_SHIFT	31
+#define IBMVETH_RXQ_VALID		0x40000000
+#define IBMVETH_RXQ_NO_CSUM		0x02000000
+#define IBMVETH_RXQ_CSUM_GOOD		0x01000000
+#define IBMVETH_RXQ_OFF_MASK		0x0000FFFF
+
+	u32 length;
+	u64 correlator;
 };
 
 #endif /* _IBMVETH_H */
diff -puN drivers/net/ibmveth.c~ibmveth_nobitfields drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_nobitfields	2007-08-09 15:15:27.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-09 15:15:27.000000000 -0500
@@ -131,19 +131,29 @@ struct ibmveth_stat ibmveth_stats[] = {
 };
 
 /* simple methods of getting data from the current rxq entry */
+static inline u32 ibmveth_rxq_flags(struct ibmveth_adapter *adapter)
+{
+	return adapter->rx_queue.queue_addr[adapter->rx_queue.index].flags_off;
+}
+
+static inline int ibmveth_rxq_toggle(struct ibmveth_adapter *adapter)
+{
+	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_TOGGLE) >> IBMVETH_RXQ_TOGGLE_SHIFT;
+}
+
 static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
 {
-	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].toggle == adapter->rx_queue.toggle);
+	return (ibmveth_rxq_toggle(adapter) == adapter->rx_queue.toggle);
 }
 
 static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter)
 {
-	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].valid);
+	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_VALID);
 }
 
 static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter)
 {
-	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].offset);
+	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK);
 }
 
 static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
@@ -153,7 +163,7 @@ static inline int ibmveth_rxq_frame_leng
 
 static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter)
 {
-	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].csum_good);
+	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_CSUM_GOOD);
 }
 
 /* setup the initial settings for a buffer pool */
@@ -253,9 +263,7 @@ static void ibmveth_replenish_buffer_poo
 		correlator = ((u64)pool->index << 32) | index;
 		*(u64*)skb->data = correlator;
 
-		desc.desc = 0;
-		desc.fields.valid = 1;
-		desc.fields.length = pool->buff_size;
+		desc.fields.flags_len = IBMVETH_BUF_VALID | pool->buff_size;
 		desc.fields.address = dma_addr;
 
 		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
@@ -396,9 +404,8 @@ static void ibmveth_rxq_recycle_buffer(s
 		return;
 	}
 
-	desc.desc = 0;
-	desc.fields.valid = 1;
-	desc.fields.length = adapter->rx_buff_pool[pool].buff_size;
+	desc.fields.flags_len = IBMVETH_BUF_VALID |
+		adapter->rx_buff_pool[pool].buff_size;
 	desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index];
 
 	lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
@@ -549,9 +556,7 @@ static int ibmveth_open(struct net_devic
 	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
 	mac_address = mac_address >> 16;
 
-	rxq_desc.desc = 0;
-	rxq_desc.fields.valid = 1;
-	rxq_desc.fields.length = adapter->rx_queue.queue_len;
+	rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_queue.queue_len;
 	rxq_desc.fields.address = adapter->rx_queue.queue_dma;
 
 	ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr);
@@ -693,7 +698,7 @@ static int ibmveth_set_csum_offload(stru
 				    void (*done) (struct net_device *, u32))
 {
 	struct ibmveth_adapter *adapter = dev->priv;
-	union ibmveth_illan_attributes set_attr, clr_attr, ret_attr;
+	u64 set_attr, clr_attr, ret_attr;
 	long ret;
 	int rc1 = 0, rc2 = 0;
 	int restart = 0;
@@ -705,21 +710,21 @@ static int ibmveth_set_csum_offload(stru
 		adapter->pool_config = 0;
 	}
 
-	set_attr.desc = 0;
-	clr_attr.desc = 0;
+	set_attr = 0;
+	clr_attr = 0;
 
 	if (data)
-		set_attr.fields.tcp_csum_offload_ipv4 = 1;
+		set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
 	else
-		clr_attr.fields.tcp_csum_offload_ipv4 = 1;
+		clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
 
-	ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr.desc);
+	ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
 
-	if (ret == H_SUCCESS && !ret_attr.fields.active_trunk &&
-	    !ret_attr.fields.trunk_priority &&
-	    ret_attr.fields.csum_offload_padded_pkt_support) {
-		ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr.desc,
-					 set_attr.desc, &ret_attr.desc);
+	if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) &&
+	    !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) &&
+	    (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) {
+		ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr,
+					 set_attr, &ret_attr);
 
 		if (ret != H_SUCCESS) {
 			rc1 = -EIO;
@@ -727,13 +732,13 @@ static int ibmveth_set_csum_offload(stru
 					     " %d rc=%ld\n", data, ret);
 
 			ret = h_illan_attributes(adapter->vdev->unit_address,
-						 set_attr.desc, clr_attr.desc, &ret_attr.desc);
+						 set_attr, clr_attr, &ret_attr);
 		} else
 			done(dev, data);
 	} else {
 		rc1 = -EIO;
 		ibmveth_error_printk("unable to change checksum offload settings."
-				     " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr.desc);
+				     " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr);
 	}
 
 	if (restart)
@@ -839,11 +844,9 @@ static int ibmveth_start_xmit(struct sk_
 	unsigned int tx_send_failed = 0;
 	unsigned int tx_map_failed = 0;
 
-	desc.desc = 0;
-	desc.fields.length  = skb->len;
+	desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
 	desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
-					     desc.fields.length, DMA_TO_DEVICE);
-	desc.fields.valid   = 1;
+					     skb->len, DMA_TO_DEVICE);
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
 	    ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
@@ -855,8 +858,7 @@ static int ibmveth_start_xmit(struct sk_
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
 
-		desc.fields.no_csum = 1;
-		desc.fields.csum_good = 1;
+		desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
 
 		/* Need to zero out the checksum */
 		buf[0] = 0;
@@ -882,7 +884,8 @@ static int ibmveth_start_xmit(struct sk_
 	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
 		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
 		ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
-				     desc.fields.valid, desc.fields.length, desc.fields.address);
+				     (desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0,
+				     skb->len, desc.fields.address);
 		tx_send_failed++;
 		tx_dropped++;
 	} else {
@@ -892,7 +895,7 @@ static int ibmveth_start_xmit(struct sk_
 	}
 
 	dma_unmap_single(&adapter->vdev->dev, desc.fields.address,
-			 desc.fields.length, DMA_TO_DEVICE);
+			 skb->len, DMA_TO_DEVICE);
 
 out:	spin_lock_irqsave(&adapter->stats_lock, flags);
 	adapter->stats.tx_dropped += tx_dropped;
@@ -1108,7 +1111,7 @@ static int __devinit ibmveth_probe(struc
 	long ret;
 	struct net_device *netdev;
 	struct ibmveth_adapter *adapter;
-	union ibmveth_illan_attributes set_attr, ret_attr;
+	u64 set_attr, ret_attr;
 
 	unsigned char *mac_addr_p;
 	unsigned int *mcastFilterSize_p;
@@ -1202,23 +1205,20 @@ static int __devinit ibmveth_probe(struc
 
 	ibmveth_debug_printk("registering netdev...\n");
 
-	ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr.desc);
+	ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr);
 
-	if (ret == H_SUCCESS && !ret_attr.fields.active_trunk &&
-	    !ret_attr.fields.trunk_priority &&
-	    ret_attr.fields.csum_offload_padded_pkt_support) {
-		set_attr.desc = 0;
-		set_attr.fields.tcp_csum_offload_ipv4 = 1;
+	if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) &&
+	    !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) &&
+	    (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) {
+		set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
 
-		ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc,
-					 &ret_attr.desc);
+		ret = h_illan_attributes(dev->unit_address, 0, set_attr, &ret_attr);
 
 		if (ret == H_SUCCESS) {
 			adapter->rx_csum = 1;
 			netdev->features |= NETIF_F_IP_CSUM;
 		} else
-			ret = h_illan_attributes(dev->unit_address, set_attr.desc,
-						 0, &ret_attr.desc);
+			ret = h_illan_attributes(dev->unit_address, set_attr, 0, &ret_attr);
 	}
 
 	rc = register_netdev(netdev);
_

^ permalink raw reply

* [PATCH 4/6] ibmveth: Add ethtool driver stats hooks
From: Brian King @ 2007-08-10 19:29 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev
In-Reply-To: <11867741331983-patch-mail.ibm.com>


Add ethtool hooks to ibmveth to retrieve driver statistics.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |   51 ++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff -puN drivers/net/ibmveth.c~ibmveth_ethtool_driver_stats drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_ethtool_driver_stats	2007-08-08 10:46:30.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-08 10:48:08.000000000 -0500
@@ -112,6 +112,28 @@ MODULE_DESCRIPTION("IBM i/pSeries Virtua
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ibmveth_driver_version);
 
+struct ibmveth_stat {
+	char name[ETH_GSTRING_LEN];
+	int offset;
+};
+
+#define IBMVETH_STAT_OFF(stat) offsetof(struct ibmveth_adapter, stat)
+#define IBMVETH_GET_STAT(a, off) *((u64 *)(((unsigned long)(a)) + off))
+
+struct ibmveth_stat ibmveth_stats[] = {
+	{ "replenish_task_cycles", IBMVETH_STAT_OFF(replenish_task_cycles) },
+	{ "replenish_no_mem", IBMVETH_STAT_OFF(replenish_no_mem) },
+	{ "replenish_add_buff_failure", IBMVETH_STAT_OFF(replenish_add_buff_failure) },
+	{ "replenish_add_buff_success", IBMVETH_STAT_OFF(replenish_add_buff_success) },
+	{ "rx_invalid_buffer", IBMVETH_STAT_OFF(rx_invalid_buffer) },
+	{ "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) },
+	{ "tx_multidesc_send", IBMVETH_STAT_OFF(tx_multidesc_send) },
+	{ "tx_linearized", IBMVETH_STAT_OFF(tx_linearized) },
+	{ "tx_linearize_failed", IBMVETH_STAT_OFF(tx_linearize_failed) },
+	{ "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) },
+	{ "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) },
+};
+
 /* simple methods of getting data from the current rxq entry */
 static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
 {
@@ -758,6 +780,32 @@ static u32 ibmveth_get_rx_csum(struct ne
 	return adapter->rx_csum;
 }
 
+static void ibmveth_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	int i;
+
+	if (stringset != ETH_SS_STATS)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(ibmveth_stats); i++, data += ETH_GSTRING_LEN)
+		memcpy(data, ibmveth_stats[i].name, ETH_GSTRING_LEN);
+}
+
+static int ibmveth_get_stats_count(struct net_device *dev)
+{
+	return ARRAY_SIZE(ibmveth_stats);
+}
+
+static void ibmveth_get_ethtool_stats(struct net_device *dev,
+				      struct ethtool_stats *stats, u64 *data)
+{
+	int i;
+	struct ibmveth_adapter *adapter = dev->priv;
+
+	for (i = 0; i < ARRAY_SIZE(ibmveth_stats); i++)
+		data[i] = IBMVETH_GET_STAT(adapter, ibmveth_stats[i].offset);
+}
+
 static const struct ethtool_ops netdev_ethtool_ops = {
 	.get_drvinfo		= netdev_get_drvinfo,
 	.get_settings		= netdev_get_settings,
@@ -769,6 +817,9 @@ static const struct ethtool_ops netdev_e
 	.set_rx_csum		= ibmveth_set_rx_csum,
 	.get_tso			= ethtool_op_get_tso,
 	.get_ufo			= ethtool_op_get_ufo,
+	.get_strings		= ibmveth_get_strings,
+	.get_stats_count		= ibmveth_get_stats_count,
+	.get_ethtool_stats	= ibmveth_get_ethtool_stats,
 };
 
 static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
diff -puN drivers/net/ibmveth.h~ibmveth_ethtool_driver_stats drivers/net/ibmveth.h
_

^ permalink raw reply

* [PATCH 3/6] ibmveth: Add ethtool TSO handlers
From: Brian King @ 2007-08-10 19:29 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev
In-Reply-To: <11867741331983-patch-mail.ibm.com>


Add handlers for get_tso and get_ufo to prevent errors being printed
by ethtool.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |    2 ++
 1 file changed, 2 insertions(+)

diff -puN drivers/net/ibmveth.c~ibmveth_ethtool_get_tso drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_ethtool_get_tso	2007-08-08 10:46:28.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-08 10:46:28.000000000 -0500
@@ -767,6 +767,8 @@ static const struct ethtool_ops netdev_e
 	.set_tx_csum		= ibmveth_set_tx_csum,
 	.get_rx_csum		= ibmveth_get_rx_csum,
 	.set_rx_csum		= ibmveth_set_rx_csum,
+	.get_tso			= ethtool_op_get_tso,
+	.get_ufo			= ethtool_op_get_ufo,
 };
 
 static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
_

^ permalink raw reply

* [PATCH 2/6] ibmveth: Implement ethtool hooks to enable/disable checksum offload
From: Brian King @ 2007-08-10 19:29 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev
In-Reply-To: <11867741331983-patch-mail.ibm.com>


This patch adds the appropriate ethtool hooks to allow for enabling/disabling
of hypervisor assisted checksum offload for TCP.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |  125 +++++++++++++++++++++++++++++++-
 linux-2.6-bjking1/drivers/net/ibmveth.h |    1 
 2 files changed, 124 insertions(+), 2 deletions(-)

diff -puN drivers/net/ibmveth.c~ibmveth_csum_offload_ethtool drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_csum_offload_ethtool	2007-08-09 15:15:07.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-09 15:15:07.000000000 -0500
@@ -641,12 +641,132 @@ static u32 netdev_get_link(struct net_de
 	return 1;
 }
 
+static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+
+	if (data)
+		adapter->rx_csum = 1;
+	else {
+		/*
+		 * Since the ibmveth firmware interface does not have the concept of
+		 * separate tx/rx checksum offload enable, if rx checksum is disabled
+		 * we also have to disable tx checksum offload. Once we disable rx
+		 * checksum offload, we are no longer allowed to send tx buffers that
+		 * are not properly checksummed.
+		 */
+		adapter->rx_csum = 0;
+		dev->features &= ~NETIF_F_IP_CSUM;
+	}
+}
+
+static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data)
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+
+	if (data) {
+		dev->features |= NETIF_F_IP_CSUM;
+		adapter->rx_csum = 1;
+	} else
+		dev->features &= ~NETIF_F_IP_CSUM;
+}
+
+static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
+				    void (*done) (struct net_device *, u32))
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+	union ibmveth_illan_attributes set_attr, clr_attr, ret_attr;
+	long ret;
+	int rc1 = 0, rc2 = 0;
+	int restart = 0;
+
+	if (netif_running(dev)) {
+		restart = 1;
+		adapter->pool_config = 1;
+		ibmveth_close(dev);
+		adapter->pool_config = 0;
+	}
+
+	set_attr.desc = 0;
+	clr_attr.desc = 0;
+
+	if (data)
+		set_attr.fields.tcp_csum_offload_ipv4 = 1;
+	else
+		clr_attr.fields.tcp_csum_offload_ipv4 = 1;
+
+	ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr.desc);
+
+	if (ret == H_SUCCESS && !ret_attr.fields.active_trunk &&
+	    !ret_attr.fields.trunk_priority &&
+	    ret_attr.fields.csum_offload_padded_pkt_support) {
+		ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr.desc,
+					 set_attr.desc, &ret_attr.desc);
+
+		if (ret != H_SUCCESS) {
+			rc1 = -EIO;
+			ibmveth_error_printk("unable to change checksum offload settings."
+					     " %d rc=%ld\n", data, ret);
+
+			ret = h_illan_attributes(adapter->vdev->unit_address,
+						 set_attr.desc, clr_attr.desc, &ret_attr.desc);
+		} else
+			done(dev, data);
+	} else {
+		rc1 = -EIO;
+		ibmveth_error_printk("unable to change checksum offload settings."
+				     " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr.desc);
+	}
+
+	if (restart)
+		rc2 = ibmveth_open(dev);
+
+	return rc1 ? rc1 : rc2;
+}
+
+static int ibmveth_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+
+	if ((data && adapter->rx_csum) || (!data && !adapter->rx_csum))
+		return 0;
+
+	return ibmveth_set_csum_offload(dev, data, ibmveth_set_rx_csum_flags);
+}
+
+static int ibmveth_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+	int rc = 0;
+
+	if (data && (dev->features & NETIF_F_IP_CSUM))
+		return 0;
+	if (!data && !(dev->features & NETIF_F_IP_CSUM))
+		return 0;
+
+	if (data && !adapter->rx_csum)
+		rc = ibmveth_set_csum_offload(dev, data, ibmveth_set_tx_csum_flags);
+	else
+		ibmveth_set_tx_csum_flags(dev, data);
+
+	return rc;
+}
+
+static u32 ibmveth_get_rx_csum(struct net_device *dev)
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+	return adapter->rx_csum;
+}
+
 static const struct ethtool_ops netdev_ethtool_ops = {
 	.get_drvinfo		= netdev_get_drvinfo,
 	.get_settings		= netdev_get_settings,
 	.get_link		= netdev_get_link,
 	.get_sg			= ethtool_op_get_sg,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum		= ibmveth_set_tx_csum,
+	.get_rx_csum		= ibmveth_get_rx_csum,
+	.set_rx_csum		= ibmveth_set_rx_csum,
 };
 
 static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1103,9 +1223,10 @@ static int __devinit ibmveth_probe(struc
 		ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc,
 					 &ret_attr.desc);
 
-		if (ret == H_SUCCESS)
+		if (ret == H_SUCCESS) {
+			adapter->rx_csum = 1;
 			netdev->features |= NETIF_F_IP_CSUM;
-		else
+		} else
 			ret = h_illan_attributes(dev->unit_address, set_attr.desc,
 						 0, &ret_attr.desc);
 	}
diff -puN drivers/net/ibmveth.h~ibmveth_csum_offload_ethtool drivers/net/ibmveth.h
--- linux-2.6/drivers/net/ibmveth.h~ibmveth_csum_offload_ethtool	2007-08-09 15:15:07.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.h	2007-08-09 15:15:07.000000000 -0500
@@ -137,6 +137,7 @@ struct ibmveth_adapter {
     struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
     struct ibmveth_rx_q rx_queue;
     int pool_config;
+    int rx_csum;
 
     /* adapter specific stats */
     u64 replenish_task_cycles;
_

^ permalink raw reply

* [PATCH 1/6] ibmveth: Enable TCP checksum offload
From: Brian King @ 2007-08-10 19:28 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev


This patchset enables TCP checksum offload support for IPV4
on ibmveth. This completely eliminates the generation and checking of
the checksum for packets that are completely virtual and never
touch a physical network. A simple TCP_STREAM netperf run on
a virtual network with maximum mtu set yielded a ~30% increase
in throughput. This feature is enabled by default on systems that
support it, but can be disabled with a module option.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |   53 ++++++++++++++++++++++++++++++++
 linux-2.6-bjking1/drivers/net/ibmveth.h |   41 +++++++++++++++++++++++-
 2 files changed, 92 insertions(+), 2 deletions(-)

diff -puN drivers/net/ibmveth.c~ibmveth_csum_offload drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_csum_offload	2007-08-09 13:08:21.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-09 13:08:21.000000000 -0500
@@ -47,6 +47,8 @@
 #include <linux/mm.h>
 #include <linux/ethtool.h>
 #include <linux/proc_fs.h>
+#include <linux/in.h>
+#include <linux/ip.h>
 #include <asm/semaphore.h>
 #include <asm/hvcall.h>
 #include <asm/atomic.h>
@@ -131,6 +133,11 @@ static inline int ibmveth_rxq_frame_leng
 	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
 }
 
+static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter)
+{
+	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].csum_good);
+}
+
 /* setup the initial settings for a buffer pool */
 static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
 {
@@ -684,6 +691,24 @@ static int ibmveth_start_xmit(struct sk_
 					desc[0].fields.length, DMA_TO_DEVICE);
 	desc[0].fields.valid   = 1;
 
+	if (skb->ip_summed == CHECKSUM_PARTIAL &&
+	    ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
+		ibmveth_error_printk("tx: failed to checksum packet\n");
+		tx_dropped++;
+		goto out;
+	}
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
+
+		desc[0].fields.no_csum = 1;
+		desc[0].fields.csum_good = 1;
+
+		/* Need to zero out the checksum */
+		buf[0] = 0;
+		buf[1] = 0;
+	}
+
 	if(dma_mapping_error(desc[0].fields.address)) {
 		ibmveth_error_printk("tx: unable to map initial fragment\n");
 		tx_map_failed++;
@@ -702,6 +727,10 @@ static int ibmveth_start_xmit(struct sk_
 				frag->size, DMA_TO_DEVICE);
 		desc[curfrag+1].fields.length = frag->size;
 		desc[curfrag+1].fields.valid  = 1;
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			desc[curfrag+1].fields.no_csum = 1;
+			desc[curfrag+1].fields.csum_good = 1;
+		}
 
 		if(dma_mapping_error(desc[curfrag+1].fields.address)) {
 			ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag);
@@ -792,7 +821,11 @@ static int ibmveth_poll(struct net_devic
 			} else {
 				int length = ibmveth_rxq_frame_length(adapter);
 				int offset = ibmveth_rxq_frame_offset(adapter);
+				int csum_good = ibmveth_rxq_csum_good(adapter);
+
 				skb = ibmveth_rxq_get_buffer(adapter);
+				if (csum_good)
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 				ibmveth_rxq_harvest_buffer(adapter);
 
@@ -962,8 +995,10 @@ static void ibmveth_poll_controller(stru
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
 	int rc, i;
+	long ret;
 	struct net_device *netdev;
 	struct ibmveth_adapter *adapter;
+	union ibmveth_illan_attributes set_attr, ret_attr;
 
 	unsigned char *mac_addr_p;
 	unsigned int *mcastFilterSize_p;
@@ -1057,6 +1092,24 @@ static int __devinit ibmveth_probe(struc
 
 	ibmveth_debug_printk("registering netdev...\n");
 
+	ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr.desc);
+
+	if (ret == H_SUCCESS && !ret_attr.fields.active_trunk &&
+	    !ret_attr.fields.trunk_priority &&
+	    ret_attr.fields.csum_offload_padded_pkt_support) {
+		set_attr.desc = 0;
+		set_attr.fields.tcp_csum_offload_ipv4 = 1;
+
+		ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc,
+					 &ret_attr.desc);
+
+		if (ret == H_SUCCESS)
+			netdev->features |= NETIF_F_IP_CSUM;
+		else
+			ret = h_illan_attributes(dev->unit_address, set_attr.desc,
+						 0, &ret_attr.desc);
+	}
+
 	rc = register_netdev(netdev);
 
 	if(rc) {
diff -puN drivers/net/ibmveth.h~ibmveth_csum_offload drivers/net/ibmveth.h
--- linux-2.6/drivers/net/ibmveth.h~ibmveth_csum_offload	2007-08-09 13:08:21.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.h	2007-08-09 13:08:21.000000000 -0500
@@ -67,6 +67,21 @@ static inline long h_send_logical_lan(un
 	return rc;
 }
 
+static inline long h_illan_attributes(unsigned long unit_address,
+				      unsigned long reset_mask, unsigned long set_mask,
+				      unsigned long *ret_attributes)
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	rc = plpar_hcall(H_ILLAN_ATTRIBUTES, retbuf, unit_address,
+			 reset_mask, set_mask);
+
+	*ret_attributes = retbuf[0];
+
+	return rc;
+}
+
 #define h_multicast_ctrl(ua, cmd, mac) \
   plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac)
 
@@ -141,7 +156,9 @@ struct ibmveth_adapter {
 struct ibmveth_buf_desc_fields {
     u32 valid : 1;
     u32 toggle : 1;
-    u32 reserved : 6;
+    u32 reserved : 4;
+    u32 no_csum : 1;
+    u32 csum_good : 1;
     u32 length : 24;
     u32 address;
 };
@@ -151,10 +168,30 @@ union ibmveth_buf_desc {
     struct ibmveth_buf_desc_fields fields;
 };
 
+struct ibmveth_illan_attributes_fields {
+	u32 reserved;
+	u32 reserved2 : 18;
+	u32 csum_offload_padded_pkt_support : 1;
+	u32 reserved3 : 1;
+	u32 trunk_priority : 4;
+	u32 reserved4 : 5;
+	u32 tcp_csum_offload_ipv6 : 1;
+	u32 tcp_csum_offload_ipv4 : 1;
+	u32 active_trunk : 1;
+};
+
+union ibmveth_illan_attributes {
+	u64 desc;
+	struct ibmveth_illan_attributes_fields fields;
+};
+
 struct ibmveth_rx_q_entry {
     u16 toggle : 1;
     u16 valid : 1;
-    u16 reserved : 14;
+    u16 reserved : 4;
+    u16 no_csum : 1;
+    u16 csum_good : 1;
+    u16 reserved2 : 8;
     u16 offset;
     u32 length;
     u64 correlator;
_

^ permalink raw reply

* Re: [PATCH 1/2] pseries: device node status can be "ok" or "okay"
From: Matt Sealey @ 2007-08-10 19:23 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: ppc-dev, Paul Mackerras
In-Reply-To: <769ccd8091fc725571c5a695a70af4b9@kernel.crashing.org>


Segher Boessenkool wrote:
>> It seems that some versions of firmware will report a device
>> node status as the string "okay". As we are not expecting this
>> string, the device node will be ignored by the EEH subsystem.
>> Which means EEH will not be enabled.
>>
>> When EEH is not enabled, PCI errors will be converted into
>> Machine Check exceptions, and we'll have a very unhappy system.
> 
>> -	if (status && strcmp(status, "ok") != 0)
>> +	if (status && strncmp(status, "ok", 2) != 0)
>>  		return NULL;	/* ignore devices with bad status */
> 
> Shouldn't you check for the two literal strings, instead of
> only matching the common prefix?  Seems safer.

What are the chances that the status string is "oklahoma" or
"okeechobee" or "okinawa"?

-- 
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations

^ permalink raw reply

* Re: [PATCH 1/2] pseries: device node status can be "ok" or "okay"
From: Segher Boessenkool @ 2007-08-10 18:06 UTC (permalink / raw)
  To: Linas Vepstas; +Cc: ppc-dev, Paul Mackerras
In-Reply-To: <20070809232700.GY25995@austin.ibm.com>

> It seems that some versions of firmware will report a device
> node status as the string "okay". As we are not expecting this
> string, the device node will be ignored by the EEH subsystem.
> Which means EEH will not be enabled.
>
> When EEH is not enabled, PCI errors will be converted into
> Machine Check exceptions, and we'll have a very unhappy system.

> -	if (status && strcmp(status, "ok") != 0)
> +	if (status && strncmp(status, "ok", 2) != 0)
>  		return NULL;	/* ignore devices with bad status */

Shouldn't you check for the two literal strings, instead of
only matching the common prefix?  Seems safer.


Segher

^ permalink raw reply

* Re: [RFC/PATCH] remove gratuitous reads from maple pci config space methods
From: Segher Boessenkool @ 2007-08-10 17:58 UTC (permalink / raw)
  To: Nathan Lynch; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
In-Reply-To: <20070809212420.GD13921@localdomain>

>>> Well, I had already checked with Ben, who wrote the code, and my
>>> understanding is that the reads are intended to work around some
>>> misbehaving Apple bridges,
>>
>> None of the PCI interfaces on the U3 or U4 bridges have that
>> problem as far as I know.  I think the workaround was copied
>> from code for older Apple bridges?
>
> Okay, then the change should be fine for maple.

Yes.  Of course, as usual, testing is needed, yada yada.

>>> but that a sync after the write (implied by
>>> releasing pci_lock in the generic pci code) should suffice for those.
>>
>> I don't see how a sync could help here at all, not more than
>> an eieio anyway?
>
> Alright, well, maybe take it up with Ben when I post the patch for
> powermac, since that's where it could actually matter.

It should be fine on PowerMac as well -- all G5s use U3/U4,
the workaround is for certain older Apple bridge chips.


Segher

^ permalink raw reply

* Re: [PATCH] powerpc: fix i2c device string format
From: Segher Boessenkool @ 2007-08-10 17:44 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <Pine.LNX.4.60.0708092233130.5995@poirot.grange>

> hm... Well, the worst that could happen, if an "evil" programmer 
> defines
> too long a name, it gets truncated, and then binds to a wrong driver,
> well, the worst that can happen is that your hardware gets damaged, 
> not a
> big thing.

:-)

> However, some might disagree, so, below is a new version...
> Wrap some long lines while at that.
>
> Signed-off-by: G. Liakhovetski <g.liakhovetski@gmx.de>

Looks good to me, thank you!


Segher

^ permalink raw reply

* Re: some questions about XUP and the generation of ace file
From: windstorm @ 2007-08-10 16:37 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded
In-Reply-To: <fa686aa40708100714m469fb7bdm3757ccf35f6a97db@mail.gmail.com>

1 it's strange. the ns16550.c do exist in the arch/ppc/boot/
directory, not arch/ppc/boot/common. I just download the source
yesterday.

2 Can you show me some reference about the "small bootloader"? Or any
web material about it?

2007/8/10, Grant Likely <grant.likely@secretlab.ca>:
> On 8/10/07, windstorm <likunarmstrong@gmail.com> wrote:
> > Hello all:
> >
> > I am trying to transfer the Linux onto XUP board. The kernel source I
> > used is from the git trees from andrei konovalov or grant likely. But
> > I encounter two questions now.
> >
> > 1 Generally, I should correct the kernel source file
> > arch/ppc/boot/common/ns16550.c, In that file, changing SERIAL_BAUD
> > from 9600 to 38400  makes the bootloader talk at 38400. I always do it
> > when I use standard kernel source. But this time I found out that the
> > ns16550.c's path is arch/ppc/boot/, not arch/ppc/boot/common/, and
> > there was no "SERIAL_BAUD" string any more. So, how can I control the
> > baud rate?
>
> ???
>
> I don't know what you're referring to.  ns16550.c is in
> arch/ppc/boot/common on my tree, and it still contains the SERIAL_BAUD
> #define.
>
> >
> > 2 I have compiled the kernel and obtained a Image.elf whose size is
> > 1.7MB, and then it's time for creating a system.ace file which I can
> > put onto a compact flash card.  I Changed the file xupGenace.opt like
> > the follow:
>
> You can do this, but I don't think it's a particularly good idea.
> Binding the kernel image into an ACE file results in a *very* large
> ace file, and it's slow.  Consider the fact that doing it that way
> means that you're transferring the entire 1.7MB image via JTAG.
>
> I've also seem problems where DDR isn't fully initialized before the
> SystemACE tries to transfer the image which results in a non-booting
> system.
>
> What I do, is I've got a small bootloader that lives in BRAM and is
> just smart enough to load an elf file off of the CF card.  If I can
> get permission to do so, I'll publish the source for my utility.
>
> >
> > -jprog
> > -board user
> > -target ppc_hw
> > -hw ./implementation/download.bit
> > -elf zImage.elf
> > -configdevice devicenr 1 idcode 0x1127e093 irlength 14 partname xc2vp30
> > -debugdevice devicenr 1 cpunr 1
> > -ace system.ace
> >
> > and executed the command: xmd -tcl genace.tcl -opt genace.opt
> >
> > and the result I saw is:  Using GenACE option file : genace.opt
> > Error: Executable zImage.elf does not contain start address..
> >
> > I examine the information by google, some said that it's the bug of
> > development tools without sp, but both my ISE and EDK was patched.
> > Others said that it's because of the "mb-objdump", we should chage it
> > into "powerpc-eaci-objdump", and actually I had done this correction.
> > BUT, the error still here.
> >
> > Could anyone please to help me about this question? I will be very grateful.
>
> Very odd.  I haven't seen this problem myself so I can't be much help. sorry.
>
> >
> > BTW, could any kind person send any basic config file, which had been
> > proved that the kernel compiled based on it could work good on XUP
> > board?
>
> I don't have that board, sorry
>
> g.
>
> --
> Grant Likely, B.Sc., P.Eng.
> Secret Lab Technologies Ltd.
> grant.likely@secretlab.ca
> (403) 399-0195
>


-- 
web: http://www.forwind.cn
msn: likunarmstrong at hotmail.com

^ permalink raw reply

* RE: Device Tree tool [was RE: [PATCH] Consolidate XILINX_VIRTEX boardsupport]
From: Stephen Neuendorffer @ 2007-08-10 15:36 UTC (permalink / raw)
  To: Grant Likely, Koss, Mike (Mission Systems); +Cc: linuxppc-embedded
In-Reply-To: <fa686aa40708100648h361bebbcp841318d87c92c45b@mail.gmail.com>


The main thing that Grant's script lacks is the ability to pull in
default
parameters that aren't listed in the MPD for a core, but not in the MHS
file...
I think the only way to easily solve that is to live within EDK's bsp
generation, unfortunately...

BTW: I'm currently hacking away to see if I can get a microblaze system
booting
using a flat device tree...  I haven't decided if it's worth it to go
that
route in the end yet, but...

Steve

> -----Original Message-----
> From:=20
> linuxppc-embedded-bounces+stephen=3Dneuendorffer.name@ozlabs.org
> =20
> [mailto:linuxppc-embedded-bounces+stephen=3Dneuendorffer.name@oz
labs.org] On Behalf Of Grant Likely
> Sent: Friday, August 10, 2007 6:48 AM
> To: Koss, Mike (Mission Systems)
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: Device Tree tool [was RE: [PATCH] Consolidate=20
> XILINX_VIRTEX boardsupport]
>=20
> On 8/10/07, Koss, Mike (Mission Systems) <mike.koss@ngc.com> wrote:
> >
> > <<SNIPPAGE>>
> > > > > diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > > b/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > > index 01aa043..34d9844 100644
> > > > > --- a/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > > +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > > @@ -15,8 +15,12 @@
> > > > >
> > > > > #if defined(CONFIG_XILINX_ML300)
> > > > > #include "xparameters_ml300.h"
> > > > > +#elif defined(CONFIG_XILINX_XUPV2P)  #include
> > > > > +"xparameters_xupv2p.h"
> > > > > #elif defined(CONFIG_XILINX_ML403)
> > > > > #include "xparameters_ml403.h"
> > > > > +#elif defined(CONFIG_XILINX_ML41x)
> > > > > + #include "xparameters_ml41x.h"
> > > > > #else
> > > > > /* Add other board xparameter includes here before=20
> the #else */
> > > > > #error No xparameters_*.h file included
> > > >
> > > > see comment above.
> >
> > > This whole xparams stuff is a special case; but it is=20
> going away for
> > arch/powerpc.  xparameters.h is generated by the xilinx EDK=20
> tool and it
> > is painful to work with in the Linux context.  For=20
> arch/powerpc, I've
> > got a tool that generates a device tree from the FPGA=20
> hardware design.
> >
> > What is the tool that you are using and are you willing to=20
> share it at
> > this point? I'm currently working on some code to generate platform
> > files for our internal drivers and the ll_temac vs using the ugle
> > xparam's file. I'd like to not duplicate, or actually=20
> assist, any effort
> > in this area.
>=20
> It's on my git tree; http://git.secretlab.ca
>=20
> I've also got some feedback from the Xilinx folks in the form of a
> patch, but I haven't integrated it yet.  Pretty experimental stuff,
> I'll probably end up rewriting it from scratch before it's done.
>=20
> Cheers,
> g.
>=20
> >
> > -- Mike Koss
> >
> >
>=20
>=20
> --=20
> Grant Likely, B.Sc., P.Eng.
> Secret Lab Technologies Ltd.
> grant.likely@secretlab.ca
> (403) 399-0195
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>=20
>=20

^ permalink raw reply

* Re: [PATCH 2/4] mpc83xx: Power Management support
From: Scott Wood @ 2007-08-10 14:47 UTC (permalink / raw)
  To: Soohyung Cho; +Cc: linuxppc-dev
In-Reply-To: <1186728172263333.40.nmailpop03@nmailpop03>

Soohyung Cho wrote:
>>+void fsl_sleep_device(struct fsl_sleep_platform_data *data) {
>>+	if (clock_regs && data->sccr_mask) {
>>+		unsigned long flags;
>>+		u32 sccr;
> 
> 
> Your && operation between clock_regs and sccr_mask seems to be a little bit
> mistake,
> cause type is different.

Hmm?  It's logical AND, not binary.  There's no need for the types to be 
the same.

> (clock->regs->sccr && data->sccr_mask) looks fine.

Except that that would be wrong.  I'm checking to make sure that the 
registers were found, not anything about the contents of the register.

-Scott

^ permalink raw reply

* Re: [PATCH] Consolidate XILINX_VIRTEX board support
From: Kumar Gala @ 2007-08-10 14:37 UTC (permalink / raw)
  To: Grant Likely; +Cc: Arnd Bergmann, linuxppc-embedded
In-Reply-To: <fa686aa40708091154t55ca4df7q7be2acf5662e6076@mail.gmail.com>


On Aug 9, 2007, at 1:54 PM, Grant Likely wrote:

> On 8/6/07, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Tuesday 07 August 2007, Wolfgang Reissnegger wrote:
>>>
>>> Make support for Xilinx boards more generic, making it easier
>>> to add new boards. Add initial support for xupv2p and ml410 boards.
>>
>> I really think we shouldn't add stuff to arch/ppc at this point,
>> it has been deprecated for over two years now.
>
> Naahh, this is pretty benign stuff.  I say let it go in.  :-)
>
> These changes are low risk and they don't hurt anything.  If Virtex
> support worked in arch/powerpc then I'd agree, but for now it allows
> us to keep the virtex device driver support somewhat current.

We've clearly stated for a while that only bug fixes should be going  
into arch/ppc.  This looks like new board support.

Also, be aware that arch/ppc is going away in Jun 2008. :)

- k

^ permalink raw reply

* Re: [PATCH] Consolidate XILINX_VIRTEX board support
From: Grant Likely @ 2007-08-10 14:28 UTC (permalink / raw)
  To: Peter Korsgaard; +Cc: linuxppc-embedded
In-Reply-To: <878x8jx3iq.fsf@sleipner.barco.com>

On 8/10/07, Peter Korsgaard <peter.korsgaard@barco.com> wrote:
> >>>>> "GL" == Grant Likely <grant.likely@secretlab.ca> writes:
>
> Hi,
>
> WR> -boot-$(CONFIG_XILINX_ML300)        += embed_config.o
> WR> -boot-$(CONFIG_XILINX_ML403)        += embed_config.o
> WR> +boot-$(CONFIG_XILINX_VIRTEX)       += embed_config.o
> >>
> >> Don't do that. Other boards with Xilinx FPGAs don't necessarily need
> >> embed_config.c
>
> GL> Then post patches for those boards so we can properly support the
> GL> different configuration.
>
> Also if the boards are not generally available? No problem for me, but
> I don't quite see the point.

GregKH likes to tell the story of one architecture that is actively
maintained, but only has about 2 users total.  The point isn't how
available the hardware is; the point is to see how others are using
the code.  Having a larger base of platform support to draw from makes
it easier to recognize patterns in the code which

Or, from a more selfish perspective; It's one thing to say "this
will/won't work because of that platform over there that you can't
see", and quite another to show the code and say "this is what I need
to do".  If you get your code merged, it is easier to influence the
design direction.  ie. you can say "Don't do that; you'll break this
supported board!"  :-)

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: i couldn't get display in Console?
From: Sergei Shtylyov @ 2007-08-10 14:20 UTC (permalink / raw)
  To: ssaravanan; +Cc: linuxppc-embedded
In-Reply-To: <380-2200784910242271@M2W022.mail2web.com>

Hello.

ssaravanan@arasor.in wrote:

>  when i am booting montavista kernel using uboot i couldn't get any message
> on Console...
> i can view the booting messages by "Dumping the printk Log Buffer".  i am
> passing the "bootargs=console=ttyS0,115200 root=/dev/ram0 rw"...is that i

    I suspect you should use ttyCPM0 instead of ttyS0. Thi board very likely 
has CPM2, so its UARTs are the only ones that exist.

> have to make any modification in kernel configuration to support
> appropriate serial port for display boot messags.. find the attached printk

    You should enable CONFIG_SERIAL_CPM (if it's not already enabled).

> buffer screen shot? can anybody help?

    You have actually replied only to me, not the maillist

> Regards,
> Saravanan.S

WBR, Sergei

^ permalink raw reply

* Re: some questions about XUP and the generation of ace file
From: Grant Likely @ 2007-08-10 14:14 UTC (permalink / raw)
  To: windstorm; +Cc: linuxppc-embedded
In-Reply-To: <c46c91d0708100613m61d8a6d9gc4ca8b379e59fca6@mail.gmail.com>

On 8/10/07, windstorm <likunarmstrong@gmail.com> wrote:
> Hello all:
>
> I am trying to transfer the Linux onto XUP board. The kernel source I
> used is from the git trees from andrei konovalov or grant likely. But
> I encounter two questions now.
>
> 1 Generally, I should correct the kernel source file
> arch/ppc/boot/common/ns16550.c, In that file, changing SERIAL_BAUD
> from 9600 to 38400  makes the bootloader talk at 38400. I always do it
> when I use standard kernel source. But this time I found out that the
> ns16550.c's path is arch/ppc/boot/, not arch/ppc/boot/common/, and
> there was no "SERIAL_BAUD" string any more. So, how can I control the
> baud rate?

???

I don't know what you're referring to.  ns16550.c is in
arch/ppc/boot/common on my tree, and it still contains the SERIAL_BAUD
#define.

>
> 2 I have compiled the kernel and obtained a Image.elf whose size is
> 1.7MB, and then it's time for creating a system.ace file which I can
> put onto a compact flash card.  I Changed the file xupGenace.opt like
> the follow:

You can do this, but I don't think it's a particularly good idea.
Binding the kernel image into an ACE file results in a *very* large
ace file, and it's slow.  Consider the fact that doing it that way
means that you're transferring the entire 1.7MB image via JTAG.

I've also seem problems where DDR isn't fully initialized before the
SystemACE tries to transfer the image which results in a non-booting
system.

What I do, is I've got a small bootloader that lives in BRAM and is
just smart enough to load an elf file off of the CF card.  If I can
get permission to do so, I'll publish the source for my utility.

>
> -jprog
> -board user
> -target ppc_hw
> -hw ./implementation/download.bit
> -elf zImage.elf
> -configdevice devicenr 1 idcode 0x1127e093 irlength 14 partname xc2vp30
> -debugdevice devicenr 1 cpunr 1
> -ace system.ace
>
> and executed the command: xmd -tcl genace.tcl -opt genace.opt
>
> and the result I saw is:  Using GenACE option file : genace.opt
> Error: Executable zImage.elf does not contain start address..
>
> I examine the information by google, some said that it's the bug of
> development tools without sp, but both my ISE and EDK was patched.
> Others said that it's because of the "mb-objdump", we should chage it
> into "powerpc-eaci-objdump", and actually I had done this correction.
> BUT, the error still here.
>
> Could anyone please to help me about this question? I will be very grateful.

Very odd.  I haven't seen this problem myself so I can't be much help. sorry.

>
> BTW, could any kind person send any basic config file, which had been
> proved that the kernel compiled based on it could work good on XUP
> board?

I don't have that board, sorry

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: Device Tree tool [was RE: [PATCH] Consolidate XILINX_VIRTEX board support]
From: Grant Likely @ 2007-08-10 13:48 UTC (permalink / raw)
  To: Koss, Mike (Mission Systems); +Cc: linuxppc-embedded
In-Reply-To: <E57AD4B83B37CA45A2BA1F0C5E4CD2EE02C92EA9@XMBVAD02.northgrum.com>

On 8/10/07, Koss, Mike (Mission Systems) <mike.koss@ngc.com> wrote:
>
> <<SNIPPAGE>>
> > > > diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > b/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > index 01aa043..34d9844 100644
> > > > --- a/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h
> > > > @@ -15,8 +15,12 @@
> > > >
> > > > #if defined(CONFIG_XILINX_ML300)
> > > > #include "xparameters_ml300.h"
> > > > +#elif defined(CONFIG_XILINX_XUPV2P)  #include
> > > > +"xparameters_xupv2p.h"
> > > > #elif defined(CONFIG_XILINX_ML403)
> > > > #include "xparameters_ml403.h"
> > > > +#elif defined(CONFIG_XILINX_ML41x)
> > > > + #include "xparameters_ml41x.h"
> > > > #else
> > > > /* Add other board xparameter includes here before the #else */
> > > > #error No xparameters_*.h file included
> > >
> > > see comment above.
>
> > This whole xparams stuff is a special case; but it is going away for
> arch/powerpc.  xparameters.h is generated by the xilinx EDK tool and it
> is painful to work with in the Linux context.  For arch/powerpc, I've
> got a tool that generates a device tree from the FPGA hardware design.
>
> What is the tool that you are using and are you willing to share it at
> this point? I'm currently working on some code to generate platform
> files for our internal drivers and the ll_temac vs using the ugle
> xparam's file. I'd like to not duplicate, or actually assist, any effort
> in this area.

It's on my git tree; http://git.secretlab.ca

I've also got some feedback from the Xilinx folks in the form of a
patch, but I haven't integrated it yet.  Pretty experimental stuff,
I'll probably end up rewriting it from scratch before it's done.

Cheers,
g.

>
> -- Mike Koss
>
>


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* some questions about XUP and the generation of ace file
From: windstorm @ 2007-08-10 13:13 UTC (permalink / raw)
  To: linuxppc-embedded

Hello all:

I am trying to transfer the Linux onto XUP board. The kernel source I
used is from the git trees from andrei konovalov or grant likely. But
I encounter two questions now.

1 Generally, I should correct the kernel source file
arch/ppc/boot/common/ns16550.c, In that file, changing SERIAL_BAUD
from 9600 to 38400  makes the bootloader talk at 38400. I always do it
when I use standard kernel source. But this time I found out that the
ns16550.c's path is arch/ppc/boot/, not arch/ppc/boot/common/, and
there was no "SERIAL_BAUD" string any more. So, how can I control the
baud rate?

2 I have compiled the kernel and obtained a Image.elf whose size is
1.7MB, and then it's time for creating a system.ace file which I can
put onto a compact flash card.  I Changed the file xupGenace.opt like
the follow:

-jprog
-board user
-target ppc_hw
-hw ./implementation/download.bit
-elf zImage.elf
-configdevice devicenr 1 idcode 0x1127e093 irlength 14 partname xc2vp30
-debugdevice devicenr 1 cpunr 1
-ace system.ace

and executed the command: xmd -tcl genace.tcl -opt genace.opt

and the result I saw is:  Using GenACE option file : genace.opt
Error: Executable zImage.elf does not contain start address..

I examine the information by google, some said that it's the bug of
development tools without sp, but both my ISE and EDK was patched.
Others said that it's because of the "mb-objdump", we should chage it
into "powerpc-eaci-objdump", and actually I had done this correction.
BUT, the error still here.

Could anyone please to help me about this question? I will be very grateful.

BTW, could any kind person send any basic config file, which had been
proved that the kernel compiled based on it could work good on XUP
board?

Thanks again.

^ permalink raw reply

* Re: [RFC PATCH v0.1] net driver: mpc52xx fec
From: Arnaldo Carvalho de Melo @ 2007-08-10 13:02 UTC (permalink / raw)
  To: Domen Puncer; +Cc: netdev, linuxppc-embedded
In-Reply-To: <20070810095153.GC13994@moe.telargo.com>

Em Fri, Aug 10, 2007 at 11:51:53AM +0200, Domen Puncer escreveu:
> Hi!
> 
> Not for merge (yet)! But please do review.
> 
> fec_mpc52xx driver (not in-tree, but floating around) isn't in very
> good shape, so I tried to change that.
> Diff against original is quite big (fec_phy.c is completely rewritten)
> and confuzing, so I'm including whole drivers/net/fec_mpc52xx/ .
> 
> I still have 'make CONFIG_FEC_MPC52xx_MDIO=n compile and work' on my
> TODO, maybe even ethtool support.
> 
> 
> 	Domen
> 
> 
>  arch/powerpc/boot/dts/lite5200b.dts |   18 
>  arch/powerpc/sysdev/bestcomm/fec.h  |   14 
>  drivers/net/fec_mpc52xx/Kconfig     |   24 
>  drivers/net/fec_mpc52xx/Makefile    |    7 
>  drivers/net/fec_mpc52xx/fec.c       | 1002 ++++++++++++++++++++++++++++++++++++
>  drivers/net/fec_mpc52xx/fec.h       |  299 ++++++++++
>  drivers/net/fec_mpc52xx/fec_phy.c   |  229 ++++++++
>  drivers/net/fec_mpc52xx/fec_phy.h   |   49 +
>  8 files changed, 1641 insertions(+), 1 deletion(-)
> 
> diff -pruN dummy/fec.c ./drivers/net/fec_mpc52xx/fec.c
> --- dummy/fec.c	1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec.c	2007-08-10 10:59:00.000000000 +0200
> @@ -0,0 +1,1002 @@
> +/*
> + * drivers/net/fec_mpc52xx/fec.c
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + *
> + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and
> + * now maintained by Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Copyright (C) 2007  Sylvain Munaut <tnt@246tNt.com>
> + * Copyrigth (C) 2003-2004  MontaVista, Software, Inc.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + *
> + */
> +
> +#include <linux/module.h>
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/crc32.h>
> +#include <linux/hardirq.h>
> +
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/ethtool.h>
> +#include <linux/skbuff.h>
> +
> +#include <asm/of_device.h>
> +#include <asm/of_platform.h>
> +#include <asm/io.h>
> +#include <asm/delay.h>
> +#include <asm/mpc52xx.h>
> +
> +#include <sysdev/bestcomm/bestcomm.h>
> +#include <sysdev/bestcomm/fec.h>
> +
> +#include "fec_phy.h"
> +#include "fec.h"
> +
> +#define DRIVER_NAME "mpc52xx-fec"
> +
> +static irqreturn_t fec_interrupt(int, void *);
> +static irqreturn_t fec_rx_interrupt(int, void *);
> +static irqreturn_t fec_tx_interrupt(int, void *);
> +static struct net_device_stats *fec_get_stats(struct net_device *);
> +static void fec_set_multicast_list(struct net_device *dev);
> +static void fec_hw_init(struct net_device *dev);
> +static void fec_stop(struct net_device *dev);
> +static void fec_start(struct net_device *dev);
> +
> +static u8 mpc52xx_fec_mac_addr[6];

> +static u8 null_mac[6];

const


> +
> +static void fec_tx_timeout(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +
> +	dev_warn(&dev->dev, "transmit timed out\n");
> +
> +	fec_stop(dev);
> +	fec_start(dev);
> +
> +	priv->stats.tx_errors++;
> +
> +	if (!priv->tx_full)
> +		netif_wake_queue(dev);
> +}
> +
> +static void fec_set_paddr(struct net_device *dev, u8 *mac)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +	out_be32(&fec->paddr1, *(u32*)(&mac[0]));
> +	out_be32(&fec->paddr2, (*(u16*)(&mac[4]) << 16) | FEC_PADDR2_TYPE);

spaces after the types on casts to pointers

> +}
> +
> +static void fec_get_paddr(struct net_device *dev, u8 *mac)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +	*(u32*)(&mac[0]) = in_be32(&fec->paddr1);
> +	*(u16*)(&mac[4]) = in_be32(&fec->paddr2) >> 16;

ditto

> +}
> +
> +static int fec_set_mac_address(struct net_device *dev, void *addr)
> +{
> +	struct sockaddr *sock = (struct sockaddr *)addr;

no need for a cast, addr is a void pointer

> +
> +	memcpy(dev->dev_addr, sock->sa_data, dev->addr_len);
> +
> +	fec_set_paddr(dev, sock->sa_data);
> +	return 0;

Why always return 0? make it void

> +}
> +
> +static void fec_free_rx_buffers(struct bcom_task *s)
> +{
> +	struct sk_buff *skb;
> +
> +	while (!bcom_queue_empty(s)) {
> +		skb = bcom_retrieve_buffer(s, NULL, NULL);
> +		kfree_skb(skb);
> +	}
> +}
> +
> +static int fec_alloc_rx_buffers(struct bcom_task *rxtsk)
> +{
> +	while (!bcom_queue_full(rxtsk)) {
> +		struct sk_buff *skb;
> +		struct bcom_fec_bd *bd;
> +
> +		skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
> +		if (skb == 0)

Test against NULL

> +			return -EAGAIN;
> +
> +		/* zero out the initial receive buffers to aid debugging */
> +		memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
> +
> +		bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk);
> +
> +		bd->status = FEC_RX_BUFFER_SIZE;
> +		bd->skb_pa = virt_to_phys(skb->data);
> +
> +		bcom_submit_next_buffer(rxtsk, skb);
> +	}
> +
> +	return 0;
> +}
> +
> +/* based on generic_adjust_link - fs_enet-main.c */
> +static void fec_adjust_link(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct phy_device *phydev = priv->phydev;
> +	int new_state = 0;
> +
> +	if (phydev->link != PHY_DOWN) {
> +		if (phydev->duplex != priv->duplex) {
> +			new_state = 1;
> +			priv->duplex = phydev->duplex;
> +		}
> +
> +		if (phydev->speed != priv->speed) {
> +			new_state = 1;
> +			priv->speed = phydev->speed;
> +		}
> +
> +		if (priv->link == PHY_DOWN) {
> +			new_state = 1;
> +			priv->link = phydev->link;
> +			netif_schedule(dev);
> +			netif_carrier_on(dev);
> +			netif_start_queue(dev);
> +		}
> +
> +	} else if (priv->link) {
> +		new_state = 1;
> +		priv->link = PHY_DOWN;
> +		priv->speed = 0;
> +		priv->duplex = -1;
> +		netif_stop_queue(dev);
> +		netif_carrier_off(dev);
> +	}
> +
> +	if (new_state && netif_msg_link(priv)) {
> +		phy_print_status(phydev);
> +	}

No need for {}, this if has only one statement

> +}
> +
> +static int fec_init_phy(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct phy_device *phydev;
> +	char phy_id[BUS_ID_SIZE];
> +
> +	struct device_node *dn, *phy_dn;
> +	unsigned int phy_addr;
> +	const phandle *ph;
> +	const unsigned int *prop;
> +	struct resource res;
> +	int ret;
> +
> +	dn = priv->ofdev->node;
> +	ph = of_get_property(dn, "phy-handle", NULL);
> +	if (!ph) {
> +		dev_err(&dev->dev, "can't find \"phy-handle\" in device tree\n");
> +		return -ENODEV;
> +	}
> +	phy_dn = of_find_node_by_phandle(*ph);
> +
> +	prop = of_get_property(phy_dn, "reg", NULL);
> +	ret = of_address_to_resource(phy_dn->parent, 0, &res);
> +	if (ret) {
> +		dev_err(&dev->dev, "of_address_to_resource failed\n");
> +		return ret;
> +	}
> +
> +	phy_addr = *prop;
> +	of_node_put(phy_dn);
> +
> +	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, res.start, phy_addr);
> +
> +	priv->link = PHY_DOWN;
> +	priv->speed = 0;
> +	priv->duplex = -1;
> +
> +	phydev = phy_connect(dev, phy_id, &fec_adjust_link, 0, PHY_INTERFACE_MODE_MII);
> +	if (IS_ERR(phydev)) {
> +		printk(KERN_ERR "%s: phy_connect failed\n", dev->name);
> +		return PTR_ERR(phydev);
> +	}
> +
> +	phydev->advertising &= ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half;
> +
> +	priv->phydev = phydev;
> +
> +	return 0;
> +}
> +
> +static int fec_open(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	int err = -EBUSY;
> +
> +	if (request_irq(dev->irq, &fec_interrupt, IRQF_DISABLED | IRQF_SHARED,
> +	                DRIVER_NAME "_ctrl", dev)) {
> +		dev_err(&dev->dev, "ctrl interrupt request failed\n");
> +		goto out;
> +	}
> +	if (request_irq(priv->r_irq, &fec_rx_interrupt, IRQF_DISABLED,
> +	                DRIVER_NAME "_rx", dev)) {
> +		dev_err(&dev->dev, "rx interrupt request failed\n");
> +		goto free_ctrl_irq;
> +	}
> +	if (request_irq(priv->t_irq, &fec_tx_interrupt, IRQF_DISABLED,
> +	                DRIVER_NAME "_tx", dev)) {
> +		dev_err(&dev->dev, "tx interrupt request failed\n");
> +		goto free_2irqs;
> +	}
> +
> +	bcom_fec_rx_reset(priv->rx_dmatsk);
> +	bcom_fec_tx_reset(priv->tx_dmatsk);
> +
> +	err = fec_alloc_rx_buffers(priv->rx_dmatsk);
> +	if (err) {
> +		dev_err(&dev->dev, "fec_alloc_rx_buffers failed\n");
> +		goto free_irqs;
> +	}
> +
> +	err = fec_init_phy(dev);
> +	if (err) {
> +		dev_err(&dev->dev, "fec_init_phy failed\n");
> +		goto free_skbs;
> +	}
> +	bcom_enable(priv->rx_dmatsk);
> +	bcom_enable(priv->tx_dmatsk);
> +
> +	/* reset phy - this also wakes it from PDOWN */
> +	phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
> +	phy_start(priv->phydev);
> +
> +	fec_start(dev);
> +
> +	netif_start_queue(dev);
> +
> +	return 0;
> +
> + free_skbs:
> +	fec_free_rx_buffers(priv->rx_dmatsk);
> +
> + free_irqs:
> +	free_irq(priv->t_irq, dev);
> + free_2irqs:
> +	free_irq(priv->r_irq, dev);
> + free_ctrl_irq:
> +	free_irq(dev->irq, dev);
> + out:
> +
> +	return err;
> +}
> +
> +static int fec_close(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +
> +	netif_stop_queue(dev);
> +
> +	fec_stop(dev);
> +
> +	fec_free_rx_buffers(priv->rx_dmatsk);
> +
> +	phy_disconnect(priv->phydev);
> +
> +	free_irq(dev->irq, dev);
> +	free_irq(priv->r_irq, dev);
> +	free_irq(priv->t_irq, dev);
> +
> +	/* power down phy */
> +	phy_stop(priv->phydev);
> +	phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN);
> +
> +	return 0;
> +}
> +
> +/* This will only be invoked if your driver is _not_ in XOFF state.
> + * What this means is that you need not check it, and that this
> + * invariant will hold if you make sure that the netif_*_queue()
> + * calls are done at the proper times.
> + */
> +static int fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct bcom_fec_bd *bd;
> +
> +	if (bcom_queue_full(priv->tx_dmatsk)) {
> +		if (net_ratelimit())
> +			dev_err(&dev->dev, "transmit queue overrun\n");
> +		return 1;
> +	}
> +
> +	spin_lock_irq(&priv->lock);
> +	dev->trans_start = jiffies;
> +
> +	bd = (struct bcom_fec_bd *)
> +		bcom_prepare_next_buffer(priv->tx_dmatsk);
> +
> +	bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_INT;
> +	bd->skb_pa = virt_to_phys(skb->data);
> +
> +	bcom_submit_next_buffer(priv->tx_dmatsk, skb);
> +
> +	if (bcom_queue_full(priv->tx_dmatsk)) {
> +		priv->tx_full = 1;
> +		netif_stop_queue(dev);
> +	}
> +
> +	spin_unlock_irq(&priv->lock);
> +
> +	return 0;
> +}
> +
> +/* This handles BestComm transmit task interrupts
> + */
> +static irqreturn_t fec_tx_interrupt(int irq, void *dev_id)
> +{
> +	struct net_device *dev = dev_id;
> +	struct fec_priv *priv = netdev_priv(dev);
> +
> +	spin_lock(&priv->lock);
> +
> +	while (bcom_buffer_done(priv->tx_dmatsk)) {
> +		struct sk_buff *skb;
> +		skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, NULL);
> +
> +		priv->tx_full = 0;
> +		dev_kfree_skb_irq(skb);
> +	}
> +
> +	if (netif_queue_stopped(dev) && !priv->tx_full)
> +		netif_wake_queue(dev);
> +
> +	spin_unlock(&priv->lock);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t fec_rx_interrupt(int irq, void *dev_id)
> +{
> +	struct net_device *dev = dev_id;
> +	struct fec_priv *priv = netdev_priv(dev);
> +
> +	while (bcom_buffer_done(priv->rx_dmatsk)) {
> +		struct sk_buff *skb;
> +		struct sk_buff *rskb;
> +		struct bcom_fec_bd *bd;
> +		u32 status;
> +
> +		rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, NULL);
> +
> +		/* Test for errors in received frame */
> +		if (status & BCOM_FEC_RX_BD_ERRORS) {
> +			/* Drop packet and reuse the buffer */
> +			bd = (struct bcom_fec_bd *)
> +				bcom_prepare_next_buffer(priv->rx_dmatsk);
> +
> +			bd->status = FEC_RX_BUFFER_SIZE;
> +			bd->skb_pa = virt_to_phys(rskb->data);
> +
> +			bcom_submit_next_buffer(priv->rx_dmatsk, rskb);
> +
> +			priv->stats.rx_dropped++;
> +
> +			continue;
> +		}
> +
> +		/* skbs are allocated on open, so now we allocate a new one,
> +		 * and remove the old (with the packet) */
> +		skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
> +		if (skb) {
> +			/* Process the received skb */
> +			int length = status & BCOM_FEC_RX_BD_LEN_MASK;
> +
> +			skb_put(rskb, length - 4);	/* length without CRC32 */
> +
> +			rskb->dev = dev;
> +			rskb->protocol = eth_type_trans(rskb, dev);
> +
> +			netif_rx(rskb);
> +			dev->last_rx = jiffies;
> +		} else {
> +			/* Can't get a new one : reuse the same & drop pkt */
> +			dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
> +			priv->stats.rx_dropped++;
> +
> +			skb = rskb;
> +		}
> +
> +		bd = (struct bcom_fec_bd *)
> +			bcom_prepare_next_buffer(priv->rx_dmatsk);
> +
> +		bd->status = FEC_RX_BUFFER_SIZE;
> +		bd->skb_pa = virt_to_phys(skb->data);
> +
> +		bcom_submit_next_buffer(priv->rx_dmatsk, skb);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t fec_interrupt(int irq, void *dev_id)
> +{
> +	struct net_device *dev = dev_id;
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +	u32 ievent;
> +
> +	ievent = in_be32(&fec->ievent);
> +
> +	ievent &= ~FEC_IEVENT_MII;	/* mii is handled separately */
> +	if (!ievent)
> +		return IRQ_NONE;
> +
> +	out_be32(&fec->ievent, ievent);		/* clear pending events */
> +
> +	if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
> +		if (ievent & ~FEC_IEVENT_TFINT)
> +			dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
> +		return IRQ_HANDLED;
> +	}
> +
> +	if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
> +		dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
> +	if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
> +		dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
> +
> +	fec_stop(dev);
> +	fec_hw_init(dev);
> +	fec_start(dev);
> +
> +	netif_wake_queue(dev);
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * Get the current statistics.
> + * This may be called with the card open or closed.
> + */
> +static struct net_device_stats *fec_get_stats(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &priv->stats;
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +/*	printk(KERN_ALERT "%s: %i, rmon_r_octets: %i, rmon_r_packets: %i, "
> +			"ieee_r_octets_ok: %i, ieee_r_frame_ok: %i, "
> +			"%i\n",
> +			__func__, __LINE__,
> +			in_be32(&fec->rmon_r_octets), in_be32(&fec->rmon_r_packets),
> +			in_be32(&fec->ieee_r_octets_ok), in_be32(&fec->ieee_r_frame_ok),
> +			0);
> +*/
> +	stats->rx_bytes = in_be32(&fec->rmon_r_octets);
> +	stats->rx_packets = in_be32(&fec->rmon_r_packets);
> +	stats->rx_errors = in_be32(&fec->rmon_r_crc_align) +
> +		in_be32(&fec->rmon_r_undersize) +
> +		in_be32(&fec->rmon_r_oversize) +
> +		in_be32(&fec->rmon_r_frag) +
> +		in_be32(&fec->rmon_r_jab);
> +
> +	stats->tx_bytes = in_be32(&fec->rmon_t_octets);
> +	stats->tx_packets = in_be32(&fec->rmon_t_packets);
> +	stats->tx_errors = in_be32(&fec->rmon_t_crc_align) +
> +		in_be32(&fec->rmon_t_undersize) +
> +		in_be32(&fec->rmon_t_oversize) +
> +		in_be32(&fec->rmon_t_frag) +
> +		in_be32(&fec->rmon_t_jab);
> +
> +	stats->multicast = in_be32(&fec->rmon_r_mc_pkt);
> +	stats->collisions = in_be32(&fec->rmon_t_col);
> +
> +	/* detailed rx_errors: */
> +	stats->rx_length_errors = in_be32(&fec->rmon_r_undersize)
> +					+ in_be32(&fec->rmon_r_oversize)
> +					+ in_be32(&fec->rmon_r_frag)
> +					+ in_be32(&fec->rmon_r_jab);
> +	stats->rx_over_errors = in_be32(&fec->r_macerr);
> +	stats->rx_crc_errors = in_be32(&fec->ieee_r_crc);
> +	stats->rx_frame_errors = in_be32(&fec->ieee_r_align);
> +	stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop);
> +	stats->rx_missed_errors = in_be32(&fec->rmon_r_drop);
> +
> +	/* detailed tx_errors: */
> +	stats->tx_aborted_errors = 0;
> +	stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr);
> +	stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop);
> +	stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe);
> +	stats->tx_window_errors = in_be32(&fec->ieee_t_lcol);
> +
> +	return stats;
> +}
> +
> +/*
> + * Read MIB counters in order to reset them,
> + * then zero all the stats fields in memory
> + */
> +static void fec_reset_stats(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +	out_be32(&fec->mib_control, FEC_MIB_DISABLE);
> +	memset_io(&fec->rmon_t_drop, 0,
> +			(u32)&fec->reserved10 - (u32)&fec->rmon_t_drop);
> +	out_be32(&fec->mib_control, 0);
> +
> +	memset(&priv->stats, 0, sizeof(priv->stats));
> +}
> +
> +/*
> + * Set or clear the multicast filter for this adaptor.
> + */
> +static void fec_set_multicast_list(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +	u32 rx_control;
> +
> +	rx_control = in_be32(&fec->r_cntrl);
> +
> +	if (dev->flags & IFF_PROMISC) {
> +		rx_control |= FEC_RCNTRL_PROM;
> +		out_be32(&fec->r_cntrl, rx_control);
> +	} else {
> +		rx_control &= ~FEC_RCNTRL_PROM;
> +		out_be32(&fec->r_cntrl, rx_control);
> +
> +		if (dev->flags & IFF_ALLMULTI) {
> +			out_be32(&fec->gaddr1, 0xffffffff);
> +			out_be32(&fec->gaddr2, 0xffffffff);
> +		} else {
> +			u32 crc;
> +			int i;
> +			struct dev_mc_list *dmi;
> +			u32 gaddr1 = 0x00000000;
> +			u32 gaddr2 = 0x00000000;
> +
> +			dmi = dev->mc_list;
> +			for (i=0; i<dev->mc_count; i++) {
> +				crc = ether_crc_le(6, dmi->dmi_addr) >> 26;
> +				if (crc >= 32)
> +					gaddr1 |= 1 << (crc-32);
> +				else
> +					gaddr2 |= 1 << crc;
> +				dmi = dmi->next;
> +			}
> +			out_be32(&fec->gaddr1, gaddr1);
> +			out_be32(&fec->gaddr2, gaddr2);
> +		}
> +	}
> +}
> +
> +static void __init fec_str2mac(char *str, unsigned char *mac)
> +{
> +	int i;
> +	u64 val64;
> +
> +	val64 = simple_strtoull(str, NULL, 16);
> +
> +	for (i = 0; i < 6; i++)
> +		mac[5-i] = val64 >> (i*8);
> +}
> +
> +static int __init mpc52xx_fec_mac_setup(char *mac_address)
> +{
> +	fec_str2mac(mac_address, mpc52xx_fec_mac_addr);
> +	return 0;
> +}
> +
> +/* XXX do we need this? */
> +__setup("mpc52xx-mac=", mpc52xx_fec_mac_setup);
> +
> +/**
> + * fec_hw_init
> + * @dev: network device
> + *
> + * Setup various hardware setting, only needed once on start
> + */
> +static void fec_hw_init(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +	int i;
> +
> +	/* Whack a reset.  We should wait for this. */
> +	out_be32(&fec->ecntrl, FEC_ECNTRL_RESET);
> +	for (i = 0; i < FEC_RESET_DELAY; ++i) {
> +		if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0)
> +			break;
> +		udelay(1);
> +	}
> +	if (i == FEC_RESET_DELAY)
> +		dev_err(&dev->dev, "FEC Reset timeout!\n");
> +
> +	/* set pause to 0x20 frames */
> +	out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20);
> +
> +	/* high service request will be deasserted when there's < 7 bytes in fifo
> +	 * low service request will be deasserted when there's < 4*7 bytes in fifo
> +	 */
> +	out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
> +	out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
> +
> +	/* alarm when <= x bytes in FIFO */
> +	out_be32(&fec->rfifo_alarm, 0x0000030c);
> +	out_be32(&fec->tfifo_alarm, 0x00000100);
> +
> +	/* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */
> +	out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B);
> +
> +	/* enable crc generation */
> +	out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC);
> +	out_be32(&fec->iaddr1, 0x00000000);	/* No individual filter */
> +	out_be32(&fec->iaddr2, 0x00000000);	/* No individual filter */
> +
> +	/* set phy speed and enable MII interrupt
> +	 * this can't be done in phy driver, since it needs to be called
> +	 * before fec stuff (even on resume) */
> +	set_phy_speed(fec, priv->phy_speed);
> +	out_be32(&fec->imask, in_be32(&fec->imask) | FEC_IMASK_MII);
> +}
> +
> +/**
> + * fec_start
> + * @dev: network device
> + *
> + * This function is called to start or restart the FEC during a link
> + * change.  This happens on fifo errors or when switching between half
> + * and full duplex.
> + */
> +static void fec_start(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +	u32 rcntrl;
> +	u32 tcntrl;
> +	u32 tmp;
> +
> +	/* clear sticky error bits */
> +	tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF;
> +	out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp);
> +	out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp);
> +
> +	/* FIFOs will reset on fec_enable */
> +	out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET);
> +
> +	/* Set station address. */
> +	fec_set_paddr(dev, dev->dev_addr);
> +
> +	fec_set_multicast_list(dev);
> +
> +	/* set max frame len, enable flow control, select mii mode */
> +	rcntrl = FEC_RX_BUFFER_SIZE << 16;	/* max frame length */
> +	rcntrl |= FEC_RCNTRL_FCE;
> +	rcntrl |= MII_RCNTL_MODE;
> +	if (priv->duplex == DUPLEX_FULL)
> +		tcntrl = FEC_TCNTRL_FDEN;	/* FD enable */
> +	else {
> +		rcntrl |= FEC_RCNTRL_DRT;	/* disable Rx on Tx (HD) */
> +		tcntrl = 0;
> +	}
> +	out_be32(&fec->r_cntrl, rcntrl);
> +	out_be32(&fec->x_cntrl, tcntrl);
> +
> +	/* Clear any outstanding interrupt. */
> +	out_be32(&fec->ievent, 0xffffffff);
> +
> +	/* Enable interrupts we wish to service. */
> +	out_be32(&fec->imask, FEC_IMASK_ENABLE);
> +
> +	/* And last, enable the transmit and receive processing. */
> +	out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN);
> +	out_be32(&fec->r_des_active, 0x01000000);
> +
> +	priv->tx_full = 0;
> +}
> +
> +/**
> + * fec_stop
> + * @dev: network device
> + *
> + * stop all activity on fec and empty dma buffers
> + */
> +static void fec_stop(struct net_device *dev)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mpc52xx_fec __iomem *fec = priv->fec;
> +	unsigned long timeout;
> +
> +	out_be32(&fec->imask, FEC_IMASK_MII);	/* disable all but MII interrupt */
> +
> +	/* Disable the rx and tx tasks. */
> +	bcom_disable(priv->rx_dmatsk);
> +
> +	/* Wait for queues to drain, but only if we're in process context */
> +	if (!in_interrupt()) {
> +		timeout = jiffies + 2*HZ;
> +		while (time_before(jiffies, timeout) &&
> +				(!bcom_queue_empty(priv->tx_dmatsk) ||
> +				!bcom_queue_empty(priv->rx_dmatsk))) {
> +			set_current_state(TASK_INTERRUPTIBLE);
> +			schedule_timeout(HZ/10);
> +		}
> +		if (time_after_eq(jiffies, timeout))
> +			dev_err(&dev->dev, "queues didn't drain\n");
> +	}
> +
> +	bcom_disable(priv->tx_dmatsk);
> +
> +	/* Stop FEC */
> +	out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN);
> +
> +	return;
> +}
> +
> +static int fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> +{
> +	struct fec_priv *priv = netdev_priv(dev);
> +	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
> +
> +	return phy_mii_ioctl(priv->phydev, mii, cmd);
> +}
> +
> +/* ======================================================================== */
> +/* OF Driver                                                                */
> +/* ======================================================================== */
> +
> +static int __devinit
> +mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
> +{
> +	int rv;
> +	struct net_device *ndev;
> +	struct fec_priv *priv = NULL;
> +	struct resource mem;
> +
> +	phys_addr_t rx_fifo;
> +	phys_addr_t tx_fifo;
> +
> +	/* Get the ether ndev & it's private zone */
> +	ndev = alloc_etherdev(sizeof(struct fec_priv));
> +	if (!ndev)
> +		return -ENOMEM;
> +
> +	priv = netdev_priv(ndev);
> +
> +	priv->ofdev = op;
> +
> +	/* Reserve FEC control zone */
> +	rv = of_address_to_resource(op->node, 0, &mem);
> +	if (rv) {
> +		printk(KERN_ERR DRIVER_NAME ": "
> +				"Error while parsing device node resource\n" );
> +		return rv;
> +	}
> +	if ((mem.end - mem.start + 1) != sizeof(struct mpc52xx_fec)) {
> +		printk(KERN_ERR DRIVER_NAME 
> +			" - invalid resource size (%lx != %x), check mpc52xx_devices.c\n",
> +			(unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec));
> +		return -EINVAL;
> +	}
> +
> +	if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), DRIVER_NAME))
> +		return -EBUSY;
> +
> +	/* Init ether ndev with what we have */
> +	ndev->open		= fec_open;
> +	ndev->stop		= fec_close;
> +	ndev->hard_start_xmit	= fec_hard_start_xmit;
> +	ndev->do_ioctl		= fec_ioctl;
> +	ndev->get_stats		= fec_get_stats;
> +	ndev->set_mac_address	= fec_set_mac_address;
> +	ndev->set_multicast_list = fec_set_multicast_list;
> +	ndev->tx_timeout	= fec_tx_timeout;
> +	ndev->watchdog_timeo	= FEC_WATCHDOG_TIMEOUT;
> +	ndev->flags &= ~IFF_RUNNING;
> +	ndev->base_addr		= mem.start;
> +
> +	priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */
> +	
> +	spin_lock_init(&priv->lock);
> +
> +	/* ioremap the zones */
> +	priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec));
> +	
> +	if (!priv->fec) {
> +		rv = -ENOMEM;
> +		goto probe_error;
> +	}
> +
> +	/* Bestcomm init */
> +	rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data);
> +	tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data);
> +
> +	priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE);
> +	priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo);
> +
> +	if (!priv->rx_dmatsk || !priv->tx_dmatsk) {
> +		printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" );
> +		rv = -ENOMEM;
> +		goto probe_error;
> +	}
> +
> +	/* Get the IRQ we need one by one */
> +		/* Control */
> +	ndev->irq = irq_of_parse_and_map(op->node, 0);
> +
> +		/* RX */
> +	priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk);
> +
> +		/* TX */
> +	priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk);
> +
> +	/* MAC address init */
> +	if (memcmp(mpc52xx_fec_mac_addr, null_mac, 6) != 0)
> +		memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
> +	else
> +		fec_get_paddr(ndev, ndev->dev_addr);
> +
> +	/* Phy speed */
> +	priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
> +
> +	priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
> +	priv->duplex = DUPLEX_HALF;
> +
> +	/* Hardware init */
> +	fec_hw_init(ndev);
> +
> +	fec_reset_stats(ndev);
> +
> +	/* Register the new network device */
> +	rv = register_netdev(ndev);
> +	if (rv < 0)
> +		goto probe_error;
> +
> +	/* We're done ! */
> +	dev_set_drvdata(&op->dev, ndev);
> +
> +	return 0;
> +
> +
> +	/* Error handling - free everything that might be allocated */
> +probe_error:
> +
> +	irq_dispose_mapping(ndev->irq);
> +
> +	if (priv->rx_dmatsk)
> +		bcom_fec_rx_release(priv->rx_dmatsk);
> +	if (priv->tx_dmatsk)
> +		bcom_fec_tx_release(priv->tx_dmatsk);
> +
> +	if (priv->fec)
> +		iounmap(priv->fec);
> +
> +	release_mem_region(mem.start, sizeof(struct mpc52xx_fec));
> +
> +	free_netdev(ndev);
> +
> +	return rv;
> +}
> +
> +static int
> +mpc52xx_fec_remove(struct of_device *op)
> +{
> +	struct net_device *ndev;
> +	struct fec_priv *priv;
> +	
> +	ndev = dev_get_drvdata(&op->dev);
> +	if (!ndev)
> +		return 0;
> +	priv = netdev_priv(ndev);
> +
> +	unregister_netdev(ndev);
> +	
> +	irq_dispose_mapping(ndev->irq);
> +
> +	bcom_fec_rx_release(priv->rx_dmatsk);
> +	bcom_fec_tx_release(priv->tx_dmatsk);
> +
> +	iounmap(priv->fec);
> +	
> +	release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec));
> +
> +	free_netdev(ndev);
> +	
> +	dev_set_drvdata(&op->dev, NULL);
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state)
> +{
> +	struct net_device *dev = dev_get_drvdata(&op->dev);
> +
> +	if (netif_running(dev))
> +		fec_close(dev);
> +
> +	return 0;
> +}
> +
> +static int mpc52xx_fec_of_resume(struct of_device *op)
> +{
> +	struct net_device *dev = dev_get_drvdata(&op->dev);
> +
> +	fec_hw_init(dev);
> +	fec_reset_stats(dev);
> +
> +	if (netif_running(dev))
> +		fec_open(dev);
> +
> +	return 0;
> +}
> +#endif
> +
> +static struct of_device_id mpc52xx_fec_match[] = {
> +	{
> +		.type		= "network",
> +		.compatible	= "mpc5200-fec",
> +	},
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, mpc52xx_fec_match);
> +
> +static struct of_platform_driver mpc52xx_fec_driver = {
> +	.owner		= THIS_MODULE,
> +	.name		= DRIVER_NAME,
> +	.match_table	= mpc52xx_fec_match,
> +	.probe		= mpc52xx_fec_probe,
> +	.remove		= mpc52xx_fec_remove,
> +#ifdef CONFIG_PM
> +	.suspend	= mpc52xx_fec_of_suspend,
> +	.resume		= mpc52xx_fec_of_resume,
> +#endif
> +};
> +
> +
> +/* ======================================================================== */
> +/* Module                                                                   */
> +/* ======================================================================== */
> +
> +static int __init
> +mpc52xx_fec_init(void)
> +{
> +	int ret;
> +	if ((ret = fec_mdio_init())) {

Why not:

	int ret = fec_mdio_init();
	if (ret) {

Less parenthesis, looks more clear

> +		printk(KERN_ERR "%s: %i fec_mdio_init failed\n", __func__, __LINE__);
> +		return ret;
> +	}
> +
> +	return of_register_platform_driver(&mpc52xx_fec_driver);
> +}
> +
> +static void __exit
> +mpc52xx_fec_exit(void)
> +{
> +	of_unregister_platform_driver(&mpc52xx_fec_driver);
> +	fec_mdio_exit();
> +}
> +
> +
> +module_init(mpc52xx_fec_init);
> +module_exit(mpc52xx_fec_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Dale Farnsworth");
> +MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC");
> +
> diff -pruN dummy/fec.h ./drivers/net/fec_mpc52xx/fec.h
> --- dummy/fec.h	1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec.h	2007-08-10 11:24:37.000000000 +0200
> @@ -0,0 +1,299 @@
> +/*
> + * drivers/net/fec_mpc52xx/fec.h
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + *
> + * Author: Dale Farnsworth <dfarnsworth@mvista.com>
> + *
> + * 2003-2004 (c) MontaVista, Software, Inc.  This file is licensed under
> + * the terms of the GNU General Public License version 2.  This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + */
> +
> +#ifndef __DRIVERS_NET_MPC52XX_FEC_H__
> +#define __DRIVERS_NET_MPC52XX_FEC_H__
> +
> +#include <linux/mii.h> // XXX, still needed?
> +#include <linux/phy.h>
> +
> +/* Tunable constant */
> +/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */
> +#define FEC_RX_BUFFER_SIZE	1522	/* max receive packet size */
> +#define FEC_RX_NUM_BD		64
> +#define FEC_TX_NUM_BD		64
> +
> +#define FEC_RESET_DELAY		50 	/* uS */
> +
> +#define FEC_WATCHDOG_TIMEOUT	((400*HZ)/1000)
> +
> +struct fec_priv {
> +	int duplex;
> +	int tx_full;
> +	int r_irq;
> +	int t_irq;
> +	struct mpc52xx_fec __iomem *fec;
> +	struct bcom_task *rx_dmatsk;
> +	struct bcom_task *tx_dmatsk;
> +	spinlock_t lock;
> +	struct net_device_stats stats;
> +	int msg_enable;
> +#ifdef CONFIG_FEC_MPC52xx_MDIO
> +	uint phy_speed;
> +
> +	struct phy_device *phydev;
> +	enum phy_state link;
> +	int speed;
> +
> +	struct of_device *ofdev;
> +#endif	/* CONFIG_FEC_MPC52xx_MDIO */
> +};
> +
> +
> +/* ======================================================================== */
> +/* Hardware register sets & bits                                            */
> +/* ======================================================================== */
> +
> +struct mpc52xx_fec {
> +	u32 fec_id;			/* FEC + 0x000 */
> +	u32 ievent;			/* FEC + 0x004 */
> +	u32 imask;			/* FEC + 0x008 */
> +
> +	u32 reserved0[1];		/* FEC + 0x00C */
> +	u32 r_des_active;		/* FEC + 0x010 */
> +	u32 x_des_active;		/* FEC + 0x014 */
> +	u32 r_des_active_cl;		/* FEC + 0x018 */
> +	u32 x_des_active_cl;		/* FEC + 0x01C */
> +	u32 ivent_set;			/* FEC + 0x020 */
> +	u32 ecntrl;			/* FEC + 0x024 */
> +
> +	u32 reserved1[6];		/* FEC + 0x028-03C */
> +	u32 mii_data;			/* FEC + 0x040 */
> +	u32 mii_speed;			/* FEC + 0x044 */
> +	u32 mii_status;			/* FEC + 0x048 */
> +
> +	u32 reserved2[5];		/* FEC + 0x04C-05C */
> +	u32 mib_data;			/* FEC + 0x060 */
> +	u32 mib_control;		/* FEC + 0x064 */
> +
> +	u32 reserved3[6];		/* FEC + 0x068-7C */
> +	u32 r_activate;			/* FEC + 0x080 */
> +	u32 r_cntrl;			/* FEC + 0x084 */
> +	u32 r_hash;			/* FEC + 0x088 */
> +	u32 r_data;			/* FEC + 0x08C */
> +	u32 ar_done;			/* FEC + 0x090 */
> +	u32 r_test;			/* FEC + 0x094 */
> +	u32 r_mib;			/* FEC + 0x098 */
> +	u32 r_da_low;			/* FEC + 0x09C */
> +	u32 r_da_high;			/* FEC + 0x0A0 */
> +
> +	u32 reserved4[7];		/* FEC + 0x0A4-0BC */
> +	u32 x_activate;			/* FEC + 0x0C0 */
> +	u32 x_cntrl;			/* FEC + 0x0C4 */
> +	u32 backoff;			/* FEC + 0x0C8 */
> +	u32 x_data;			/* FEC + 0x0CC */
> +	u32 x_status;			/* FEC + 0x0D0 */
> +	u32 x_mib;			/* FEC + 0x0D4 */
> +	u32 x_test;			/* FEC + 0x0D8 */
> +	u32 fdxfc_da1;			/* FEC + 0x0DC */
> +	u32 fdxfc_da2;			/* FEC + 0x0E0 */
> +	u32 paddr1;			/* FEC + 0x0E4 */
> +	u32 paddr2;			/* FEC + 0x0E8 */
> +	u32 op_pause;			/* FEC + 0x0EC */
> +
> +	u32 reserved5[4];		/* FEC + 0x0F0-0FC */
> +	u32 instr_reg;			/* FEC + 0x100 */
> +	u32 context_reg;		/* FEC + 0x104 */
> +	u32 test_cntrl;			/* FEC + 0x108 */
> +	u32 acc_reg;			/* FEC + 0x10C */
> +	u32 ones;			/* FEC + 0x110 */
> +	u32 zeros;			/* FEC + 0x114 */
> +	u32 iaddr1;			/* FEC + 0x118 */
> +	u32 iaddr2;			/* FEC + 0x11C */
> +	u32 gaddr1;			/* FEC + 0x120 */
> +	u32 gaddr2;			/* FEC + 0x124 */
> +	u32 random;			/* FEC + 0x128 */
> +	u32 rand1;			/* FEC + 0x12C */
> +	u32 tmp;			/* FEC + 0x130 */
> +
> +	u32 reserved6[3];		/* FEC + 0x134-13C */
> +	u32 fifo_id;			/* FEC + 0x140 */
> +	u32 x_wmrk;			/* FEC + 0x144 */
> +	u32 fcntrl;			/* FEC + 0x148 */
> +	u32 r_bound;			/* FEC + 0x14C */
> +	u32 r_fstart;			/* FEC + 0x150 */
> +	u32 r_count;			/* FEC + 0x154 */
> +	u32 r_lag;			/* FEC + 0x158 */
> +	u32 r_read;			/* FEC + 0x15C */
> +	u32 r_write;			/* FEC + 0x160 */
> +	u32 x_count;			/* FEC + 0x164 */
> +	u32 x_lag;			/* FEC + 0x168 */
> +	u32 x_retry;			/* FEC + 0x16C */
> +	u32 x_write;			/* FEC + 0x170 */
> +	u32 x_read;			/* FEC + 0x174 */
> +
> +	u32 reserved7[2];		/* FEC + 0x178-17C */
> +	u32 fm_cntrl;			/* FEC + 0x180 */
> +	u32 rfifo_data;			/* FEC + 0x184 */
> +	u32 rfifo_status;		/* FEC + 0x188 */
> +	u32 rfifo_cntrl;		/* FEC + 0x18C */
> +	u32 rfifo_lrf_ptr;		/* FEC + 0x190 */
> +	u32 rfifo_lwf_ptr;		/* FEC + 0x194 */
> +	u32 rfifo_alarm;		/* FEC + 0x198 */
> +	u32 rfifo_rdptr;		/* FEC + 0x19C */
> +	u32 rfifo_wrptr;		/* FEC + 0x1A0 */
> +	u32 tfifo_data;			/* FEC + 0x1A4 */
> +	u32 tfifo_status;		/* FEC + 0x1A8 */
> +	u32 tfifo_cntrl;		/* FEC + 0x1AC */
> +	u32 tfifo_lrf_ptr;		/* FEC + 0x1B0 */
> +	u32 tfifo_lwf_ptr;		/* FEC + 0x1B4 */
> +	u32 tfifo_alarm;		/* FEC + 0x1B8 */
> +	u32 tfifo_rdptr;		/* FEC + 0x1BC */
> +	u32 tfifo_wrptr;		/* FEC + 0x1C0 */
> +
> +	u32 reset_cntrl;		/* FEC + 0x1C4 */
> +	u32 xmit_fsm;			/* FEC + 0x1C8 */
> +
> +	u32 reserved8[3];		/* FEC + 0x1CC-1D4 */
> +	u32 rdes_data0;			/* FEC + 0x1D8 */
> +	u32 rdes_data1;			/* FEC + 0x1DC */
> +	u32 r_length;			/* FEC + 0x1E0 */
> +	u32 x_length;			/* FEC + 0x1E4 */
> +	u32 x_addr;			/* FEC + 0x1E8 */
> +	u32 cdes_data;			/* FEC + 0x1EC */
> +	u32 status;			/* FEC + 0x1F0 */
> +	u32 dma_control;		/* FEC + 0x1F4 */
> +	u32 des_cmnd;			/* FEC + 0x1F8 */
> +	u32 data;			/* FEC + 0x1FC */
> +
> +	u32 rmon_t_drop;		/* FEC + 0x200 */
> +	u32 rmon_t_packets;		/* FEC + 0x204 */
> +	u32 rmon_t_bc_pkt;		/* FEC + 0x208 */
> +	u32 rmon_t_mc_pkt;		/* FEC + 0x20C */
> +	u32 rmon_t_crc_align;		/* FEC + 0x210 */
> +	u32 rmon_t_undersize;		/* FEC + 0x214 */
> +	u32 rmon_t_oversize;		/* FEC + 0x218 */
> +	u32 rmon_t_frag;		/* FEC + 0x21C */
> +	u32 rmon_t_jab;			/* FEC + 0x220 */
> +	u32 rmon_t_col;			/* FEC + 0x224 */
> +	u32 rmon_t_p64;			/* FEC + 0x228 */
> +	u32 rmon_t_p65to127;		/* FEC + 0x22C */
> +	u32 rmon_t_p128to255;		/* FEC + 0x230 */
> +	u32 rmon_t_p256to511;		/* FEC + 0x234 */
> +	u32 rmon_t_p512to1023;		/* FEC + 0x238 */
> +	u32 rmon_t_p1024to2047;		/* FEC + 0x23C */
> +	u32 rmon_t_p_gte2048;		/* FEC + 0x240 */
> +	u32 rmon_t_octets;		/* FEC + 0x244 */
> +	u32 ieee_t_drop;		/* FEC + 0x248 */
> +	u32 ieee_t_frame_ok;		/* FEC + 0x24C */
> +	u32 ieee_t_1col;		/* FEC + 0x250 */
> +	u32 ieee_t_mcol;		/* FEC + 0x254 */
> +	u32 ieee_t_def;			/* FEC + 0x258 */
> +	u32 ieee_t_lcol;		/* FEC + 0x25C */
> +	u32 ieee_t_excol;		/* FEC + 0x260 */
> +	u32 ieee_t_macerr;		/* FEC + 0x264 */
> +	u32 ieee_t_cserr;		/* FEC + 0x268 */
> +	u32 ieee_t_sqe;			/* FEC + 0x26C */
> +	u32 t_fdxfc;			/* FEC + 0x270 */
> +	u32 ieee_t_octets_ok;		/* FEC + 0x274 */
> +
> +	u32 reserved9[2];		/* FEC + 0x278-27C */
> +	u32 rmon_r_drop;		/* FEC + 0x280 */
> +	u32 rmon_r_packets;		/* FEC + 0x284 */
> +	u32 rmon_r_bc_pkt;		/* FEC + 0x288 */
> +	u32 rmon_r_mc_pkt;		/* FEC + 0x28C */
> +	u32 rmon_r_crc_align;		/* FEC + 0x290 */
> +	u32 rmon_r_undersize;		/* FEC + 0x294 */
> +	u32 rmon_r_oversize;		/* FEC + 0x298 */
> +	u32 rmon_r_frag;		/* FEC + 0x29C */
> +	u32 rmon_r_jab;			/* FEC + 0x2A0 */
> +
> +	u32 rmon_r_resvd_0;		/* FEC + 0x2A4 */
> +
> +	u32 rmon_r_p64;			/* FEC + 0x2A8 */
> +	u32 rmon_r_p65to127;		/* FEC + 0x2AC */
> +	u32 rmon_r_p128to255;		/* FEC + 0x2B0 */
> +	u32 rmon_r_p256to511;		/* FEC + 0x2B4 */
> +	u32 rmon_r_p512to1023;		/* FEC + 0x2B8 */
> +	u32 rmon_r_p1024to2047;		/* FEC + 0x2BC */
> +	u32 rmon_r_p_gte2048;		/* FEC + 0x2C0 */
> +	u32 rmon_r_octets;		/* FEC + 0x2C4 */
> +	u32 ieee_r_drop;		/* FEC + 0x2C8 */
> +	u32 ieee_r_frame_ok;		/* FEC + 0x2CC */
> +	u32 ieee_r_crc;			/* FEC + 0x2D0 */
> +	u32 ieee_r_align;		/* FEC + 0x2D4 */
> +	u32 r_macerr;			/* FEC + 0x2D8 */
> +	u32 r_fdxfc;			/* FEC + 0x2DC */
> +	u32 ieee_r_octets_ok;		/* FEC + 0x2E0 */
> +
> +	u32 reserved10[7];		/* FEC + 0x2E4-2FC */
> +
> +	u32 reserved11[64];		/* FEC + 0x300-3FF */
> +};
> +
> +#define	FEC_MIB_DISABLE			0x80000000
> +
> +#define	FEC_IEVENT_HBERR		0x80000000
> +#define	FEC_IEVENT_BABR			0x40000000
> +#define	FEC_IEVENT_BABT			0x20000000
> +#define	FEC_IEVENT_GRA			0x10000000
> +#define	FEC_IEVENT_TFINT		0x08000000
> +#define	FEC_IEVENT_MII			0x00800000
> +#define	FEC_IEVENT_LATE_COL		0x00200000
> +#define	FEC_IEVENT_COL_RETRY_LIM	0x00100000
> +#define	FEC_IEVENT_XFIFO_UN		0x00080000
> +#define	FEC_IEVENT_XFIFO_ERROR		0x00040000
> +#define	FEC_IEVENT_RFIFO_ERROR		0x00020000
> +
> +#define	FEC_IMASK_HBERR			0x80000000
> +#define	FEC_IMASK_BABR			0x40000000
> +#define	FEC_IMASK_BABT			0x20000000
> +#define	FEC_IMASK_GRA			0x10000000
> +#define	FEC_IMASK_MII			0x00800000
> +#define	FEC_IMASK_LATE_COL		0x00200000
> +#define	FEC_IMASK_COL_RETRY_LIM		0x00100000
> +#define	FEC_IMASK_XFIFO_UN		0x00080000
> +#define	FEC_IMASK_XFIFO_ERROR		0x00040000
> +#define	FEC_IMASK_RFIFO_ERROR		0x00020000
> +
> +#define	FEC_RCNTRL_MAX_FL_SHIFT		16
> +#define	FEC_RCNTRL_LOOP			0x01
> +#define	FEC_RCNTRL_DRT			0x02
> +#define	FEC_RCNTRL_MII_MODE		0x04
> +#define	FEC_RCNTRL_PROM			0x08
> +#define	FEC_RCNTRL_BC_REJ		0x10
> +#define	FEC_RCNTRL_FCE			0x20
> +
> +#define	FEC_TCNTRL_GTS			0x00000001
> +#define	FEC_TCNTRL_HBC			0x00000002
> +#define	FEC_TCNTRL_FDEN			0x00000004
> +#define	FEC_TCNTRL_TFC_PAUSE		0x00000008
> +#define	FEC_TCNTRL_RFC_PAUSE		0x00000010
> +
> +#define	FEC_ECNTRL_RESET		0x00000001
> +#define	FEC_ECNTRL_ETHER_EN		0x00000002
> +
> +#define FEC_PADDR2_TYPE			0x8808
> +
> +#define FEC_OP_PAUSE_OPCODE		0x00010000
> +
> +#define FEC_FIFO_WMRK_256B		0x3
> +
> +#define FEC_FIFO_STATUS_ERR		0x00400000
> +#define FEC_FIFO_STATUS_UF		0x00200000
> +#define FEC_FIFO_STATUS_OF		0x00100000
> +
> +#define FEC_FIFO_CNTRL_FRAME		0x08000000
> +#define FEC_FIFO_CNTRL_LTG_7		0x07000000
> +
> +#define FEC_RESET_CNTRL_RESET_FIFO	0x02000000
> +#define FEC_RESET_CNTRL_ENABLE_IS_RESET	0x01000000
> +
> +#define FEC_XMIT_FSM_APPEND_CRC		0x02000000
> +#define FEC_XMIT_FSM_ENABLE_CRC		0x01000000
> +
> +
> +int __init fec_mdio_init(void);
> +void __exit fec_mdio_exit(void);
> +
> +#endif	/* __DRIVERS_NET_MPC52XX_FEC_H__ */
> diff -pruN dummy/fec_phy.c ./drivers/net/fec_mpc52xx/fec_phy.c
> --- dummy/fec_phy.c	1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec_phy.c	2007-08-10 10:59:53.000000000 +0200
> @@ -0,0 +1,229 @@
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/phy.h>
> +#include <asm/io.h>
> +#include <asm/mpc52xx.h>
> +#include <asm/of_platform.h>
> +#include "fec_phy.h"
> +#include "fec.h"
> +
> +struct fec_mdio_priv {
> +	int completed;
> +	wait_queue_head_t wq;
> +	struct mpc52xx_fec __iomem *regs;
> +	int irq;
> +};
> +
> +static int fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
> +{
> +	struct fec_mdio_priv *priv = bus->priv;
> +	int tries = 100;
> +
> +	u32 request = FEC_MII_READ_FRAME;
> +	request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
> +	request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
> +
> +	out_be32(&priv->regs->mii_data, request);
> +
> +	/* wait for it to finish, this takes about 23 us on lite5200b */
> +	while (priv->completed == 0 && tries--)
> +		udelay(5);
> +
> +	priv->completed = 0;
> +
> +	if (tries == 0)
> +		return -ETIMEDOUT;
> +
> +	return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK;
> +}
> +
> +static int fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
> +{
> +	struct fec_mdio_priv *priv = bus->priv;
> +	u32 value = data;
> +	int tries = 100;
> +
> +	value |= FEC_MII_WRITE_FRAME;
> +	value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
> +	value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
> +
> +	out_be32(&priv->regs->mii_data, value);
> +
> +	/* wait for request to finish */
> +	while (priv->completed == 0 && tries--)
> +		udelay(5);
> +
> +	priv->completed = 0;
> +
> +	if (tries == 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static irqreturn_t fec_mdio_interrupt(int irq, void *dev_id)
> +{
> +	struct fec_mdio_priv *priv = dev_id;
> +	struct mpc52xx_fec __iomem *fec;
> +	int ievent;
> +
> +	fec = priv->regs;
> +	ievent = in_be32(&fec->ievent);
> +
> +	ievent &= FEC_IEVENT_MII;
> +	if (!ievent)
> +		return IRQ_NONE;
> +
> +	out_be32(&fec->ievent, ievent);
> +
> +	priv->completed = 1;
> +	wake_up(&priv->wq);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int fec_mdio_probe(struct of_device *of, const struct of_device_id *match)
> +{
> +	struct device *dev = &of->dev;
> +	struct device_node *np = of->node;
> +	struct device_node *child = NULL;
> +	struct mii_bus *bus;
> +	struct fec_mdio_priv *priv;
> +	struct resource res = {};
> +	int err;
> +	int i;
> +
> +	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
> +	if (bus == NULL)
> +		return -ENOMEM;
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (priv == NULL) {
> +		err = -ENOMEM;
> +		goto out_free;
> +	}
> +
> +	bus->name = "mpc52xx MII bus";
> +	bus->read = fec_mdio_read;
> +	bus->write = fec_mdio_write;
> +
> +	/* setup irqs */
> +	bus->irq = kcalloc(sizeof(bus->irq[0]), PHY_MAX_ADDR, GFP_KERNEL);
> +	if (bus->irq == NULL) {
> +		err = -ENOMEM;
> +		goto out_free;
> +	}
> +	for (i=0; i<PHY_MAX_ADDR; i++)
> +		bus->irq[i] = PHY_POLL;
> +
> +	while ((child = of_get_next_child(np, child)) != NULL) {
> +		int irq = irq_of_parse_and_map(child, 0);
> +		if (irq != NO_IRQ) {
> +			const u32 *id = of_get_property(child, "reg", NULL);
> +			bus->irq[*id] = irq;
> +		}
> +	}
> +
> +	/* setup registers */
> +	err = of_address_to_resource(np, 0, &res);
> +	if (err)
> +		goto out_free;
> +	priv->regs = ioremap(res.start, res.end - res.start + 1);
> +	if (priv->regs == NULL) {
> +		err = -ENOMEM;
> +		goto out_free;
> +	}
> +
> +	priv->irq = irq_of_parse_and_map(np, 0);
> +	err = request_irq(priv->irq, &fec_mdio_interrupt, IRQF_DISABLED | IRQF_SHARED,
> +	                "fec_mdio", priv);
> +	if (err) {
> +		printk(KERN_ERR "%s: interrupt request failed with %i\n", __func__, err);
> +		goto out_unmap;
> +	}
> +
> +	bus->id = res.start;
> +	bus->priv = priv;
> +
> +	bus->dev = dev;
> +	dev_set_drvdata(dev, bus);
> +
> +	init_waitqueue_head(&priv->wq);
> +
> +	/* set MII speed */
> +	out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
> +
> +	/* enable MII interrupt */
> +	out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII);
> +
> +	err = mdiobus_register(bus);
> +	if (err)
> +		goto out_free_irq;
> +
> +	return 0;
> +
> + out_free_irq:
> +	free_irq(priv->irq, dev);
> +	irq_dispose_mapping(priv->irq);
> + out_unmap:
> +	iounmap(priv->regs);
> + out_free:
> +	for (i=0; i<PHY_MAX_ADDR; i++)
> +		if (bus->irq[i])
> +			irq_dispose_mapping(bus->irq[i]);
> +	kfree(bus->irq);
> +	kfree(priv);
> +	kfree(bus);
> +
> +	return err;
> +}
> +
> +static int fec_mdio_remove(struct of_device *of)
> +{
> +	struct device *dev = &of->dev;
> +	struct mii_bus *bus = dev_get_drvdata(dev);
> +	struct fec_mdio_priv *priv = bus->priv;
> +	int i;
> +
> +	mdiobus_unregister(bus);
> +	dev_set_drvdata(dev, NULL);
> +
> +	free_irq(priv->irq, dev);
> +	irq_dispose_mapping(priv->irq);
> +	iounmap(priv->regs);
> +	for (i=0; i<PHY_MAX_ADDR; i++)
> +		if (bus->irq[i])
> +			irq_dispose_mapping(bus->irq[i]);
> +	kfree(priv);
> +	kfree(bus->irq);
> +	kfree(bus);
> +
> +	return 0;
> +}
> +
> +
> +static struct of_device_id fec_mdio_match[] = {
> +	{
> +		.type = "mdio",
> +		.compatible = "mpc5200b-fec-phy",
> +	},
> +	{},
> +};
> +
> +static struct of_platform_driver fec_mdio_driver = {
> +	.name = "mpc5200b-fec-phy",
> +	.probe = fec_mdio_probe,
> +	.remove = fec_mdio_remove,
> +	.match_table = fec_mdio_match,
> +};
> +
> +
> +int __init fec_mdio_init(void)
> +{
> +	return of_register_platform_driver(&fec_mdio_driver);
> +}
> +
> +void __exit fec_mdio_exit(void)
> +{
> +	of_unregister_platform_driver(&fec_mdio_driver);
> +}
> diff -pruN dummy/fec_phy.h ./drivers/net/fec_mpc52xx/fec_phy.h
> --- dummy/fec_phy.h	1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec_phy.h	2007-08-10 11:22:54.000000000 +0200
> @@ -0,0 +1,49 @@
> +/*
> + * arch/ppc/52xx_io/fec_phy.h
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + * Based heavily on the MII support for the MPC8xx by Dan Malek
> + *
> + * Author: Dale Farnsworth <dfarnsworth@mvista.com>
> + *
> + * 2003-2004 (c) MontaVista, Software, Inc.  This file is licensed under
> + * the terms of the GNU General Public License version 2.  This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + */
> +
> +#define FEC_IMASK_ALL		(FEC_IMASK_HBERR | FEC_IMASK_BABR | \
> +		FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_MII | \
> +		FEC_IMASK_LATE_COL | FEC_IMASK_COL_RETRY_LIM | \
> +		FEC_IMASK_XFIFO_UN | FEC_IMASK_XFIFO_ERROR | \
> +		FEC_IMASK_RFIFO_ERROR)
> +
> +#ifdef CONFIG_FEC_MPC52xx_MDIO
> +#define MII_RCNTL_MODE		FEC_RCNTRL_MII_MODE
> +#define FEC_IMASK_ENABLE	FEC_IMASK_ALL
> +#define set_phy_speed(fec, s)	out_be32(&fec->mii_speed, s)
> +#else
> +#define MII_RCNTL_MODE		0
> +#define FEC_IMASK_ENABLE	(FEC_IMASK_ALL & ~FEC_IMASK_MII)
> +#define set_phy_speed(fec, s)	do { } while (0)
> +#define fec_mii_start(dev)	do { } while (0)
> +#define fec_mii(dev)	printk(KERN_WARNING "unexpected FEC_IEVENT_MII\n")
> +#define fec_mii_init(dev)	do { } while (0)
> +#define fec_mii_suspend(dev)	do { } while (0)
> +#define fec_mii_resume(dev)	do { } while (0)
> +#endif	/* CONFIG_FEC_MPC52xx_MDIO */
> +
> +/* MII-related definitions */
> +#define FEC_MII_DATA_ST		0x40000000	/* Start frame */
> +#define FEC_MII_DATA_OP_RD	0x20000000	/* Perform read */
> +#define FEC_MII_DATA_OP_WR	0x10000000	/* Perform write */
> +#define FEC_MII_DATA_PA_MSK	0x0f800000	/* PHY Address mask */
> +#define FEC_MII_DATA_RA_MSK	0x007c0000	/* PHY Register mask */
> +#define FEC_MII_DATA_TA		0x00020000	/* Turnaround */
> +#define FEC_MII_DATA_DATAMSK	0x0000ffff	/* PHY data mask */
> +
> +#define FEC_MII_READ_FRAME	(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA)
> +#define FEC_MII_WRITE_FRAME	(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA)
> +
> +#define FEC_MII_DATA_RA_SHIFT	0x12		/* MII reg addr bits */
> +#define FEC_MII_DATA_PA_SHIFT	0x17		/* MII PHY addr bits */
> diff -pruN dummy/Kconfig ./drivers/net/fec_mpc52xx/Kconfig
> --- dummy/Kconfig	1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/Kconfig	2007-08-08 10:50:04.000000000 +0200
> @@ -0,0 +1,24 @@
> +menu "MPC5200 Networking Options"
> +	depends PPC_MPC52xx && NET_ETHERNET
> +
> +config FEC_MPC52xx
> +	tristate "FEC Ethernet"
> +	depends on NET_ETHERNET
> +	select PPC_BESTCOMM
> +	select PPC_BESTCOMM_FEC
> +	select CRC32
> +	---help---
> +	  This option enables support for the MPC5200's on-chip
> +	  Fast Ethernet Controller
> +
> +config USE_MDIO
> +	bool "Use external Ethernet MII PHY"
> +	select MII
> +	depends FEC_MPC52xx
> +	---help---
> +	  The MPC5200's FEC can connect to the Ethernet either with
> +	  an external MII PHY chip or 10 Mbps 7-wire interface 
> +	  (Motorola? industry standard).
> +	  If your board uses an external PHY, say y, else n.
> +
> +endmenu
> diff -pruN dummy/Makefile ./drivers/net/fec_mpc52xx/Makefile
> --- dummy/Makefile	1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/Makefile	2007-08-08 10:50:04.000000000 +0200
> @@ -0,0 +1,7 @@
> +obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
> +
> +fec_mpc52xx-objs := fec.o
> +
> +ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
> +fec_mpc52xx-objs += fec_phy.o
> +endif
> Index: work-powerpc.git/arch/powerpc/boot/dts/lite5200b.dts
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/boot/dts/lite5200b.dts
> +++ work-powerpc.git/arch/powerpc/boot/dts/lite5200b.dts
> @@ -365,10 +365,26 @@
>  		ethernet@3000 {
>  			device_type = "network";
>  			compatible = "mpc5200b-fec\0mpc5200-fec";
> -			reg = <3000 800>;
> +			reg = <3000 400>;
>  			mac-address = [ 02 03 04 05 06 07 ]; // Bad!
>  			interrupts = <2 5 0>;
>  			interrupt-parent = <&mpc5200_pic>;
> +			phy-handle = <&phy0>;
> +		};
> +
> +		mdio@3000 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			device_type = "mdio";
> +			compatible = "mpc5200b-fec-phy";
> +			reg = <3000 400>;	// fec range, since we need to setup fec interrupts
> +			interrupts = <2 5 0>;	// these are for "mii command finished", not link changes & co.
> +			interrupt-parent = <&mpc5200_pic>;
> +
> +			phy0:ethernet-phy@0 {
> +				device_type = "ethernet-phy";
> +				reg = <0>;
> +			};
>  		};
>  
>  		ata@3a00 {
> Index: work-powerpc.git/arch/powerpc/sysdev/bestcomm/fec.h
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/sysdev/bestcomm/fec.h
> +++ work-powerpc.git/arch/powerpc/sysdev/bestcomm/fec.h
> @@ -22,6 +22,20 @@ struct bcom_fec_bd {
>  
>  #define BCOM_FEC_TX_BD_TFD	0x08000000ul	/* transmit frame done */
>  #define BCOM_FEC_TX_BD_INT	0x04000000ul	/* interrupt */
> +#define BCOM_FEC_TX_BD_TC	0x04000000ul	/* transmit CRC XXX same as ^? */
> +#define BCOM_FEC_TX_BD_ABC	0x02000000ul	/* append bad CRC */
> +
> +#define BCOM_FEC_RX_BD_L	0x08000000ul	/* buffer is last in frame */
> +#define BCOM_FEC_RX_BD_BC	0x00800000ul	/* DA is broadcast */
> +#define BCOM_FEC_RX_BD_MC	0x00400000ul	/* DA is multicast and not broadcast */
> +#define BCOM_FEC_RX_BD_LG	0x00200000ul	/* Rx frame length violation */
> +#define BCOM_FEC_RX_BD_NO	0x00100000ul	/* Rx non-octet aligned frame */
> +#define BCOM_FEC_RX_BD_CR	0x00040000ul	/* Rx CRC error */
> +#define BCOM_FEC_RX_BD_OV	0x00020000ul	/* overrun */
> +#define BCOM_FEC_RX_BD_TR	0x00010000ul	/* Rx frame truncated */
> +#define BCOM_FEC_RX_BD_LEN_MASK	0x000007fful	/* mask for length of received frame */
> +#define BCOM_FEC_RX_BD_ERRORS	(BCOM_FEC_RX_BD_LG | BCOM_FEC_RX_BD_NO | \
> +		BCOM_FEC_RX_BD_CR | BCOM_FEC_RX_BD_OV | BCOM_FEC_RX_BD_TR)
>  
>  
>  extern struct bcom_task *
> -
> 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

^ permalink raw reply

* How to increase the kernel stack size
From: suresh suresh @ 2007-08-10 12:43 UTC (permalink / raw)
  To: linuxppc-embedded

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

Hi,

I want to know how to increase the kernel stack size for 2.4.21 kernel.

Thanks,
Suresh

[-- Attachment #2: Type: text/html, Size: 117 bytes --]

^ 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