diff options
author | Horst Hummel <horst.hummel@de.ibm.com> | 2006-06-29 09:08:18 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-06-29 09:08:18 -0400 |
commit | 405455734e1cdec09c37233216f9240cb1a058e5 (patch) | |
tree | 36e88909f646b635117041b19a851031fc8ffb41 | |
parent | 8f27766a883149926e7c1f69d9f1d8f68efcd65f (diff) |
[S390] add PAV support to the dasd driver.
Add support for parallel-access-volumes to the dasd driver. This
allows concurrent access to dasd devices with multiple channel
programs.
Signed-off-by: Horst Hummel <horst.hummel@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/block/dasd.c | 51 | ||||
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 80 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 140 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.h | 16 | ||||
-rw-r--r-- | drivers/s390/block/dasd_fba.c | 20 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 2 | ||||
-rw-r--r-- | include/asm-s390/dasd.h | 8 |
7 files changed, 227 insertions, 90 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 7e9978ad1445..bafcd2f20ae2 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1855,15 +1855,34 @@ dasd_generic_probe (struct ccw_device *cdev, | |||
1855 | { | 1855 | { |
1856 | int ret; | 1856 | int ret; |
1857 | 1857 | ||
1858 | ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); | ||
1859 | if (ret) { | ||
1860 | printk(KERN_WARNING | ||
1861 | "dasd_generic_probe: could not set ccw-device options " | ||
1862 | "for %s\n", cdev->dev.bus_id); | ||
1863 | return ret; | ||
1864 | } | ||
1858 | ret = dasd_add_sysfs_files(cdev); | 1865 | ret = dasd_add_sysfs_files(cdev); |
1859 | if (ret) { | 1866 | if (ret) { |
1860 | printk(KERN_WARNING | 1867 | printk(KERN_WARNING |
1861 | "dasd_generic_probe: could not add sysfs entries " | 1868 | "dasd_generic_probe: could not add sysfs entries " |
1862 | "for %s\n", cdev->dev.bus_id); | 1869 | "for %s\n", cdev->dev.bus_id); |
1863 | } else { | 1870 | return ret; |
1864 | cdev->handler = &dasd_int_handler; | ||
1865 | } | 1871 | } |
1872 | cdev->handler = &dasd_int_handler; | ||
1866 | 1873 | ||
1874 | /* | ||
1875 | * Automatically online either all dasd devices (dasd_autodetect) | ||
1876 | * or all devices specified with dasd= parameters during | ||
1877 | * initial probe. | ||
1878 | */ | ||
1879 | if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || | ||
1880 | (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0)) | ||
1881 | ret = ccw_device_set_online(cdev); | ||
1882 | if (ret) | ||
1883 | printk(KERN_WARNING | ||
1884 | "dasd_generic_probe: could not initially online " | ||
1885 | "ccw-device %s\n", cdev->dev.bus_id); | ||
1867 | return ret; | 1886 | return ret; |
1868 | } | 1887 | } |
1869 | 1888 | ||
@@ -1911,6 +1930,8 @@ dasd_generic_set_online (struct ccw_device *cdev, | |||
1911 | struct dasd_device *device; | 1930 | struct dasd_device *device; |
1912 | int rc; | 1931 | int rc; |
1913 | 1932 | ||
1933 | /* first online clears initial online feature flag */ | ||
1934 | dasd_set_feature(cdev, DASD_FEATURE_INITIAL_ONLINE, 0); | ||
1914 | device = dasd_create_device(cdev); | 1935 | device = dasd_create_device(cdev); |
1915 | if (IS_ERR(device)) | 1936 | if (IS_ERR(device)) |
1916 | return PTR_ERR(device); | 1937 | return PTR_ERR(device); |
@@ -2065,31 +2086,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) | |||
2065 | return ret; | 2086 | return ret; |
2066 | } | 2087 | } |
2067 | 2088 | ||
2068 | /* | ||
2069 | * Automatically online either all dasd devices (dasd_autodetect) or | ||
2070 | * all devices specified with dasd= parameters. | ||
2071 | */ | ||
2072 | static int | ||
2073 | __dasd_auto_online(struct device *dev, void *data) | ||
2074 | { | ||
2075 | struct ccw_device *cdev; | ||
2076 | |||
2077 | cdev = to_ccwdev(dev); | ||
2078 | if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0) | ||
2079 | ccw_device_set_online(cdev); | ||
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | void | ||
2084 | dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) | ||
2085 | { | ||
2086 | struct device_driver *drv; | ||
2087 | |||
2088 | drv = get_driver(&dasd_discipline_driver->driver); | ||
2089 | driver_for_each_device(drv, NULL, NULL, __dasd_auto_online); | ||
2090 | put_driver(drv); | ||
2091 | } | ||
2092 | |||
2093 | 2089 | ||
2094 | static int __init | 2090 | static int __init |
2095 | dasd_init(void) | 2091 | dasd_init(void) |
@@ -2170,5 +2166,4 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove); | |||
2170 | EXPORT_SYMBOL_GPL(dasd_generic_notify); | 2166 | EXPORT_SYMBOL_GPL(dasd_generic_notify); |
2171 | EXPORT_SYMBOL_GPL(dasd_generic_set_online); | 2167 | EXPORT_SYMBOL_GPL(dasd_generic_set_online); |
2172 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); | 2168 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); |
2173 | EXPORT_SYMBOL_GPL(dasd_generic_auto_online); | ||
2174 | 2169 | ||
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 672e50314b12..9e9ae7179602 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "dasd_int.h" | 27 | #include "dasd_int.h" |
28 | 28 | ||
29 | kmem_cache_t *dasd_page_cache; | 29 | kmem_cache_t *dasd_page_cache; |
30 | EXPORT_SYMBOL(dasd_page_cache); | 30 | EXPORT_SYMBOL_GPL(dasd_page_cache); |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * dasd_devmap_t is used to store the features and the relation | 33 | * dasd_devmap_t is used to store the features and the relation |
@@ -49,6 +49,20 @@ struct dasd_devmap { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * dasd_servermap is used to store the server_id of all storage servers | ||
53 | * accessed by DASD device driver. | ||
54 | */ | ||
55 | struct dasd_servermap { | ||
56 | struct list_head list; | ||
57 | struct server_id { | ||
58 | char vendor[4]; | ||
59 | char serial[15]; | ||
60 | } sid; | ||
61 | }; | ||
62 | |||
63 | static struct list_head dasd_serverlist; | ||
64 | |||
65 | /* | ||
52 | * Parameter parsing functions for dasd= parameter. The syntax is: | 66 | * Parameter parsing functions for dasd= parameter. The syntax is: |
53 | * <devno> : (0x)?[0-9a-fA-F]+ | 67 | * <devno> : (0x)?[0-9a-fA-F]+ |
54 | * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+ | 68 | * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+ |
@@ -64,6 +78,8 @@ struct dasd_devmap { | |||
64 | 78 | ||
65 | int dasd_probeonly = 0; /* is true, when probeonly mode is active */ | 79 | int dasd_probeonly = 0; /* is true, when probeonly mode is active */ |
66 | int dasd_autodetect = 0; /* is true, when autodetection is active */ | 80 | int dasd_autodetect = 0; /* is true, when autodetection is active */ |
81 | int dasd_nopav = 0; /* is true, when PAV is disabled */ | ||
82 | EXPORT_SYMBOL_GPL(dasd_nopav); | ||
67 | 83 | ||
68 | /* | 84 | /* |
69 | * char *dasd[] is intended to hold the ranges supplied by the dasd= statement | 85 | * char *dasd[] is intended to hold the ranges supplied by the dasd= statement |
@@ -228,19 +244,24 @@ dasd_parse_keyword( char *parsestring ) { | |||
228 | length = strlen(parsestring); | 244 | length = strlen(parsestring); |
229 | residual_str = parsestring + length; | 245 | residual_str = parsestring + length; |
230 | } | 246 | } |
231 | if (strncmp ("autodetect", parsestring, length) == 0) { | 247 | if (strncmp("autodetect", parsestring, length) == 0) { |
232 | dasd_autodetect = 1; | 248 | dasd_autodetect = 1; |
233 | MESSAGE (KERN_INFO, "%s", | 249 | MESSAGE (KERN_INFO, "%s", |
234 | "turning to autodetection mode"); | 250 | "turning to autodetection mode"); |
235 | return residual_str; | 251 | return residual_str; |
236 | } | 252 | } |
237 | if (strncmp ("probeonly", parsestring, length) == 0) { | 253 | if (strncmp("probeonly", parsestring, length) == 0) { |
238 | dasd_probeonly = 1; | 254 | dasd_probeonly = 1; |
239 | MESSAGE(KERN_INFO, "%s", | 255 | MESSAGE(KERN_INFO, "%s", |
240 | "turning to probeonly mode"); | 256 | "turning to probeonly mode"); |
241 | return residual_str; | 257 | return residual_str; |
242 | } | 258 | } |
243 | if (strncmp ("fixedbuffers", parsestring, length) == 0) { | 259 | if (strncmp("nopav", parsestring, length) == 0) { |
260 | dasd_nopav = 1; | ||
261 | MESSAGE(KERN_INFO, "%s", "disable PAV mode"); | ||
262 | return residual_str; | ||
263 | } | ||
264 | if (strncmp("fixedbuffers", parsestring, length) == 0) { | ||
244 | if (dasd_page_cache) | 265 | if (dasd_page_cache) |
245 | return residual_str; | 266 | return residual_str; |
246 | dasd_page_cache = | 267 | dasd_page_cache = |
@@ -294,6 +315,8 @@ dasd_parse_range( char *parsestring ) { | |||
294 | features = dasd_feature_list(str, &str); | 315 | features = dasd_feature_list(str, &str); |
295 | if (features < 0) | 316 | if (features < 0) |
296 | return ERR_PTR(-EINVAL); | 317 | return ERR_PTR(-EINVAL); |
318 | /* each device in dasd= parameter should be set initially online */ | ||
319 | features |= DASD_FEATURE_INITIAL_ONLINE; | ||
297 | while (from <= to) { | 320 | while (from <= to) { |
298 | sprintf(bus_id, "%01x.%01x.%04x", | 321 | sprintf(bus_id, "%01x.%01x.%04x", |
299 | from_id0, from_id1, from++); | 322 | from_id0, from_id1, from++); |
@@ -836,6 +859,38 @@ static struct attribute_group dasd_attr_group = { | |||
836 | .attrs = dasd_attrs, | 859 | .attrs = dasd_attrs, |
837 | }; | 860 | }; |
838 | 861 | ||
862 | /* | ||
863 | * Check if the related storage server is already contained in the | ||
864 | * dasd_serverlist. If server is not contained, create new entry. | ||
865 | * Return 0 if server was already in serverlist, | ||
866 | * 1 if the server was added successfully | ||
867 | * <0 in case of error. | ||
868 | */ | ||
869 | static int | ||
870 | dasd_add_server(struct dasd_uid *uid) | ||
871 | { | ||
872 | struct dasd_servermap *new, *tmp; | ||
873 | |||
874 | /* check if server is already contained */ | ||
875 | list_for_each_entry(tmp, &dasd_serverlist, list) | ||
876 | // normale cmp? | ||
877 | if (strncmp(tmp->sid.vendor, uid->vendor, | ||
878 | sizeof(tmp->sid.vendor)) == 0 | ||
879 | && strncmp(tmp->sid.serial, uid->serial, | ||
880 | sizeof(tmp->sid.serial)) == 0) | ||
881 | return 0; | ||
882 | |||
883 | new = (struct dasd_servermap *) | ||
884 | kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); | ||
885 | if (!new) | ||
886 | return -ENOMEM; | ||
887 | |||
888 | strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor)); | ||
889 | strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial)); | ||
890 | list_add(&new->list, &dasd_serverlist); | ||
891 | return 1; | ||
892 | } | ||
893 | |||
839 | 894 | ||
840 | /* | 895 | /* |
841 | * Return copy of the device unique identifier. | 896 | * Return copy of the device unique identifier. |
@@ -856,21 +911,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | |||
856 | 911 | ||
857 | /* | 912 | /* |
858 | * Register the given device unique identifier into devmap struct. | 913 | * Register the given device unique identifier into devmap struct. |
914 | * Return 0 if server was already in serverlist, | ||
915 | * 1 if the server was added successful | ||
916 | * <0 in case of error. | ||
859 | */ | 917 | */ |
860 | int | 918 | int |
861 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | 919 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) |
862 | { | 920 | { |
863 | struct dasd_devmap *devmap; | 921 | struct dasd_devmap *devmap; |
922 | int rc; | ||
864 | 923 | ||
865 | devmap = dasd_find_busid(cdev->dev.bus_id); | 924 | devmap = dasd_find_busid(cdev->dev.bus_id); |
866 | if (IS_ERR(devmap)) | 925 | if (IS_ERR(devmap)) |
867 | return PTR_ERR(devmap); | 926 | return PTR_ERR(devmap); |
868 | spin_lock(&dasd_devmap_lock); | 927 | spin_lock(&dasd_devmap_lock); |
869 | devmap->uid = *uid; | 928 | devmap->uid = *uid; |
929 | rc = dasd_add_server(uid); | ||
870 | spin_unlock(&dasd_devmap_lock); | 930 | spin_unlock(&dasd_devmap_lock); |
871 | return 0; | 931 | return rc; |
872 | } | 932 | } |
873 | EXPORT_SYMBOL(dasd_set_uid); | 933 | EXPORT_SYMBOL_GPL(dasd_set_uid); |
874 | 934 | ||
875 | /* | 935 | /* |
876 | * Return value of the specified feature. | 936 | * Return value of the specified feature. |
@@ -882,7 +942,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature) | |||
882 | 942 | ||
883 | devmap = dasd_find_busid(cdev->dev.bus_id); | 943 | devmap = dasd_find_busid(cdev->dev.bus_id); |
884 | if (IS_ERR(devmap)) | 944 | if (IS_ERR(devmap)) |
885 | return (int) PTR_ERR(devmap); | 945 | return PTR_ERR(devmap); |
886 | 946 | ||
887 | return ((devmap->features & feature) != 0); | 947 | return ((devmap->features & feature) != 0); |
888 | } | 948 | } |
@@ -898,7 +958,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) | |||
898 | 958 | ||
899 | devmap = dasd_find_busid(cdev->dev.bus_id); | 959 | devmap = dasd_find_busid(cdev->dev.bus_id); |
900 | if (IS_ERR(devmap)) | 960 | if (IS_ERR(devmap)) |
901 | return (int) PTR_ERR(devmap); | 961 | return PTR_ERR(devmap); |
902 | 962 | ||
903 | spin_lock(&dasd_devmap_lock); | 963 | spin_lock(&dasd_devmap_lock); |
904 | if (flag) | 964 | if (flag) |
@@ -934,8 +994,10 @@ dasd_devmap_init(void) | |||
934 | dasd_max_devindex = 0; | 994 | dasd_max_devindex = 0; |
935 | for (i = 0; i < 256; i++) | 995 | for (i = 0; i < 256; i++) |
936 | INIT_LIST_HEAD(&dasd_hashlists[i]); | 996 | INIT_LIST_HEAD(&dasd_hashlists[i]); |
937 | return 0; | ||
938 | 997 | ||
998 | /* Initialize servermap structure. */ | ||
999 | INIT_LIST_HEAD(&dasd_serverlist); | ||
1000 | return 0; | ||
939 | } | 1001 | } |
940 | 1002 | ||
941 | void | 1003 | void |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 12257776e79b..0dfab30e8089 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/todclk.h> | 25 | #include <asm/todclk.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/cio.h> | ||
27 | #include <asm/ccwdev.h> | 28 | #include <asm/ccwdev.h> |
28 | 29 | ||
29 | #include "dasd_int.h" | 30 | #include "dasd_int.h" |
@@ -89,17 +90,22 @@ dasd_eckd_probe (struct ccw_device *cdev) | |||
89 | { | 90 | { |
90 | int ret; | 91 | int ret; |
91 | 92 | ||
92 | ret = dasd_generic_probe (cdev, &dasd_eckd_discipline); | 93 | /* set ECKD specific ccw-device options */ |
93 | if (ret) | 94 | ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); |
95 | if (ret) { | ||
96 | printk(KERN_WARNING | ||
97 | "dasd_eckd_probe: could not set ccw-device options " | ||
98 | "for %s\n", cdev->dev.bus_id); | ||
94 | return ret; | 99 | return ret; |
95 | ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE); | 100 | } |
96 | return 0; | 101 | ret = dasd_generic_probe(cdev, &dasd_eckd_discipline); |
102 | return ret; | ||
97 | } | 103 | } |
98 | 104 | ||
99 | static int | 105 | static int |
100 | dasd_eckd_set_online(struct ccw_device *cdev) | 106 | dasd_eckd_set_online(struct ccw_device *cdev) |
101 | { | 107 | { |
102 | return dasd_generic_set_online (cdev, &dasd_eckd_discipline); | 108 | return dasd_generic_set_online(cdev, &dasd_eckd_discipline); |
103 | } | 109 | } |
104 | 110 | ||
105 | static struct ccw_driver dasd_eckd_driver = { | 111 | static struct ccw_driver dasd_eckd_driver = { |
@@ -541,6 +547,86 @@ dasd_eckd_read_conf(struct dasd_device *device) | |||
541 | } | 547 | } |
542 | 548 | ||
543 | /* | 549 | /* |
550 | * Build CP for Perform Subsystem Function - SSC. | ||
551 | */ | ||
552 | struct dasd_ccw_req * | ||
553 | dasd_eckd_build_psf_ssc(struct dasd_device *device) | ||
554 | { | ||
555 | struct dasd_ccw_req *cqr; | ||
556 | struct dasd_psf_ssc_data *psf_ssc_data; | ||
557 | struct ccw1 *ccw; | ||
558 | |||
559 | cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ , | ||
560 | sizeof(struct dasd_psf_ssc_data), | ||
561 | device); | ||
562 | |||
563 | if (IS_ERR(cqr)) { | ||
564 | DEV_MESSAGE(KERN_WARNING, device, "%s", | ||
565 | "Could not allocate PSF-SSC request"); | ||
566 | return cqr; | ||
567 | } | ||
568 | psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data; | ||
569 | psf_ssc_data->order = PSF_ORDER_SSC; | ||
570 | psf_ssc_data->suborder = 0x08; | ||
571 | |||
572 | ccw = cqr->cpaddr; | ||
573 | ccw->cmd_code = DASD_ECKD_CCW_PSF; | ||
574 | ccw->cda = (__u32)(addr_t)psf_ssc_data; | ||
575 | ccw->count = 66; | ||
576 | |||
577 | cqr->device = device; | ||
578 | cqr->expires = 10*HZ; | ||
579 | cqr->buildclk = get_clock(); | ||
580 | cqr->status = DASD_CQR_FILLED; | ||
581 | return cqr; | ||
582 | } | ||
583 | |||
584 | /* | ||
585 | * Perform Subsystem Function. | ||
586 | * It is necessary to trigger CIO for channel revalidation since this | ||
587 | * call might change behaviour of DASD devices. | ||
588 | */ | ||
589 | static int | ||
590 | dasd_eckd_psf_ssc(struct dasd_device *device) | ||
591 | { | ||
592 | struct dasd_ccw_req *cqr; | ||
593 | int rc; | ||
594 | |||
595 | cqr = dasd_eckd_build_psf_ssc(device); | ||
596 | if (IS_ERR(cqr)) | ||
597 | return PTR_ERR(cqr); | ||
598 | |||
599 | rc = dasd_sleep_on(cqr); | ||
600 | if (!rc) | ||
601 | /* trigger CIO to reprobe devices */ | ||
602 | css_schedule_reprobe(); | ||
603 | dasd_sfree_request(cqr, cqr->device); | ||
604 | return rc; | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * Valide storage server of current device. | ||
609 | */ | ||
610 | static int | ||
611 | dasd_eckd_validate_server(struct dasd_device *device) | ||
612 | { | ||
613 | int rc; | ||
614 | |||
615 | /* Currently PAV is the only reason to 'validate' server on LPAR */ | ||
616 | if (dasd_nopav || MACHINE_IS_VM) | ||
617 | return 0; | ||
618 | |||
619 | rc = dasd_eckd_psf_ssc(device); | ||
620 | if (rc) | ||
621 | /* may be requested feature is not available on server, | ||
622 | * therefore just report error and go ahead */ | ||
623 | DEV_MESSAGE(KERN_INFO, device, | ||
624 | "Perform Subsystem Function returned rc=%d", rc); | ||
625 | /* RE-Read Configuration Data */ | ||
626 | return dasd_eckd_read_conf(device); | ||
627 | } | ||
628 | |||
629 | /* | ||
544 | * Check device characteristics. | 630 | * Check device characteristics. |
545 | * If the device is accessible using ECKD discipline, the device is enabled. | 631 | * If the device is accessible using ECKD discipline, the device is enabled. |
546 | */ | 632 | */ |
@@ -570,16 +656,29 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
570 | private->attrib.operation = DASD_NORMAL_CACHE; | 656 | private->attrib.operation = DASD_NORMAL_CACHE; |
571 | private->attrib.nr_cyl = 0; | 657 | private->attrib.nr_cyl = 0; |
572 | 658 | ||
659 | /* Read Configuration Data */ | ||
660 | rc = dasd_eckd_read_conf(device); | ||
661 | if (rc) | ||
662 | return rc; | ||
663 | |||
664 | /* Generate device unique id and register in devmap */ | ||
665 | rc = dasd_eckd_generate_uid(device, &uid); | ||
666 | if (rc) | ||
667 | return rc; | ||
668 | rc = dasd_set_uid(device->cdev, &uid); | ||
669 | if (rc == 1) /* new server found */ | ||
670 | rc = dasd_eckd_validate_server(device); | ||
671 | if (rc) | ||
672 | return rc; | ||
673 | |||
573 | /* Read Device Characteristics */ | 674 | /* Read Device Characteristics */ |
574 | rdc_data = (void *) &(private->rdc_data); | 675 | rdc_data = (void *) &(private->rdc_data); |
575 | memset(rdc_data, 0, sizeof(rdc_data)); | 676 | memset(rdc_data, 0, sizeof(rdc_data)); |
576 | rc = read_dev_chars(device->cdev, &rdc_data, 64); | 677 | rc = read_dev_chars(device->cdev, &rdc_data, 64); |
577 | if (rc) { | 678 | if (rc) |
578 | DEV_MESSAGE(KERN_WARNING, device, | 679 | DEV_MESSAGE(KERN_WARNING, device, |
579 | "Read device characteristics returned error %d", | 680 | "Read device characteristics returned " |
580 | rc); | 681 | "rc=%d", rc); |
581 | return rc; | ||
582 | } | ||
583 | 682 | ||
584 | DEV_MESSAGE(KERN_INFO, device, | 683 | DEV_MESSAGE(KERN_INFO, device, |
585 | "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", | 684 | "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", |
@@ -590,19 +689,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
590 | private->rdc_data.no_cyl, | 689 | private->rdc_data.no_cyl, |
591 | private->rdc_data.trk_per_cyl, | 690 | private->rdc_data.trk_per_cyl, |
592 | private->rdc_data.sec_per_trk); | 691 | private->rdc_data.sec_per_trk); |
593 | |||
594 | /* Read Configuration Data */ | ||
595 | rc = dasd_eckd_read_conf (device); | ||
596 | if (rc) | ||
597 | return rc; | ||
598 | |||
599 | /* Generate device unique id and register in devmap */ | ||
600 | rc = dasd_eckd_generate_uid(device, &uid); | ||
601 | if (rc) | ||
602 | return rc; | ||
603 | |||
604 | rc = dasd_set_uid(device->cdev, &uid); | ||
605 | |||
606 | return rc; | 692 | return rc; |
607 | } | 693 | } |
608 | 694 | ||
@@ -1687,14 +1773,8 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
1687 | static int __init | 1773 | static int __init |
1688 | dasd_eckd_init(void) | 1774 | dasd_eckd_init(void) |
1689 | { | 1775 | { |
1690 | int ret; | ||
1691 | |||
1692 | ASCEBC(dasd_eckd_discipline.ebcname, 4); | 1776 | ASCEBC(dasd_eckd_discipline.ebcname, 4); |
1693 | 1777 | return ccw_driver_register(&dasd_eckd_driver); | |
1694 | ret = ccw_driver_register(&dasd_eckd_driver); | ||
1695 | if (!ret) | ||
1696 | dasd_generic_auto_online(&dasd_eckd_driver); | ||
1697 | return ret; | ||
1698 | } | 1778 | } |
1699 | 1779 | ||
1700 | static void __exit | 1780 | static void __exit |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 9d91c8632569..712ff1650134 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
@@ -41,9 +41,10 @@ | |||
41 | #define DASD_ECKD_CCW_RESERVE 0xB4 | 41 | #define DASD_ECKD_CCW_RESERVE 0xB4 |
42 | 42 | ||
43 | /* | 43 | /* |
44 | *Perform Subsystem Function / Sub-Orders | 44 | * Perform Subsystem Function / Sub-Orders |
45 | */ | 45 | */ |
46 | #define PSF_ORDER_PRSSD 0x18 | 46 | #define PSF_ORDER_PRSSD 0x18 |
47 | #define PSF_ORDER_SSC 0x1D | ||
47 | 48 | ||
48 | /***************************************************************************** | 49 | /***************************************************************************** |
49 | * SECTION: Type Definitions | 50 | * SECTION: Type Definitions |
@@ -353,4 +354,15 @@ struct dasd_psf_prssd_data { | |||
353 | unsigned char varies[9]; | 354 | unsigned char varies[9]; |
354 | } __attribute__ ((packed)); | 355 | } __attribute__ ((packed)); |
355 | 356 | ||
357 | /* | ||
358 | * Perform Subsystem Function - Set Subsystem Characteristics | ||
359 | */ | ||
360 | struct dasd_psf_ssc_data { | ||
361 | unsigned char order; | ||
362 | unsigned char flags; | ||
363 | unsigned char cu_type[4]; | ||
364 | unsigned char suborder; | ||
365 | unsigned char reserved[59]; | ||
366 | } __attribute__((packed)); | ||
367 | |||
356 | #endif /* DASD_ECKD_H */ | 368 | #endif /* DASD_ECKD_H */ |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index d331c6e22c59..bb7755b9b19d 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -56,19 +56,13 @@ static struct ccw_driver dasd_fba_driver; /* see below */ | |||
56 | static int | 56 | static int |
57 | dasd_fba_probe(struct ccw_device *cdev) | 57 | dasd_fba_probe(struct ccw_device *cdev) |
58 | { | 58 | { |
59 | int ret; | 59 | return dasd_generic_probe(cdev, &dasd_fba_discipline); |
60 | |||
61 | ret = dasd_generic_probe (cdev, &dasd_fba_discipline); | ||
62 | if (ret) | ||
63 | return ret; | ||
64 | ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); | ||
65 | return 0; | ||
66 | } | 60 | } |
67 | 61 | ||
68 | static int | 62 | static int |
69 | dasd_fba_set_online(struct ccw_device *cdev) | 63 | dasd_fba_set_online(struct ccw_device *cdev) |
70 | { | 64 | { |
71 | return dasd_generic_set_online (cdev, &dasd_fba_discipline); | 65 | return dasd_generic_set_online(cdev, &dasd_fba_discipline); |
72 | } | 66 | } |
73 | 67 | ||
74 | static struct ccw_driver dasd_fba_driver = { | 68 | static struct ccw_driver dasd_fba_driver = { |
@@ -569,16 +563,8 @@ static struct dasd_discipline dasd_fba_discipline = { | |||
569 | static int __init | 563 | static int __init |
570 | dasd_fba_init(void) | 564 | dasd_fba_init(void) |
571 | { | 565 | { |
572 | int ret; | ||
573 | |||
574 | ASCEBC(dasd_fba_discipline.ebcname, 4); | 566 | ASCEBC(dasd_fba_discipline.ebcname, 4); |
575 | 567 | return ccw_driver_register(&dasd_fba_driver); | |
576 | ret = ccw_driver_register(&dasd_fba_driver); | ||
577 | if (ret) | ||
578 | return ret; | ||
579 | |||
580 | dasd_generic_auto_online(&dasd_fba_driver); | ||
581 | return 0; | ||
582 | } | 568 | } |
583 | 569 | ||
584 | static void __exit | 570 | static void __exit |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 2c1fa85a3dad..03a83efc34c4 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -513,12 +513,12 @@ void dasd_generic_remove (struct ccw_device *cdev); | |||
513 | int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); | 513 | int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); |
514 | int dasd_generic_set_offline (struct ccw_device *cdev); | 514 | int dasd_generic_set_offline (struct ccw_device *cdev); |
515 | int dasd_generic_notify(struct ccw_device *, int); | 515 | int dasd_generic_notify(struct ccw_device *, int); |
516 | void dasd_generic_auto_online (struct ccw_driver *); | ||
517 | 516 | ||
518 | /* externals in dasd_devmap.c */ | 517 | /* externals in dasd_devmap.c */ |
519 | extern int dasd_max_devindex; | 518 | extern int dasd_max_devindex; |
520 | extern int dasd_probeonly; | 519 | extern int dasd_probeonly; |
521 | extern int dasd_autodetect; | 520 | extern int dasd_autodetect; |
521 | extern int dasd_nopav; | ||
522 | 522 | ||
523 | int dasd_devmap_init(void); | 523 | int dasd_devmap_init(void); |
524 | void dasd_devmap_exit(void); | 524 | void dasd_devmap_exit(void); |
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h index 1630c26e8f45..c042f9578081 100644 --- a/include/asm-s390/dasd.h +++ b/include/asm-s390/dasd.h | |||
@@ -68,10 +68,12 @@ typedef struct dasd_information2_t { | |||
68 | * 0x00: default features | 68 | * 0x00: default features |
69 | * 0x01: readonly (ro) | 69 | * 0x01: readonly (ro) |
70 | * 0x02: use diag discipline (diag) | 70 | * 0x02: use diag discipline (diag) |
71 | * 0x04: set the device initially online (internal use only) | ||
71 | */ | 72 | */ |
72 | #define DASD_FEATURE_DEFAULT 0 | 73 | #define DASD_FEATURE_DEFAULT 0x00 |
73 | #define DASD_FEATURE_READONLY 1 | 74 | #define DASD_FEATURE_READONLY 0x01 |
74 | #define DASD_FEATURE_USEDIAG 2 | 75 | #define DASD_FEATURE_USEDIAG 0x02 |
76 | #define DASD_FEATURE_INITIAL_ONLINE 0x04 | ||
75 | 77 | ||
76 | #define DASD_PARTN_BITS 2 | 78 | #define DASD_PARTN_BITS 2 |
77 | 79 | ||