diff options
author | David S. Miller <davem@davemloft.net> | 2008-09-16 23:11:43 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-16 23:11:43 +0200 |
commit | 2e57572a50a4de41c6cbc879a4866a312d4cd316 (patch) | |
tree | c4f58ec96c06642c4b415b881d3f0a3b673d5b44 /drivers/net/niu.c | |
parent | sparc32: Use PROM device probing for sun4m timer registers. (diff) | |
parent | sparc64: Fix OOPS in psycho_pcierr_intr_other(). (diff) | |
download | linux-2e57572a50a4de41c6cbc879a4866a312d4cd316.tar.xz linux-2e57572a50a4de41c6cbc879a4866a312d4cd316.zip |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
Conflicts:
arch/sparc64/kernel/pci_psycho.c
Diffstat (limited to 'drivers/net/niu.c')
-rw-r--r-- | drivers/net/niu.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 016d9e08692d..ebc812702903 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -5984,6 +5984,56 @@ static void niu_netif_start(struct niu *np) niu_enable_interrupts(np, 1); } +static void niu_reset_buffers(struct niu *np) +{ + int i, j, k, err; + + if (np->rx_rings) { + for (i = 0; i < np->num_rx_rings; i++) { + struct rx_ring_info *rp = &np->rx_rings[i]; + + for (j = 0, k = 0; j < MAX_RBR_RING_SIZE; j++) { + struct page *page; + + page = rp->rxhash[j]; + while (page) { + struct page *next = + (struct page *) page->mapping; + u64 base = page->index; + base = base >> RBR_DESCR_ADDR_SHIFT; + rp->rbr[k++] = cpu_to_le32(base); + page = next; + } + } + for (; k < MAX_RBR_RING_SIZE; k++) { + err = niu_rbr_add_page(np, rp, GFP_ATOMIC, k); + if (unlikely(err)) + break; + } + + rp->rbr_index = rp->rbr_table_size - 1; + rp->rcr_index = 0; + rp->rbr_pending = 0; + rp->rbr_refill_pending = 0; + } + } + if (np->tx_rings) { + for (i = 0; i < np->num_tx_rings; i++) { + struct tx_ring_info *rp = &np->tx_rings[i]; + + for (j = 0; j < MAX_TX_RING_SIZE; j++) { + if (rp->tx_buffs[j].skb) + (void) release_tx_packet(np, rp, j); + } + + rp->pending = MAX_TX_RING_SIZE; + rp->prod = 0; + rp->cons = 0; + rp->wrap_bit = 0; + } + } +} + static void niu_reset_task(struct work_struct *work) { struct niu *np = container_of(work, struct niu, reset_task); @@ -6006,6 +6056,12 @@ static void niu_reset_task(struct work_struct *work) niu_stop_hw(np); + spin_unlock_irqrestore(&np->lock, flags); + + niu_reset_buffers(np); + + spin_lock_irqsave(&np->lock, flags); + err = niu_init_hw(np); if (!err) { np->timer.expires = jiffies + HZ; |