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);
 
        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
 
        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;
                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);
        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,
        .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,
 };
 
        spin_unlock_irqrestore(&dbf->pay_lock, flags);
 }
 
+/**
+ * zfcp_dbf_hba_basic - trace event for basic adapter events
+ * @adapter: pointer to struct zfcp_adapter
+ */
+void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter)
+{
+       struct zfcp_dbf *dbf = adapter->dbf;
+       struct zfcp_dbf_hba *rec = &dbf->hba_buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dbf->hba_lock, flags);
+       memset(rec, 0, sizeof(*rec));
+
+       memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+       rec->id = ZFCP_DBF_HBA_BASIC;
+
+       debug_event(dbf->hba, 1, rec, sizeof(*rec));
+       spin_unlock_irqrestore(&dbf->hba_lock, flags);
+}
+
 static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
                                struct zfcp_adapter *adapter,
                                struct zfcp_port *port,