Andrew,
Please apply and forward upstream. This series of 16 small patches
consist of mostly of various cleanups, a few fixes, and a clarification
of the flow of the RX side of the spidernet ethernet driver. The
first patch, though, is a resubmit of an old patch.
--linas
The current driver code performs 512 DMA mappings of a bunch of
32-byte structures. This is silly, as they are all in contiguous
memory. Ths patch changes the code to DMA map the entie area
with just one call.
Signed-off-by: Linas Vepstas <redacted>
Acked-by: Joel Schopp <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 107 +++++++++++++++++++++++------------------------
drivers/net/spider_net.h | 16 ++-----
2 files changed, 59 insertions(+), 64 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -316,17 +297,12 @@ spider_net_init_chain(struct spider_net_for(i=0;i<no;i++,descr++){descr->dmac_cmd_status=SPIDER_NET_DESCR_NOT_IN_USE;-buf=pci_map_single(card->pdev,descr,-SPIDER_NET_DESCR_SIZE,-PCI_DMA_BIDIRECTIONAL);--if(pci_dma_mapping_error(buf))-gotoiommu_error;-descr->bus_addr=buf;+descr->next_descr_addr=0;descr->next=descr+1;descr->prev=descr-1;+buf+=sizeof(structspider_net_descr);}/* do actual circular list */(descr-1)->next=start_descr;
@@ -397,8 +397,6 @@ struct spider_net_descr_chain {*701b8000wouldbecorrect,buteverypacketsgetsthatflag*/#define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000-#define SPIDER_NET_DESCR_SIZE 32-/* this will be bigger some time */structspider_net_options{intrx_csum;/* for rx: if 0 ip_summed=NONE,
@@ -437,28 +435,26 @@ struct spider_net_card {void__iomem*regs;+intnum_rx_desc;+intnum_tx_desc;structspider_net_descr_chaintx_chain;structspider_net_descr_chainrx_chain;structspider_net_descr*low_watermark;+dma_addr_tdescr_dma_addr;-structnet_device_statsnetdev_stats;--structspider_net_optionsoptions;--spinlock_tintmask_lock;structtasklet_structrxram_full_tl;structtimer_listtx_timer;-structwork_structtx_timeout_task;atomic_ttx_timeout_task_counter;wait_queue_head_twaitq;/* for ethtool */intmsg_enable;-intnum_rx_desc;-intnum_tx_desc;+structnet_device_statsnetdev_stats;structspider_net_extra_statsspider_stats;+structspider_net_optionsoptions;+/* Must be last element in the structure */structspider_net_descrdescr[0];};
This patch adds net_ratelimit to many of the printks
in order to limit extraneous warning messages
This patch supercedes all previous ratelimit patches.
This has been tested, please apply.
From: James K Lewis <redacted>
Signed-off-by: James K Lewis <redacted>
Signed-off-by: Linas Vepstas <redacted>
----
drivers/net/spider_net.c | 11 +++++------
drivers/net/spider_net.h | 2 +-
2 files changed, 6 insertions(+), 7 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
The RX packet handling can be called from several
places, yet does not protect the rx ring structure.
This patch places the ring buffer pointers under a lock.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -969,28 +969,33 @@ static intspider_net_decode_one_descr(structspider_net_card*card,intnapi){structspider_net_descr_chain*chain=&card->rx_chain;-structspider_net_descr*descr=chain->tail;+structspider_net_descr*descr;intstatus;intresult;+unsignedlongflags;++spin_lock_irqsave(&chain->lock,flags);+descr=chain->tail;status=spider_net_get_descr_status(descr);if(status==SPIDER_NET_DESCR_CARDOWNED){/* nothing in the descriptor yet */-result=0;-gotoout;+spin_unlock_irqrestore(&chain->lock,flags);+return0;}if(status==SPIDER_NET_DESCR_NOT_IN_USE){/* not initialized yet, the ring must be empty */+spin_unlock_irqrestore(&chain->lock,flags);spider_net_refill_rx_chain(card);spider_net_enable_rxdmac(card);-result=0;-gotoout;+return0;}/* descriptor definitively used -- move on tail */chain->tail=descr->next;+spin_unlock_irqrestore(&chain->lock,flags);result=0;if((status==SPIDER_NET_DESCR_RESPONSE_ERROR)||
@@ -1022,7 +1027,6 @@ refill:/* change the descriptor state: */if(!napi)spider_net_refill_rx_chain(card);-out:returnresult;}
Refactor how spider_net_refill_rx_chain() is called.
No functional change; this just simplifies the code
by moving the subroutine call to a more appropriate spot.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
One of the unlikely error branches has an skb memory leak.
Fix this by handling the error conditions consistently.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -1005,8 +1006,6 @@ spider_net_decode_one_descr(struct spidepr_err("%s: dropping RX descriptor with state %d\n",card->netdev->name,status);card->netdev_stats.rx_dropped++;-pci_unmap_single(card->pdev,descr->buf_addr,-SPIDER_NET_MAX_FRAME,PCI_DMA_FROMDEVICE);dev_kfree_skb_irq(descr->skb);gotorefill;}
@@ -1014,9 +1013,10 @@ spider_net_decode_one_descr(struct spideif((status!=SPIDER_NET_DESCR_COMPLETE)&&(status!=SPIDER_NET_DESCR_FRAME_END)){if(netif_msg_rx_err(card))-pr_err("%s: RX descriptor with state %d\n",+pr_err("%s: RX descriptor with unkown state %d\n",card->netdev->name,status);card->spider_stats.rx_desc_unk_state++;+dev_kfree_skb_irq(descr->skb);gotorefill;}
Another skb leak in an error branch. Fix this by adding
call to dev_kfree_skb_irq() after moving to a more
appropriate spot.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -897,19 +897,8 @@ spider_net_pass_skb_up(struct spider_netdata_status=descr->data_status;data_error=descr->data_error;-netdev=card->netdev;-/* the cases we'll throw away the packet immediately */-if(data_error&SPIDER_NET_DESTROY_RX_FLAGS){-if(netif_msg_rx_err(card))-pr_err("error in received descriptor found, "-"data_status=x%08x, data_error=x%08x\n",-data_status,data_error);-card->spider_stats.rx_desc_error++;-return0;-}-skb=descr->skb;skb->dev=netdev;skb_put(skb,descr->valid_size);
@@ -1020,6 +1009,18 @@ spider_net_decode_one_descr(struct spidegotorefill;}+/* The cases we'll throw away the packet immediately */+if(descr->data_error&SPIDER_NET_DESTROY_RX_FLAGS){+if(netif_msg_rx_err(card))+pr_err("%s: error in received descriptor found, "+"data_status=x%08x, data_error=x%08x\n",+card->netdev->name,+descr->data_status,descr->data_error);+card->spider_stats.rx_desc_error++;+dev_kfree_skb_irq(descr->skb);+gotorefill;+}+/* ok, we've got a packet in descr */result=spider_net_pass_skb_up(descr,card,napi);refill:
Simplify the somewhat convoluted use of return codes
in the rx buffre handling.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 31 ++++++++++++-------------------
1 file changed, 12 insertions(+), 19 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
The invocation of the rx ring refill routine is haphazard;
centralize and make its usage consistent.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -968,8 +968,6 @@ spider_net_decode_one_descr(struct spideif(status==SPIDER_NET_DESCR_NOT_IN_USE){/* not initialized yet, the ring must be empty */spin_unlock_irqrestore(&chain->lock,flags);-spider_net_refill_rx_chain(card);-spider_net_enable_rxdmac(card);return0;}
@@ -1058,6 +1056,7 @@ spider_net_poll(struct net_device *netdenetdev->quota-=packets_done;*budget-=packets_done;spider_net_refill_rx_chain(card);+spider_net_enable_rxdmac(card);/* if all packets are in the stack, enable interrupts and return 0 *//* if not, return 1 */
Two distinct if() statements have the ame body. Merge the clauses.
Also clean up punctuation, capitalization, etc.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -959,23 +960,18 @@ spider_net_decode_one_descr(struct spidestatus=spider_net_get_descr_status(descr);-if(status==SPIDER_NET_DESCR_CARDOWNED){-/* nothing in the descriptor yet */+/* Nothing in the descriptor yet, or ring is empty */+if((status==SPIDER_NET_DESCR_CARDOWNED)||+(status==SPIDER_NET_DESCR_NOT_IN_USE)){spin_unlock_irqrestore(&chain->lock,flags);return0;}-if(status==SPIDER_NET_DESCR_NOT_IN_USE){-/* not initialized yet, the ring must be empty */-spin_unlock_irqrestore(&chain->lock,flags);-return0;-}--/* descriptor definitively used -- move on tail */+/* Descriptor definitively used -- move on tail. */chain->tail=descr->next;spin_unlock_irqrestore(&chain->lock,flags);-/* unmap descriptor */+/* Unmap descriptor. */pci_unmap_single(card->pdev,descr->buf_addr,SPIDER_NET_MAX_FRAME,PCI_DMA_FROMDEVICE);
@@ -998,7 +994,7 @@ spider_net_decode_one_descr(struct spidegotobad_desc;}-/* The cases we'll throw away the packet immediately */+/* The cases we'll throw away the packet immediately. */if(descr->data_error&SPIDER_NET_DESTROY_RX_FLAGS){if(netif_msg_rx_err(card))pr_err("%s: error in received descriptor found, "
Tell the hardware the location of the rx ring tail.
More punctuation cleanup.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
@@ -471,17 +471,18 @@ spider_net_alloc_rx_skbs(struct spider_nresult=-ENOMEM;chain=&card->rx_chain;-/* put at least one buffer into the chain. if this fails,-*we'vegotaproblem.ifnot,spider_net_refill_rx_chain-*willdotherestattheendofthisfunction*/+/* Put at least one buffer into the chain. if this fails,+*we'vegotaproblem.Ifnot,spider_net_refill_rx_chain+*willdotherestattheendofthisfunction.*/if(spider_net_prepare_rx_descr(card,chain->head))gotoerror;elsechain->head=chain->head->next;-/* this will allocate the rest of the rx buffers; if not, it's-*businessasusuallateron*/+/* This will allocate the rest of the rx buffers;+*ifnot,it'sbusinessasusuallateron.*/spider_net_refill_rx_chain(card);+spider_net_enable_rxchtails(card);spider_net_enable_rxdmac(card);return0;
Re-enable irq's after emptying the RX ring; these had
been previously turned off on reception of the rxram_full
interrupt. More punctuation cleanup.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
Add memory barrier to make sure that the rest of the
RX descriptor state is flushed to memory before we tell
the hardware that its ready to go.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 1 +
1 file changed, 1 insertion(+)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
Delete possible source of chain corruption; the hardware
already knows the location of the tail, and writing it
again is likely to mess it up.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 1 -
1 file changed, 1 deletion(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
Add some debugging and error printing.
The show_rx_chain() prints out the status of the rx chain,
which shows that the status of the descriptors gets
messed up after the second & subsequent RX ramfulls.
Print out contents of bad packets if error occurs.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
Make the hardware perceive the RX descriptor ring as a
null-terminated linked list, instead of a circular ring.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
----
drivers/net/spider_net.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
Index: linux-2.6.19-git7/drivers/net/spider_net.c
===================================================================
From: Jeff Garzik <hidden> Date: 2006-12-07 10:09:31
Linas Vepstas wrote:
The RX packet handling can be called from several
places, yet does not protect the rx ring structure.
This patch places the ring buffer pointers under a lock.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
This is a HUGELY invasive patch. A sledgehammer.
What /specifically/ are these "several places", and what other
non-sledgehammer approaches were discarded before arriving at this one?
Jeff
From: Christoph Hellwig <hch@infradead.org> Date: 2006-12-07 10:12:07
On Wed, Dec 06, 2006 at 05:27:45PM -0600, Linas Vepstas wrote:
The current driver code performs 512 DMA mappings of a bunch of
32-byte structures. This is silly, as they are all in contiguous
memory. Ths patch changes the code to DMA map the entie area
with just one call.
This is still wrong. The descriptor array must be in dma_alloc_coherent
memory, not a streaming mapping. (I also think I pointed this out a while
ago when I made dma_alloc_coherent node-aware)
On Wed, Dec 06, 2006 at 11:08:47PM -0800, Andrew Morton wrote:
It worries me when a patch series gets resent a few hours later.
Did anything change?
I did not resend this patch series. However, I did receive a large
number of MTA errors:
[off-list ref]: mail forwarding loop for linuxppc-dev@ozlabs.org
which might be related to what you saw.
(I also cc'ed several lists, and delivry on one of the lists may have
been delayed by a few hours??)
--linas
On Thu, Dec 07, 2006 at 05:09:20AM -0500, Jeff Garzik wrote:
Linas Vepstas wrote:
quoted
The RX packet handling can be called from several
places, yet does not protect the rx ring structure.
This patch places the ring buffer pointers under a lock.
Signed-off-by: Linas Vepstas <redacted>
Cc: James K Lewis <redacted>
Cc: Arnd Bergmann <arnd@arndb.de>
This is a HUGELY invasive patch. A sledgehammer.
I am rather unlear what you perceive as being invasive,
since the patch summary states:
drivers/net/spider_net.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
What /specifically/ are these "several places",
spider_net_decode_one_descr() is called from
spider_net_poll() (which is the netdev->poll callback)
and also from spider_net_handle_rxram_full().
The rxramfull routine is called from a tasklet that
is fired off after a "RX ram full" interrupt is receved.
This interrupt is generated when the hardware runs out
of space to store incoming packets. We are seeing this
interrupt fire when the CPU is heavily loaded, and a
lot of traffic is being fired at the device.
and what other
non-sledgehammer approaches were discarded before arriving at this one?
Well, I'm not that good at kernel programming, so I guess
I did not perceive this as a "sledgehammer." And alternative
approach is to simply ignore the rxramfull interrupt entirely,
and depend on poll() do all the work. I'll try this shortly.
--linas
From: Stephen Rothwell <hidden> Date: 2006-12-08 02:12:08
On Thu, 7 Dec 2006 11:16:30 -0600 linas@austin.ibm.com (Linas Vepstas) wrote:
On Wed, Dec 06, 2006 at 11:08:47PM -0800, Andrew Morton wrote:
quoted
It worries me when a patch series gets resent a few hours later.
Did anything change?
I did not resend this patch series. However, I did receive a large
number of MTA errors:
[off-list ref]: mail forwarding loop for linuxppc-dev@ozlabs.org
Please report such things to postmaster@ozlabs.org and we may be able to
do something about them ... If you do report them, please attach the
full email with the error.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2006-12-08 22:47:26
A spinlock is expensive in the fast path, which is why Jeff says it's
invasive.
spider_net_decode_one_descr() is called from
spider_net_poll() (which is the netdev->poll callback)
and also from spider_net_handle_rxram_full().
The rxramfull routine is called from a tasklet that
is fired off after a "RX ram full" interrupt is receved.
This interrupt is generated when the hardware runs out
of space to store incoming packets. We are seeing this
interrupt fire when the CPU is heavily loaded, and a
lot of traffic is being fired at the device.
How often does that interrupt happen in that case ?
A better approach is to keep the fast path (ie. poll()) lockless, and in
handle_rxram_full(), the slow path, protect against poll using
netif_disable_poll(). Though that means using a work queue, not a
tasklet, since it needs to schedule.
quoted
and what other
non-sledgehammer approaches were discarded before arriving at this one?
Well, I'm not that good at kernel programming, so I guess
I did not perceive this as a "sledgehammer." And alternative
approach is to simply ignore the rxramfull interrupt entirely,
and depend on poll() do all the work. I'll try this shortly.
or you can schedule rx work from the rxramfull interrupt after setting a
"something bad happened" flag. Then, poll can check this flag and do the
right thing.
Ben.
On Sat, Dec 09, 2006 at 09:47:05AM +1100, Benjamin Herrenschmidt wrote:
A spinlock is expensive in the fast path, which is why Jeff says it's
invasive.
quoted
spider_net_decode_one_descr() is called from
spider_net_poll() (which is the netdev->poll callback)
and also from spider_net_handle_rxram_full().
The rxramfull routine is called from a tasklet that
is fired off after a "RX ram full" interrupt is receved.
This interrupt is generated when the hardware runs out
of space to store incoming packets. We are seeing this
interrupt fire when the CPU is heavily loaded, and a
lot of traffic is being fired at the device.
How often does that interrupt happen in that case ?
It is hard to reproduce; it is highly dependent on kernel version
and network config. It seems to occur when the system is somehow
loaded, and the tcp stack is unable to empty out the rx ring in a
timely manner. Jim is able o trigger this trivially for some kernels,
but not others.
A better approach is to keep the fast path (ie. poll()) lockless, and in
handle_rxram_full(), the slow path, protect against poll using
netif_disable_poll(). Though that means using a work queue, not a
tasklet, since it needs to schedule.
Yes. Actually, I am thinking of treating this interrupt as if it were
just another RX interrupt. What the original drivers seemed to want to
do was to treat this as some sort of "high priority" rx interrupt, but
there doesn't seem to be any real way of doing this, so it seems simpler
just to rip out the tasklet and leave it at that.
or you can schedule rx work from the rxramfull interrupt after setting a
"something bad happened" flag. Then, poll can check this flag and do the
right thing.
On Thu, Dec 07, 2006 at 10:11:51AM +0000, Christoph Hellwig wrote:
On Wed, Dec 06, 2006 at 05:27:45PM -0600, Linas Vepstas wrote:
quoted
The current driver code performs 512 DMA mappings of a bunch of
32-byte structures. This is silly, as they are all in contiguous
memory. Ths patch changes the code to DMA map the entie area
with just one call.
This is still wrong. The descriptor array must be in dma_alloc_coherent
memory, not a streaming mapping. (I also think I pointed this out a while
ago when I made dma_alloc_coherent node-aware)
Sorry, I missed this the first time. I'm splitting this off now; will
resubmit shortly.
--linas