Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f4d6d00466ef4879e4289f18c2f59210a06a7ada
Commit:     f4d6d00466ef4879e4289f18c2f59210a06a7ada
Parent:     1626aeb881236c8cb022b5e4ca594146a951d669
Author:     Tejun Heo <[EMAIL PROTECTED]>
AuthorDate: Tue May 1 11:50:15 2007 +0200
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Fri May 11 18:09:18 2007 -0400

    libata: ignore EH scheduling during initialization
    
    libata enables SCSI host during ATA host activation which happens
    after IRQ handler is registered and IRQ is enabled.  All ATA ports are
    in frozen state when IRQ is enabled but frozen ports may raise limited
    number of IRQs after being frozen - IOW, ->freeze() is not responsible
    for clearing pending IRQs.  During normal operation, the IRQ handler
    is responsible for clearing spurious IRQs on frozen ports and it
    usually doesn't require any extra code.
    
    Unfortunately, during host initialization, the IRQ handler can end up
    scheduling EH for a port whose SCSI host isn't initialized yet.  This
    results in OOPS in the SCSI midlayer.  This is relatively short window
    and scheduling EH for probing is the first thing libata does after
    initialization, so ignoring EH scheduling until initialization is
    complete solves the problem nicely.
    
    This problem was spotted by Berck E. Nash in the following thread.
    
      http://thread.gmane.org/gmane.linux.kernel/519412
    
    Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
    Cc: Berck E. Nash <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/libata-core.c |    2 ++
 drivers/ata/libata-eh.c   |    3 +++
 include/linux/libata.h    |    1 +
 3 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9cff5c5..6ac4f32 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5964,6 +5964,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
        if (!ap)
                return NULL;
 
+       ap->pflags |= ATA_PFLAG_INITIALIZING;
        ap->lock = &host->lock;
        ap->flags = ATA_FLAG_DISABLED;
        ap->print_id = -1;
@@ -6332,6 +6333,7 @@ int ata_host_register(struct ata_host *host, struct 
scsi_host_template *sht)
                        ehi->action |= ATA_EH_SOFTRESET;
                        ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
+                       ap->pflags &= ~ATA_PFLAG_INITIALIZING;
                        ap->pflags |= ATA_PFLAG_LOADING;
                        ata_port_schedule_eh(ap);
 
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 412d604..ee9bb53 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -551,6 +551,9 @@ void ata_port_schedule_eh(struct ata_port *ap)
 {
        WARN_ON(!ap->ops->error_handler);
 
+       if (ap->pflags & ATA_PFLAG_INITIALIZING)
+               return;
+
        ap->pflags |= ATA_PFLAG_EH_PENDING;
        scsi_schedule_eh(ap->scsi_host);
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 95b74ba..90abcdc 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -190,6 +190,7 @@ enum {
        ATA_PFLAG_LOADING       = (1 << 4), /* boot/loading probe */
        ATA_PFLAG_UNLOADING     = (1 << 5), /* module is unloading */
        ATA_PFLAG_SCSI_HOTPLUG  = (1 << 6), /* SCSI hotplug scheduled */
+       ATA_PFLAG_INITIALIZING  = (1 << 7), /* being initialized, don't touch */
 
        ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
        ATA_PFLAG_SUSPENDED     = (1 << 17), /* port is suspended (power) */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to