lkml.org 
[lkml]   [2008]   [Oct]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 54/71] niu: panic on reset
    2.6.26-stable review patch.  If anyone has any objections, please let us
    know.

    ------------------
    From: Santwona Behera <santwona.behera@sun.com>

    [ Upstream commit cff502a38394fd33693f6233e03fca363dfa956d ]

    The reset_task function in the niu driver does not reset the tx and rx
    buffers properly. This leads to panic on reset. This patch is a
    modified implementation of the previously posted fix.

    Signed-off-by: Santwona Behera <santwona.behera@sun.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/net/niu.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 56 insertions(+)

    --- a/drivers/net/niu.c
    +++ b/drivers/net/niu.c
    @@ -5978,6 +5978,56 @@ static void niu_netif_start(struct niu *
    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);
    @@ -6000,6 +6050,12 @@ static void niu_reset_task(struct work_s

    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;
    --


    \
     
     \ /
      Last update: 2008-10-07 03:03    [W:0.024 / U:122.952 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site