scsi: zfcp: Handle event-lost notification for Version Change events
authorJulian Wiedmann <jwi@linux.ibm.com>
Wed, 28 Oct 2020 18:30:52 +0000 (19:30 +0100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 30 Oct 2020 02:17:01 +0000 (22:17 -0400)
As recovery for a lost Version Change event, trigger an Exchange Config
Data cmd to retrieve the current FW version.

Doing so requires process context (as eg. zfcp_qdio_sbal_get() might need
to sleep), so defer from tasklet context into a work item.

Link: https://lore.kernel.org/r/297c7be2944c3714863fcd22d531d910312d29f0.1603908167.git.bblock@linux.ibm.com
Suggested-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h

index 18b713a616de900c42cfb123332a0abeeb161d67..768873dd55b86abee0c1976db2f4f2af4a08192d 100644 (file)
@@ -292,6 +292,14 @@ static void _zfcp_status_read_scheduler(struct work_struct *work)
                                             stat_work));
 }
 
+static void zfcp_version_change_lost_work(struct work_struct *work)
+{
+       struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
+                                                   version_change_lost_work);
+
+       zfcp_fsf_exchange_config_data_sync(adapter->qdio, NULL);
+}
+
 static void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
 {
        struct zfcp_adapter *adapter =
@@ -353,6 +361,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
        INIT_DELAYED_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
        INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
+       INIT_WORK(&adapter->version_change_lost_work,
+                 zfcp_version_change_lost_work);
 
        adapter->next_port_scan = jiffies;
 
@@ -429,6 +439,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
        cancel_delayed_work_sync(&adapter->scan_work);
        cancel_work_sync(&adapter->stat_work);
        cancel_work_sync(&adapter->ns_up_work);
+       cancel_work_sync(&adapter->version_change_lost_work);
        zfcp_destroy_adapter_work_queue(adapter);
 
        zfcp_fc_wka_ports_force_offline(adapter->gs);
index da8a5ceb615cc7379cd3dd646f183c7448943c63..f656d74a5f94f63b87e3dbc09c55748c20a4bb8e 100644 (file)
@@ -201,6 +201,7 @@ struct zfcp_adapter {
        struct zfcp_fc_events events;
        unsigned long           next_port_scan;
        struct zfcp_diag_adapter        *diagnostics;
+       struct work_struct      version_change_lost_work;
 };
 
 struct zfcp_port {
index afa95e04ecebdbb354a249c7755bcde6a7487971..7593a9667b3e83512e247674a14f4232249b0283 100644 (file)
@@ -309,6 +309,9 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
        case FSF_STATUS_READ_NOTIFICATION_LOST:
                if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
                        zfcp_fc_conditional_port_scan(adapter);
+               if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_VERSION_CHANGE)
+                       queue_work(adapter->work_queue,
+                                  &adapter->version_change_lost_work);
                break;
        case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
                adapter->adapter_features = sr_buf->payload.word[0];
index 26ad7a0c5ce300b09fb32e9b0532d6082e343a66..5e6b601af98051f25ffc45e23986cf25a0a141f1 100644 (file)
 
 /* status subtypes for unsolicited status notification lost */
 #define FSF_STATUS_READ_SUB_INCOMING_ELS       0x00000001
+#define FSF_STATUS_READ_SUB_VERSION_CHANGE     0x00000100
 
 /* status subtypes for version change */
 #define FSF_STATUS_READ_SUB_LIC_CHANGE         0x00000001