aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
authorStefan Weinhuber <wein@de.ibm.com>2006-02-03 06:03:49 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-03 11:32:01 -0500
commit12c3a54848a6eba2b38cd92ba5925433d223332b (patch)
tree79f06b7bfc761610d38a2bd27774d691e45ca55f /drivers/s390/block/dasd.c
parentd237bf49261ed812a17f7123fea9b80ef673ca0f (diff)
[PATCH] s390: dasd extended error reporting module
The DASD extended error reporting is a facility that allows to get detailed information about certain problems in the DASD I/O. This information can be used to implement fail-over applications that can recover these problems. Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index abdf1ee633e7..08c88fcd8963 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/buffer_head.h> 19#include <linux/buffer_head.h>
20#include <linux/hdreg.h> 20#include <linux/hdreg.h>
21#include <linux/notifier.h>
21 22
22#include <asm/ccwdev.h> 23#include <asm/ccwdev.h>
23#include <asm/ebcdic.h> 24#include <asm/ebcdic.h>
@@ -57,6 +58,7 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
57static void dasd_flush_ccw_queue(struct dasd_device *, int); 58static void dasd_flush_ccw_queue(struct dasd_device *, int);
58static void dasd_tasklet(struct dasd_device *); 59static void dasd_tasklet(struct dasd_device *);
59static void do_kick_device(void *data); 60static void do_kick_device(void *data);
61static void dasd_disable_eer(struct dasd_device *device);
60 62
61/* 63/*
62 * SECTION: Operations on the device structure. 64 * SECTION: Operations on the device structure.
@@ -151,6 +153,8 @@ dasd_state_new_to_known(struct dasd_device *device)
151static inline void 153static inline void
152dasd_state_known_to_new(struct dasd_device * device) 154dasd_state_known_to_new(struct dasd_device * device)
153{ 155{
156 /* disable extended error reporting for this device */
157 dasd_disable_eer(device);
154 /* Forget the discipline information. */ 158 /* Forget the discipline information. */
155 device->discipline = NULL; 159 device->discipline = NULL;
156 device->state = DASD_STATE_NEW; 160 device->state = DASD_STATE_NEW;
@@ -867,6 +871,9 @@ dasd_handle_state_change_pending(struct dasd_device *device)
867 struct dasd_ccw_req *cqr; 871 struct dasd_ccw_req *cqr;
868 struct list_head *l, *n; 872 struct list_head *l, *n;
869 873
874 /* first of all call extended error reporting */
875 dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL);
876
870 device->stopped &= ~DASD_STOPPED_PENDING; 877 device->stopped &= ~DASD_STOPPED_PENDING;
871 878
872 /* restart all 'running' IO on queue */ 879 /* restart all 'running' IO on queue */
@@ -1086,6 +1093,19 @@ restart:
1086 } 1093 }
1087 goto restart; 1094 goto restart;
1088 } 1095 }
1096
1097 /* first of all call extended error reporting */
1098 if (device->eer && cqr->status == DASD_CQR_FAILED) {
1099 dasd_write_eer_trigger(DASD_EER_FATALERROR,
1100 device, cqr);
1101
1102 /* restart request */
1103 cqr->status = DASD_CQR_QUEUED;
1104 cqr->retries = 255;
1105 device->stopped |= DASD_STOPPED_QUIESCE;
1106 goto restart;
1107 }
1108
1089 /* Process finished ERP request. */ 1109 /* Process finished ERP request. */
1090 if (cqr->refers) { 1110 if (cqr->refers) {
1091 __dasd_process_erp(device, cqr); 1111 __dasd_process_erp(device, cqr);
@@ -1223,7 +1243,8 @@ __dasd_start_head(struct dasd_device * device)
1223 cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); 1243 cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
1224 /* check FAILFAST */ 1244 /* check FAILFAST */
1225 if (device->stopped & ~DASD_STOPPED_PENDING && 1245 if (device->stopped & ~DASD_STOPPED_PENDING &&
1226 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { 1246 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
1247 (!device->eer)) {
1227 cqr->status = DASD_CQR_FAILED; 1248 cqr->status = DASD_CQR_FAILED;
1228 dasd_schedule_bh(device); 1249 dasd_schedule_bh(device);
1229 } 1250 }
@@ -1965,6 +1986,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
1965 switch (event) { 1986 switch (event) {
1966 case CIO_GONE: 1987 case CIO_GONE:
1967 case CIO_NO_PATH: 1988 case CIO_NO_PATH:
1989 /* first of all call extended error reporting */
1990 dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL);
1991
1968 if (device->state < DASD_STATE_BASIC) 1992 if (device->state < DASD_STATE_BASIC)
1969 break; 1993 break;
1970 /* Device is active. We want to keep it. */ 1994 /* Device is active. We want to keep it. */
@@ -2022,6 +2046,51 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
2022 put_driver(drv); 2046 put_driver(drv);
2023} 2047}
2024 2048
2049/*
2050 * notifications for extended error reports
2051 */
2052static struct notifier_block *dasd_eer_chain;
2053
2054int
2055dasd_register_eer_notifier(struct notifier_block *nb)
2056{
2057 return notifier_chain_register(&dasd_eer_chain, nb);
2058}
2059
2060int
2061dasd_unregister_eer_notifier(struct notifier_block *nb)
2062{
2063 return notifier_chain_unregister(&dasd_eer_chain, nb);
2064}
2065
2066/*
2067 * Notify the registered error reporting module of a problem
2068 */
2069void
2070dasd_write_eer_trigger(unsigned int id, struct dasd_device *device,
2071 struct dasd_ccw_req *cqr)
2072{
2073 if (device->eer) {
2074 struct dasd_eer_trigger temp;
2075 temp.id = id;
2076 temp.device = device;
2077 temp.cqr = cqr;
2078 notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER,
2079 (void *)&temp);
2080 }
2081}
2082
2083/*
2084 * Tell the registered error reporting module to disable error reporting for
2085 * a given device and to cleanup any private data structures on that device.
2086 */
2087static void
2088dasd_disable_eer(struct dasd_device *device)
2089{
2090 notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device);
2091}
2092
2093
2025static int __init 2094static int __init
2026dasd_init(void) 2095dasd_init(void)
2027{ 2096{
@@ -2103,6 +2172,11 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online);
2103EXPORT_SYMBOL_GPL(dasd_generic_set_offline); 2172EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
2104EXPORT_SYMBOL_GPL(dasd_generic_auto_online); 2173EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
2105 2174
2175EXPORT_SYMBOL(dasd_register_eer_notifier);
2176EXPORT_SYMBOL(dasd_unregister_eer_notifier);
2177EXPORT_SYMBOL(dasd_write_eer_trigger);
2178
2179
2106/* 2180/*
2107 * Overrides for Emacs so that we follow Linus's tabbing style. 2181 * Overrides for Emacs so that we follow Linus's tabbing style.
2108 * Emacs will notice this stuff at the end of the file and automatically 2182 * Emacs will notice this stuff at the end of the file and automatically