lkml.org 
[lkml]   [2008]   [Jul]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 31/62] sparc64: Fix lockdep issues in LDC protocol layer.
    2.6.26 -stable review patch.  If anyone has any objections, please let
    us know.

    ------------------
    From: David S. Miller <davem@davemloft.net>

    [ Upstream commit b7c2a75725dee9b5643a0aae3a4cb47f52e00a49 ]

    We're calling request_irq() with a IRQs disabled.

    No straightforward fix exists because we want to
    enable these IRQs and setup state atomically before
    getting into the IRQ handler the first time.

    What happens now is that we mark the VIRQ to not be
    automatically enabled by request_irq(). Then we
    make explicit enable_irq() calls when we grab the
    LDC channel.

    This way we don't need to call request_irq() illegally
    under the LDC channel lock any more.

    Bump LDC version and release date.

    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    arch/sparc64/kernel/irq.c | 10 +++++++++-
    arch/sparc64/kernel/ldc.c | 38 +++++++++++++++++++-------------------
    2 files changed, 28 insertions(+), 20 deletions(-)

    --- a/arch/sparc64/kernel/irq.c
    +++ b/arch/sparc64/kernel/irq.c
    @@ -621,8 +621,9 @@ unsigned int sun4v_build_irq(u32 devhand
    unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
    {
    struct irq_handler_data *data;
    - struct ino_bucket *bucket;
    unsigned long hv_err, cookie;
    + struct ino_bucket *bucket;
    + struct irq_desc *desc;
    unsigned int virt_irq;

    bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
    @@ -643,6 +644,13 @@ unsigned int sun4v_build_virq(u32 devhan
    if (unlikely(!data))
    return 0;

    + /* In order to make the LDC channel startup sequence easier,
    + * especially wrt. locking, we do not let request_irq() enable
    + * the interrupt.
    + */
    + desc = irq_desc + virt_irq;
    + desc->status |= IRQ_NOAUTOEN;
    +
    set_irq_chip_data(virt_irq, data);

    /* Catch accidental accesses to these things. IMAP/ICLR handling
    --- a/arch/sparc64/kernel/ldc.c
    +++ b/arch/sparc64/kernel/ldc.c
    @@ -1,6 +1,6 @@
    /* ldc.c: Logical Domain Channel link-layer protocol driver.
    *
    - * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
    + * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
    */

    #include <linux/kernel.h>
    @@ -23,8 +23,8 @@

    #define DRV_MODULE_NAME "ldc"
    #define PFX DRV_MODULE_NAME ": "
    -#define DRV_MODULE_VERSION "1.0"
    -#define DRV_MODULE_RELDATE "June 25, 2007"
    +#define DRV_MODULE_VERSION "1.1"
    +#define DRV_MODULE_RELDATE "July 22, 2008"

    static char version[] __devinitdata =
    DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
    @@ -1235,13 +1235,9 @@ int ldc_bind(struct ldc_channel *lp, con
    unsigned long hv_err, flags;
    int err = -EINVAL;

    - spin_lock_irqsave(&lp->lock, flags);
    -
    - if (!name)
    - goto out_err;
    -
    - if (lp->state != LDC_STATE_INIT)
    - goto out_err;
    + if (!name ||
    + (lp->state != LDC_STATE_INIT))
    + return -EINVAL;

    snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
    snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
    @@ -1250,25 +1246,32 @@ int ldc_bind(struct ldc_channel *lp, con
    IRQF_SAMPLE_RANDOM | IRQF_SHARED,
    lp->rx_irq_name, lp);
    if (err)
    - goto out_err;
    + return err;

    err = request_irq(lp->cfg.tx_irq, ldc_tx,
    IRQF_SAMPLE_RANDOM | IRQF_SHARED,
    lp->tx_irq_name, lp);
    - if (err)
    - goto out_free_rx_irq;
    + if (err) {
    + free_irq(lp->cfg.rx_irq, lp);
    + return err;
    + }
    +

    + spin_lock_irqsave(&lp->lock, flags);
    +
    + enable_irq(lp->cfg.rx_irq);
    + enable_irq(lp->cfg.tx_irq);

    lp->flags |= LDC_FLAG_REGISTERED_IRQS;

    err = -ENODEV;
    hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
    if (hv_err)
    - goto out_free_tx_irq;
    + goto out_free_irqs;

    hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
    if (hv_err)
    - goto out_free_tx_irq;
    + goto out_free_irqs;

    hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
    if (hv_err)
    @@ -1304,14 +1307,11 @@ out_unmap_rx:
    out_unmap_tx:
    sun4v_ldc_tx_qconf(lp->id, 0, 0);

    -out_free_tx_irq:
    +out_free_irqs:
    lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
    free_irq(lp->cfg.tx_irq, lp);
    -
    -out_free_rx_irq:
    free_irq(lp->cfg.rx_irq, lp);

    -out_err:
    spin_unlock_irqrestore(&lp->lock, flags);

    return err;
    --


    \
     
     \ /
      Last update: 2008-07-31 02:19    [W:4.113 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site