]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/scsi/zfcp_fsf.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / drivers / s390 / scsi / zfcp_fsf.c
index 9d1d7d1842cef7f3d8abd73fc7be931502360110..2eb7dd56ab800af62da15d6a4cde42f2caf6177f 100644 (file)
@@ -61,45 +61,6 @@ static u32 fsf_qtcb_type[] = {
        [FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
 };
 
-static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
-{
-       u16 subtable = table >> 16;
-       u16 rule = table & 0xffff;
-       const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
-
-       if (subtable && subtable < ARRAY_SIZE(act_type))
-               dev_warn(&adapter->ccw_device->dev,
-                        "Access denied according to ACT rule type %s, "
-                        "rule %d\n", act_type[subtable], rule);
-}
-
-static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
-                                       struct zfcp_port *port)
-{
-       struct fsf_qtcb_header *header = &req->qtcb->header;
-       dev_warn(&req->adapter->ccw_device->dev,
-                "Access denied to port 0x%016Lx\n",
-                (unsigned long long)port->wwpn);
-       zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
-       zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
-       zfcp_erp_port_access_denied(port, "fspad_1", req);
-       req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
-static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
-                                       struct zfcp_unit *unit)
-{
-       struct fsf_qtcb_header *header = &req->qtcb->header;
-       dev_warn(&req->adapter->ccw_device->dev,
-                "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
-                (unsigned long long)unit->fcp_lun,
-                (unsigned long long)unit->port->wwpn);
-       zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
-       zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
-       zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
-       req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
 static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
 {
        dev_err(&req->adapter->ccw_device->dev, "FCP device not "
@@ -143,7 +104,7 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
 
-static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
+static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
                                         struct fsf_link_down_info *link_down)
 {
        struct zfcp_adapter *adapter = req->adapter;
@@ -223,7 +184,7 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
                         "the FC fabric is down\n");
        }
 out:
-       zfcp_erp_adapter_failed(adapter, id, req);
+       zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
 }
 
 static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
@@ -234,13 +195,13 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
 
        switch (sr_buf->status_subtype) {
        case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
-               zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
+               zfcp_fsf_link_down_info_eval(req, ldi);
                break;
        case FSF_STATUS_READ_SUB_FDISC_FAILED:
-               zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
+               zfcp_fsf_link_down_info_eval(req, ldi);
                break;
        case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
-               zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
+               zfcp_fsf_link_down_info_eval(req, NULL);
        };
 }
 
@@ -281,9 +242,8 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
                dev_info(&adapter->ccw_device->dev,
                         "The local link has been restored\n");
                /* All ports should be marked as ready to run again */
-               zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
-                                              ZFCP_STATUS_COMMON_RUNNING,
-                                              ZFCP_SET);
+               zfcp_erp_set_adapter_status(adapter,
+                                           ZFCP_STATUS_COMMON_RUNNING);
                zfcp_erp_adapter_reopen(adapter,
                                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
                                        ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -293,13 +253,12 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
                break;
        case FSF_STATUS_READ_NOTIFICATION_LOST:
                if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
-                       zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
-                                                       req);
+                       zfcp_cfdc_adapter_access_changed(adapter);
                if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
                        queue_work(adapter->work_queue, &adapter->scan_work);
                break;
        case FSF_STATUS_READ_CFDC_UPDATED:
-               zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
+               zfcp_cfdc_adapter_access_changed(adapter);
                break;
        case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
                adapter->adapter_features = sr_buf->payload.word[0];
@@ -399,16 +358,14 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
                zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
                break;
        case FSF_PROT_LINK_DOWN:
-               zfcp_fsf_link_down_info_eval(req, "fspse_5",
-                                            &psq->link_down_info);
+               zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
                /* go through reopen to flush pending requests */
                zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
                break;
        case FSF_PROT_REEST_QUEUE:
                /* All ports should be marked as ready to run again */
