diff options
author | Len Brown <len.brown@intel.com> | 2006-06-29 19:57:46 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-06-29 19:57:46 -0400 |
commit | d120cfb544ed6161b9d32fb6c4648c471807ee6b (patch) | |
tree | 7757ad0198d8df76ff5c60f939a687687c41da00 /drivers/s390/block/dasd_devmap.c | |
parent | 9dce0e950dbfab4148f35ac6f297d8638cdc63c4 (diff) | |
parent | bf7e8511088963078484132636839b59e25cf14f (diff) |
merge linus into release branch
Conflicts:
drivers/acpi/acpi_memhotplug.c
Diffstat (limited to 'drivers/s390/block/dasd_devmap.c')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 102 |
1 files changed, 83 insertions, 19 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 216bc4fba199..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 |
@@ -123,7 +139,7 @@ static inline int | |||
123 | dasd_busid(char **str, int *id0, int *id1, int *devno) | 139 | dasd_busid(char **str, int *id0, int *id1, int *devno) |
124 | { | 140 | { |
125 | int val, old_style; | 141 | int val, old_style; |
126 | 142 | ||
127 | /* check for leading '0x' */ | 143 | /* check for leading '0x' */ |
128 | old_style = 0; | 144 | old_style = 0; |
129 | if ((*str)[0] == '0' && (*str)[1] == 'x') { | 145 | if ((*str)[0] == '0' && (*str)[1] == 'x') { |
@@ -179,7 +195,7 @@ dasd_feature_list(char *str, char **endp) | |||
179 | features = 0; | 195 | features = 0; |
180 | 196 | ||
181 | while (1) { | 197 | while (1) { |
182 | for (len = 0; | 198 | for (len = 0; |
183 | str[len] && str[len] != ':' && str[len] != ')'; len++); | 199 | str[len] && str[len] != ':' && str[len] != ')'; len++); |
184 | if (len == 2 && !strncmp(str, "ro", 2)) | 200 | if (len == 2 && !strncmp(str, "ro", 2)) |
185 | features |= DASD_FEATURE_READONLY; | 201 | features |= DASD_FEATURE_READONLY; |
@@ -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++); |
@@ -359,7 +382,7 @@ dasd_parse(void) | |||
359 | * Add a devmap for the device specified by busid. It is possible that | 382 | * Add a devmap for the device specified by busid. It is possible that |
360 | * the devmap already exists (dasd= parameter). The order of the devices | 383 | * the devmap already exists (dasd= parameter). The order of the devices |
361 | * added through this function will define the kdevs for the individual | 384 | * added through this function will define the kdevs for the individual |
362 | * devices. | 385 | * devices. |
363 | */ | 386 | */ |
364 | static struct dasd_devmap * | 387 | static struct dasd_devmap * |
365 | dasd_add_busid(char *bus_id, int features) | 388 | dasd_add_busid(char *bus_id, int features) |
@@ -368,7 +391,7 @@ dasd_add_busid(char *bus_id, int features) | |||
368 | int hash; | 391 | int hash; |
369 | 392 | ||
370 | new = (struct dasd_devmap *) | 393 | new = (struct dasd_devmap *) |
371 | kmalloc(sizeof(struct dasd_devmap), GFP_KERNEL); | 394 | kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL); |
372 | if (!new) | 395 | if (!new) |
373 | return ERR_PTR(-ENOMEM); | 396 | return ERR_PTR(-ENOMEM); |
374 | spin_lock(&dasd_devmap_lock); | 397 | spin_lock(&dasd_devmap_lock); |
@@ -630,7 +653,8 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
630 | } | 653 | } |
631 | 654 | ||
632 | static ssize_t | 655 | static ssize_t |
633 | dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 656 | dasd_ro_store(struct device *dev, struct device_attribute *attr, |
657 | const char *buf, size_t count) | ||
634 | { | 658 | { |
635 | struct dasd_devmap *devmap; | 659 | struct dasd_devmap *devmap; |
636 | int ro_flag; | 660 | int ro_flag; |
@@ -658,7 +682,7 @@ static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store); | |||
658 | * use_diag controls whether the driver should use diag rather than ssch | 682 | * use_diag controls whether the driver should use diag rather than ssch |
659 | * to talk to the device | 683 | * to talk to the device |
660 | */ | 684 | */ |
661 | static ssize_t | 685 | static ssize_t |
662 | dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) | 686 | dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) |
663 | { | 687 | { |
664 | struct dasd_devmap *devmap; | 688 | struct dasd_devmap *devmap; |
@@ -673,7 +697,8 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
673 | } | 697 | } |
674 | 698 | ||
675 | static ssize_t | 699 | static ssize_t |
676 | dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 700 | dasd_use_diag_store(struct device *dev, struct device_attribute *attr, |
701 | const char *buf, size_t count) | ||
677 | { | 702 | { |
678 | struct dasd_devmap *devmap; | 703 | struct dasd_devmap *devmap; |
679 | ssize_t rc; | 704 | ssize_t rc; |
@@ -697,11 +722,11 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const cha | |||
697 | return rc; | 722 | return rc; |
698 | } | 723 | } |
699 | 724 | ||
700 | static | 725 | static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); |
701 | DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); | ||
702 | 726 | ||
703 | static ssize_t | 727 | static ssize_t |
704 | dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf) | 728 | dasd_discipline_show(struct device *dev, struct device_attribute *attr, |
729 | char *buf) | ||
705 | { | 730 | { |
706 | struct dasd_devmap *devmap; | 731 | struct dasd_devmap *devmap; |
707 | char *dname; | 732 | char *dname; |
@@ -834,6 +859,38 @@ static struct attribute_group dasd_attr_group = { | |||
834 | .attrs = dasd_attrs, | 859 | .attrs = dasd_attrs, |
835 | }; | 860 | }; |
836 | 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 | |||
837 | 894 | ||
838 | /* | 895 | /* |
839 | * Return copy of the device unique identifier. | 896 | * Return copy of the device unique identifier. |
@@ -854,21 +911,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | |||
854 | 911 | ||
855 | /* | 912 | /* |
856 | * 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. | ||
857 | */ | 917 | */ |
858 | int | 918 | int |
859 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | 919 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) |
860 | { | 920 | { |
861 | struct dasd_devmap *devmap; | 921 | struct dasd_devmap *devmap; |
922 | int rc; | ||
862 | 923 | ||
863 | devmap = dasd_find_busid(cdev->dev.bus_id); | 924 | devmap = dasd_find_busid(cdev->dev.bus_id); |
864 | if (IS_ERR(devmap)) | 925 | if (IS_ERR(devmap)) |
865 | return PTR_ERR(devmap); | 926 | return PTR_ERR(devmap); |
866 | spin_lock(&dasd_devmap_lock); | 927 | spin_lock(&dasd_devmap_lock); |
867 | devmap->uid = *uid; | 928 | devmap->uid = *uid; |
929 | rc = dasd_add_server(uid); | ||
868 | spin_unlock(&dasd_devmap_lock); | 930 | spin_unlock(&dasd_devmap_lock); |
869 | return 0; | 931 | return rc; |
870 | } | 932 | } |
871 | EXPORT_SYMBOL(dasd_set_uid); | 933 | EXPORT_SYMBOL_GPL(dasd_set_uid); |
872 | 934 | ||
873 | /* | 935 | /* |
874 | * Return value of the specified feature. | 936 | * Return value of the specified feature. |
@@ -880,7 +942,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature) | |||
880 | 942 | ||
881 | devmap = dasd_find_busid(cdev->dev.bus_id); | 943 | devmap = dasd_find_busid(cdev->dev.bus_id); |
882 | if (IS_ERR(devmap)) | 944 | if (IS_ERR(devmap)) |
883 | return (int) PTR_ERR(devmap); | 945 | return PTR_ERR(devmap); |
884 | 946 | ||
885 | return ((devmap->features & feature) != 0); | 947 | return ((devmap->features & feature) != 0); |
886 | } | 948 | } |
@@ -896,7 +958,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) | |||
896 | 958 | ||
897 | devmap = dasd_find_busid(cdev->dev.bus_id); | 959 | devmap = dasd_find_busid(cdev->dev.bus_id); |
898 | if (IS_ERR(devmap)) | 960 | if (IS_ERR(devmap)) |
899 | return (int) PTR_ERR(devmap); | 961 | return PTR_ERR(devmap); |
900 | 962 | ||
901 | spin_lock(&dasd_devmap_lock); | 963 | spin_lock(&dasd_devmap_lock); |
902 | if (flag) | 964 | if (flag) |
@@ -932,8 +994,10 @@ dasd_devmap_init(void) | |||
932 | dasd_max_devindex = 0; | 994 | dasd_max_devindex = 0; |
933 | for (i = 0; i < 256; i++) | 995 | for (i = 0; i < 256; i++) |
934 | INIT_LIST_HEAD(&dasd_hashlists[i]); | 996 | INIT_LIST_HEAD(&dasd_hashlists[i]); |
935 | return 0; | ||
936 | 997 | ||
998 | /* Initialize servermap structure. */ | ||
999 | INIT_LIST_HEAD(&dasd_serverlist); | ||
1000 | return 0; | ||
937 | } | 1001 | } |
938 | 1002 | ||
939 | void | 1003 | void |