aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block')
-rw-r--r--drivers/s390/block/dasd.c32
-rw-r--r--drivers/s390/block/dasd_3990_erp.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c28
-rw-r--r--drivers/s390/block/dasd_eckd.c132
-rw-r--r--drivers/s390/block/dasd_eer.c6
-rw-r--r--drivers/s390/block/dasd_fba.c4
-rw-r--r--drivers/s390/block/dasd_int.h4
-rw-r--r--drivers/s390/block/dasd_proc.c2
-rw-r--r--drivers/s390/block/dcssblk.c516
-rw-r--r--drivers/s390/block/xpram.c37
10 files changed, 564 insertions, 199 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index acb78017e7d0..0a225ccda026 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -215,7 +215,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
215 return rc; 215 return rc;
216 } 216 }
217 /* register 'device' debug area, used for all DBF_DEV_XXX calls */ 217 /* register 'device' debug area, used for all DBF_DEV_XXX calls */
218 device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 1, 218 device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1,
219 8 * sizeof(long)); 219 8 * sizeof(long));
220 debug_register_view(device->debug_area, &debug_sprintf_view); 220 debug_register_view(device->debug_area, &debug_sprintf_view);
221 debug_set_level(device->debug_area, DBF_WARNING); 221 debug_set_level(device->debug_area, DBF_WARNING);
@@ -933,7 +933,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
933 MESSAGE(KERN_DEBUG, 933 MESSAGE(KERN_DEBUG,
934 "invalid status in handle_killed_request: " 934 "invalid status in handle_killed_request: "
935 "bus_id %s, status %02x", 935 "bus_id %s, status %02x",
936 cdev->dev.bus_id, cqr->status); 936 dev_name(&cdev->dev), cqr->status);
937 return; 937 return;
938 } 938 }
939 939
@@ -942,7 +942,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
942 device != dasd_device_from_cdev_locked(cdev) || 942 device != dasd_device_from_cdev_locked(cdev) ||
943 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { 943 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
944 MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", 944 MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
945 cdev->dev.bus_id); 945 dev_name(&cdev->dev));
946 return; 946 return;
947 } 947 }
948 948
@@ -982,11 +982,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
982 break; 982 break;
983 case -ETIMEDOUT: 983 case -ETIMEDOUT:
984 printk(KERN_WARNING"%s(%s): request timed out\n", 984 printk(KERN_WARNING"%s(%s): request timed out\n",
985 __func__, cdev->dev.bus_id); 985 __func__, dev_name(&cdev->dev));
986 break; 986 break;
987 default: 987 default:
988 printk(KERN_WARNING"%s(%s): unknown error %ld\n", 988 printk(KERN_WARNING"%s(%s): unknown error %ld\n",
989 __func__, cdev->dev.bus_id, PTR_ERR(irb)); 989 __func__, dev_name(&cdev->dev), PTR_ERR(irb));
990 } 990 }
991 dasd_handle_killed_request(cdev, intparm); 991 dasd_handle_killed_request(cdev, intparm);
992 return; 992 return;
@@ -995,7 +995,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
995 now = get_clock(); 995 now = get_clock();
996 996
997 DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x", 997 DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
998 cdev->dev.bus_id, ((irb->scsw.cmd.cstat << 8) | 998 dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) |
999 irb->scsw.cmd.dstat), (unsigned int) intparm); 999 irb->scsw.cmd.dstat), (unsigned int) intparm);
1000 1000
1001 /* check for unsolicited interrupts */ 1001 /* check for unsolicited interrupts */
@@ -1019,7 +1019,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1019 if (!device || 1019 if (!device ||
1020 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { 1020 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
1021 MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", 1021 MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
1022 cdev->dev.bus_id); 1022 dev_name(&cdev->dev));
1023 return; 1023 return;
1024 } 1024 }
1025 1025
@@ -1037,7 +1037,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1037 if (cqr->status != DASD_CQR_IN_IO) { 1037 if (cqr->status != DASD_CQR_IN_IO) {
1038 MESSAGE(KERN_DEBUG, 1038 MESSAGE(KERN_DEBUG,
1039 "invalid status: bus_id %s, status %02x", 1039 "invalid status: bus_id %s, status %02x",
1040 cdev->dev.bus_id, cqr->status); 1040 dev_name(&cdev->dev), cqr->status);
1041 return; 1041 return;
1042 } 1042 }
1043 DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p", 1043 DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
@@ -2134,14 +2134,14 @@ int dasd_generic_probe(struct ccw_device *cdev,
2134 if (ret) { 2134 if (ret) {
2135 printk(KERN_WARNING 2135 printk(KERN_WARNING
2136 "dasd_generic_probe: could not set ccw-device options " 2136 "dasd_generic_probe: could not set ccw-device options "
2137 "for %s\n", cdev->dev.bus_id); 2137 "for %s\n", dev_name(&cdev->dev));
2138 return ret; 2138 return ret;
2139 } 2139 }
2140 ret = dasd_add_sysfs_files(cdev); 2140 ret = dasd_add_sysfs_files(cdev);
2141 if (ret) { 2141 if (ret) {
2142 printk(KERN_WARNING 2142 printk(KERN_WARNING
2143 "dasd_generic_probe: could not add sysfs entries " 2143 "dasd_generic_probe: could not add sysfs entries "
2144 "for %s\n", cdev->dev.bus_id); 2144 "for %s\n", dev_name(&cdev->dev));
2145 return ret; 2145 return ret;
2146 } 2146 }
2147 cdev->handler = &dasd_int_handler; 2147 cdev->handler = &dasd_int_handler;
@@ -2152,13 +2152,13 @@ int dasd_generic_probe(struct ccw_device *cdev,
2152 * initial probe. 2152 * initial probe.
2153 */ 2153 */
2154 if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || 2154 if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
2155 (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0)) 2155 (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0))
2156 ret = ccw_device_set_online(cdev); 2156 ret = ccw_device_set_online(cdev);
2157 if (ret) 2157 if (ret)
2158 printk(KERN_WARNING 2158 printk(KERN_WARNING
2159 "dasd_generic_probe: could not initially " 2159 "dasd_generic_probe: could not initially "
2160 "online ccw-device %s; return code: %d\n", 2160 "online ccw-device %s; return code: %d\n",
2161 cdev->dev.bus_id, ret); 2161 dev_name(&cdev->dev), ret);
2162 return 0; 2162 return 0;
2163} 2163}
2164 2164
@@ -2224,7 +2224,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
2224 printk (KERN_WARNING 2224 printk (KERN_WARNING
2225 "dasd_generic couldn't online device %s " 2225 "dasd_generic couldn't online device %s "
2226 "- discipline DIAG not available\n", 2226 "- discipline DIAG not available\n",
2227 cdev->dev.bus_id); 2227 dev_name(&cdev->dev));
2228 dasd_delete_device(device); 2228 dasd_delete_device(device);
2229 return -ENODEV; 2229 return -ENODEV;
2230 } 2230 }
@@ -2248,7 +2248,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
2248 printk (KERN_WARNING 2248 printk (KERN_WARNING
2249 "dasd_generic couldn't online device %s " 2249 "dasd_generic couldn't online device %s "
2250 "with discipline %s rc=%i\n", 2250 "with discipline %s rc=%i\n",
2251 cdev->dev.bus_id, discipline->name, rc); 2251 dev_name(&cdev->dev), discipline->name, rc);
2252 module_put(discipline->owner); 2252 module_put(discipline->owner);
2253 module_put(base_discipline->owner); 2253 module_put(base_discipline->owner);
2254 dasd_delete_device(device); 2254 dasd_delete_device(device);
@@ -2259,7 +2259,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
2259 if (device->state <= DASD_STATE_KNOWN) { 2259 if (device->state <= DASD_STATE_KNOWN) {
2260 printk (KERN_WARNING 2260 printk (KERN_WARNING
2261 "dasd_generic discipline not found for %s\n", 2261 "dasd_generic discipline not found for %s\n",
2262 cdev->dev.bus_id); 2262 dev_name(&cdev->dev));
2263 rc = -ENODEV; 2263 rc = -ENODEV;
2264 dasd_set_target_state(device, DASD_STATE_NEW); 2264 dasd_set_target_state(device, DASD_STATE_NEW);
2265 if (device->block) 2265 if (device->block)
@@ -2267,7 +2267,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
2267 dasd_delete_device(device); 2267 dasd_delete_device(device);
2268 } else 2268 } else
2269 pr_debug("dasd_generic device %s found\n", 2269 pr_debug("dasd_generic device %s found\n",
2270 cdev->dev.bus_id); 2270 dev_name(&cdev->dev));
2271 2271
2272 /* FIXME: we have to wait for the root device but we don't want 2272 /* FIXME: we have to wait for the root device but we don't want
2273 * to wait for each single device but for all at once. */ 2273 * to wait for each single device but for all at once. */
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 5c6e6f331cb0..b8f9c00633f3 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1397,7 +1397,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(
1397 DEV_MESSAGE(KERN_ERR, cqr->startdev, 1397 DEV_MESSAGE(KERN_ERR, cqr->startdev,
1398 "ERP on alias device for request %p," 1398 "ERP on alias device for request %p,"
1399 " recover on base device %s", cqr, 1399 " recover on base device %s", cqr,
1400 cqr->block->base->cdev->dev.bus_id); 1400 dev_name(&cqr->block->base->cdev->dev));
1401 } 1401 }
1402 dasd_eckd_reset_ccw_to_base_io(cqr); 1402 dasd_eckd_reset_ccw_to_base_io(cqr);
1403 erp->startdev = cqr->block->base; 1403 erp->startdev = cqr->block->base;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index cd3335c1c307..921443b01d16 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -515,9 +515,9 @@ dasd_devmap_from_cdev(struct ccw_device *cdev)
515{ 515{
516 struct dasd_devmap *devmap; 516 struct dasd_devmap *devmap;
517 517
518 devmap = dasd_find_busid(cdev->dev.bus_id); 518 devmap = dasd_find_busid(dev_name(&cdev->dev));
519 if (IS_ERR(devmap)) 519 if (IS_ERR(devmap))
520 devmap = dasd_add_busid(cdev->dev.bus_id, 520 devmap = dasd_add_busid(dev_name(&cdev->dev),
521 DASD_FEATURE_DEFAULT); 521 DASD_FEATURE_DEFAULT);
522 return devmap; 522 return devmap;
523} 523}
@@ -584,7 +584,7 @@ dasd_delete_device(struct dasd_device *device)
584 unsigned long flags; 584 unsigned long flags;
585 585
586 /* First remove device pointer from devmap. */ 586 /* First remove device pointer from devmap. */
587 devmap = dasd_find_busid(device->cdev->dev.bus_id); 587 devmap = dasd_find_busid(dev_name(&device->cdev->dev));
588 BUG_ON(IS_ERR(devmap)); 588 BUG_ON(IS_ERR(devmap));
589 spin_lock(&dasd_devmap_lock); 589 spin_lock(&dasd_devmap_lock);
590 if (devmap->device != device) { 590 if (devmap->device != device) {
@@ -674,7 +674,7 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
674 struct dasd_devmap *devmap; 674 struct dasd_devmap *devmap;
675 int ro_flag; 675 int ro_flag;
676 676
677 devmap = dasd_find_busid(dev->bus_id); 677 devmap = dasd_find_busid(dev_name(dev));
678 if (!IS_ERR(devmap)) 678 if (!IS_ERR(devmap))
679 ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0; 679 ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
680 else 680 else
@@ -723,7 +723,7 @@ dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
723 struct dasd_devmap *devmap; 723 struct dasd_devmap *devmap;
724 int erplog; 724 int erplog;
725 725
726 devmap = dasd_find_busid(dev->bus_id); 726 devmap = dasd_find_busid(dev_name(dev));
727 if (!IS_ERR(devmap)) 727 if (!IS_ERR(devmap))
728 erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0; 728 erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
729 else 729 else
@@ -770,7 +770,7 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
770 struct dasd_devmap *devmap; 770 struct dasd_devmap *devmap;
771 int use_diag; 771 int use_diag;
772 772
773 devmap = dasd_find_busid(dev->bus_id); 773 devmap = dasd_find_busid(dev_name(dev));
774 if (!IS_ERR(devmap)) 774 if (!IS_ERR(devmap))
775 use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0; 775 use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
776 else 776 else
@@ -876,7 +876,7 @@ dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
876 struct dasd_devmap *devmap; 876 struct dasd_devmap *devmap;
877 int alias; 877 int alias;
878 878
879 devmap = dasd_find_busid(dev->bus_id); 879 devmap = dasd_find_busid(dev_name(dev));
880 spin_lock(&dasd_devmap_lock); 880 spin_lock(&dasd_devmap_lock);
881 if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { 881 if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
882 spin_unlock(&dasd_devmap_lock); 882 spin_unlock(&dasd_devmap_lock);
@@ -899,7 +899,7 @@ dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
899 struct dasd_devmap *devmap; 899 struct dasd_devmap *devmap;
900 char *vendor; 900 char *vendor;
901 901
902 devmap = dasd_find_busid(dev->bus_id); 902 devmap = dasd_find_busid(dev_name(dev));
903 spin_lock(&dasd_devmap_lock); 903 spin_lock(&dasd_devmap_lock);
904 if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) 904 if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
905 vendor = devmap->uid.vendor; 905 vendor = devmap->uid.vendor;
@@ -924,7 +924,7 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
924 char ua_string[3]; 924 char ua_string[3];
925 struct dasd_uid *uid; 925 struct dasd_uid *uid;
926 926
927 devmap = dasd_find_busid(dev->bus_id); 927 devmap = dasd_find_busid(dev_name(dev));
928 spin_lock(&dasd_devmap_lock); 928 spin_lock(&dasd_devmap_lock);
929 if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { 929 if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
930 spin_unlock(&dasd_devmap_lock); 930 spin_unlock(&dasd_devmap_lock);
@@ -972,7 +972,7 @@ dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
972 struct dasd_devmap *devmap; 972 struct dasd_devmap *devmap;
973 int eer_flag; 973 int eer_flag;
974 974
975 devmap = dasd_find_busid(dev->bus_id); 975 devmap = dasd_find_busid(dev_name(dev));
976 if (!IS_ERR(devmap) && devmap->device) 976 if (!IS_ERR(devmap) && devmap->device)
977 eer_flag = dasd_eer_enabled(devmap->device); 977 eer_flag = dasd_eer_enabled(devmap->device);
978 else 978 else
@@ -1034,7 +1034,7 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
1034{ 1034{
1035 struct dasd_devmap *devmap; 1035 struct dasd_devmap *devmap;
1036 1036
1037 devmap = dasd_find_busid(cdev->dev.bus_id); 1037 devmap = dasd_find_busid(dev_name(&cdev->dev));
1038 if (IS_ERR(devmap)) 1038 if (IS_ERR(devmap))
1039 return PTR_ERR(devmap); 1039 return PTR_ERR(devmap);
1040 spin_lock(&dasd_devmap_lock); 1040 spin_lock(&dasd_devmap_lock);
@@ -1057,7 +1057,7 @@ dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
1057{ 1057{
1058 struct dasd_devmap *devmap; 1058 struct dasd_devmap *devmap;
1059 1059
1060 devmap = dasd_find_busid(cdev->dev.bus_id); 1060 devmap = dasd_find_busid(dev_name(&cdev->dev));
1061 if (IS_ERR(devmap)) 1061 if (IS_ERR(devmap))
1062 return PTR_ERR(devmap); 1062 return PTR_ERR(devmap);
1063 1063
@@ -1077,7 +1077,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
1077{ 1077{
1078 struct dasd_devmap *devmap; 1078 struct dasd_devmap *devmap;
1079 1079
1080 devmap = dasd_find_busid(cdev->dev.bus_id); 1080 devmap = dasd_find_busid(dev_name(&cdev->dev));
1081 if (IS_ERR(devmap)) 1081 if (IS_ERR(devmap))
1082 return PTR_ERR(devmap); 1082 return PTR_ERR(devmap);
1083 1083
@@ -1093,7 +1093,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
1093{ 1093{
1094 struct dasd_devmap *devmap; 1094 struct dasd_devmap *devmap;
1095 1095
1096 devmap = dasd_find_busid(cdev->dev.bus_id); 1096 devmap = dasd_find_busid(dev_name(&cdev->dev));
1097 if (IS_ERR(devmap)) 1097 if (IS_ERR(devmap))
1098 return PTR_ERR(devmap); 1098 return PTR_ERR(devmap);
1099 1099
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 773b3fe275b2..49f9d221e23d 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -6,6 +6,8 @@
6 * Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * Bugreports.to..: <Linux390@de.ibm.com> 7 * Bugreports.to..: <Linux390@de.ibm.com>
8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
9 * EMC Symmetrix ioctl Copyright EMC Corporation, 2008
10 * Author.........: Nigel Hislop <hislop_nigel@emc.com>
9 * 11 *
10 */ 12 */
11 13
@@ -84,7 +86,7 @@ dasd_eckd_probe (struct ccw_device *cdev)
84 if (ret) { 86 if (ret) {
85 printk(KERN_WARNING 87 printk(KERN_WARNING
86 "dasd_eckd_probe: could not set ccw-device options " 88 "dasd_eckd_probe: could not set ccw-device options "
87 "for %s\n", cdev->dev.bus_id); 89 "for %s\n", dev_name(&cdev->dev));
88 return ret; 90 return ret;
89 } 91 }
90 ret = dasd_generic_probe(cdev, &dasd_eckd_discipline); 92 ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
@@ -1501,12 +1503,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
1501 return; 1503 return;
1502 } 1504 }
1503 1505
1504 /* just report other unsolicited interrupts */ 1506 if ((irb->scsw.cmd.cc == 1) &&
1505 DEV_MESSAGE(KERN_DEBUG, device, "%s", 1507 (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
1506 "unsolicited interrupt received"); 1508 (irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) &&
1507 device->discipline->dump_sense(device, NULL, irb); 1509 (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) {
1508 dasd_schedule_device_bh(device); 1510 /* fake irb do nothing, they are handled elsewhere */
1511 dasd_schedule_device_bh(device);
1512 return;
1513 }
1514
1515 if (!(irb->esw.esw0.erw.cons)) {
1516 /* just report other unsolicited interrupts */
1517 DEV_MESSAGE(KERN_ERR, device, "%s",
1518 "unsolicited interrupt received");
1519 } else {
1520 DEV_MESSAGE(KERN_ERR, device, "%s",
1521 "unsolicited interrupt received "
1522 "(sense available)");
1523 device->discipline->dump_sense(device, NULL, irb);
1524 }
1509 1525
1526 dasd_schedule_device_bh(device);
1510 return; 1527 return;
1511}; 1528};
1512 1529
@@ -2068,6 +2085,103 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
2068 return 0; 2085 return 0;
2069} 2086}
2070 2087
2088/*
2089 * Issue syscall I/O to EMC Symmetrix array.
2090 * CCWs are PSF and RSSD
2091 */
2092static int dasd_symm_io(struct dasd_device *device, void __user *argp)
2093{
2094 struct dasd_symmio_parms usrparm;
2095 char *psf_data, *rssd_result;
2096 struct dasd_ccw_req *cqr;
2097 struct ccw1 *ccw;
2098 int rc;
2099
2100 /* Copy parms from caller */
2101 rc = -EFAULT;
2102 if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
2103 goto out;
2104#ifndef CONFIG_64BIT
2105 /* Make sure pointers are sane even on 31 bit. */
2106 if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) {
2107 rc = -EINVAL;
2108 goto out;
2109 }
2110#endif
2111 /* alloc I/O data area */
2112 psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
2113 rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
2114 if (!psf_data || !rssd_result) {
2115 rc = -ENOMEM;
2116 goto out_free;
2117 }
2118
2119 /* get syscall header from user space */
2120 rc = -EFAULT;
2121 if (copy_from_user(psf_data,
2122 (void __user *)(unsigned long) usrparm.psf_data,
2123 usrparm.psf_data_len))
2124 goto out_free;
2125
2126 /* sanity check on syscall header */
2127 if (psf_data[0] != 0x17 && psf_data[1] != 0xce) {
2128 rc = -EINVAL;
2129 goto out_free;
2130 }
2131
2132 /* setup CCWs for PSF + RSSD */
2133 cqr = dasd_smalloc_request("ECKD", 2 , 0, device);
2134 if (IS_ERR(cqr)) {
2135 DEV_MESSAGE(KERN_WARNING, device, "%s",
2136 "Could not allocate initialization request");
2137 rc = PTR_ERR(cqr);
2138 goto out_free;
2139 }
2140
2141 cqr->startdev = device;
2142 cqr->memdev = device;
2143 cqr->retries = 3;
2144 cqr->expires = 10 * HZ;
2145 cqr->buildclk = get_clock();
2146 cqr->status = DASD_CQR_FILLED;
2147
2148 /* Build the ccws */
2149 ccw = cqr->cpaddr;
2150
2151 /* PSF ccw */
2152 ccw->cmd_code = DASD_ECKD_CCW_PSF;
2153 ccw->count = usrparm.psf_data_len;
2154 ccw->flags |= CCW_FLAG_CC;
2155 ccw->cda = (__u32)(addr_t) psf_data;
2156
2157 ccw++;
2158
2159 /* RSSD ccw */
2160 ccw->cmd_code = DASD_ECKD_CCW_RSSD;
2161 ccw->count = usrparm.rssd_result_len;
2162 ccw->flags = CCW_FLAG_SLI ;
2163 ccw->cda = (__u32)(addr_t) rssd_result;
2164
2165 rc = dasd_sleep_on(cqr);
2166 if (rc)
2167 goto out_sfree;
2168
2169 rc = -EFAULT;
2170 if (copy_to_user((void __user *)(unsigned long) usrparm.rssd_result,
2171 rssd_result, usrparm.rssd_result_len))
2172 goto out_sfree;
2173 rc = 0;
2174
2175out_sfree:
2176 dasd_sfree_request(cqr, cqr->memdev);
2177out_free:
2178 kfree(rssd_result);
2179 kfree(psf_data);
2180out:
2181 DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc);
2182 return rc;
2183}
2184
2071static int 2185static int
2072dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) 2186dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
2073{ 2187{
@@ -2086,6 +2200,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
2086 return dasd_eckd_reserve(device); 2200 return dasd_eckd_reserve(device);
2087 case BIODASDSLCK: 2201 case BIODASDSLCK:
2088 return dasd_eckd_steal_lock(device); 2202 return dasd_eckd_steal_lock(device);
2203 case BIODASDSYMMIO:
2204 return dasd_symm_io(device, argp);
2089 default: 2205 default:
2090 return -ENOIOCTLCMD; 2206 return -ENOIOCTLCMD;
2091 } 2207 }
@@ -2145,13 +2261,13 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
2145 /* dump the sense data */ 2261 /* dump the sense data */
2146 len = sprintf(page, KERN_ERR PRINTK_HEADER 2262 len = sprintf(page, KERN_ERR PRINTK_HEADER
2147 " I/O status report for device %s:\n", 2263 " I/O status report for device %s:\n",
2148 device->cdev->dev.bus_id); 2264 dev_name(&device->cdev->dev));
2149 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 2265 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
2150 " in req: %p CS: 0x%02X DS: 0x%02X\n", req, 2266 " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
2151 irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); 2267 irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
2152 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 2268 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
2153 " device %s: Failing CCW: %p\n", 2269 " device %s: Failing CCW: %p\n",
2154 device->cdev->dev.bus_id, 2270 dev_name(&device->cdev->dev),
2155 (void *) (addr_t) irb->scsw.cmd.cpa); 2271 (void *) (addr_t) irb->scsw.cmd.cpa);
2156 if (irb->esw.esw0.erw.cons) { 2272 if (irb->esw.esw0.erw.cons) {
2157 for (sl = 0; sl < 4; sl++) { 2273 for (sl = 0; sl < 4; sl++) {
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index bf512ac75b9e..892e2878d61b 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -309,7 +309,8 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
309 do_gettimeofday(&tv); 309 do_gettimeofday(&tv);
310 header.tv_sec = tv.tv_sec; 310 header.tv_sec = tv.tv_sec;
311 header.tv_usec = tv.tv_usec; 311 header.tv_usec = tv.tv_usec;
312 strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); 312 strncpy(header.busid, dev_name(&device->cdev->dev),
313 DASD_EER_BUSID_SIZE);
313 314
314 spin_lock_irqsave(&bufferlock, flags); 315 spin_lock_irqsave(&bufferlock, flags);
315 list_for_each_entry(eerb, &bufferlist, list) { 316 list_for_each_entry(eerb, &bufferlist, list) {
@@ -349,7 +350,8 @@ static void dasd_eer_write_snss_trigger(struct dasd_device *device,
349 do_gettimeofday(&tv); 350 do_gettimeofday(&tv);
350 header.tv_sec = tv.tv_sec; 351 header.tv_sec = tv.tv_sec;
351 header.tv_usec = tv.tv_usec; 352 header.tv_usec = tv.tv_usec;
352 strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); 353 strncpy(header.busid, dev_name(&device->cdev->dev),
354 DASD_EER_BUSID_SIZE);
353 355
354 spin_lock_irqsave(&bufferlock, flags); 356 spin_lock_irqsave(&bufferlock, flags);
355 list_for_each_entry(eerb, &bufferlist, list) { 357 list_for_each_entry(eerb, &bufferlist, list) {
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index aa0c533423a5..93d9b6452a94 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -451,13 +451,13 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
451 } 451 }
452 len = sprintf(page, KERN_ERR PRINTK_HEADER 452 len = sprintf(page, KERN_ERR PRINTK_HEADER
453 " I/O status report for device %s:\n", 453 " I/O status report for device %s:\n",
454 device->cdev->dev.bus_id); 454 dev_name(&device->cdev->dev));
455 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 455 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
456 " in req: %p CS: 0x%02X DS: 0x%02X\n", req, 456 " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
457 irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); 457 irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
458 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 458 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
459 " device %s: Failing CCW: %p\n", 459 " device %s: Failing CCW: %p\n",
460 device->cdev->dev.bus_id, 460 dev_name(&device->cdev->dev),
461 (void *) (addr_t) irb->scsw.cmd.cpa); 461 (void *) (addr_t) irb->scsw.cmd.cpa);
462 if (irb->esw.esw0.erw.cons) { 462 if (irb->esw.esw0.erw.cons) {
463 for (sl = 0; sl < 4; sl++) { 463 for (sl = 0; sl < 4; sl++) {
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 31ecaa4a40e4..489d5fe488fb 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -126,7 +126,7 @@ do { \
126#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\ 126#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
127do { \ 127do { \
128 printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \ 128 printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
129 d_device->cdev->dev.bus_id, d_args); \ 129 dev_name(&d_device->cdev->dev), d_args); \
130 DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \ 130 DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
131} while(0) 131} while(0)
132 132
@@ -140,7 +140,7 @@ do { \
140#define DEV_MESSAGE_LOG(d_loglevel,d_device,d_string,d_args...)\ 140#define DEV_MESSAGE_LOG(d_loglevel,d_device,d_string,d_args...)\
141do { \ 141do { \
142 printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \ 142 printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
143 d_device->cdev->dev.bus_id, d_args); \ 143 dev_name(&d_device->cdev->dev), d_args); \
144} while(0) 144} while(0)
145 145
146#define MESSAGE_LOG(d_loglevel,d_string,d_args...)\ 146#define MESSAGE_LOG(d_loglevel,d_string,d_args...)\
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index e3b5c4d3036e..9088de84b45d 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -67,7 +67,7 @@ dasd_devices_show(struct seq_file *m, void *v)
67 return 0; 67 return 0;
68 } 68 }
69 /* Print device number. */ 69 /* Print device number. */
70 seq_printf(m, "%s", device->cdev->dev.bus_id); 70 seq_printf(m, "%s", dev_name(&device->cdev->dev));
71 /* Print discipline string. */ 71 /* Print discipline string. */
72 if (device != NULL && device->discipline != NULL) 72 if (device != NULL && device->discipline != NULL)
73 seq_printf(m, "(%s)", device->discipline->name); 73 seq_printf(m, "(%s)", device->discipline->name);
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 9481e4a3f76e..a7ff167d5b81 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -31,7 +31,6 @@
31#define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x) 31#define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x)
32#define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x) 32#define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x)
33 33
34
35static int dcssblk_open(struct inode *inode, struct file *filp); 34static int dcssblk_open(struct inode *inode, struct file *filp);
36static int dcssblk_release(struct inode *inode, struct file *filp); 35static int dcssblk_release(struct inode *inode, struct file *filp);
37static int dcssblk_make_request(struct request_queue *q, struct bio *bio); 36static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
@@ -48,6 +47,30 @@ static struct block_device_operations dcssblk_devops = {
48 .direct_access = dcssblk_direct_access, 47 .direct_access = dcssblk_direct_access,
49}; 48};
50 49
50struct dcssblk_dev_info {
51 struct list_head lh;
52 struct device dev;
53 char segment_name[BUS_ID_SIZE];
54 atomic_t use_count;
55 struct gendisk *gd;
56 unsigned long start;
57 unsigned long end;
58 int segment_type;
59 unsigned char save_pending;
60 unsigned char is_shared;
61 struct request_queue *dcssblk_queue;
62 int num_of_segments;
63 struct list_head seg_list;
64};
65
66struct segment_info {
67 struct list_head lh;
68 char segment_name[BUS_ID_SIZE];
69 unsigned long start;
70 unsigned long end;
71 int segment_type;
72};
73
51static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, 74static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
52 size_t count); 75 size_t count);
53static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf, 76static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
@@ -58,30 +81,20 @@ static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *at
58static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf, 81static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
59 size_t count); 82 size_t count);
60static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf); 83static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
84static ssize_t dcssblk_seglist_show(struct device *dev,
85 struct device_attribute *attr,
86 char *buf);
61 87
62static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store); 88static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
63static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store); 89static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
64static DEVICE_ATTR(save, S_IWUSR | S_IRUGO, dcssblk_save_show, 90static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
65 dcssblk_save_store); 91 dcssblk_save_store);
66static DEVICE_ATTR(shared, S_IWUSR | S_IRUGO, dcssblk_shared_show, 92static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
67 dcssblk_shared_store); 93 dcssblk_shared_store);
94static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
68 95
69static struct device *dcssblk_root_dev; 96static struct device *dcssblk_root_dev;
70 97
71struct dcssblk_dev_info {
72 struct list_head lh;
73 struct device dev;
74 char segment_name[BUS_ID_SIZE];
75 atomic_t use_count;
76 struct gendisk *gd;
77 unsigned long start;
78 unsigned long end;
79 int segment_type;
80 unsigned char save_pending;
81 unsigned char is_shared;
82 struct request_queue *dcssblk_queue;
83};
84
85static LIST_HEAD(dcssblk_devices); 98static LIST_HEAD(dcssblk_devices);
86static struct rw_semaphore dcssblk_devices_sem; 99static struct rw_semaphore dcssblk_devices_sem;
87 100
@@ -91,8 +104,15 @@ static struct rw_semaphore dcssblk_devices_sem;
91static void 104static void
92dcssblk_release_segment(struct device *dev) 105dcssblk_release_segment(struct device *dev)
93{ 106{
94 PRINT_DEBUG("segment release fn called for %s\n", dev->bus_id); 107 struct dcssblk_dev_info *dev_info;
95 kfree(container_of(dev, struct dcssblk_dev_info, dev)); 108 struct segment_info *entry, *temp;
109
110 dev_info = container_of(dev, struct dcssblk_dev_info, dev);
111 list_for_each_entry_safe(entry, temp, &dev_info->seg_list, lh) {
112 list_del(&entry->lh);
113 kfree(entry);
114 }
115 kfree(dev_info);
96 module_put(THIS_MODULE); 116 module_put(THIS_MODULE);
97} 117}
98 118
@@ -142,6 +162,169 @@ dcssblk_get_device_by_name(char *name)
142 return NULL; 162 return NULL;
143} 163}
144 164
165/*
166 * get the struct segment_info from seg_list
167 * for the given name.
168 * down_read(&dcssblk_devices_sem) must be held.
169 */
170static struct segment_info *
171dcssblk_get_segment_by_name(char *name)
172{
173 struct dcssblk_dev_info *dev_info;
174 struct segment_info *entry;
175
176 list_for_each_entry(dev_info, &dcssblk_devices, lh) {
177 list_for_each_entry(entry, &dev_info->seg_list, lh) {
178 if (!strcmp(name, entry->segment_name))
179 return entry;
180 }
181 }
182 return NULL;
183}
184
185/*
186 * get the highest address of the multi-segment block.
187 */
188static unsigned long
189dcssblk_find_highest_addr(struct dcssblk_dev_info *dev_info)
190{
191 unsigned long highest_addr;
192 struct segment_info *entry;
193
194 highest_addr = 0;
195 list_for_each_entry(entry, &dev_info->seg_list, lh) {
196 if (highest_addr < entry->end)
197 highest_addr = entry->end;
198 }
199 return highest_addr;
200}
201
202/*
203 * get the lowest address of the multi-segment block.
204 */
205static unsigned long
206dcssblk_find_lowest_addr(struct dcssblk_dev_info *dev_info)
207{
208 int set_first;
209 unsigned long lowest_addr;
210 struct segment_info *entry;
211
212 set_first = 0;
213 lowest_addr = 0;
214 list_for_each_entry(entry, &dev_info->seg_list, lh) {
215 if (set_first == 0) {
216 lowest_addr = entry->start;
217 set_first = 1;
218 } else {
219 if (lowest_addr > entry->start)
220 lowest_addr = entry->start;
221 }
222 }
223 return lowest_addr;
224}
225
226/*
227 * Check continuity of segments.
228 */
229static int
230dcssblk_is_continuous(struct dcssblk_dev_info *dev_info)
231{
232 int i, j, rc;
233 struct segment_info *sort_list, *entry, temp;
234
235 if (dev_info->num_of_segments <= 1)
236 return 0;
237
238 sort_list = kzalloc(
239 sizeof(struct segment_info) * dev_info->num_of_segments,
240 GFP_KERNEL);
241 if (sort_list == NULL)
242 return -ENOMEM;
243 i = 0;
244 list_for_each_entry(entry, &dev_info->seg_list, lh) {
245 memcpy(&sort_list[i], entry, sizeof(struct segment_info));
246 i++;
247 }
248
249 /* sort segments */
250 for (i = 0; i < dev_info->num_of_segments; i++)
251 for (j = 0; j < dev_info->num_of_segments; j++)
252 if (sort_list[j].start > sort_list[i].start) {
253 memcpy(&temp, &sort_list[i],
254 sizeof(struct segment_info));
255 memcpy(&sort_list[i], &sort_list[j],
256 sizeof(struct segment_info));
257 memcpy(&sort_list[j], &temp,
258 sizeof(struct segment_info));
259 }
260
261 /* check continuity */
262 for (i = 0; i < dev_info->num_of_segments - 1; i++) {
263 if ((sort_list[i].end + 1) != sort_list[i+1].start) {
264 PRINT_ERR("Segment %s is not contiguous with "
265 "segment %s\n",
266 sort_list[i].segment_name,
267 sort_list[i+1].segment_name);
268 rc = -EINVAL;
269 goto out;
270 }
271 /* EN and EW are allowed in a block device */
272 if (sort_list[i].segment_type != sort_list[i+1].segment_type) {
273 if (!(sort_list[i].segment_type & SEGMENT_EXCLUSIVE) ||
274 (sort_list[i].segment_type == SEG_TYPE_ER) ||
275 !(sort_list[i+1].segment_type &
276 SEGMENT_EXCLUSIVE) ||
277 (sort_list[i+1].segment_type == SEG_TYPE_ER)) {
278 PRINT_ERR("Segment %s has different type from "
279 "segment %s\n",
280 sort_list[i].segment_name,
281 sort_list[i+1].segment_name);
282 rc = -EINVAL;
283 goto out;
284 }
285 }
286 }
287 rc = 0;
288out:
289 kfree(sort_list);
290 return rc;
291}
292
293/*
294 * Load a segment
295 */
296static int
297dcssblk_load_segment(char *name, struct segment_info **seg_info)
298{
299 int rc;
300
301 /* already loaded? */
302 down_read(&dcssblk_devices_sem);
303 *seg_info = dcssblk_get_segment_by_name(name);
304 up_read(&dcssblk_devices_sem);
305 if (*seg_info != NULL)
306 return -EEXIST;
307
308 /* get a struct segment_info */
309 *seg_info = kzalloc(sizeof(struct segment_info), GFP_KERNEL);
310 if (*seg_info == NULL)
311 return -ENOMEM;
312
313 strcpy((*seg_info)->segment_name, name);
314
315 /* load the segment */
316 rc = segment_load(name, SEGMENT_SHARED,
317 &(*seg_info)->start, &(*seg_info)->end);
318 if (rc < 0) {
319 segment_warning(rc, (*seg_info)->segment_name);
320 kfree(*seg_info);
321 } else {
322 INIT_LIST_HEAD(&(*seg_info)->lh);
323 (*seg_info)->segment_type = rc;
324 }
325 return rc;
326}
327
145static void dcssblk_unregister_callback(struct device *dev) 328static void dcssblk_unregister_callback(struct device *dev)
146{ 329{
147 device_unregister(dev); 330 device_unregister(dev);
@@ -165,6 +348,7 @@ static ssize_t
165dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count) 348dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
166{ 349{
167 struct dcssblk_dev_info *dev_info; 350 struct dcssblk_dev_info *dev_info;
351 struct segment_info *entry, *temp;
168 int rc; 352 int rc;
169 353
170 if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) 354 if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
@@ -172,46 +356,46 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
172 down_write(&dcssblk_devices_sem); 356 down_write(&dcssblk_devices_sem);
173 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 357 dev_info = container_of(dev, struct dcssblk_dev_info, dev);
174 if (atomic_read(&dev_info->use_count)) { 358 if (atomic_read(&dev_info->use_count)) {
175 PRINT_ERR("share: segment %s is busy!\n",
176 dev_info->segment_name);
177 rc = -EBUSY; 359 rc = -EBUSY;
178 goto out; 360 goto out;
179 } 361 }
180 if (inbuf[0] == '1') { 362 if (inbuf[0] == '1') {
181 // reload segment in shared mode 363 /* reload segments in shared mode */
182 rc = segment_modify_shared(dev_info->segment_name, 364 list_for_each_entry(entry, &dev_info->seg_list, lh) {
183 SEGMENT_SHARED); 365 rc = segment_modify_shared(entry->segment_name,
184 if (rc < 0) { 366 SEGMENT_SHARED);
185 BUG_ON(rc == -EINVAL); 367 if (rc < 0) {
186 if (rc != -EAGAIN) 368 BUG_ON(rc == -EINVAL);
187 goto removeseg; 369 if (rc != -EAGAIN)
188 } else { 370 goto removeseg;
189 dev_info->is_shared = 1;
190 switch (dev_info->segment_type) {
191 case SEG_TYPE_SR:
192 case SEG_TYPE_ER:
193 case SEG_TYPE_SC:
194 set_disk_ro(dev_info->gd,1);
195 } 371 }
196 } 372 }
373 dev_info->is_shared = 1;
374 switch (dev_info->segment_type) {
375 case SEG_TYPE_SR:
376 case SEG_TYPE_ER:
377 case SEG_TYPE_SC:
378 set_disk_ro(dev_info->gd, 1);
379 }
197 } else if (inbuf[0] == '0') { 380 } else if (inbuf[0] == '0') {
198 // reload segment in exclusive mode 381 /* reload segments in exclusive mode */
199 if (dev_info->segment_type == SEG_TYPE_SC) { 382 if (dev_info->segment_type == SEG_TYPE_SC) {
200 PRINT_ERR("Segment type SC (%s) cannot be loaded in " 383 PRINT_ERR("Segment type SC (%s) cannot be loaded in "
201 "non-shared mode\n", dev_info->segment_name); 384 "non-shared mode\n", dev_info->segment_name);
202 rc = -EINVAL; 385 rc = -EINVAL;
203 goto out; 386 goto out;
204 } 387 }
205 rc = segment_modify_shared(dev_info->segment_name, 388 list_for_each_entry(entry, &dev_info->seg_list, lh) {
206 SEGMENT_EXCLUSIVE); 389 rc = segment_modify_shared(entry->segment_name,
207 if (rc < 0) { 390 SEGMENT_EXCLUSIVE);
208 BUG_ON(rc == -EINVAL); 391 if (rc < 0) {
209 if (rc != -EAGAIN) 392 BUG_ON(rc == -EINVAL);
210 goto removeseg; 393 if (rc != -EAGAIN)
211 } else { 394 goto removeseg;
212 dev_info->is_shared = 0; 395 }
213 set_disk_ro(dev_info->gd, 0);
214 } 396 }
397 dev_info->is_shared = 0;
398 set_disk_ro(dev_info->gd, 0);
215 } else { 399 } else {
216 rc = -EINVAL; 400 rc = -EINVAL;
217 goto out; 401 goto out;
@@ -220,8 +404,14 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
220 goto out; 404 goto out;
221 405
222removeseg: 406removeseg:
223 PRINT_ERR("Could not reload segment %s, removing it now!\n", 407 PRINT_ERR("Could not reload segment(s) of the device %s, removing "
224 dev_info->segment_name); 408 "segment(s) now!\n",
409 dev_info->segment_name);
410 temp = entry;
411 list_for_each_entry(entry, &dev_info->seg_list, lh) {
412 if (entry != temp)
413 segment_unload(entry->segment_name);
414 }
225 list_del(&dev_info->lh); 415 list_del(&dev_info->lh);
226 416
227 del_gendisk(dev_info->gd); 417 del_gendisk(dev_info->gd);
@@ -254,6 +444,7 @@ static ssize_t
254dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count) 444dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
255{ 445{
256 struct dcssblk_dev_info *dev_info; 446 struct dcssblk_dev_info *dev_info;
447 struct segment_info *entry;
257 448
258 if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) 449 if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
259 return -EINVAL; 450 return -EINVAL;
@@ -263,14 +454,16 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
263 if (inbuf[0] == '1') { 454 if (inbuf[0] == '1') {
264 if (atomic_read(&dev_info->use_count) == 0) { 455 if (atomic_read(&dev_info->use_count) == 0) {
265 // device is idle => we save immediately 456 // device is idle => we save immediately
266 PRINT_INFO("Saving segment %s\n", 457 PRINT_INFO("Saving segment(s) of the device %s\n",
267 dev_info->segment_name); 458 dev_info->segment_name);
268 segment_save(dev_info->segment_name); 459 list_for_each_entry(entry, &dev_info->seg_list, lh) {
460 segment_save(entry->segment_name);
461 }
269 } else { 462 } else {
270 // device is busy => we save it when it becomes 463 // device is busy => we save it when it becomes
271 // idle in dcssblk_release 464 // idle in dcssblk_release
272 PRINT_INFO("Segment %s is currently busy, it will " 465 PRINT_INFO("Device %s is currently busy, segment(s) "
273 "be saved when it becomes idle...\n", 466 "will be saved when it becomes idle...\n",
274 dev_info->segment_name); 467 dev_info->segment_name);
275 dev_info->save_pending = 1; 468 dev_info->save_pending = 1;
276 } 469 }
@@ -279,7 +472,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
279 // device is busy & the user wants to undo his save 472 // device is busy & the user wants to undo his save
280 // request 473 // request
281 dev_info->save_pending = 0; 474 dev_info->save_pending = 0;
282 PRINT_INFO("Pending save for segment %s deactivated\n", 475 PRINT_INFO("Pending save for segment(s) of the device "
476 "%s deactivated\n",
283 dev_info->segment_name); 477 dev_info->segment_name);
284 } 478 }
285 } else { 479 } else {
@@ -291,66 +485,123 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
291} 485}
292 486
293/* 487/*
488 * device attribute for showing all segments in a device
489 */
490static ssize_t
491dcssblk_seglist_show(struct device *dev, struct device_attribute *attr,
492 char *buf)
493{
494 int i;
495
496 struct dcssblk_dev_info *dev_info;
497 struct segment_info *entry;
498
499 down_read(&dcssblk_devices_sem);
500 dev_info = container_of(dev, struct dcssblk_dev_info, dev);
501 i = 0;
502 buf[0] = '\0';
503 list_for_each_entry(entry, &dev_info->seg_list, lh) {
504 strcpy(&buf[i], entry->segment_name);
505 i += strlen(entry->segment_name);
506 buf[i] = '\n';
507 i++;
508 }
509 up_read(&dcssblk_devices_sem);
510 return i;
511}
512
513/*
294 * device attribute for adding devices 514 * device attribute for adding devices
295 */ 515 */
296static ssize_t 516static ssize_t
297dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 517dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
298{ 518{
299 int rc, i; 519 int rc, i, j, num_of_segments;
300 struct dcssblk_dev_info *dev_info; 520 struct dcssblk_dev_info *dev_info;
521 struct segment_info *seg_info, *temp;
301 char *local_buf; 522 char *local_buf;
302 unsigned long seg_byte_size; 523 unsigned long seg_byte_size;
303 524
304 dev_info = NULL; 525 dev_info = NULL;
526 seg_info = NULL;
305 if (dev != dcssblk_root_dev) { 527 if (dev != dcssblk_root_dev) {
306 rc = -EINVAL; 528 rc = -EINVAL;
307 goto out_nobuf; 529 goto out_nobuf;
308 } 530 }
531 if ((count < 1) || (buf[0] == '\0') || (buf[0] == '\n')) {
532 rc = -ENAMETOOLONG;
533 goto out_nobuf;
534 }
535
309 local_buf = kmalloc(count + 1, GFP_KERNEL); 536 local_buf = kmalloc(count + 1, GFP_KERNEL);
310 if (local_buf == NULL) { 537 if (local_buf == NULL) {
311 rc = -ENOMEM; 538 rc = -ENOMEM;
312 goto out_nobuf; 539 goto out_nobuf;
313 } 540 }
541
314 /* 542 /*
315 * parse input 543 * parse input
316 */ 544 */
545 num_of_segments = 0;
317 for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) { 546 for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) {
318 local_buf[i] = toupper(buf[i]); 547 for (j = i; (buf[j] != ':') &&
548 (buf[j] != '\0') &&
549 (buf[j] != '\n') &&
550 j < count; j++) {
551 local_buf[j-i] = toupper(buf[j]);
552 }
553 local_buf[j-i] = '\0';
554 if (((j - i) == 0) || ((j - i) > 8)) {
555 rc = -ENAMETOOLONG;
556 goto seg_list_del;
557 }
558
559 rc = dcssblk_load_segment(local_buf, &seg_info);
560 if (rc < 0)
561 goto seg_list_del;
562 /*
563 * get a struct dcssblk_dev_info
564 */
565 if (num_of_segments == 0) {
566 dev_info = kzalloc(sizeof(struct dcssblk_dev_info),
567 GFP_KERNEL);
568 if (dev_info == NULL) {
569 rc = -ENOMEM;
570 goto out;
571 }
572 strcpy(dev_info->segment_name, local_buf);
573 dev_info->segment_type = seg_info->segment_type;
574 INIT_LIST_HEAD(&dev_info->seg_list);
575 }
576 list_add_tail(&seg_info->lh, &dev_info->seg_list);
577 num_of_segments++;
578 i = j;
579
580 if ((buf[j] == '\0') || (buf[j] == '\n'))
581 break;
319 } 582 }
320 local_buf[i] = '\0'; 583
321 if ((i == 0) || (i > 8)) { 584 /* no trailing colon at the end of the input */
585 if ((i > 0) && (buf[i-1] == ':')) {
322 rc = -ENAMETOOLONG; 586 rc = -ENAMETOOLONG;
323 goto out; 587 goto seg_list_del;
324 }
325 /*
326 * already loaded?
327 */
328 down_read(&dcssblk_devices_sem);
329 dev_info = dcssblk_get_device_by_name(local_buf);
330 up_read(&dcssblk_devices_sem);
331 if (dev_info != NULL) {
332 PRINT_WARN("Segment %s already loaded!\n", local_buf);
333 rc = -EEXIST;
334 goto out;
335 }
336 /*
337 * get a struct dcssblk_dev_info
338 */
339 dev_info = kzalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL);
340 if (dev_info == NULL) {
341 rc = -ENOMEM;
342 goto out;
343 } 588 }
589 strlcpy(local_buf, buf, i + 1);
590 dev_info->num_of_segments = num_of_segments;
591 rc = dcssblk_is_continuous(dev_info);
592 if (rc < 0)
593 goto seg_list_del;
594
595 dev_info->start = dcssblk_find_lowest_addr(dev_info);
596 dev_info->end = dcssblk_find_highest_addr(dev_info);
344 597
345 strcpy(dev_info->segment_name, local_buf); 598 dev_set_name(&dev_info->dev, dev_info->segment_name);
346 strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE);
347 dev_info->dev.release = dcssblk_release_segment; 599 dev_info->dev.release = dcssblk_release_segment;
348 INIT_LIST_HEAD(&dev_info->lh); 600 INIT_LIST_HEAD(&dev_info->lh);
349
350 dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK); 601 dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK);
351 if (dev_info->gd == NULL) { 602 if (dev_info->gd == NULL) {
352 rc = -ENOMEM; 603 rc = -ENOMEM;
353 goto free_dev_info; 604 goto seg_list_del;
354 } 605 }
355 dev_info->gd->major = dcssblk_major; 606 dev_info->gd->major = dcssblk_major;
356 dev_info->gd->fops = &dcssblk_devops; 607 dev_info->gd->fops = &dcssblk_devops;
@@ -360,59 +611,43 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
360 dev_info->gd->driverfs_dev = &dev_info->dev; 611 dev_info->gd->driverfs_dev = &dev_info->dev;
361 blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); 612 blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request);
362 blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); 613 blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
363 /* 614
364 * load the segment
365 */
366 rc = segment_load(local_buf, SEGMENT_SHARED,
367 &dev_info->start, &dev_info->end);
368 if (rc < 0) {
369 segment_warning(rc, dev_info->segment_name);
370 goto dealloc_gendisk;
371 }
372 seg_byte_size = (dev_info->end - dev_info->start + 1); 615 seg_byte_size = (dev_info->end - dev_info->start + 1);
373 set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors 616 set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
374 PRINT_INFO("Loaded segment %s, size = %lu Byte, " 617 PRINT_INFO("Loaded segment(s) %s, size = %lu Byte, "
375 "capacity = %lu (512 Byte) sectors\n", local_buf, 618 "capacity = %lu (512 Byte) sectors\n", local_buf,
376 seg_byte_size, seg_byte_size >> 9); 619 seg_byte_size, seg_byte_size >> 9);
377 620
378 dev_info->segment_type = rc;
379 dev_info->save_pending = 0; 621 dev_info->save_pending = 0;
380 dev_info->is_shared = 1; 622 dev_info->is_shared = 1;
381 dev_info->dev.parent = dcssblk_root_dev; 623 dev_info->dev.parent = dcssblk_root_dev;
382 624
383 /* 625 /*
384 * get minor, add to list 626 *get minor, add to list
385 */ 627 */
386 down_write(&dcssblk_devices_sem); 628 down_write(&dcssblk_devices_sem);
387 if (dcssblk_get_device_by_name(local_buf)) { 629 if (dcssblk_get_segment_by_name(local_buf)) {
388 up_write(&dcssblk_devices_sem);
389 rc = -EEXIST; 630 rc = -EEXIST;
390 goto unload_seg; 631 goto release_gd;
391 } 632 }
392 rc = dcssblk_assign_free_minor(dev_info); 633 rc = dcssblk_assign_free_minor(dev_info);
393 if (rc) { 634 if (rc)
394 up_write(&dcssblk_devices_sem); 635 goto release_gd;
395 PRINT_ERR("No free minor number available! "
396 "Unloading segment...\n");
397 goto unload_seg;
398 }
399 sprintf(dev_info->gd->disk_name, "dcssblk%d", 636 sprintf(dev_info->gd->disk_name, "dcssblk%d",
400 MINOR(disk_devt(dev_info->gd))); 637 MINOR(disk_devt(dev_info->gd)));
401 list_add_tail(&dev_info->lh, &dcssblk_devices); 638 list_add_tail(&dev_info->lh, &dcssblk_devices);
402 639
403 if (!try_module_get(THIS_MODULE)) { 640 if (!try_module_get(THIS_MODULE)) {
404 rc = -ENODEV; 641 rc = -ENODEV;
405 goto list_del; 642 goto dev_list_del;
406 } 643 }
407 /* 644 /*
408 * register the device 645 * register the device
409 */ 646 */
410 rc = device_register(&dev_info->dev); 647 rc = device_register(&dev_info->dev);
411 if (rc) { 648 if (rc) {
412 PRINT_ERR("Segment %s could not be registered RC=%d\n",
413 local_buf, rc);
414 module_put(THIS_MODULE); 649 module_put(THIS_MODULE);
415 goto list_del; 650 goto dev_list_del;
416 } 651 }
417 get_device(&dev_info->dev); 652 get_device(&dev_info->dev);
418 rc = device_create_file(&dev_info->dev, &dev_attr_shared); 653 rc = device_create_file(&dev_info->dev, &dev_attr_shared);
@@ -421,6 +656,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
421 rc = device_create_file(&dev_info->dev, &dev_attr_save); 656 rc = device_create_file(&dev_info->dev, &dev_attr_save);
422 if (rc) 657 if (rc)
423 goto unregister_dev; 658 goto unregister_dev;
659 rc = device_create_file(&dev_info->dev, &dev_attr_seglist);
660 if (rc)
661 goto unregister_dev;
424 662
425 add_disk(dev_info->gd); 663 add_disk(dev_info->gd);
426 664
@@ -434,7 +672,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
434 set_disk_ro(dev_info->gd,0); 672 set_disk_ro(dev_info->gd,0);
435 break; 673 break;
436 } 674 }
437 PRINT_DEBUG("Segment %s loaded successfully\n", local_buf);
438 up_write(&dcssblk_devices_sem); 675 up_write(&dcssblk_devices_sem);
439 rc = count; 676 rc = count;
440 goto out; 677 goto out;
@@ -445,20 +682,27 @@ unregister_dev:
445 dev_info->gd->queue = NULL; 682 dev_info->gd->queue = NULL;
446 put_disk(dev_info->gd); 683 put_disk(dev_info->gd);
447 device_unregister(&dev_info->dev); 684 device_unregister(&dev_info->dev);
448 segment_unload(dev_info->segment_name); 685 list_for_each_entry(seg_info, &dev_info->seg_list, lh) {
686 segment_unload(seg_info->segment_name);
687 }
449 put_device(&dev_info->dev); 688 put_device(&dev_info->dev);
450 up_write(&dcssblk_devices_sem); 689 up_write(&dcssblk_devices_sem);
451 goto out; 690 goto out;
452list_del: 691dev_list_del:
453 list_del(&dev_info->lh); 692 list_del(&dev_info->lh);
454 up_write(&dcssblk_devices_sem); 693release_gd:
455unload_seg:
456 segment_unload(local_buf);
457dealloc_gendisk:
458 blk_cleanup_queue(dev_info->dcssblk_queue); 694 blk_cleanup_queue(dev_info->dcssblk_queue);
459 dev_info->gd->queue = NULL; 695 dev_info->gd->queue = NULL;
460 put_disk(dev_info->gd); 696 put_disk(dev_info->gd);
461free_dev_info: 697 up_write(&dcssblk_devices_sem);
698seg_list_del:
699 if (dev_info == NULL)
700 goto out;
701 list_for_each_entry_safe(seg_info, temp, &dev_info->seg_list, lh) {
702 list_del(&seg_info->lh);
703 segment_unload(seg_info->segment_name);
704 kfree(seg_info);
705 }
462 kfree(dev_info); 706 kfree(dev_info);
463out: 707out:
464 kfree(local_buf); 708 kfree(local_buf);
@@ -473,6 +717,7 @@ static ssize_t
473dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 717dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
474{ 718{
475 struct dcssblk_dev_info *dev_info; 719 struct dcssblk_dev_info *dev_info;
720 struct segment_info *entry;
476 int rc, i; 721 int rc, i;
477 char *local_buf; 722 char *local_buf;
478 723
@@ -499,26 +744,28 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
499 dev_info = dcssblk_get_device_by_name(local_buf); 744 dev_info = dcssblk_get_device_by_name(local_buf);
500 if (dev_info == NULL) { 745 if (dev_info == NULL) {
501 up_write(&dcssblk_devices_sem); 746 up_write(&dcssblk_devices_sem);
502 PRINT_WARN("Segment %s is not loaded!\n", local_buf); 747 PRINT_WARN("Device %s is not loaded!\n", local_buf);
503 rc = -ENODEV; 748 rc = -ENODEV;
504 goto out_buf; 749 goto out_buf;
505 } 750 }
506 if (atomic_read(&dev_info->use_count) != 0) { 751 if (atomic_read(&dev_info->use_count) != 0) {
507 up_write(&dcssblk_devices_sem); 752 up_write(&dcssblk_devices_sem);
508 PRINT_WARN("Segment %s is in use!\n", local_buf); 753 PRINT_WARN("Device %s is in use!\n", local_buf);
509 rc = -EBUSY; 754 rc = -EBUSY;
510 goto out_buf; 755 goto out_buf;
511 } 756 }
512 list_del(&dev_info->lh);
513 757
758 list_del(&dev_info->lh);
514 del_gendisk(dev_info->gd); 759 del_gendisk(dev_info->gd);
515 blk_cleanup_queue(dev_info->dcssblk_queue); 760 blk_cleanup_queue(dev_info->dcssblk_queue);
516 dev_info->gd->queue = NULL; 761 dev_info->gd->queue = NULL;
517 put_disk(dev_info->gd); 762 put_disk(dev_info->gd);
518 device_unregister(&dev_info->dev); 763 device_unregister(&dev_info->dev);
519 segment_unload(dev_info->segment_name); 764
520 PRINT_DEBUG("Segment %s unloaded successfully\n", 765 /* unload all related segments */
521 dev_info->segment_name); 766 list_for_each_entry(entry, &dev_info->seg_list, lh)
767 segment_unload(entry->segment_name);
768
522 put_device(&dev_info->dev); 769 put_device(&dev_info->dev);
523 up_write(&dcssblk_devices_sem); 770 up_write(&dcssblk_devices_sem);
524 771
@@ -550,6 +797,7 @@ static int
550dcssblk_release(struct inode *inode, struct file *filp) 797dcssblk_release(struct inode *inode, struct file *filp)
551{ 798{
552 struct dcssblk_dev_info *dev_info; 799 struct dcssblk_dev_info *dev_info;
800 struct segment_info *entry;
553 int rc; 801 int rc;
554 802
555 dev_info = inode->i_bdev->bd_disk->private_data; 803 dev_info = inode->i_bdev->bd_disk->private_data;
@@ -560,9 +808,11 @@ dcssblk_release(struct inode *inode, struct file *filp)
560 down_write(&dcssblk_devices_sem); 808 down_write(&dcssblk_devices_sem);
561 if (atomic_dec_and_test(&dev_info->use_count) 809 if (atomic_dec_and_test(&dev_info->use_count)
562 && (dev_info->save_pending)) { 810 && (dev_info->save_pending)) {
563 PRINT_INFO("Segment %s became idle and is being saved now\n", 811 PRINT_INFO("Device %s became idle and is being saved now\n",
564 dev_info->segment_name); 812 dev_info->segment_name);
565 segment_save(dev_info->segment_name); 813 list_for_each_entry(entry, &dev_info->seg_list, lh) {
814 segment_save(entry->segment_name);
815 }
566 dev_info->save_pending = 0; 816 dev_info->save_pending = 0;
567 } 817 }
568 up_write(&dcssblk_devices_sem); 818 up_write(&dcssblk_devices_sem);
@@ -602,7 +852,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
602 case SEG_TYPE_SC: 852 case SEG_TYPE_SC:
603 /* cannot write to these segments */ 853 /* cannot write to these segments */
604 if (bio_data_dir(bio) == WRITE) { 854 if (bio_data_dir(bio) == WRITE) {
605 PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id); 855 PRINT_WARN("rejecting write to ro device %s\n",
856 dev_name(&dev_info->dev));
606 goto fail; 857 goto fail;
607 } 858 }
608 } 859 }
@@ -657,7 +908,7 @@ static void
657dcssblk_check_params(void) 908dcssblk_check_params(void)
658{ 909{
659 int rc, i, j, k; 910 int rc, i, j, k;
660 char buf[9]; 911 char buf[DCSSBLK_PARM_LEN + 1];
661 struct dcssblk_dev_info *dev_info; 912 struct dcssblk_dev_info *dev_info;
662 913
663 for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0'); 914 for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
@@ -665,15 +916,16 @@ dcssblk_check_params(void)
665 for (j = i; (dcssblk_segments[j] != ',') && 916 for (j = i; (dcssblk_segments[j] != ',') &&
666 (dcssblk_segments[j] != '\0') && 917 (dcssblk_segments[j] != '\0') &&
667 (dcssblk_segments[j] != '(') && 918 (dcssblk_segments[j] != '(') &&
668 (j - i) < 8; j++) 919 (j < DCSSBLK_PARM_LEN); j++)
669 { 920 {
670 buf[j-i] = dcssblk_segments[j]; 921 buf[j-i] = dcssblk_segments[j];
671 } 922 }
672 buf[j-i] = '\0'; 923 buf[j-i] = '\0';
673 rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i); 924 rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i);
674 if ((rc >= 0) && (dcssblk_segments[j] == '(')) { 925 if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
675 for (k = 0; buf[k] != '\0'; k++) 926 for (k = 0; (buf[k] != ':') && (buf[k] != '\0'); k++)
676 buf[k] = toupper(buf[k]); 927 buf[k] = toupper(buf[k]);
928 buf[k] = '\0';
677 if (!strncmp(&dcssblk_segments[j], "(local)", 7)) { 929 if (!strncmp(&dcssblk_segments[j], "(local)", 7)) {
678 down_read(&dcssblk_devices_sem); 930 down_read(&dcssblk_devices_sem);
679 dev_info = dcssblk_get_device_by_name(buf); 931 dev_info = dcssblk_get_device_by_name(buf);
@@ -740,10 +992,12 @@ module_exit(dcssblk_exit);
740 992
741module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444); 993module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444);
742MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, " 994MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, "
743 "comma-separated list, each name max. 8 chars.\n" 995 "comma-separated list, names in each set separated "
744 "Adding \"(local)\" to segment name equals echoing 0 to " 996 "by commas are separated by colons, each set contains "
745 "/sys/devices/dcssblk/<segment name>/shared after loading " 997 "names of contiguous segments and each name max. 8 chars.\n"
746 "the segment - \n" 998 "Adding \"(local)\" to the end of each set equals echoing 0 "
747 "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\""); 999 "to /sys/devices/dcssblk/<device name>/shared after loading "
1000 "the contiguous segments - \n"
1001 "e.g. segments=\"mydcss1,mydcss2:mydcss3,mydcss4(local)\"");
748 1002
749MODULE_LICENSE("GPL"); 1003MODULE_LICENSE("GPL");
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index dd9b986389a2..03916989ed2d 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -56,6 +56,7 @@ typedef struct {
56static xpram_device_t xpram_devices[XPRAM_MAX_DEVS]; 56static xpram_device_t xpram_devices[XPRAM_MAX_DEVS];
57static unsigned int xpram_sizes[XPRAM_MAX_DEVS]; 57static unsigned int xpram_sizes[XPRAM_MAX_DEVS];
58static struct gendisk *xpram_disks[XPRAM_MAX_DEVS]; 58static struct gendisk *xpram_disks[XPRAM_MAX_DEVS];
59static struct request_queue *xpram_queues[XPRAM_MAX_DEVS];
59static unsigned int xpram_pages; 60static unsigned int xpram_pages;
60static int xpram_devs; 61static int xpram_devs;
61 62
@@ -330,18 +331,22 @@ static int __init xpram_setup_sizes(unsigned long pages)
330 return 0; 331 return 0;
331} 332}
332 333
333static struct request_queue *xpram_queue;
334
335static int __init xpram_setup_blkdev(void) 334static int __init xpram_setup_blkdev(void)
336{ 335{
337 unsigned long offset; 336 unsigned long offset;
338 int i, rc = -ENOMEM; 337 int i, rc = -ENOMEM;
339 338
340 for (i = 0; i < xpram_devs; i++) { 339 for (i = 0; i < xpram_devs; i++) {
341 struct gendisk *disk = alloc_disk(1); 340 xpram_disks[i] = alloc_disk(1);
342 if (!disk) 341 if (!xpram_disks[i])
342 goto out;
343 xpram_queues[i] = blk_alloc_queue(GFP_KERNEL);
344 if (!xpram_queues[i]) {
345 put_disk(xpram_disks[i]);
343 goto out; 346 goto out;
344 xpram_disks[i] = disk; 347 }
348 blk_queue_make_request(xpram_queues[i], xpram_make_request);
349 blk_queue_hardsect_size(xpram_queues[i], 4096);
345 } 350 }
346 351
347 /* 352 /*
@@ -352,18 +357,6 @@ static int __init xpram_setup_blkdev(void)
352 goto out; 357 goto out;
353 358
354 /* 359 /*
355 * Assign the other needed values: make request function, sizes and
356 * hardsect size. All the minor devices feature the same value.
357 */
358 xpram_queue = blk_alloc_queue(GFP_KERNEL);
359 if (!xpram_queue) {
360 rc = -ENOMEM;
361 goto out_unreg;
362 }
363 blk_queue_make_request(xpram_queue, xpram_make_request);
364 blk_queue_hardsect_size(xpram_queue, 4096);
365
366 /*
367 * Setup device structures. 360 * Setup device structures.
368 */ 361 */
369 offset = 0; 362 offset = 0;
@@ -377,18 +370,18 @@ static int __init xpram_setup_blkdev(void)
377 disk->first_minor = i; 370 disk->first_minor = i;
378 disk->fops = &xpram_devops; 371 disk->fops = &xpram_devops;
379 disk->private_data = &xpram_devices[i]; 372 disk->private_data = &xpram_devices[i];
380 disk->queue = xpram_queue; 373 disk->queue = xpram_queues[i];
381 sprintf(disk->disk_name, "slram%d", i); 374 sprintf(disk->disk_name, "slram%d", i);
382 set_capacity(disk, xpram_sizes[i] << 1); 375 set_capacity(disk, xpram_sizes[i] << 1);
383 add_disk(disk); 376 add_disk(disk);
384 } 377 }
385 378
386 return 0; 379 return 0;
387out_unreg:
388 unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
389out: 380out:
390 while (i--) 381 while (i--) {
382 blk_cleanup_queue(xpram_queues[i]);
391 put_disk(xpram_disks[i]); 383 put_disk(xpram_disks[i]);
384 }
392 return rc; 385 return rc;
393} 386}
394 387
@@ -400,10 +393,10 @@ static void __exit xpram_exit(void)
400 int i; 393 int i;
401 for (i = 0; i < xpram_devs; i++) { 394 for (i = 0; i < xpram_devs; i++) {
402 del_gendisk(xpram_disks[i]); 395 del_gendisk(xpram_disks[i]);
396 blk_cleanup_queue(xpram_queues[i]);
403 put_disk(xpram_disks[i]); 397 put_disk(xpram_disks[i]);
404 } 398 }
405 unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); 399 unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
406 blk_cleanup_queue(xpram_queue);
407} 400}
408 401
409static int __init xpram_init(void) 402static int __init xpram_init(void)