This is the second part of my Xilleon port. I am sending the full set of patches to linux-mips@xxxxxxxxxxxxxx which is archived at: http://www.linux-mips.org/archives/ Only the patches that touch generic parts of the kernel are coming here. The Xilleon (32bit MIPS SOC) has a write back buffer that seems to operate on the pci bus and does not get flushed before a read. The result is that a memory barrier must be done before a read intended to flush PCI writes. The second problem is that writes need to be flushed in e100_exec_cmd. I am not sure exactly what was going wrong, but without this patch packets in the send queue were not being sent until... Well I don't know exactly when, but reception of packets and interrupts by other devices on the PCI bus seemed to get them to be kicked out. The result was that when pinging from an external host, the round trip time was usually the same as the ping interval (i.e. one second). This lead to very poor NFS performance. With the patch applied the ethernet seems to work flawlessly Patch against 2.6.14-rc2 from linux-mips.org Signed-off-by: David Daney <ddaney@xxxxxxxxxx> Memory barriers and write flushing added for use with xilleon port. --- commit 8817d129d5d5fc662858925aa39ddda0cb3b73a0 tree bfc8ec97ad24b9477919f861cc29fc396258dc5f parent 7c598df35a43f53dd6704bb2490f82fcd1e28a9a author David Daney <daney@xxxxxxxxxxxxxxxxxx> Tue, 04 Oct 2005 13:11:51 -0700 committer David Daney <daney@xxxxxxxxxxxxxxxxxx> Tue, 04 Oct 2005 13:11:51 -0700 drivers/net/e100.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -584,6 +584,7 @@ static inline void e100_write_flush(stru { /* Flush previous PCI writes through intermediate bridges * by doing a benign read */ + wmb(); (void)readb(&nic->csr->scb.status); } @@ -807,9 +808,13 @@ static inline int e100_exec_cmd(struct n goto err_unlock; } - if(unlikely(cmd != cuc_resume)) + wmb(); + if(unlikely(cmd != cuc_resume)) { writel(dma_addr, &nic->csr->scb.gen_ptr); + e100_write_flush(nic); + } writeb(cmd, &nic->csr->scb.cmd_lo); + e100_write_flush(nic); err_unlock: spin_unlock_irqrestore(&nic->cmd_lock, flags);