diff options
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r-- | drivers/s390/block/dasd.c | 97 |
1 files changed, 21 insertions, 76 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 08c88fcd8963..af1d5b404cee 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -18,7 +18,6 @@ | |||
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> | ||
22 | 21 | ||
23 | #include <asm/ccwdev.h> | 22 | #include <asm/ccwdev.h> |
24 | #include <asm/ebcdic.h> | 23 | #include <asm/ebcdic.h> |
@@ -58,7 +57,6 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); | |||
58 | static void dasd_flush_ccw_queue(struct dasd_device *, int); | 57 | static void dasd_flush_ccw_queue(struct dasd_device *, int); |
59 | static void dasd_tasklet(struct dasd_device *); | 58 | static void dasd_tasklet(struct dasd_device *); |
60 | static void do_kick_device(void *data); | 59 | static void do_kick_device(void *data); |
61 | static void dasd_disable_eer(struct dasd_device *device); | ||
62 | 60 | ||
63 | /* | 61 | /* |
64 | * SECTION: Operations on the device structure. | 62 | * SECTION: Operations on the device structure. |
@@ -153,10 +151,13 @@ dasd_state_new_to_known(struct dasd_device *device) | |||
153 | static inline void | 151 | static inline void |
154 | dasd_state_known_to_new(struct dasd_device * device) | 152 | dasd_state_known_to_new(struct dasd_device * device) |
155 | { | 153 | { |
156 | /* disable extended error reporting for this device */ | ||
157 | dasd_disable_eer(device); | ||
158 | /* Forget the discipline information. */ | 154 | /* Forget the discipline information. */ |
155 | if (device->discipline) | ||
156 | module_put(device->discipline->owner); | ||
159 | device->discipline = NULL; | 157 | device->discipline = NULL; |
158 | if (device->base_discipline) | ||
159 | module_put(device->base_discipline->owner); | ||
160 | device->base_discipline = NULL; | ||
160 | device->state = DASD_STATE_NEW; | 161 | device->state = DASD_STATE_NEW; |
161 | 162 | ||
162 | dasd_free_queue(device); | 163 | dasd_free_queue(device); |
@@ -871,9 +872,6 @@ dasd_handle_state_change_pending(struct dasd_device *device) | |||
871 | struct dasd_ccw_req *cqr; | 872 | struct dasd_ccw_req *cqr; |
872 | struct list_head *l, *n; | 873 | struct list_head *l, *n; |
873 | 874 | ||
874 | /* first of all call extended error reporting */ | ||
875 | dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL); | ||
876 | |||
877 | device->stopped &= ~DASD_STOPPED_PENDING; | 875 | device->stopped &= ~DASD_STOPPED_PENDING; |
878 | 876 | ||
879 | /* restart all 'running' IO on queue */ | 877 | /* restart all 'running' IO on queue */ |
@@ -1093,19 +1091,6 @@ restart: | |||
1093 | } | 1091 | } |
1094 | goto restart; | 1092 | goto restart; |
1095 | } | 1093 | } |
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 | |||
1109 | /* Process finished ERP request. */ | 1094 | /* Process finished ERP request. */ |
1110 | if (cqr->refers) { | 1095 | if (cqr->refers) { |
1111 | __dasd_process_erp(device, cqr); | 1096 | __dasd_process_erp(device, cqr); |
@@ -1243,8 +1228,7 @@ __dasd_start_head(struct dasd_device * device) | |||
1243 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); | 1228 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); |
1244 | /* check FAILFAST */ | 1229 | /* check FAILFAST */ |
1245 | if (device->stopped & ~DASD_STOPPED_PENDING && | 1230 | if (device->stopped & ~DASD_STOPPED_PENDING && |
1246 | test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && | 1231 | test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { |
1247 | (!device->eer)) { | ||
1248 | cqr->status = DASD_CQR_FAILED; | 1232 | cqr->status = DASD_CQR_FAILED; |
1249 | dasd_schedule_bh(device); | 1233 | dasd_schedule_bh(device); |
1250 | } | 1234 | } |
@@ -1880,9 +1864,10 @@ dasd_generic_remove (struct ccw_device *cdev) | |||
1880 | */ | 1864 | */ |
1881 | int | 1865 | int |
1882 | dasd_generic_set_online (struct ccw_device *cdev, | 1866 | dasd_generic_set_online (struct ccw_device *cdev, |
1883 | struct dasd_discipline *discipline) | 1867 | struct dasd_discipline *base_discipline) |
1884 | 1868 | ||
1885 | { | 1869 | { |
1870 | struct dasd_discipline *discipline; | ||
1886 | struct dasd_device *device; | 1871 | struct dasd_device *device; |
1887 | int rc; | 1872 | int rc; |
1888 | 1873 | ||
@@ -1890,6 +1875,7 @@ dasd_generic_set_online (struct ccw_device *cdev, | |||
1890 | if (IS_ERR(device)) | 1875 | if (IS_ERR(device)) |
1891 | return PTR_ERR(device); | 1876 | return PTR_ERR(device); |
1892 | 1877 | ||
1878 | discipline = base_discipline; | ||
1893 | if (device->features & DASD_FEATURE_USEDIAG) { | 1879 | if (device->features & DASD_FEATURE_USEDIAG) { |
1894 | if (!dasd_diag_discipline_pointer) { | 1880 | if (!dasd_diag_discipline_pointer) { |
1895 | printk (KERN_WARNING | 1881 | printk (KERN_WARNING |
@@ -1901,6 +1887,16 @@ dasd_generic_set_online (struct ccw_device *cdev, | |||
1901 | } | 1887 | } |
1902 | discipline = dasd_diag_discipline_pointer; | 1888 | discipline = dasd_diag_discipline_pointer; |
1903 | } | 1889 | } |
1890 | if (!try_module_get(base_discipline->owner)) { | ||
1891 | dasd_delete_device(device); | ||
1892 | return -EINVAL; | ||
1893 | } | ||
1894 | if (!try_module_get(discipline->owner)) { | ||
1895 | module_put(base_discipline->owner); | ||
1896 | dasd_delete_device(device); | ||
1897 | return -EINVAL; | ||
1898 | } | ||
1899 | device->base_discipline = base_discipline; | ||
1904 | device->discipline = discipline; | 1900 | device->discipline = discipline; |
1905 | 1901 | ||
1906 | rc = discipline->check_device(device); | 1902 | rc = discipline->check_device(device); |
@@ -1909,6 +1905,8 @@ dasd_generic_set_online (struct ccw_device *cdev, | |||
1909 | "dasd_generic couldn't online device %s " | 1905 | "dasd_generic couldn't online device %s " |
1910 | "with discipline %s rc=%i\n", | 1906 | "with discipline %s rc=%i\n", |
1911 | cdev->dev.bus_id, discipline->name, rc); | 1907 | cdev->dev.bus_id, discipline->name, rc); |
1908 | module_put(discipline->owner); | ||
1909 | module_put(base_discipline->owner); | ||
1912 | dasd_delete_device(device); | 1910 | dasd_delete_device(device); |
1913 | return rc; | 1911 | return rc; |
1914 | } | 1912 | } |
@@ -1986,9 +1984,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) | |||
1986 | switch (event) { | 1984 | switch (event) { |
1987 | case CIO_GONE: | 1985 | case CIO_GONE: |
1988 | case CIO_NO_PATH: | 1986 | case CIO_NO_PATH: |
1989 | /* first of all call extended error reporting */ | ||
1990 | dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL); | ||
1991 | |||
1992 | if (device->state < DASD_STATE_BASIC) | 1987 | if (device->state < DASD_STATE_BASIC) |
1993 | break; | 1988 | break; |
1994 | /* Device is active. We want to keep it. */ | 1989 | /* Device is active. We want to keep it. */ |
@@ -2046,51 +2041,6 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) | |||
2046 | put_driver(drv); | 2041 | put_driver(drv); |
2047 | } | 2042 | } |
2048 | 2043 | ||
2049 | /* | ||
2050 | * notifications for extended error reports | ||
2051 | */ | ||
2052 | static struct notifier_block *dasd_eer_chain; | ||
2053 | |||
2054 | int | ||
2055 | dasd_register_eer_notifier(struct notifier_block *nb) | ||
2056 | { | ||
2057 | return notifier_chain_register(&dasd_eer_chain, nb); | ||
2058 | } | ||
2059 | |||
2060 | int | ||
2061 | dasd_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 | */ | ||
2069 | void | ||
2070 | dasd_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 | */ | ||
2087 | static void | ||
2088 | dasd_disable_eer(struct dasd_device *device) | ||
2089 | { | ||
2090 | notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device); | ||
2091 | } | ||
2092 | |||
2093 | |||
2094 | static int __init | 2044 | static int __init |
2095 | dasd_init(void) | 2045 | dasd_init(void) |
2096 | { | 2046 | { |
@@ -2172,11 +2122,6 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online); | |||
2172 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); | 2122 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); |
2173 | EXPORT_SYMBOL_GPL(dasd_generic_auto_online); | 2123 | EXPORT_SYMBOL_GPL(dasd_generic_auto_online); |
2174 | 2124 | ||
2175 | EXPORT_SYMBOL(dasd_register_eer_notifier); | ||
2176 | EXPORT_SYMBOL(dasd_unregister_eer_notifier); | ||
2177 | EXPORT_SYMBOL(dasd_write_eer_trigger); | ||
2178 | |||
2179 | |||
2180 | /* | 2125 | /* |
2181 | * Overrides for Emacs so that we follow Linus's tabbing style. | 2126 | * Overrides for Emacs so that we follow Linus's tabbing style. |
2182 | * Emacs will notice this stuff at the end of the file and automatically | 2127 | * Emacs will notice this stuff at the end of the file and automatically |