|
@@ -39,17 +39,23 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
|
|
|
spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
|
|
|
}
|
|
|
|
|
|
-static int zfcp_ccw_activate(struct ccw_device *cdev)
|
|
|
-
|
|
|
+/**
|
|
|
+ * zfcp_ccw_activate - activate adapter and wait for it to finish
|
|
|
+ * @cdev: pointer to belonging ccw device
|
|
|
+ * @clear: Status flags to clear.
|
|
|
+ * @tag: s390dbf trace record tag
|
|
|
+ */
|
|
|
+static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
|
|
|
{
|
|
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
|
|
|
|
|
if (!adapter)
|
|
|
return 0;
|
|
|
|
|
|
+ zfcp_erp_clear_adapter_status(adapter, clear);
|
|
|
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
|
|
|
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
|
|
|
- "ccresu2");
|
|
|
+ tag);
|
|
|
zfcp_erp_wait(adapter);
|
|
|
flush_work(&adapter->scan_work);
|
|
|
|
|
@@ -164,32 +170,47 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
|
|
|
BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
|
|
|
adapter->req_no = 0;
|
|
|
|
|
|
- zfcp_ccw_activate(cdev);
|
|
|
+ zfcp_ccw_activate(cdev, 0, "ccsonl1");
|
|
|
zfcp_ccw_adapter_put(adapter);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * zfcp_ccw_set_offline - set_offline function of zfcp driver
|
|
|
+ * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
|
|
|
* @cdev: pointer to belonging ccw device
|
|
|
+ * @set: Status flags to set.
|
|
|
+ * @tag: s390dbf trace record tag
|
|
|
*
|
|
|
* This function gets called by the common i/o layer and sets an adapter
|
|
|
* into state offline.
|
|
|
*/
|
|
|
-static int zfcp_ccw_set_offline(struct ccw_device *cdev)
|
|
|
+static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
|
|
|
{
|
|
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
|
|
|
|
|
if (!adapter)
|
|
|
return 0;
|
|
|
|
|
|
- zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");
|
|
|
+ zfcp_erp_set_adapter_status(adapter, set);
|
|
|
+ zfcp_erp_adapter_shutdown(adapter, 0, tag);
|
|
|
zfcp_erp_wait(adapter);
|
|
|
|
|
|
zfcp_ccw_adapter_put(adapter);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * zfcp_ccw_set_offline - set_offline function of zfcp driver
|
|
|
+ * @cdev: pointer to belonging ccw device
|
|
|
+ *
|
|
|
+ * This function gets called by the common i/o layer and sets an adapter
|
|
|
+ * into state offline.
|
|
|
+ */
|
|
|
+static int zfcp_ccw_set_offline(struct ccw_device *cdev)
|
|
|
+{
|
|
|
+ return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* zfcp_ccw_notify - ccw notify function
|
|
|
* @cdev: pointer to belonging ccw device
|
|
@@ -207,6 +228,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
|
|
|
|
|
|
switch (event) {
|
|
|
case CIO_GONE:
|
|
|
+ if (atomic_read(&adapter->status) &
|
|
|
+ ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
|
|
|
+ zfcp_dbf_hba_basic("ccnigo1", adapter);
|
|
|
+ break;
|
|
|
+ }
|
|
|
dev_warn(&cdev->dev, "The FCP device has been detached\n");
|
|
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
|
|
|
break;
|
|
@@ -216,6 +242,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
|
|
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
|
|
|
break;
|
|
|
case CIO_OPER:
|
|
|
+ if (atomic_read(&adapter->status) &
|
|
|
+ ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
|
|
|
+ zfcp_dbf_hba_basic("ccniop1", adapter);
|
|
|
+ break;
|
|
|
+ }
|
|
|
dev_info(&cdev->dev, "The FCP device is operational again\n");
|
|
|
zfcp_erp_set_adapter_status(adapter,
|
|
|
ZFCP_STATUS_COMMON_RUNNING);
|
|
@@ -251,6 +282,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
|
|
|
zfcp_ccw_adapter_put(adapter);
|
|
|
}
|
|
|
|
|
|
+static int zfcp_ccw_suspend(struct ccw_device *cdev)
|
|
|
+{
|
|
|
+ zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int zfcp_ccw_thaw(struct ccw_device *cdev)
|
|
|
+{
|
|
|
+ /* trace records for thaw and final shutdown during suspend
|
|
|
+ can only be found in system dump until the end of suspend
|
|
|
+ but not after resume because it's based on the memory image
|
|
|
+ right after the very first suspend (freeze) callback */
|
|
|
+ zfcp_ccw_activate(cdev, 0, "ccthaw1");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int zfcp_ccw_resume(struct ccw_device *cdev)
|
|
|
+{
|
|
|
+ zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
struct ccw_driver zfcp_ccw_driver = {
|
|
|
.driver = {
|
|
|
.owner = THIS_MODULE,
|
|
@@ -263,7 +316,7 @@ struct ccw_driver zfcp_ccw_driver = {
|
|
|
.set_offline = zfcp_ccw_set_offline,
|
|
|
.notify = zfcp_ccw_notify,
|
|
|
.shutdown = zfcp_ccw_shutdown,
|
|
|
- .freeze = zfcp_ccw_set_offline,
|
|
|
- .thaw = zfcp_ccw_activate,
|
|
|
- .restore = zfcp_ccw_activate,
|
|
|
+ .freeze = zfcp_ccw_suspend,
|
|
|
+ .thaw = zfcp_ccw_thaw,
|
|
|
+ .restore = zfcp_ccw_resume,
|
|
|
};
|