diff options
| -rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 1 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 1 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 7 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 35 |
4 files changed, 40 insertions, 4 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 6c6374ba1807..e1c6b6e05a75 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
| @@ -73,6 +73,7 @@ struct zfcp_reqlist; | |||
| 73 | 73 | ||
| 74 | /* adapter status */ | 74 | /* adapter status */ |
| 75 | #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 | 75 | #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 |
| 76 | #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 | ||
| 76 | #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 | 77 | #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 |
| 77 | #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 | 78 | #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 |
| 78 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 | 79 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index de0925f25dcc..3b93239c6f69 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
| @@ -152,6 +152,7 @@ extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *, | |||
| 152 | struct scatterlist *); | 152 | struct scatterlist *); |
| 153 | extern int zfcp_qdio_open(struct zfcp_qdio *); | 153 | extern int zfcp_qdio_open(struct zfcp_qdio *); |
| 154 | extern void zfcp_qdio_close(struct zfcp_qdio *); | 154 | extern void zfcp_qdio_close(struct zfcp_qdio *); |
| 155 | extern void zfcp_qdio_siosl(struct zfcp_adapter *); | ||
| 155 | 156 | ||
| 156 | /* zfcp_scsi.c */ | 157 | /* zfcp_scsi.c */ |
| 157 | extern struct zfcp_data zfcp_data; | 158 | extern struct zfcp_data zfcp_data; |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index f9be5d60d92a..9d1d7d1842ce 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | 21 | static void zfcp_fsf_request_timeout_handler(unsigned long data) |
| 22 | { | 22 | { |
| 23 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | 23 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; |
| 24 | zfcp_qdio_siosl(adapter); | ||
| 24 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 25 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
| 25 | "fsrth_1", NULL); | 26 | "fsrth_1", NULL); |
| 26 | } | 27 | } |
| @@ -326,6 +327,7 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) | |||
| 326 | dev_err(&req->adapter->ccw_device->dev, | 327 | dev_err(&req->adapter->ccw_device->dev, |
| 327 | "The FCP adapter reported a problem " | 328 | "The FCP adapter reported a problem " |
| 328 | "that cannot be recovered\n"); | 329 | "that cannot be recovered\n"); |
| 330 | zfcp_qdio_siosl(req->adapter); | ||
| 329 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req); | 331 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req); |
| 330 | break; | 332 | break; |
| 331 | } | 333 | } |
| @@ -416,6 +418,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
| 416 | dev_err(&adapter->ccw_device->dev, | 418 | dev_err(&adapter->ccw_device->dev, |
| 417 | "0x%x is not a valid transfer protocol status\n", | 419 | "0x%x is not a valid transfer protocol status\n", |
| 418 | qtcb->prefix.prot_status); | 420 | qtcb->prefix.prot_status); |
| 421 | zfcp_qdio_siosl(adapter); | ||
| 419 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req); | 422 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req); |
| 420 | } | 423 | } |
| 421 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 424 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
| @@ -2485,13 +2488,15 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) | |||
| 2485 | req_id = (unsigned long) sbale->addr; | 2488 | req_id = (unsigned long) sbale->addr; |
| 2486 | fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id); | 2489 | fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id); |
| 2487 | 2490 | ||
| 2488 | if (!fsf_req) | 2491 | if (!fsf_req) { |
| 2489 | /* | 2492 | /* |
| 2490 | * Unknown request means that we have potentially memory | 2493 | * Unknown request means that we have potentially memory |
| 2491 | * corruption and must stop the machine immediately. | 2494 | * corruption and must stop the machine immediately. |
| 2492 | */ | 2495 | */ |
| 2496 | zfcp_qdio_siosl(adapter); | ||
| 2493 | panic("error: unknown req_id (%lx) on adapter %s.\n", | 2497 | panic("error: unknown req_id (%lx) on adapter %s.\n", |
| 2494 | req_id, dev_name(&adapter->ccw_device->dev)); | 2498 | req_id, dev_name(&adapter->ccw_device->dev)); |
| 2499 | } | ||
| 2495 | 2500 | ||
| 2496 | fsf_req->qdio_req.sbal_response = sbal_idx; | 2501 | fsf_req->qdio_req.sbal_response = sbal_idx; |
| 2497 | zfcp_fsf_req_complete(fsf_req); | 2502 | zfcp_fsf_req_complete(fsf_req); |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index aceced8ec7e4..b2635759721c 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
| @@ -30,12 +30,15 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) | |||
| 30 | return 0; | 30 | return 0; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id) | 33 | static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id, |
| 34 | unsigned int qdio_err) | ||
| 34 | { | 35 | { |
| 35 | struct zfcp_adapter *adapter = qdio->adapter; | 36 | struct zfcp_adapter *adapter = qdio->adapter; |
| 36 | 37 | ||
| 37 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); | 38 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); |
| 38 | 39 | ||
| 40 | if (qdio_err & QDIO_ERROR_SLSB_STATE) | ||
| 41 | zfcp_qdio_siosl(adapter); | ||
| 39 | zfcp_erp_adapter_reopen(adapter, | 42 | zfcp_erp_adapter_reopen(adapter, |
| 40 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 43 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
| 41 | ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL); | 44 | ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL); |
| @@ -74,7 +77,7 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | |||
| 74 | 77 | ||
| 75 | if (unlikely(qdio_err)) { | 78 | if (unlikely(qdio_err)) { |
| 76 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); | 79 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); |
| 77 | zfcp_qdio_handler_error(qdio, "qdireq1"); | 80 | zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err); |
| 78 | return; | 81 | return; |
| 79 | } | 82 | } |
| 80 | 83 | ||
| @@ -95,7 +98,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
| 95 | 98 | ||
| 96 | if (unlikely(qdio_err)) { | 99 | if (unlikely(qdio_err)) { |
| 97 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); | 100 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); |
| 98 | zfcp_qdio_handler_error(qdio, "qdires1"); | 101 | zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); |
| 99 | return; | 102 | return; |
| 100 | } | 103 | } |
| 101 | 104 | ||
| @@ -361,6 +364,9 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) | |||
| 361 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) | 364 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) |
| 362 | return -EIO; | 365 | return -EIO; |
| 363 | 366 | ||
| 367 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED, | ||
| 368 | &qdio->adapter->status); | ||
| 369 | |||
| 364 | zfcp_qdio_setup_init_data(&init_data, qdio); | 370 | zfcp_qdio_setup_init_data(&init_data, qdio); |
| 365 | 371 | ||
| 366 | if (qdio_establish(&init_data)) | 372 | if (qdio_establish(&init_data)) |
| @@ -440,3 +446,26 @@ int zfcp_qdio_setup(struct zfcp_adapter *adapter) | |||
| 440 | return 0; | 446 | return 0; |
| 441 | } | 447 | } |
| 442 | 448 | ||
| 449 | /** | ||
| 450 | * zfcp_qdio_siosl - Trigger logging in FCP channel | ||
| 451 | * @adapter: The zfcp_adapter where to trigger logging | ||
| 452 | * | ||
| 453 | * Call the cio siosl function to trigger hardware logging. This | ||
| 454 | * wrapper function sets a flag to ensure hardware logging is only | ||
| 455 | * triggered once before going through qdio shutdown. | ||
| 456 | * | ||
| 457 | * The triggers are always run from qdio tasklet context, so no | ||
| 458 | * additional synchronization is necessary. | ||
| 459 | */ | ||
| 460 | void zfcp_qdio_siosl(struct zfcp_adapter *adapter) | ||
| 461 | { | ||
| 462 | int rc; | ||
| 463 | |||
| 464 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_SIOSL_ISSUED) | ||
| 465 | return; | ||
| 466 | |||
| 467 | rc = ccw_device_siosl(adapter->ccw_device); | ||
| 468 | if (!rc) | ||
| 469 | atomic_set_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED, | ||
| 470 | &adapter->status); | ||
| 471 | } | ||
