diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2010-07-16 15:37:43 +0200 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 09:48:58 -0500 |
commit | 339f4f4eab80caa6cf0d39fb057ad6ddb84ba91e (patch) | |
tree | 495dc5a18c128d3e802a8b1914f978bf4262ac3d /drivers/s390/scsi/zfcp_qdio.c | |
parent | ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4 (diff) |
[SCSI] zfcp: Trigger logging in the FCP channel on qdio error conditions
Exploit the cio siosl function to trigger logging in the FCP channel
on qdio error conditions. Add a helper function in zfcp_qdio to ensure
that tracing is only triggered once before calling qdio_shutdown.
Trigger in zfcp for hardware logs are:
- timeout for FSF requests to the FCP channel
- "no recommendation" status from FCP channel
- invalid FSF protocol status
- stalled outbound queue
- unknown request id on inbound queue
- QDIO_ERROR_SLSB_STATE
All of the above triggers run from the Linux qdio softirq context, so
no additional synchronization is necessary for the handling of the
ZFCP_STATUS_ADAPTER_SIOSL_ISSUED flag.
Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 35 |
1 files changed, 32 insertions, 3 deletions
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) return 0; } -static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id) +static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id, + unsigned int qdio_err) { struct zfcp_adapter *adapter = qdio->adapter; dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); + if (qdio_err & QDIO_ERROR_SLSB_STATE) + zfcp_qdio_siosl(adapter); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 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, if (unlikely(qdio_err)) { zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); - zfcp_qdio_handler_error(qdio, "qdireq1"); + zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err); return; } @@ -95,7 +98,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, if (unlikely(qdio_err)) { zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); - zfcp_qdio_handler_error(qdio, "qdires1"); + zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); return; } @@ -361,6 +364,9 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) return -EIO; + atomic_clear_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED, + &qdio->adapter->status); + zfcp_qdio_setup_init_data(&init_data, qdio); if (qdio_establish(&init_data)) @@ -440,3 +446,26 @@ int zfcp_qdio_setup(struct zfcp_adapter *adapter) return 0; } +/** + * zfcp_qdio_siosl - Trigger logging in FCP channel + * @adapter: The zfcp_adapter where to trigger logging + * + * Call the cio siosl function to trigger hardware logging. This + * wrapper function sets a flag to ensure hardware logging is only + * triggered once before going through qdio shutdown. + * + * The triggers are always run from qdio tasklet context, so no + * additional synchronization is necessary. + */ +void zfcp_qdio_siosl(struct zfcp_adapter *adapter) +{ + int rc; + + if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_SIOSL_ISSUED) + return; + + rc = ccw_device_siosl(adapter->ccw_device); + if (!rc) + atomic_set_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED, + &adapter->status); +} |