aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c3
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c6
-rw-r--r--drivers/s390/scsi/zfcp_def.h22
-rw-r--r--drivers/s390/scsi/zfcp_erp.c14
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c70
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c24
7 files changed, 72 insertions, 69 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 00118499018..874b55ed00a 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -844,8 +844,6 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
unit->sysfs_device.release = zfcp_sysfs_unit_release;
dev_set_drvdata(&unit->sysfs_device, unit);
- init_waitqueue_head(&unit->scsi_scan_wq);
-
/* mark unit unusable as long as sysfs registration is not complete */
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 86c3f6539a7..edc5015e920 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -123,6 +123,9 @@ zfcp_ccw_remove(struct ccw_device *ccw_device)
list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) {
list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) {
+ if (atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED,
+ &unit->status))
+ scsi_remove_device(unit->device);
zfcp_unit_dequeue(unit);
}
zfcp_port_dequeue(port);
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index ffa3bf75694..701046c9bb3 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -161,12 +161,6 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
(fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
level = 4;
- } else if ((prot_status_qual->doubleword[0] != 0) ||
- (prot_status_qual->doubleword[1] != 0) ||
- (fsf_status_qual->doubleword[0] != 0) ||
- (fsf_status_qual->doubleword[1] != 0)) {
- strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE);
- level = 3;
} else {
strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
level = 6;
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index e268f79bdbd..9e9f6c1e4e5 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -118,7 +118,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
#define ZFCP_SBAL_TIMEOUT (5*HZ)
-#define ZFCP_TYPE2_RECOVERY_TIME (8*HZ)
+#define ZFCP_TYPE2_RECOVERY_TIME 8 /* seconds */
/* queue polling (values in microseconds) */
#define ZFCP_MAX_INPUT_THRESHOLD 5000 /* FIXME: tune */
@@ -139,7 +139,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
#define ZFCP_STATUS_READS_RECOM FSF_STATUS_READS_RECOM
/* Do 1st retry in 1 second, then double the timeout for each following retry */
-#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
+#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 1
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
/* timeout value for "default timer" for fsf requests */
@@ -983,10 +983,6 @@ struct zfcp_unit {
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
- wait_queue_head_t scsi_scan_wq; /* can be used to wait until
- all scsi_scan_target
- requests have been
- completed. */
};
/* FSF request */
@@ -1127,6 +1123,20 @@ zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id)
return NULL;
}
+static inline struct zfcp_fsf_req *
+zfcp_reqlist_find_safe(struct zfcp_adapter *adapter, struct zfcp_fsf_req *req)
+{
+ struct zfcp_fsf_req *request;
+ unsigned int idx;
+
+ for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) {
+ list_for_each_entry(request, &adapter->req_list[idx], list)
+ if (request == req)
+ return request;
+ }
+ return NULL;
+}
+
/*
* functions needed for reference/usage counting
*/
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 07fa824d179..4f86c0e1296 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -131,7 +131,7 @@ static void zfcp_close_qdio(struct zfcp_adapter *adapter)
debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
while (qdio_shutdown(adapter->ccw_device,
QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
- msleep(1000);
+ ssleep(1);
debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
/* cleanup used outbound sbals */
@@ -456,7 +456,7 @@ zfcp_test_link(struct zfcp_port *port)
zfcp_port_get(port);
retval = zfcp_erp_adisc(port);
- if (retval != 0) {
+ if (retval != 0 && retval != -EBUSY) {
zfcp_port_put(port);
ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
"on adapter %s\n ", port->wwpn,
@@ -846,7 +846,8 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
if (erp_action->fsf_req) {
/* take lock to ensure that request is not deleted meanwhile */
spin_lock(&adapter->req_list_lock);
- if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) {
+ if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) &&
+ erp_action->fsf_req->erp_action == erp_action) {
/* fsf_req still exists */
debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
@@ -1609,7 +1610,6 @@ static void zfcp_erp_scsi_scan(struct work_struct *work)
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
unit->scsi_lun, 0);
atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
- wake_up(&unit->scsi_scan_wq);
zfcp_unit_put(unit);
kfree(p);
}
@@ -1900,7 +1900,7 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action)
ZFCP_LOG_INFO("Waiting to allow the adapter %s "
"to recover itself\n",
zfcp_get_busid_by_adapter(adapter));
- msleep(jiffies_to_msecs(ZFCP_TYPE2_RECOVERY_TIME));
+ ssleep(ZFCP_TYPE2_RECOVERY_TIME);
}
return retval;
@@ -2080,7 +2080,7 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
debug_text_event(adapter->erp_dbf, 3, "qdio_down1a");
while (qdio_shutdown(adapter->ccw_device,
QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
- msleep(1000);
+ ssleep(1);
debug_text_event(adapter->erp_dbf, 3, "qdio_down1b");
failed_qdio_establish:
@@ -2165,7 +2165,7 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
ZFCP_LOG_DEBUG("host connection still initialising... "
"waiting and retrying...\n");
/* sleep a little bit before retry */
- msleep(jiffies_to_msecs(sleep));
+ ssleep(sleep);
sleep *= 2;
}
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ff866ebd44a..fe57941ab55 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1116,6 +1116,10 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
goto out;
}
+ if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &unit->status)))
+ goto unit_blocked;
+
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -1131,22 +1135,13 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT);
retval = zfcp_fsf_req_send(fsf_req);
- if (retval) {
- ZFCP_LOG_INFO("error: Failed to send abort command request "
- "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
- zfcp_get_busid_by_adapter(adapter),
- unit->port->wwpn, unit->fcp_lun);
+ if (!retval)
+ goto out;
+
+ unit_blocked:
zfcp_fsf_req_free(fsf_req);
fsf_req = NULL;
- goto out;
- }
- ZFCP_LOG_DEBUG("Abort FCP Command request initiated "
- "(adapter%s, port d_id=0x%06x, "
- "unit x%016Lx, old_req_id=0x%lx)\n",
- zfcp_get_busid_by_adapter(adapter),
- unit->port->d_id,
- unit->fcp_lun, old_req_id);
out:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
return fsf_req;
@@ -1164,8 +1159,8 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
{
int retval = -EINVAL;
struct zfcp_unit *unit;
- unsigned char status_qual =
- new_fsf_req->qtcb->header.fsf_status_qual.word[0];
+ union fsf_status_qual *fsf_stat_qual =
+ &new_fsf_req->qtcb->header.fsf_status_qual;
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */
@@ -1178,7 +1173,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
switch (new_fsf_req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- if (status_qual >> 4 != status_qual % 0xf) {
+ if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_phand_nv0");
/*
@@ -1207,8 +1202,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
break;
case FSF_LUN_HANDLE_NOT_VALID:
- if (status_qual >> 4 != status_qual % 0xf) {
- /* 2 */
+ if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_lhand_nv0");
/*
@@ -1674,6 +1668,12 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
goto failed_req;
}
+ if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &els->port->status))) {
+ ret = -EBUSY;
+ goto port_blocked;
+ }
+
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
if (zfcp_use_one_sbal(els->req, els->req_count,
els->resp, els->resp_count)){
@@ -1755,6 +1755,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
"0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id);
goto out;
+ port_blocked:
failed_send:
zfcp_fsf_req_free(fsf_req);
@@ -3592,6 +3593,12 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
goto failed_req_create;
}
+ if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &unit->status))) {
+ retval = -EBUSY;
+ goto unit_blocked;
+ }
+
zfcp_unit_get(unit);
fsf_req->unit = unit;
@@ -3732,6 +3739,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
send_failed:
no_fit:
failed_scsi_cmnd:
+ unit_blocked:
zfcp_unit_put(unit);
zfcp_fsf_req_free(fsf_req);
fsf_req = NULL;
@@ -3766,6 +3774,10 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
goto out;
}
+ if (unlikely(!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &unit->status)))
+ goto unit_blocked;
+
/*
* Used to decide on proper handler in the return path,
* could be either zfcp_fsf_send_fcp_command_task_handler or
@@ -3799,25 +3811,13 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT);
retval = zfcp_fsf_req_send(fsf_req);
- if (retval) {
- ZFCP_LOG_INFO("error: Could not send an FCP-command (task "
- "management) on adapter %s, port 0x%016Lx for "
- "unit LUN 0x%016Lx\n",
- zfcp_get_busid_by_adapter(adapter),
- unit->port->wwpn,
- unit->fcp_lun);
- zfcp_fsf_req_free(fsf_req);
- fsf_req = NULL;
+ if (!retval)
goto out;
- }
- ZFCP_LOG_TRACE("Send FCP Command (task management function) initiated "
- "(adapter %s, port 0x%016Lx, unit 0x%016Lx, "
- "tm_flags=0x%x)\n",
- zfcp_get_busid_by_adapter(adapter),
- unit->port->wwpn,
- unit->fcp_lun,
- tm_flags);
+ unit_blocked:
+ zfcp_fsf_req_free(fsf_req);
+ fsf_req = NULL;
+
out:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
return fsf_req;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index abae2027f7e..b9daf5c0586 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -51,7 +51,6 @@ struct zfcp_data zfcp_data = {
.queuecommand = zfcp_scsi_queuecommand,
.eh_abort_handler = zfcp_scsi_eh_abort_handler,
.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
- .eh_bus_reset_handler = zfcp_scsi_eh_host_reset_handler,
.eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler,
.can_queue = 4096,
.this_id = -1,
@@ -181,9 +180,6 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
if (unit) {
zfcp_erp_wait(unit->port->adapter);
- wait_event(unit->scsi_scan_wq,
- atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
- &unit->status) == 0);
atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
sdpnt->hostdata = NULL;
unit->device = NULL;
@@ -262,8 +258,9 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
goto out;
}
- if (unlikely(
- !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))) {
+ tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer,
+ ZFCP_REQ_AUTO_CLEANUP);
+ if (unlikely(tmp == -EBUSY)) {
ZFCP_LOG_DEBUG("adapter %s not ready or unit 0x%016Lx "
"on port 0x%016Lx in recovery\n",
zfcp_get_busid_by_unit(unit),
@@ -272,9 +269,6 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
goto out;
}
- tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer,
- ZFCP_REQ_AUTO_CLEANUP);
-
if (unlikely(tmp < 0)) {
ZFCP_LOG_DEBUG("error: initiation of Send FCP Cmnd failed\n");
retval = SCSI_MLQUEUE_HOST_BUSY;
@@ -459,7 +453,9 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
retval = SUCCESS;
goto out;
}
- ZFCP_LOG_NORMAL("resetting unit 0x%016Lx\n", unit->fcp_lun);
+ ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n",
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_adapter(unit->port->adapter));
/*
* If we do not know whether the unit supports 'logical unit reset'
@@ -542,7 +538,7 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,
}
/**
- * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset
+ * zfcp_scsi_eh_host_reset_handler - handler for host reset
*/
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
@@ -552,8 +548,10 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
unit = (struct zfcp_unit*) scpnt->device->hostdata;
adapter = unit->port->adapter;
- ZFCP_LOG_NORMAL("host/bus reset because of problems with "
- "unit 0x%016Lx\n", unit->fcp_lun);
+ ZFCP_LOG_NORMAL("host reset because of problems with "
+ "unit 0x%016Lx on port 0x%016Lx, adapter %s\n",
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_adapter(unit->port->adapter));
zfcp_erp_adapter_reopen(adapter, 0);
zfcp_erp_wait(adapter);