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 |
