cxlflash: Fix host link up event handling
authorMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Wed, 21 Oct 2015 20:13:37 +0000 (15:13 -0500)
committerJames Bottomley <JBottomley@Odin.com>
Fri, 30 Oct 2015 08:12:22 +0000 (17:12 +0900)
Following a link up event, the LUNs available to the host may
have changed. Without rescanning the host, the LUN topology is
unknown to the user. In such a state, the user would be unable
to locate provisioned resources.

To remedy, the host should be rescanned after a link up event.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Manoj N. Kumar <manoj@linux.vnet.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
drivers/scsi/cxlflash/common.h
drivers/scsi/cxlflash/main.c
drivers/scsi/cxlflash/main.h

index 7a0cb5c..faf7f56 100644 (file)
@@ -102,6 +102,7 @@ struct cxlflash_cfg {
        enum cxlflash_init_state init_state;
        enum cxlflash_lr_state lr_state;
        int lr_port;
+       atomic_t scan_host_needed;
 
        struct cxl_afu *cxl_afu;
 
index 5503a40..98fdac1 100644 (file)
@@ -1119,17 +1119,17 @@ static const struct asyc_intr_info ainfo[] = {
        {SISL_ASTATUS_FC0_CRC_T, "CRC threshold exceeded", 0, LINK_RESET},
        {SISL_ASTATUS_FC0_LOGI_R, "login timed out, retrying", 0, 0},
        {SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR},
-       {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, 0},
+       {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST},
        {SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0},
-       {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0},
+       {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST},
        {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET},
        {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0},
        {SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET},
        {SISL_ASTATUS_FC1_LOGI_R, "login timed out, retrying", 1, 0},
        {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR},
-       {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, 0},
+       {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST},
        {SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0},
-       {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0},
+       {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST},
        {0x0, "", 0, 0}         /* terminator */
 };
 
@@ -1350,6 +1350,11 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data)
                        writeq_be(reg, &global->fc_regs[port][FC_ERROR / 8]);
                        writeq_be(0, &global->fc_regs[port][FC_ERRCAP / 8]);
                }
+
+               if (info->action & SCAN_HOST) {
+                       atomic_inc(&cfg->scan_host_needed);
+                       schedule_work(&cfg->work_q);
+               }
        }
 
 out:
@@ -2309,6 +2314,7 @@ MODULE_DEVICE_TABLE(pci, cxlflash_pci_table);
  * - Link reset which cannot be performed on interrupt context due to
  * blocking up to a few seconds
  * - Read AFU command room
+ * - Rescan the host
  */
 static void cxlflash_worker_thread(struct work_struct *work)
 {
@@ -2351,6 +2357,9 @@ static void cxlflash_worker_thread(struct work_struct *work)
        }
 
        spin_unlock_irqrestore(cfg->host->host_lock, lock_flags);
+
+       if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0)
+               scsi_scan_host(cfg->host);
 }
 
 /**
index cf0e809..6032456 100644 (file)
@@ -99,6 +99,7 @@ struct asyc_intr_info {
        u8 action;
 #define CLR_FC_ERROR   0x01
 #define LINK_RESET     0x02
+#define SCAN_HOST      0x04
 };
 
 #ifndef CONFIG_CXL_EEH