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 /drivers/s390/block/dasd_devmap.c | |
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>
Diffstat (limited to 'drivers/s390/block/dasd_devmap.c')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 80 |
1 files changed, 71 insertions, 9 deletions
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 |