aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2010-07-16 09:37:43 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:48:58 -0400
commit339f4f4eab80caa6cf0d39fb057ad6ddb84ba91e (patch)
tree495dc5a18c128d3e802a8b1914f978bf4262ac3d /drivers/s390
parentef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4 (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')
-rw-r--r--drivers/s390/scsi/zfcp_def.h1
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c7
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c35
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 *);
153extern int zfcp_qdio_open(struct zfcp_qdio *); 153extern int zfcp_qdio_open(struct zfcp_qdio *);
154extern void zfcp_qdio_close(struct zfcp_qdio *); 154extern void zfcp_qdio_close(struct zfcp_qdio *);
155extern void zfcp_qdio_siosl(struct zfcp_adapter *);
155 156
156/* zfcp_scsi.c */ 157/* zfcp_scsi.c */
157extern struct zfcp_data zfcp_data; 158extern 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 @@
21static void zfcp_fsf_request_timeout_handler(unsigned long data) 21static 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
33static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id) 33static 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 */
460void 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}