diff options
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 6 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 22 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 14 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 70 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 24 |
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); |