[SCSI] hpsa: do not rescan controllers known to be locked up
authorStephen M. Cameron <scameron@beardog.cce.hp.com>
Tue, 18 Feb 2014 19:55:48 +0000 (13:55 -0600)
committerJames Bottomley <JBottomley@Parallels.com>
Sat, 15 Mar 2014 17:19:04 +0000 (10:19 -0700)
* Do not check event bits on locked up controllers to
  see if they need to be rescanned.
* Do not initiate any device rescans on controllers
  which are known to be locked up.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/hpsa.c

index ee17556058c2cfc7a4b934becd221ee8081328f7..67e059cd9e57ca9a5b3ee49ff1ec751b5f090592 100644 (file)
@@ -2868,11 +2868,38 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
 
 static DEF_SCSI_QCMD(hpsa_scsi_queue_command)
 
+static int do_not_scan_if_controller_locked_up(struct ctlr_info *h)
+{
+       unsigned long flags;
+
+       /*
+        * Don't let rescans be initiated on a controller known
+        * to be locked up.  If the controller locks up *during*
+        * a rescan, that thread is probably hosed, but at least
+        * we can prevent new rescan threads from piling up on a
+        * locked up controller.
+        */
+       spin_lock_irqsave(&h->lock, flags);
+       if (unlikely(h->lockup_detected)) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               spin_lock_irqsave(&h->scan_lock, flags);
+               h->scan_finished = 1;
+               wake_up_all(&h->scan_wait_queue);
+               spin_unlock_irqrestore(&h->scan_lock, flags);
+               return 1;
+       }
+       spin_unlock_irqrestore(&h->lock, flags);
+       return 0;
+}
+
 static void hpsa_scan_start(struct Scsi_Host *sh)
 {
        struct ctlr_info *h = shost_to_hba(sh);
        unsigned long flags;
 
+       if (do_not_scan_if_controller_locked_up(h))
+               return;
+
        /* wait until any scan already in progress is finished. */
        while (1) {
                spin_lock_irqsave(&h->scan_lock, flags);
@@ -2889,6 +2916,9 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
        h->scan_finished = 0; /* mark scan as in progress */
        spin_unlock_irqrestore(&h->scan_lock, flags);
 
+       if (do_not_scan_if_controller_locked_up(h))
+               return;
+
        hpsa_update_scsi_devices(h, h->scsi_host->host_no);
 
        spin_lock_irqsave(&h->scan_lock, flags);