-               zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
-                                              ZFCP_STATUS_COMMON_RUNNING,
-                                              ZFCP_SET);
+               zfcp_erp_set_adapter_status(adapter,
+                                           ZFCP_STATUS_COMMON_RUNNING);
                zfcp_erp_adapter_reopen(adapter,
                                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
                                        ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -575,10 +532,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
                fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
                adapter->hydra_version = 0;
 
-               atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
-                               &adapter->status);
-
-               zfcp_fsf_link_down_info_eval(req, "fsecdh2",
+               zfcp_fsf_link_down_info_eval(req,
                        &qtcb->header.fsf_status_qual.link_down_info);
                break;
        default:
@@ -644,7 +598,7 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
                break;
        case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
                zfcp_fsf_exchange_port_evaluate(req);
-               zfcp_fsf_link_down_info_eval(req, "fsepdh1",
+               zfcp_fsf_link_down_info_eval(req,
                        &qtcb->header.fsf_status_qual.link_down_info);
                break;
        }
@@ -771,7 +725,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
        struct fsf_status_read_buffer *sr_buf;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -805,13 +759,14 @@ failed_buf:
        zfcp_fsf_req_free(req);
        zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
 static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 {
-       struct zfcp_unit *unit = req->data;
+       struct scsi_device *sdev = req->data;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
        union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
 
        if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -820,14 +775,15 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
        switch (req->qtcb->header.fsf_status) {
        case FSF_PORT_HANDLE_NOT_VALID:
                if (fsq->word[0] == fsq->word[1]) {
-                       zfcp_erp_adapter_reopen(unit->port->adapter, 0,
+                       zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
                                                "fsafch1", req);
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                }
                break;
        case FSF_LUN_HANDLE_NOT_VALID:
                if (fsq->word[0] == fsq->word[1]) {
-                       zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
+                       zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
+                                            req);
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                }
                break;
@@ -835,17 +791,23 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
                req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
                break;
        case FSF_PORT_BOXED:
-               zfcp_erp_port_boxed(unit->port, "fsafch3", req);
+               zfcp_erp_set_port_status(zfcp_sdev->port,
+                                        ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_port_reopen(zfcp_sdev->port,
+                                    ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3",
+                                    req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_LUN_BOXED:
-               zfcp_erp_unit_boxed(unit, "fsafch4", req);
+               zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+                                   "fsafch4", req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                 break;
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (fsq->word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       zfcp_fc_test_link(unit->port);
+                       zfcp_fc_test_link(zfcp_sdev->port);
                        /* fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -859,19 +821,20 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 }
 
 /**
- * zfcp_fsf_abort_fcp_command - abort running SCSI command
- * @old_req_id: unsigned long
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
+ * @scmnd: The SCSI command to abort
  * Returns: pointer to struct zfcp_fsf_req
  */
 
-struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
-                                               struct zfcp_unit *unit)
+struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
 {
        struct zfcp_fsf_req *req = NULL;
-       struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+       struct scsi_device *sdev = scmnd->device;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+       struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
+       unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
@@ -882,16 +845,16 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
                goto out;
        }
 
-       if (unlikely(!(atomic_read(&unit->status) &
+       if (unlikely(!(atomic_read(&zfcp_sdev->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                goto out_error_free;
 
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
-       req->data = unit;
+       req->data = sdev;
        req->handler = zfcp_fsf_abort_fcp_command_handler;
-       req->qtcb->header.lun_handle = unit->handle;
-       req->qtcb->header.port_handle = unit->port->handle;
+       req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+       req->qtcb->header.port_handle = zfcp_sdev->port->handle;
        req->qtcb->bottom.support.req_handle = (u64) old_req_id;
 
        zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
@@ -902,7 +865,7 @@ out_error_free:
        zfcp_fsf_req_free(req);
        req = NULL;
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return req;
 }
 
@@ -1041,7 +1004,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
        struct zfcp_fsf_req *req;
        int ret = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1073,7 +1036,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
 failed_send:
        zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return ret;
 }
 
@@ -1111,8 +1074,10 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
        case FSF_RESPONSE_SIZE_TOO_LARGE:
                break;
        case FSF_ACCESS_DENIED:
-               if (port)
-                       zfcp_fsf_access_denied_port(req, port);
+               if (port) {
+                       zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+                       req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               }
                break;
        case FSF_SBAL_MISMATCH:
                /* should never occure, avoided in zfcp_fsf_send_els */
@@ -1137,7 +1102,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
        struct zfcp_qdio *qdio = adapter->qdio;
        int ret = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1173,7 +1138,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
 failed_send:
        zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return ret;
 }
 
@@ -1183,7 +1148,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
        struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1215,7 +1180,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req_id = 0;
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1225,7 +1190,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
        struct zfcp_fsf_req *req = NULL;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out_unlock;
 
@@ -1251,7 +1216,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
 
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        retval = zfcp_fsf_req_send(req);
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        if (!retval)
                wait_for_completion(&req->completion);
 
@@ -1259,7 +1224,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
        return retval;
 
 out_unlock:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1277,7 +1242,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
        if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
                return -EOPNOTSUPP;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1304,7 +1269,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req_id = 0;
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1323,7 +1288,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
        if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
                return -EOPNOTSUPP;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out_unlock;
 
@@ -1343,7 +1308,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
        req->handler = zfcp_fsf_exchange_port_data_handler;
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        retval = zfcp_fsf_req_send(req);
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
 
        if (!retval)
                wait_for_completion(&req->completion);
@@ -1353,7 +1318,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
        return retval;
 
 out_unlock:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1370,14 +1335,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
        case FSF_PORT_ALREADY_OPEN:
                break;
        case FSF_ACCESS_DENIED:
-               zfcp_fsf_access_denied_port(req, port);
+               zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
                dev_warn(&req->adapter->ccw_device->dev,
                         "Not enough FCP adapter resources to open "
                         "remote port 0x%016Lx\n",
                         (unsigned long long)port->wwpn);
-               zfcp_erp_port_failed(port, "fsoph_1", req);
+               zfcp_erp_set_port_status(port,
+                                        ZFCP_STATUS_COMMON_ERP_FAILED);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1437,7 +1404,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1468,7 +1435,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
                put_device(&port->dev);
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1487,9 +1454,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                break;
        case FSF_GOOD:
-               zfcp_erp_modify_port_status(port, "fscph_2", req,
-                                           ZFCP_STATUS_COMMON_OPEN,
-                                           ZFCP_CLEAR);
+               zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
                break;
        }
 }
@@ -1505,7 +1470,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1534,7 +1499,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req_id = 0;
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1580,7 +1545,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1605,7 +1570,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
        if (retval)
                zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1633,7 +1598,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1658,7 +1623,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
        if (retval)
                zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1666,7 +1631,7 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
 {
        struct zfcp_port *port = req->data;
        struct fsf_qtcb_header *header = &req->qtcb->header;
-       struct zfcp_unit *unit;
+       struct scsi_device *sdev;
 
        if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
                return;
@@ -1677,18 +1642,19 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_ACCESS_DENIED:
-               zfcp_fsf_access_denied_port(req, port);
+               zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
                break;
        case FSF_PORT_BOXED:
                /* can't use generic zfcp_erp_modify_port_status because
                 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
                atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-               read_lock(&port->unit_list_lock);
-               list_for_each_entry(unit, &port->unit_list, list)
-                       atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
-                                         &unit->status);
-               read_unlock(&port->unit_list_lock);
-               zfcp_erp_port_boxed(port, "fscpph2", req);
+               shost_for_each_device(sdev, port->adapter->scsi_host)
+                       if (sdev_to_zfcp(sdev)->port == port)
+                               atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+                                                 &sdev_to_zfcp(sdev)->status);
+               zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
+                                    "fscpph2", req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1705,11 +1671,10 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
                 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
                 */
                atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-               read_lock(&port->unit_list_lock);
-               list_for_each_entry(unit, &port->unit_list, list)
-                       atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
-                                         &unit->status);
-               read_unlock(&port->unit_list_lock);
+               shost_for_each_device(sdev, port->adapter->scsi_host)
+                       if (sdev_to_zfcp(sdev)->port == port)
+                               atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+                                                 &sdev_to_zfcp(sdev)->status);
                break;
        }
 }
@@ -1725,7 +1690,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1754,69 +1719,57 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req_id = 0;
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
-static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
 {
        struct zfcp_adapter *adapter = req->adapter;
-       struct zfcp_unit *unit = req->data;
+       struct scsi_device *sdev = req->data;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
        struct fsf_qtcb_header *header = &req->qtcb->header;
        struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
-       struct fsf_queue_designator *queue_designator =
-                               &header->fsf_status_qual.fsf_queue_designator;
-       int exclusive, readwrite;
 
        if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
                return;
 
        atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
                          ZFCP_STATUS_COMMON_ACCESS_BOXED |
-                         ZFCP_STATUS_UNIT_SHARED |
-                         ZFCP_STATUS_UNIT_READONLY,
-                         &unit->status);
+                         ZFCP_STATUS_LUN_SHARED |
+                         ZFCP_STATUS_LUN_READONLY,
+                         &zfcp_sdev->status);
 
        switch (header->fsf_status) {
 
        case FSF_PORT_HANDLE_NOT_VALID:
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
+               zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req);
                /* fall through */
        case FSF_LUN_ALREADY_OPEN:
                break;
        case FSF_ACCESS_DENIED:
-               zfcp_fsf_access_denied_unit(req, unit);
-               atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
-               atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+               zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_PORT_BOXED:
-               zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
+               zfcp_erp_set_port_status(zfcp_sdev->port,
+                                        ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_port_reopen(zfcp_sdev->port,
+                                    ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2",
+                                    req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_LUN_SHARING_VIOLATION:
-               if (header->fsf_status_qual.word[0])
-                       dev_warn(&adapter->ccw_device->dev,
-                                "LUN 0x%Lx on port 0x%Lx is already in "
-                                "use by CSS%d, MIF Image ID %x\n",
-                                (unsigned long long)unit->fcp_lun,
-                                (unsigned long long)unit->port->wwpn,
-                                queue_designator->cssid,
-                                queue_designator->hla);
-               else
-                       zfcp_act_eval_err(adapter,
-                                         header->fsf_status_qual.word[2]);
-               zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
-               atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
-               atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+               zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
                dev_warn(&adapter->ccw_device->dev,
                         "No handle is available for LUN "
                         "0x%016Lx on port 0x%016Lx\n",
-                        (unsigned long long)unit->fcp_lun,
-                        (unsigned long long)unit->port->wwpn);
-               zfcp_erp_unit_failed(unit, "fsouh_4", req);
+                        (unsigned long long)zfcp_scsi_dev_lun(sdev),
+                        (unsigned long long)zfcp_sdev->port->wwpn);
+               zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
                /* fall through */
        case FSF_INVALID_COMMAND_OPTION:
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1824,7 +1777,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       zfcp_fc_test_link(unit->port);
+                       zfcp_fc_test_link(zfcp_sdev->port);
                        /* fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1833,70 +1786,26 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
                break;
 
        case FSF_GOOD:
-               unit->handle = header->lun_handle;
-               atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-
-               if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
-                   (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
-                   !zfcp_ccw_priv_sch(adapter)) {
-                       exclusive = (bottom->lun_access_info &
-                                       FSF_UNIT_ACCESS_EXCLUSIVE);
-                       readwrite = (bottom->lun_access_info &
-                                       FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
-
-                       if (!exclusive)
-                               atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
-                                               &unit->status);
-
-                       if (!readwrite) {
-                               atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
-                                               &unit->status);
-                               dev_info(&adapter->ccw_device->dev,
-                                        "SCSI device at LUN 0x%016Lx on port "
-                                        "0x%016Lx opened read-only\n",
-                                        (unsigned long long)unit->fcp_lun,
-                                        (unsigned long long)unit->port->wwpn);
-                       }
-
-                       if (exclusive && !readwrite) {
-                               dev_err(&adapter->ccw_device->dev,
-                                       "Exclusive read-only access not "
-                                       "supported (unit 0x%016Lx, "
-                                       "port 0x%016Lx)\n",
-                                       (unsigned long long)unit->fcp_lun,
-                                       (unsigned long long)unit->port->wwpn);
-                               zfcp_erp_unit_failed(unit, "fsouh_5", req);
-                               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-                               zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
-                       } else if (!exclusive && readwrite) {
-                               dev_err(&adapter->ccw_device->dev,
-                                       "Shared read-write access not "
-                                       "supported (unit 0x%016Lx, port "
-                                       "0x%016Lx)\n",
-                                       (unsigned long long)unit->fcp_lun,
-                                       (unsigned long long)unit->port->wwpn);
-                               zfcp_erp_unit_failed(unit, "fsouh_7", req);
-                               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-                               zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
-                       }
-               }
+               zfcp_sdev->lun_handle = header->lun_handle;
+               atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
+               zfcp_cfdc_open_lun_eval(sdev, bottom);
                break;
        }
 }
 
 /**
- * zfcp_fsf_open_unit - open unit
+ * zfcp_fsf_open_lun - open LUN
  * @erp_action: pointer to struct zfcp_erp_action
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_qdio *qdio = adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1913,9 +1822,9 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->qtcb->header.port_handle = erp_action->port->handle;
-       req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
-       req->handler = zfcp_fsf_open_unit_handler;
-       req->data = erp_action->unit;
+       req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev);
+       req->handler = zfcp_fsf_open_lun_handler;
+       req->data = erp_action->sdev;
        req->erp_action = erp_action;
        erp_action->fsf_req_id = req->req_id;
 
@@ -1929,34 +1838,40 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req_id = 0;
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
-static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
 {
-       struct zfcp_unit *unit = req->data;
+       struct scsi_device *sdev = req->data;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 
        if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
                return;
 
        switch (req->qtcb->header.fsf_status) {
        case FSF_PORT_HANDLE_NOT_VALID:
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
+               zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1",
+                                       req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_LUN_HANDLE_NOT_VALID:
-               zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
+               zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_PORT_BOXED:
-               zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
+               zfcp_erp_set_port_status(zfcp_sdev->port,
+                                        ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_port_reopen(zfcp_sdev->port,
+                                    ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3",
+                                    req);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (req->qtcb->header.fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       zfcp_fc_test_link(unit->port);
+                       zfcp_fc_test_link(zfcp_sdev->port);
                        /* fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1964,23 +1879,24 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
                }
                break;
        case FSF_GOOD:
-               atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
+               atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
                break;
        }
 }
 
 /**
- * zfcp_fsf_close_unit - close zfcp unit
- * @erp_action: pointer to struct zfcp_unit
+ * zfcp_fsf_close_LUN - close LUN
+ * @erp_action: pointer to erp_action triggering the "close LUN"
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_qdio *qdio = erp_action->adapter->qdio;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -1997,9 +1913,9 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->qtcb->header.port_handle = erp_action->port->handle;
-       req->qtcb->header.lun_handle = erp_action->unit->handle;
-       req->handler = zfcp_fsf_close_unit_handler;
-       req->data = erp_action->unit;
+       req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+       req->handler = zfcp_fsf_close_lun_handler;
+       req->data = erp_action->sdev;
        req->erp_action = erp_action;
        erp_action->fsf_req_id = req->req_id;
 
@@ -2010,7 +1926,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req_id = 0;
        }
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return retval;
 }
 
@@ -2025,7 +1941,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
 {
        struct fsf_qual_latency_info *lat_in;
        struct latency_cont *lat = NULL;
-       struct zfcp_unit *unit = req->unit;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
        struct zfcp_blk_drv_data blktrc;
        int ticks = req->adapter->timer_ticks;
 
@@ -2048,24 +1964,24 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
                case FSF_DATADIR_DIF_READ_STRIP:
                case FSF_DATADIR_DIF_READ_CONVERT:
                case FSF_DATADIR_READ:
-                       lat = &unit->latencies.read;
+                       lat = &zfcp_sdev->latencies.read;
                        break;
                case FSF_DATADIR_DIF_WRITE_INSERT:
                case FSF_DATADIR_DIF_WRITE_CONVERT:
                case FSF_DATADIR_WRITE:
-                       lat = &unit->latencies.write;
+                       lat = &zfcp_sdev->latencies.write;
                        break;
                case FSF_DATADIR_CMND:
-                       lat = &unit->latencies.cmd;
+                       lat = &zfcp_sdev->latencies.cmd;
                        break;
                }
 
                if (lat) {
-                       spin_lock(&unit->latencies.lock);
+                       spin_lock(&zfcp_sdev->latencies.lock);
                        zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
                        zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
                        lat->counter++;
-                       spin_unlock(&unit->latencies.lock);
+                       spin_unlock(&zfcp_sdev->latencies.lock);
                }
        }
 
@@ -2073,7 +1989,81 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
                            sizeof(blktrc));
 }
 
-static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
+{
+       struct scsi_cmnd *scmnd = req->data;
+       struct scsi_device *sdev = scmnd->device;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+       struct fsf_qtcb_header *header = &req->qtcb->header;
+
+       if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
+               return;
+
+       switch (header->fsf_status) {
+       case FSF_HANDLE_MISMATCH:
+       case FSF_PORT_HANDLE_NOT_VALID:
+               zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
+                                       req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_FCPLUN_NOT_VALID:
+       case FSF_LUN_HANDLE_NOT_VALID:
+               zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_SERVICE_CLASS_NOT_SUPPORTED:
+               zfcp_fsf_class_not_supp(req);
+               break;
+       case FSF_ACCESS_DENIED:
+               zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_DIRECTION_INDICATOR_NOT_VALID:
+               dev_err(&req->adapter->ccw_device->dev,
+                       "Incorrect direction %d, LUN 0x%016Lx on port "
+                       "0x%016Lx closed\n",
+                       req->qtcb->bottom.io.data_direction,
+                       (unsigned long long)zfcp_scsi_dev_lun(sdev),
+                       (unsigned long long)zfcp_sdev->port->wwpn);
+               zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+                                         "fssfch3", req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_CMND_LENGTH_NOT_VALID:
+               dev_err(&req->adapter->ccw_device->dev,
+                       "Incorrect CDB length %d, LUN 0x%016Lx on "
+                       "port 0x%016Lx closed\n",
+                       req->qtcb->bottom.io.fcp_cmnd_length,
+                       (unsigned long long)zfcp_scsi_dev_lun(sdev),
+                       (unsigned long long)zfcp_sdev->port->wwpn);
+               zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+                                         "fssfch4", req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_PORT_BOXED:
+               zfcp_erp_set_port_status(zfcp_sdev->port,
+                                        ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_port_reopen(zfcp_sdev->port,
+                                    ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5",
+                                    req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_LUN_BOXED:
+               zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+               zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+                                   "fssfch6", req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       case FSF_ADAPTER_STATUS_AVAILABLE:
+               if (header->fsf_status_qual.word[0] ==
+                   FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
+                       zfcp_fc_test_link(zfcp_sdev->port);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+               break;
+       }
+}
+
+static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
 {
        struct scsi_cmnd *scpnt;
        struct fcp_resp_with_ext *fcp_rsp;
@@ -2087,6 +2077,8 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
                return;
        }
 
+       zfcp_fsf_fcp_handler_common(req);
+
        if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
                set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
                goto skip_fsfstatus;
@@ -2125,97 +2117,6 @@ skip_fsfstatus:
        read_unlock_irqrestore(&req->adapter->abort_lock, flags);
 }
 
-static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
-{
-       struct fcp_resp_with_ext *fcp_rsp;
-       struct fcp_resp_rsp_info *rsp_info;
-
-       fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
-       rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
-
-       if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
-            (req->status & ZFCP_STATUS_FSFREQ_ERROR))
-               req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
-}
-
-
-static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
-{
-       struct zfcp_unit *unit;
-       struct fsf_qtcb_header *header = &req->qtcb->header;
-
-       if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
-               unit = req->data;
-       else
-               unit = req->unit;
-
-       if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
-               goto skip_fsfstatus;
-
-       switch (header->fsf_status) {
-       case FSF_HANDLE_MISMATCH:
-       case FSF_PORT_HANDLE_NOT_VALID:
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       case FSF_FCPLUN_NOT_VALID:
-       case FSF_LUN_HANDLE_NOT_VALID:
-               zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-               zfcp_fsf_class_not_supp(req);
-               break;
-       case FSF_ACCESS_DENIED:
-               zfcp_fsf_access_denied_unit(req, unit);
-               break;
-       case FSF_DIRECTION_INDICATOR_NOT_VALID:
-               dev_err(&req->adapter->ccw_device->dev,
-                       "Incorrect direction %d, unit 0x%016Lx on port "
-                       "0x%016Lx closed\n",
-                       req->qtcb->bottom.io.data_direction,
-                       (unsigned long long)unit->fcp_lun,
-                       (unsigned long long)unit->port->wwpn);
-               zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
-                                         req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       case FSF_CMND_LENGTH_NOT_VALID:
-               dev_err(&req->adapter->ccw_device->dev,
-                       "Incorrect CDB length %d, unit 0x%016Lx on "
-                       "port 0x%016Lx closed\n",
-                       req->qtcb->bottom.io.fcp_cmnd_length,
-                       (unsigned long long)unit->fcp_lun,
-                       (unsigned long long)unit->port->wwpn);
-               zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
-                                         req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       case FSF_PORT_BOXED:
-               zfcp_erp_port_boxed(unit->port, "fssfch5", req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       case FSF_LUN_BOXED:
-               zfcp_erp_unit_boxed(unit, "fssfch6", req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       case FSF_ADAPTER_STATUS_AVAILABLE:
-               if (header->fsf_status_qual.word[0] ==
-                   FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
-                       zfcp_fc_test_link(unit->port);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-               break;
-       }
-skip_fsfstatus:
-       if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
-               zfcp_fsf_send_fcp_ctm_handler(req);
-       else {
-               zfcp_fsf_send_fcp_command_task_handler(req);
-               req->unit = NULL;
-               put_device(&unit->dev);
-       }
-}
-
 static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
 {
        switch (scsi_get_prot_op(scsi_cmnd)) {
@@ -2255,26 +2156,27 @@ static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
 }
 
 /**
- * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
- * @unit: unit where command is sent to
+ * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
  * @scsi_cmnd: scsi command to be sent
  */
-int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
-                                  struct scsi_cmnd *scsi_cmnd)
+int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
 {
        struct zfcp_fsf_req *req;
        struct fcp_cmnd *fcp_cmnd;
        unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
        int real_bytes, retval = -EIO, dix_bytes = 0;
-       struct zfcp_adapter *adapter = unit->port->adapter;
+       struct scsi_device *sdev = scsi_cmnd->device;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+       struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        struct zfcp_qdio *qdio = adapter->qdio;
        struct fsf_qtcb_bottom_io *io;
+       unsigned long flags;
 
-       if (unlikely(!(atomic_read(&unit->status) &
+       if (unlikely(!(atomic_read(&zfcp_sdev->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return -EBUSY;
 
-       spin_lock(&qdio->req_q_lock);
+       spin_lock_irqsave(&qdio->req_q_lock, flags);
        if (atomic_read(&qdio->req_q_free) <= 0) {
                atomic_inc(&qdio->req_q_full);
                goto out;
@@ -2295,11 +2197,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 
        io = &req->qtcb->bottom.io;
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       req->unit = unit;
        req->data = scsi_cmnd;
-       req->handler = zfcp_fsf_send_fcp_command_handler;
-       req->qtcb->header.lun_handle = unit->handle;
-       req->qtcb->header.port_handle = unit->port->handle;
+       req->handler = zfcp_fsf_fcp_cmnd_handler;
+       req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+       req->qtcb->header.port_handle = zfcp_sdev->port->handle;
        io->service_class = FSF_CLASS_3;
        io->fcp_cmnd_length = FCP_CMND_LEN;
 
@@ -2310,8 +2211,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
 
        zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
 
-       get_device(&unit->dev);
-
        fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
        zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
 
@@ -2338,31 +2237,47 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
        goto out;
 
 failed_scsi_cmnd:
-       put_device(&unit->dev);
        zfcp_fsf_req_free(req);
        scsi_cmnd->host_scribble = NULL;
 out:
-       spin_unlock(&qdio->req_q_lock);
+       spin_unlock_irqrestore(&qdio->req_q_lock, flags);
        return retval;
 }
 
+static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
+{
+       struct fcp_resp_with_ext *fcp_rsp;
+       struct fcp_resp_rsp_info *rsp_info;
+
+       zfcp_fsf_fcp_handler_common(req);
+
+       fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+       rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+
+       if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
+            (req->status & ZFCP_STATUS_FSFREQ_ERROR))
+               req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
+}
+
 /**
- * zfcp_fsf_send_fcp_ctm - send SCSI task management command
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
+ * @scmnd: SCSI command to send the task management command for
  * @tm_flags: unsigned byte for task management flags
  * Returns: on success pointer to struct fsf_req, NULL otherwise
  */
-struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
+struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
+                                           u8 tm_flags)
 {
        struct zfcp_fsf_req *req = NULL;
        struct fcp_cmnd *fcp_cmnd;
-       struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+       struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
 
-       if (unlikely(!(atomic_read(&unit->status) &
+       if (unlikely(!(atomic_read(&zfcp_sdev->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return NULL;
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -2376,10 +2291,10 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
-       req->data = unit;
-       req->handler = zfcp_fsf_send_fcp_command_handler;
-       req->qtcb->header.lun_handle = unit->handle;
-       req->qtcb->header.port_handle = unit->port->handle;
+       req->data = scmnd;
+       req->handler = zfcp_fsf_fcp_task_mgmt_handler;
+       req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+       req->qtcb->header.port_handle = zfcp_sdev->port->handle;
        req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
        req->qtcb->bottom.io.service_class = FSF_CLASS_3;
        req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
@@ -2387,7 +2302,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
-       zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
+       zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
 
        zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
        if (!zfcp_fsf_req_send(req))
@@ -2396,7 +2311,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        zfcp_fsf_req_free(req);
        req = NULL;
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
        return req;
 }
 
@@ -2432,7 +2347,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
                return ERR_PTR(-EINVAL);
        }
 
-       spin_lock_bh(&qdio->req_q_lock);
+       spin_lock_irq(&qdio->req_q_lock);
        if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
@@ -2459,7 +2374,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        retval = zfcp_fsf_req_send(req);
 out:
-       spin_unlock_bh(&qdio->req_q_lock);
+       spin_unlock_irq(&qdio->req_q_lock);
 
        if (!retval) {
                wait_for_completion(&req->completion);