diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 17:01:26 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 17:01:26 -0400 |
| commit | 0d6ffdb8f151a2b685c7b45bde7ab2d49fc1bb00 (patch) | |
| tree | 1768c906e87750dc897a2f113e335886d9b906e8 | |
| parent | 7233e392760b3493095d3d5885cb15e44493d74a (diff) | |
| parent | 7c8faa86290c1a2607d6b768a0b874ec392a5c2a (diff) | |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
[S390] dasd: tunable missing interrupt handler
[S390] dasd: allocate fallback cqr for reserve/release
[S390] topology: use default MC domain initializer
[S390] initrd: change default load address
[S390] cmm, smsgiucv_app: convert sender to uppercase
[S390] cmm: add missing __init/__exit annotations
[S390] cio: use all available paths for some internal I/O
[S390] ccwreq: add ability to use all paths
[S390] cio: ccw_device_online_store return -EINVAL in case of missing driver
[S390] cio: Log the response from the unit check handler
[S390] cio: CHSC SIOSL Support
| -rw-r--r-- | arch/s390/include/asm/ccwdev.h | 2 | ||||
| -rw-r--r-- | arch/s390/include/asm/topology.h | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/head.S | 2 | ||||
| -rw-r--r-- | arch/s390/mm/cmm.c | 11 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_devmap.c | 44 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_diag.c | 6 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 94 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.h | 7 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_fba.c | 4 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_int.h | 8 | ||||
| -rw-r--r-- | drivers/s390/cio/ccwreq.c | 16 | ||||
| -rw-r--r-- | drivers/s390/cio/chsc.c | 48 | ||||
| -rw-r--r-- | drivers/s390/cio/chsc.h | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 47 | ||||
| -rw-r--r-- | drivers/s390/cio/device_pgid.c | 3 | ||||
| -rw-r--r-- | drivers/s390/cio/io_sch.h | 10 | ||||
| -rw-r--r-- | drivers/s390/net/smsgiucv_app.c | 7 |
17 files changed, 275 insertions, 38 deletions
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index 1c0030f9b890..f3ba0fa98de6 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h | |||
| @@ -208,6 +208,8 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *); | |||
| 208 | extern struct ccw_device *ccw_device_probe_console(void); | 208 | extern struct ccw_device *ccw_device_probe_console(void); |
| 209 | extern int ccw_device_force_console(void); | 209 | extern int ccw_device_force_console(void); |
| 210 | 210 | ||
| 211 | int ccw_device_siosl(struct ccw_device *); | ||
| 212 | |||
| 211 | // FIXME: these have to go | 213 | // FIXME: these have to go |
| 212 | extern int _ccw_device_get_subchannel_number(struct ccw_device *); | 214 | extern int _ccw_device_get_subchannel_number(struct ccw_device *); |
| 213 | 215 | ||
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index dc8a67297d0f..831bd033ea77 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h | |||
| @@ -30,8 +30,6 @@ static inline void s390_init_cpu_topology(void) | |||
| 30 | }; | 30 | }; |
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | #define SD_MC_INIT SD_CPU_INIT | ||
| 34 | |||
| 35 | #include <asm-generic/topology.h> | 33 | #include <asm-generic/topology.h> |
| 36 | 34 | ||
| 37 | #endif /* _ASM_S390_TOPOLOGY_H */ | 35 | #endif /* _ASM_S390_TOPOLOGY_H */ |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 51838ad42d56..db1696e210af 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
| @@ -366,7 +366,7 @@ iplstart: | |||
| 366 | l %r1,.Lstartup | 366 | l %r1,.Lstartup |
| 367 | br %r1 | 367 | br %r1 |
| 368 | 368 | ||
| 369 | .Linitrd:.long _end + 0x400000 # default address of initrd | 369 | .Linitrd:.long _end # default address of initrd |
| 370 | .Lparm: .long PARMAREA | 370 | .Lparm: .long PARMAREA |
| 371 | .Lstartup: .long startup | 371 | .Lstartup: .long startup |
| 372 | .Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 | 372 | .Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 |
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index eb6a2ef5f82e..a9550dca3e4b 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
| @@ -427,7 +427,7 @@ static struct notifier_block cmm_power_notifier = { | |||
| 427 | .notifier_call = cmm_power_event, | 427 | .notifier_call = cmm_power_event, |
| 428 | }; | 428 | }; |
| 429 | 429 | ||
| 430 | static int cmm_init(void) | 430 | static int __init cmm_init(void) |
| 431 | { | 431 | { |
| 432 | int rc = -ENOMEM; | 432 | int rc = -ENOMEM; |
| 433 | 433 | ||
| @@ -435,6 +435,13 @@ static int cmm_init(void) | |||
| 435 | if (!cmm_sysctl_header) | 435 | if (!cmm_sysctl_header) |
| 436 | goto out_sysctl; | 436 | goto out_sysctl; |
| 437 | #ifdef CONFIG_CMM_IUCV | 437 | #ifdef CONFIG_CMM_IUCV |
| 438 | /* convert sender to uppercase characters */ | ||
| 439 | if (sender) { | ||
| 440 | int len = strlen(sender); | ||
| 441 | while (len--) | ||
| 442 | sender[len] = toupper(sender[len]); | ||
| 443 | } | ||
| 444 | |||
| 438 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); | 445 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); |
| 439 | if (rc < 0) | 446 | if (rc < 0) |
| 440 | goto out_smsg; | 447 | goto out_smsg; |
| @@ -467,7 +474,7 @@ out_sysctl: | |||
| 467 | } | 474 | } |
| 468 | module_init(cmm_init); | 475 | module_init(cmm_init); |
| 469 | 476 | ||
| 470 | static void cmm_exit(void) | 477 | static void __exit cmm_exit(void) |
| 471 | { | 478 | { |
| 472 | unregister_sysctl_table(cmm_sysctl_header); | 479 | unregister_sysctl_table(cmm_sysctl_header); |
| 473 | #ifdef CONFIG_CMM_IUCV | 480 | #ifdef CONFIG_CMM_IUCV |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index bed7b4634ccd..8d41f3ed38d7 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
| @@ -1083,6 +1083,49 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, | |||
| 1083 | 1083 | ||
| 1084 | static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); | 1084 | static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); |
| 1085 | 1085 | ||
| 1086 | /* | ||
| 1087 | * expiration time for default requests | ||
| 1088 | */ | ||
| 1089 | static ssize_t | ||
| 1090 | dasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1091 | { | ||
| 1092 | struct dasd_device *device; | ||
| 1093 | int len; | ||
| 1094 | |||
| 1095 | device = dasd_device_from_cdev(to_ccwdev(dev)); | ||
| 1096 | if (IS_ERR(device)) | ||
| 1097 | return -ENODEV; | ||
| 1098 | len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires); | ||
| 1099 | dasd_put_device(device); | ||
| 1100 | return len; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | static ssize_t | ||
| 1104 | dasd_expires_store(struct device *dev, struct device_attribute *attr, | ||
| 1105 | const char *buf, size_t count) | ||
| 1106 | { | ||
| 1107 | struct dasd_device *device; | ||
| 1108 | unsigned long val; | ||
| 1109 | |||
| 1110 | device = dasd_device_from_cdev(to_ccwdev(dev)); | ||
| 1111 | if (IS_ERR(device)) | ||
| 1112 | return -ENODEV; | ||
| 1113 | |||
| 1114 | if ((strict_strtoul(buf, 10, &val) != 0) || | ||
| 1115 | (val > DASD_EXPIRES_MAX) || val == 0) { | ||
| 1116 | dasd_put_device(device); | ||
| 1117 | return -EINVAL; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | if (val) | ||
| 1121 | device->default_expires = val; | ||
| 1122 | |||
| 1123 | dasd_put_device(device); | ||
| 1124 | return count; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store); | ||
| 1128 | |||
| 1086 | static struct attribute * dasd_attrs[] = { | 1129 | static struct attribute * dasd_attrs[] = { |
| 1087 | &dev_attr_readonly.attr, | 1130 | &dev_attr_readonly.attr, |
| 1088 | &dev_attr_discipline.attr, | 1131 | &dev_attr_discipline.attr, |
| @@ -1094,6 +1137,7 @@ static struct attribute * dasd_attrs[] = { | |||
| 1094 | &dev_attr_eer_enabled.attr, | 1137 | &dev_attr_eer_enabled.attr, |
| 1095 | &dev_attr_erplog.attr, | 1138 | &dev_attr_erplog.attr, |
| 1096 | &dev_attr_failfast.attr, | 1139 | &dev_attr_failfast.attr, |
| 1140 | &dev_attr_expires.attr, | ||
| 1097 | NULL, | 1141 | NULL, |
| 1098 | }; | 1142 | }; |
| 1099 | 1143 | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 687f323cdc38..2b3bc3ec0541 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
| @@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); | |||
| 43 | sizeof(struct dasd_diag_req)) / \ | 43 | sizeof(struct dasd_diag_req)) / \ |
| 44 | sizeof(struct dasd_diag_bio)) / 2) | 44 | sizeof(struct dasd_diag_bio)) / 2) |
| 45 | #define DIAG_MAX_RETRIES 32 | 45 | #define DIAG_MAX_RETRIES 32 |
| 46 | #define DIAG_TIMEOUT 50 * HZ | 46 | #define DIAG_TIMEOUT 50 |
| 47 | 47 | ||
| 48 | static struct dasd_discipline dasd_diag_discipline; | 48 | static struct dasd_discipline dasd_diag_discipline; |
| 49 | 49 | ||
| @@ -360,6 +360,8 @@ dasd_diag_check_device(struct dasd_device *device) | |||
| 360 | goto out; | 360 | goto out; |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | device->default_expires = DIAG_TIMEOUT; | ||
| 364 | |||
| 363 | /* Figure out position of label block */ | 365 | /* Figure out position of label block */ |
| 364 | switch (private->rdc_data.vdev_class) { | 366 | switch (private->rdc_data.vdev_class) { |
| 365 | case DEV_CLASS_FBA: | 367 | case DEV_CLASS_FBA: |
| @@ -563,7 +565,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, | |||
| 563 | cqr->startdev = memdev; | 565 | cqr->startdev = memdev; |
| 564 | cqr->memdev = memdev; | 566 | cqr->memdev = memdev; |
| 565 | cqr->block = block; | 567 | cqr->block = block; |
| 566 | cqr->expires = DIAG_TIMEOUT; | 568 | cqr->expires = memdev->default_expires * HZ; |
| 567 | cqr->status = DASD_CQR_FILLED; | 569 | cqr->status = DASD_CQR_FILLED; |
| 568 | return cqr; | 570 | return cqr; |
| 569 | } | 571 | } |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ab84da5592e8..66360c24bd48 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -82,6 +82,14 @@ static struct ccw_driver dasd_eckd_driver; /* see below */ | |||
| 82 | #define INIT_CQR_UNFORMATTED 1 | 82 | #define INIT_CQR_UNFORMATTED 1 |
| 83 | #define INIT_CQR_ERROR 2 | 83 | #define INIT_CQR_ERROR 2 |
| 84 | 84 | ||
| 85 | /* emergency request for reserve/release */ | ||
| 86 | static struct { | ||
| 87 | struct dasd_ccw_req cqr; | ||
| 88 | struct ccw1 ccw; | ||
| 89 | char data[32]; | ||
| 90 | } *dasd_reserve_req; | ||
| 91 | static DEFINE_MUTEX(dasd_reserve_mutex); | ||
| 92 | |||
| 85 | 93 | ||
| 86 | /* initial attempt at a probe function. this can be simplified once | 94 | /* initial attempt at a probe function. this can be simplified once |
| 87 | * the other detection code is gone */ | 95 | * the other detection code is gone */ |
| @@ -1107,8 +1115,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1107 | struct dasd_eckd_private *private; | 1115 | struct dasd_eckd_private *private; |
| 1108 | struct dasd_block *block; | 1116 | struct dasd_block *block; |
| 1109 | struct dasd_uid temp_uid; | 1117 | struct dasd_uid temp_uid; |
| 1110 | int is_known, rc; | 1118 | int is_known, rc, i; |
| 1111 | int readonly; | 1119 | int readonly; |
| 1120 | unsigned long value; | ||
| 1112 | 1121 | ||
| 1113 | if (!ccw_device_is_pathgroup(device->cdev)) { | 1122 | if (!ccw_device_is_pathgroup(device->cdev)) { |
| 1114 | dev_warn(&device->cdev->dev, | 1123 | dev_warn(&device->cdev->dev, |
| @@ -1143,6 +1152,18 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1143 | if (rc) | 1152 | if (rc) |
| 1144 | goto out_err1; | 1153 | goto out_err1; |
| 1145 | 1154 | ||
| 1155 | /* set default timeout */ | ||
| 1156 | device->default_expires = DASD_EXPIRES; | ||
| 1157 | if (private->gneq) { | ||
| 1158 | value = 1; | ||
| 1159 | for (i = 0; i < private->gneq->timeout.value; i++) | ||
| 1160 | value = 10 * value; | ||
| 1161 | value = value * private->gneq->timeout.number; | ||
| 1162 | /* do not accept useless values */ | ||
| 1163 | if (value != 0 && value <= DASD_EXPIRES_MAX) | ||
| 1164 | device->default_expires = value; | ||
| 1165 | } | ||
| 1166 | |||
| 1146 | /* Generate device unique id */ | 1167 | /* Generate device unique id */ |
| 1147 | rc = dasd_eckd_generate_uid(device); | 1168 | rc = dasd_eckd_generate_uid(device); |
| 1148 | if (rc) | 1169 | if (rc) |
| @@ -1973,7 +1994,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( | |||
| 1973 | cqr->startdev = startdev; | 1994 | cqr->startdev = startdev; |
| 1974 | cqr->memdev = startdev; | 1995 | cqr->memdev = startdev; |
| 1975 | cqr->block = block; | 1996 | cqr->block = block; |
| 1976 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 1997 | cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ |
| 1977 | cqr->lpm = private->path_data.ppm; | 1998 | cqr->lpm = private->path_data.ppm; |
| 1978 | cqr->retries = 256; | 1999 | cqr->retries = 256; |
| 1979 | cqr->buildclk = get_clock(); | 2000 | cqr->buildclk = get_clock(); |
| @@ -2150,7 +2171,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
| 2150 | cqr->startdev = startdev; | 2171 | cqr->startdev = startdev; |
| 2151 | cqr->memdev = startdev; | 2172 | cqr->memdev = startdev; |
| 2152 | cqr->block = block; | 2173 | cqr->block = block; |
| 2153 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 2174 | cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ |
| 2154 | cqr->lpm = private->path_data.ppm; | 2175 | cqr->lpm = private->path_data.ppm; |
| 2155 | cqr->retries = 256; | 2176 | cqr->retries = 256; |
| 2156 | cqr->buildclk = get_clock(); | 2177 | cqr->buildclk = get_clock(); |
| @@ -2398,7 +2419,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
| 2398 | cqr->startdev = startdev; | 2419 | cqr->startdev = startdev; |
| 2399 | cqr->memdev = startdev; | 2420 | cqr->memdev = startdev; |
| 2400 | cqr->block = block; | 2421 | cqr->block = block; |
| 2401 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 2422 | cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ |
| 2402 | cqr->lpm = private->path_data.ppm; | 2423 | cqr->lpm = private->path_data.ppm; |
| 2403 | cqr->retries = 256; | 2424 | cqr->retries = 256; |
| 2404 | cqr->buildclk = get_clock(); | 2425 | cqr->buildclk = get_clock(); |
| @@ -2645,15 +2666,23 @@ dasd_eckd_release(struct dasd_device *device) | |||
| 2645 | struct dasd_ccw_req *cqr; | 2666 | struct dasd_ccw_req *cqr; |
| 2646 | int rc; | 2667 | int rc; |
| 2647 | struct ccw1 *ccw; | 2668 | struct ccw1 *ccw; |
| 2669 | int useglobal; | ||
| 2648 | 2670 | ||
| 2649 | if (!capable(CAP_SYS_ADMIN)) | 2671 | if (!capable(CAP_SYS_ADMIN)) |
| 2650 | return -EACCES; | 2672 | return -EACCES; |
| 2651 | 2673 | ||
| 2674 | useglobal = 0; | ||
| 2652 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); | 2675 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
| 2653 | if (IS_ERR(cqr)) { | 2676 | if (IS_ERR(cqr)) { |
| 2654 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2677 | mutex_lock(&dasd_reserve_mutex); |
| 2655 | "Could not allocate initialization request"); | 2678 | useglobal = 1; |
| 2656 | return PTR_ERR(cqr); | 2679 | cqr = &dasd_reserve_req->cqr; |
| 2680 | memset(cqr, 0, sizeof(*cqr)); | ||
| 2681 | memset(&dasd_reserve_req->ccw, 0, | ||
| 2682 | sizeof(dasd_reserve_req->ccw)); | ||
| 2683 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
| 2684 | cqr->data = &dasd_reserve_req->data; | ||
| 2685 | cqr->magic = DASD_ECKD_MAGIC; | ||
| 2657 | } | 2686 | } |
| 2658 | ccw = cqr->cpaddr; | 2687 | ccw = cqr->cpaddr; |
| 2659 | ccw->cmd_code = DASD_ECKD_CCW_RELEASE; | 2688 | ccw->cmd_code = DASD_ECKD_CCW_RELEASE; |
| @@ -2671,7 +2700,10 @@ dasd_eckd_release(struct dasd_device *device) | |||
| 2671 | 2700 | ||
| 2672 | rc = dasd_sleep_on_immediatly(cqr); | 2701 | rc = dasd_sleep_on_immediatly(cqr); |
| 2673 | 2702 | ||
| 2674 | dasd_sfree_request(cqr, cqr->memdev); | 2703 | if (useglobal) |
| 2704 | mutex_unlock(&dasd_reserve_mutex); | ||
| 2705 | else | ||
| 2706 | dasd_sfree_request(cqr, cqr->memdev); | ||
| 2675 | return rc; | 2707 | return rc; |
| 2676 | } | 2708 | } |
| 2677 | 2709 | ||
| @@ -2687,15 +2719,23 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
| 2687 | struct dasd_ccw_req *cqr; | 2719 | struct dasd_ccw_req *cqr; |
| 2688 | int rc; | 2720 | int rc; |
| 2689 | struct ccw1 *ccw; | 2721 | struct ccw1 *ccw; |
| 2722 | int useglobal; | ||
| 2690 | 2723 | ||
| 2691 | if (!capable(CAP_SYS_ADMIN)) | 2724 | if (!capable(CAP_SYS_ADMIN)) |
| 2692 | return -EACCES; | 2725 | return -EACCES; |
| 2693 | 2726 | ||
| 2727 | useglobal = 0; | ||
| 2694 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); | 2728 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
| 2695 | if (IS_ERR(cqr)) { | 2729 | if (IS_ERR(cqr)) { |
| 2696 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2730 | mutex_lock(&dasd_reserve_mutex); |
| 2697 | "Could not allocate initialization request"); | 2731 | useglobal = 1; |
| 2698 | return PTR_ERR(cqr); | 2732 | cqr = &dasd_reserve_req->cqr; |
| 2733 | memset(cqr, 0, sizeof(*cqr)); | ||
| 2734 | memset(&dasd_reserve_req->ccw, 0, | ||
| 2735 | sizeof(dasd_reserve_req->ccw)); | ||
| 2736 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
| 2737 | cqr->data = &dasd_reserve_req->data; | ||
| 2738 | cqr->magic = DASD_ECKD_MAGIC; | ||
| 2699 | } | 2739 | } |
| 2700 | ccw = cqr->cpaddr; | 2740 | ccw = cqr->cpaddr; |
| 2701 | ccw->cmd_code = DASD_ECKD_CCW_RESERVE; | 2741 | ccw->cmd_code = DASD_ECKD_CCW_RESERVE; |
| @@ -2713,7 +2753,10 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
| 2713 | 2753 | ||
| 2714 | rc = dasd_sleep_on_immediatly(cqr); | 2754 | rc = dasd_sleep_on_immediatly(cqr); |
| 2715 | 2755 | ||
| 2716 | dasd_sfree_request(cqr, cqr->memdev); | 2756 | if (useglobal) |
| 2757 | mutex_unlock(&dasd_reserve_mutex); | ||
| 2758 | else | ||
| 2759 | dasd_sfree_request(cqr, cqr->memdev); | ||
| 2717 | return rc; | 2760 | return rc; |
| 2718 | } | 2761 | } |
| 2719 | 2762 | ||
| @@ -2728,15 +2771,23 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
| 2728 | struct dasd_ccw_req *cqr; | 2771 | struct dasd_ccw_req *cqr; |
| 2729 | int rc; | 2772 | int rc; |
| 2730 | struct ccw1 *ccw; | 2773 | struct ccw1 *ccw; |
| 2774 | int useglobal; | ||
| 2731 | 2775 | ||
| 2732 | if (!capable(CAP_SYS_ADMIN)) | 2776 | if (!capable(CAP_SYS_ADMIN)) |
| 2733 | return -EACCES; | 2777 | return -EACCES; |
| 2734 | 2778 | ||
| 2779 | useglobal = 0; | ||
| 2735 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); | 2780 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
| 2736 | if (IS_ERR(cqr)) { | 2781 | if (IS_ERR(cqr)) { |
| 2737 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2782 | mutex_lock(&dasd_reserve_mutex); |
| 2738 | "Could not allocate initialization request"); | 2783 | useglobal = 1; |
| 2739 | return PTR_ERR(cqr); | 2784 | cqr = &dasd_reserve_req->cqr; |
| 2785 | memset(cqr, 0, sizeof(*cqr)); | ||
| 2786 | memset(&dasd_reserve_req->ccw, 0, | ||
| 2787 | sizeof(dasd_reserve_req->ccw)); | ||
| 2788 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
| 2789 | cqr->data = &dasd_reserve_req->data; | ||
| 2790 | cqr->magic = DASD_ECKD_MAGIC; | ||
| 2740 | } | 2791 | } |
| 2741 | ccw = cqr->cpaddr; | 2792 | ccw = cqr->cpaddr; |
| 2742 | ccw->cmd_code = DASD_ECKD_CCW_SLCK; | 2793 | ccw->cmd_code = DASD_ECKD_CCW_SLCK; |
| @@ -2754,7 +2805,10 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
| 2754 | 2805 | ||
| 2755 | rc = dasd_sleep_on_immediatly(cqr); | 2806 | rc = dasd_sleep_on_immediatly(cqr); |
| 2756 | 2807 | ||
| 2757 | dasd_sfree_request(cqr, cqr->memdev); | 2808 | if (useglobal) |
| 2809 | mutex_unlock(&dasd_reserve_mutex); | ||
| 2810 | else | ||
| 2811 | dasd_sfree_request(cqr, cqr->memdev); | ||
| 2758 | return rc; | 2812 | return rc; |
| 2759 | } | 2813 | } |
| 2760 | 2814 | ||
| @@ -3488,10 +3542,15 @@ dasd_eckd_init(void) | |||
| 3488 | int ret; | 3542 | int ret; |
| 3489 | 3543 | ||
| 3490 | ASCEBC(dasd_eckd_discipline.ebcname, 4); | 3544 | ASCEBC(dasd_eckd_discipline.ebcname, 4); |
| 3545 | dasd_reserve_req = kmalloc(sizeof(*dasd_reserve_req), | ||
| 3546 | GFP_KERNEL | GFP_DMA); | ||
| 3547 | if (!dasd_reserve_req) | ||
| 3548 | return -ENOMEM; | ||
| 3491 | ret = ccw_driver_register(&dasd_eckd_driver); | 3549 | ret = ccw_driver_register(&dasd_eckd_driver); |
| 3492 | if (!ret) | 3550 | if (!ret) |
| 3493 | wait_for_device_probe(); | 3551 | wait_for_device_probe(); |
| 3494 | 3552 | else | |
| 3553 | kfree(dasd_reserve_req); | ||
| 3495 | return ret; | 3554 | return ret; |
| 3496 | } | 3555 | } |
| 3497 | 3556 | ||
| @@ -3499,6 +3558,7 @@ static void __exit | |||
| 3499 | dasd_eckd_cleanup(void) | 3558 | dasd_eckd_cleanup(void) |
| 3500 | { | 3559 | { |
| 3501 | ccw_driver_unregister(&dasd_eckd_driver); | 3560 | ccw_driver_unregister(&dasd_eckd_driver); |
| 3561 | kfree(dasd_reserve_req); | ||
| 3502 | } | 3562 | } |
| 3503 | 3563 | ||
| 3504 | module_init(dasd_eckd_init); | 3564 | module_init(dasd_eckd_init); |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index dd6385a5af14..0eb49655a6cd 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
| @@ -320,7 +320,12 @@ struct dasd_gneq { | |||
| 320 | __u8 identifier:2; | 320 | __u8 identifier:2; |
| 321 | __u8 reserved:6; | 321 | __u8 reserved:6; |
| 322 | } __attribute__ ((packed)) flags; | 322 | } __attribute__ ((packed)) flags; |
| 323 | __u8 reserved[7]; | 323 | __u8 reserved[5]; |
| 324 | struct { | ||
| 325 | __u8 value:2; | ||
| 326 | __u8 number:6; | ||
| 327 | } __attribute__ ((packed)) timeout; | ||
| 328 | __u8 reserved3; | ||
| 324 | __u16 subsystemID; | 329 | __u16 subsystemID; |
| 325 | __u8 reserved2[22]; | 330 | __u8 reserved2[22]; |
| 326 | } __attribute__ ((packed)); | 331 | } __attribute__ ((packed)); |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 37282b90eecc..bec5486e0e6d 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
| @@ -163,6 +163,8 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
| 163 | return rc; | 163 | return rc; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | device->default_expires = DASD_EXPIRES; | ||
| 167 | |||
| 166 | readonly = dasd_device_is_ro(device); | 168 | readonly = dasd_device_is_ro(device); |
| 167 | if (readonly) | 169 | if (readonly) |
| 168 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); | 170 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); |
| @@ -370,7 +372,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, | |||
| 370 | cqr->startdev = memdev; | 372 | cqr->startdev = memdev; |
| 371 | cqr->memdev = memdev; | 373 | cqr->memdev = memdev; |
| 372 | cqr->block = block; | 374 | cqr->block = block; |
| 373 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 375 | cqr->expires = memdev->default_expires * HZ; /* default 5 minutes */ |
| 374 | cqr->retries = 32; | 376 | cqr->retries = 32; |
| 375 | cqr->buildclk = get_clock(); | 377 | cqr->buildclk = get_clock(); |
| 376 | cqr->status = DASD_CQR_FILLED; | 378 | cqr->status = DASD_CQR_FILLED; |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 49b431d135e0..500678d7116c 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -186,7 +186,7 @@ struct dasd_ccw_req { | |||
| 186 | 186 | ||
| 187 | /* ... and how */ | 187 | /* ... and how */ |
| 188 | unsigned long starttime; /* jiffies time of request start */ | 188 | unsigned long starttime; /* jiffies time of request start */ |
| 189 | int expires; /* expiration period in jiffies */ | 189 | unsigned long expires; /* expiration period in jiffies */ |
| 190 | char lpm; /* logical path mask */ | 190 | char lpm; /* logical path mask */ |
| 191 | void *data; /* pointer to data area */ | 191 | void *data; /* pointer to data area */ |
| 192 | 192 | ||
| @@ -224,6 +224,9 @@ struct dasd_ccw_req { | |||
| 224 | #define DASD_CQR_CLEARED 0x84 /* request was cleared */ | 224 | #define DASD_CQR_CLEARED 0x84 /* request was cleared */ |
| 225 | #define DASD_CQR_SUCCESS 0x85 /* request was successful */ | 225 | #define DASD_CQR_SUCCESS 0x85 /* request was successful */ |
| 226 | 226 | ||
| 227 | /* default expiration time*/ | ||
| 228 | #define DASD_EXPIRES 300 | ||
| 229 | #define DASD_EXPIRES_MAX 40000000 | ||
| 227 | 230 | ||
| 228 | /* per dasd_ccw_req flags */ | 231 | /* per dasd_ccw_req flags */ |
| 229 | #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ | 232 | #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ |
| @@ -404,6 +407,9 @@ struct dasd_device { | |||
| 404 | 407 | ||
| 405 | /* hook for alias management */ | 408 | /* hook for alias management */ |
| 406 | struct list_head alias_list; | 409 | struct list_head alias_list; |
| 410 | |||
| 411 | /* default expiration time in s */ | ||
| 412 | unsigned long default_expires; | ||
| 407 | }; | 413 | }; |
| 408 | 414 | ||
| 409 | struct dasd_block { | 415 | struct dasd_block { |
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c index 7f206ed44fdf..d15f8b4d78bd 100644 --- a/drivers/s390/cio/ccwreq.c +++ b/drivers/s390/cio/ccwreq.c | |||
| @@ -38,9 +38,13 @@ static u16 ccwreq_next_path(struct ccw_device *cdev) | |||
| 38 | { | 38 | { |
| 39 | struct ccw_request *req = &cdev->private->req; | 39 | struct ccw_request *req = &cdev->private->req; |
| 40 | 40 | ||
| 41 | if (!req->singlepath) { | ||
| 42 | req->mask = 0; | ||
| 43 | goto out; | ||
| 44 | } | ||
| 41 | req->retries = req->maxretries; | 45 | req->retries = req->maxretries; |
| 42 | req->mask = lpm_adjust(req->mask >>= 1, req->lpm); | 46 | req->mask = lpm_adjust(req->mask >>= 1, req->lpm); |
| 43 | 47 | out: | |
| 44 | return req->mask; | 48 | return req->mask; |
| 45 | } | 49 | } |
| 46 | 50 | ||
| @@ -113,8 +117,12 @@ void ccw_request_start(struct ccw_device *cdev) | |||
| 113 | { | 117 | { |
| 114 | struct ccw_request *req = &cdev->private->req; | 118 | struct ccw_request *req = &cdev->private->req; |
| 115 | 119 | ||
| 116 | /* Try all paths twice to counter link flapping. */ | 120 | if (req->singlepath) { |
| 117 | req->mask = 0x8080; | 121 | /* Try all paths twice to counter link flapping. */ |
| 122 | req->mask = 0x8080; | ||
| 123 | } else | ||
| 124 | req->mask = req->lpm; | ||
| 125 | |||
| 118 | req->retries = req->maxretries; | 126 | req->retries = req->maxretries; |
| 119 | req->mask = lpm_adjust(req->mask, req->lpm); | 127 | req->mask = lpm_adjust(req->mask, req->lpm); |
| 120 | req->drc = 0; | 128 | req->drc = 0; |
| @@ -182,6 +190,8 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
| 182 | /* Ask the driver what to do */ | 190 | /* Ask the driver what to do */ |
| 183 | if (cdev->drv && cdev->drv->uc_handler) { | 191 | if (cdev->drv && cdev->drv->uc_handler) { |
| 184 | todo = cdev->drv->uc_handler(cdev, lcirb); | 192 | todo = cdev->drv->uc_handler(cdev, lcirb); |
| 193 | CIO_TRACE_EVENT(2, "uc_response"); | ||
| 194 | CIO_HEX_EVENT(2, &todo, sizeof(todo)); | ||
| 185 | switch (todo) { | 195 | switch (todo) { |
| 186 | case UC_TODO_RETRY: | 196 | case UC_TODO_RETRY: |
| 187 | return IO_STATUS_ERROR; | 197 | return IO_STATUS_ERROR; |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 407d0e9adfaf..4cbb1a6ca33c 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "chsc.h" | 29 | #include "chsc.h" |
| 30 | 30 | ||
| 31 | static void *sei_page; | 31 | static void *sei_page; |
| 32 | static DEFINE_SPINLOCK(siosl_lock); | ||
| 32 | static DEFINE_SPINLOCK(sda_lock); | 33 | static DEFINE_SPINLOCK(sda_lock); |
| 33 | 34 | ||
| 34 | /** | 35 | /** |
| @@ -48,6 +49,7 @@ int chsc_error_from_response(int response) | |||
| 48 | case 0x0007: | 49 | case 0x0007: |
| 49 | case 0x0008: | 50 | case 0x0008: |
| 50 | case 0x000a: | 51 | case 0x000a: |
| 52 | case 0x0104: | ||
| 51 | return -EINVAL; | 53 | return -EINVAL; |
| 52 | case 0x0004: | 54 | case 0x0004: |
| 53 | return -EOPNOTSUPP; | 55 | return -EOPNOTSUPP; |
| @@ -974,3 +976,49 @@ int chsc_sstpi(void *page, void *result, size_t size) | |||
| 974 | return (rr->response.code == 0x0001) ? 0 : -EIO; | 976 | return (rr->response.code == 0x0001) ? 0 : -EIO; |
| 975 | } | 977 | } |
| 976 | 978 | ||
| 979 | static struct { | ||
| 980 | struct chsc_header request; | ||
| 981 | u32 word1; | ||
| 982 | struct subchannel_id sid; | ||
| 983 | u32 word3; | ||
| 984 | struct chsc_header response; | ||
| 985 | u32 word[11]; | ||
| 986 | } __attribute__ ((packed)) siosl_area __attribute__ ((__aligned__(PAGE_SIZE))); | ||
| 987 | |||
| 988 | int chsc_siosl(struct subchannel_id schid) | ||
| 989 | { | ||
| 990 | unsigned long flags; | ||
| 991 | int ccode; | ||
| 992 | int rc; | ||
| 993 | |||
| 994 | spin_lock_irqsave(&siosl_lock, flags); | ||
| 995 | memset(&siosl_area, 0, sizeof(siosl_area)); | ||
| 996 | siosl_area.request.length = 0x0010; | ||
| 997 | siosl_area.request.code = 0x0046; | ||
| 998 | siosl_area.word1 = 0x80000000; | ||
| 999 | siosl_area.sid = schid; | ||
| 1000 | |||
| 1001 | ccode = chsc(&siosl_area); | ||
| 1002 | if (ccode > 0) { | ||
| 1003 | if (ccode == 3) | ||
| 1004 | rc = -ENODEV; | ||
| 1005 | else | ||
| 1006 | rc = -EBUSY; | ||
| 1007 | CIO_MSG_EVENT(2, "chsc: chsc failed for 0.%x.%04x (ccode=%d)\n", | ||
| 1008 | schid.ssid, schid.sch_no, ccode); | ||
| 1009 | goto out; | ||
| 1010 | } | ||
| 1011 | rc = chsc_error_from_response(siosl_area.response.code); | ||
| 1012 | if (rc) | ||
| 1013 | CIO_MSG_EVENT(2, "chsc: siosl failed for 0.%x.%04x (rc=%04x)\n", | ||
| 1014 | schid.ssid, schid.sch_no, | ||
| 1015 | siosl_area.response.code); | ||
| 1016 | else | ||
| 1017 | CIO_MSG_EVENT(4, "chsc: siosl succeeded for 0.%x.%04x\n", | ||
| 1018 | schid.ssid, schid.sch_no); | ||
| 1019 | out: | ||
| 1020 | spin_unlock_irqrestore(&siosl_lock, flags); | ||
| 1021 | |||
| 1022 | return rc; | ||
| 1023 | } | ||
| 1024 | EXPORT_SYMBOL_GPL(chsc_siosl); | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 37aa611d4ac5..5453013f094b 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
| @@ -80,4 +80,6 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp); | |||
| 80 | 80 | ||
| 81 | int chsc_error_from_response(int response); | 81 | int chsc_error_from_response(int response); |
| 82 | 82 | ||
| 83 | int chsc_siosl(struct subchannel_id schid); | ||
| 84 | |||
| 83 | #endif | 85 | #endif |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6d229f3523a0..51bd3687d163 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "ioasm.h" | 36 | #include "ioasm.h" |
| 37 | #include "io_sch.h" | 37 | #include "io_sch.h" |
| 38 | #include "blacklist.h" | 38 | #include "blacklist.h" |
| 39 | #include "chsc.h" | ||
| 39 | 40 | ||
| 40 | static struct timer_list recovery_timer; | 41 | static struct timer_list recovery_timer; |
| 41 | static DEFINE_SPINLOCK(recovery_lock); | 42 | static DEFINE_SPINLOCK(recovery_lock); |
| @@ -486,9 +487,11 @@ static int online_store_handle_offline(struct ccw_device *cdev) | |||
| 486 | spin_lock_irq(cdev->ccwlock); | 487 | spin_lock_irq(cdev->ccwlock); |
| 487 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); | 488 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); |
| 488 | spin_unlock_irq(cdev->ccwlock); | 489 | spin_unlock_irq(cdev->ccwlock); |
| 489 | } else if (cdev->online && cdev->drv && cdev->drv->set_offline) | 490 | return 0; |
| 491 | } | ||
| 492 | if (cdev->drv && cdev->drv->set_offline) | ||
| 490 | return ccw_device_set_offline(cdev); | 493 | return ccw_device_set_offline(cdev); |
| 491 | return 0; | 494 | return -EINVAL; |
| 492 | } | 495 | } |
| 493 | 496 | ||
| 494 | static int online_store_recog_and_online(struct ccw_device *cdev) | 497 | static int online_store_recog_and_online(struct ccw_device *cdev) |
| @@ -505,8 +508,8 @@ static int online_store_recog_and_online(struct ccw_device *cdev) | |||
| 505 | return -EAGAIN; | 508 | return -EAGAIN; |
| 506 | } | 509 | } |
| 507 | if (cdev->drv && cdev->drv->set_online) | 510 | if (cdev->drv && cdev->drv->set_online) |
| 508 | ccw_device_set_online(cdev); | 511 | return ccw_device_set_online(cdev); |
| 509 | return 0; | 512 | return -EINVAL; |
| 510 | } | 513 | } |
| 511 | 514 | ||
| 512 | static int online_store_handle_online(struct ccw_device *cdev, int force) | 515 | static int online_store_handle_online(struct ccw_device *cdev, int force) |
| @@ -598,6 +601,25 @@ available_show (struct device *dev, struct device_attribute *attr, char *buf) | |||
| 598 | } | 601 | } |
| 599 | } | 602 | } |
| 600 | 603 | ||
| 604 | static ssize_t | ||
| 605 | initiate_logging(struct device *dev, struct device_attribute *attr, | ||
| 606 | const char *buf, size_t count) | ||
| 607 | { | ||
| 608 | struct subchannel *sch = to_subchannel(dev); | ||
| 609 | int rc; | ||
| 610 | |||
| 611 | rc = chsc_siosl(sch->schid); | ||
| 612 | if (rc < 0) { | ||
| 613 | pr_warning("Logging for subchannel 0.%x.%04x failed with " | ||
| 614 | "errno=%d\n", | ||
| 615 | sch->schid.ssid, sch->schid.sch_no, rc); | ||
| 616 | return rc; | ||
| 617 | } | ||
| 618 | pr_notice("Logging for subchannel 0.%x.%04x was triggered\n", | ||
| 619 | sch->schid.ssid, sch->schid.sch_no); | ||
| 620 | return count; | ||
| 621 | } | ||
| 622 | |||
| 601 | static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); | 623 | static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); |
| 602 | static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); | 624 | static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); |
| 603 | static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); | 625 | static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); |
| @@ -605,10 +627,12 @@ static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); | |||
| 605 | static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); | 627 | static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); |
| 606 | static DEVICE_ATTR(online, 0644, online_show, online_store); | 628 | static DEVICE_ATTR(online, 0644, online_show, online_store); |
| 607 | static DEVICE_ATTR(availability, 0444, available_show, NULL); | 629 | static DEVICE_ATTR(availability, 0444, available_show, NULL); |
| 630 | static DEVICE_ATTR(logging, 0200, NULL, initiate_logging); | ||
| 608 | 631 | ||
| 609 | static struct attribute *io_subchannel_attrs[] = { | 632 | static struct attribute *io_subchannel_attrs[] = { |
| 610 | &dev_attr_chpids.attr, | 633 | &dev_attr_chpids.attr, |
| 611 | &dev_attr_pimpampom.attr, | 634 | &dev_attr_pimpampom.attr, |
| 635 | &dev_attr_logging.attr, | ||
| 612 | NULL, | 636 | NULL, |
| 613 | }; | 637 | }; |
| 614 | 638 | ||
| @@ -2036,6 +2060,21 @@ void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo) | |||
| 2036 | } | 2060 | } |
| 2037 | } | 2061 | } |
| 2038 | 2062 | ||
| 2063 | /** | ||
| 2064 | * ccw_device_siosl() - initiate logging | ||
| 2065 | * @cdev: ccw device | ||
| 2066 | * | ||
| 2067 | * This function is used to invoke model-dependent logging within the channel | ||
| 2068 | * subsystem. | ||
| 2069 | */ | ||
| 2070 | int ccw_device_siosl(struct ccw_device *cdev) | ||
| 2071 | { | ||
| 2072 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
| 2073 | |||
| 2074 | return chsc_siosl(sch->schid); | ||
| 2075 | } | ||
| 2076 | EXPORT_SYMBOL_GPL(ccw_device_siosl); | ||
| 2077 | |||
| 2039 | MODULE_LICENSE("GPL"); | 2078 | MODULE_LICENSE("GPL"); |
| 2040 | EXPORT_SYMBOL(ccw_device_set_online); | 2079 | EXPORT_SYMBOL(ccw_device_set_online); |
| 2041 | EXPORT_SYMBOL(ccw_device_set_offline); | 2080 | EXPORT_SYMBOL(ccw_device_set_offline); |
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 6facb5499a65..82a5ad0d63f6 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c | |||
| @@ -208,6 +208,7 @@ static void spid_start(struct ccw_device *cdev) | |||
| 208 | req->timeout = PGID_TIMEOUT; | 208 | req->timeout = PGID_TIMEOUT; |
| 209 | req->maxretries = PGID_RETRIES; | 209 | req->maxretries = PGID_RETRIES; |
| 210 | req->lpm = 0x80; | 210 | req->lpm = 0x80; |
| 211 | req->singlepath = 1; | ||
| 211 | req->callback = spid_callback; | 212 | req->callback = spid_callback; |
| 212 | spid_do(cdev); | 213 | spid_do(cdev); |
| 213 | } | 214 | } |
| @@ -420,6 +421,7 @@ static void verify_start(struct ccw_device *cdev) | |||
| 420 | req->timeout = PGID_TIMEOUT; | 421 | req->timeout = PGID_TIMEOUT; |
| 421 | req->maxretries = PGID_RETRIES; | 422 | req->maxretries = PGID_RETRIES; |
| 422 | req->lpm = 0x80; | 423 | req->lpm = 0x80; |
| 424 | req->singlepath = 1; | ||
| 423 | if (cdev->private->flags.pgroup) { | 425 | if (cdev->private->flags.pgroup) { |
| 424 | CIO_TRACE_EVENT(4, "snid"); | 426 | CIO_TRACE_EVENT(4, "snid"); |
| 425 | CIO_HEX_EVENT(4, devid, sizeof(*devid)); | 427 | CIO_HEX_EVENT(4, devid, sizeof(*devid)); |
| @@ -507,6 +509,7 @@ void ccw_device_disband_start(struct ccw_device *cdev) | |||
| 507 | req->timeout = PGID_TIMEOUT; | 509 | req->timeout = PGID_TIMEOUT; |
| 508 | req->maxretries = PGID_RETRIES; | 510 | req->maxretries = PGID_RETRIES; |
| 509 | req->lpm = sch->schib.pmcw.pam & sch->opm; | 511 | req->lpm = sch->schib.pmcw.pam & sch->opm; |
| 512 | req->singlepath = 1; | ||
| 510 | req->callback = disband_callback; | 513 | req->callback = disband_callback; |
| 511 | fn = SPID_FUNC_DISBAND; | 514 | fn = SPID_FUNC_DISBAND; |
| 512 | if (cdev->private->flags.mpath) | 515 | if (cdev->private->flags.mpath) |
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index b9ce712a7f25..469ef93f2302 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h | |||
| @@ -92,11 +92,12 @@ enum io_status { | |||
| 92 | * @filter: optional callback to adjust request status based on IRB data | 92 | * @filter: optional callback to adjust request status based on IRB data |
| 93 | * @callback: final callback | 93 | * @callback: final callback |
| 94 | * @data: user-defined pointer passed to all callbacks | 94 | * @data: user-defined pointer passed to all callbacks |
| 95 | * @singlepath: if set, use only one path from @lpm per start I/O | ||
| 96 | * @cancel: non-zero if request was cancelled | ||
| 97 | * @done: non-zero if request was finished | ||
| 95 | * @mask: current path mask | 98 | * @mask: current path mask |
| 96 | * @retries: current number of retries | 99 | * @retries: current number of retries |
| 97 | * @drc: delayed return code | 100 | * @drc: delayed return code |
| 98 | * @cancel: non-zero if request was cancelled | ||
| 99 | * @done: non-zero if request was finished | ||
| 100 | */ | 101 | */ |
| 101 | struct ccw_request { | 102 | struct ccw_request { |
| 102 | struct ccw1 *cp; | 103 | struct ccw1 *cp; |
| @@ -108,12 +109,13 @@ struct ccw_request { | |||
| 108 | enum io_status); | 109 | enum io_status); |
| 109 | void (*callback)(struct ccw_device *, void *, int); | 110 | void (*callback)(struct ccw_device *, void *, int); |
| 110 | void *data; | 111 | void *data; |
| 112 | unsigned int singlepath:1; | ||
| 111 | /* These fields are used internally. */ | 113 | /* These fields are used internally. */ |
| 114 | unsigned int cancel:1; | ||
| 115 | unsigned int done:1; | ||
| 112 | u16 mask; | 116 | u16 mask; |
| 113 | u16 retries; | 117 | u16 retries; |
| 114 | int drc; | 118 | int drc; |
| 115 | int cancel:1; | ||
| 116 | int done:1; | ||
| 117 | } __attribute__((packed)); | 119 | } __attribute__((packed)); |
| 118 | 120 | ||
| 119 | /* | 121 | /* |
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c index 137688790207..4d2ea4000422 100644 --- a/drivers/s390/net/smsgiucv_app.c +++ b/drivers/s390/net/smsgiucv_app.c | |||
| @@ -180,6 +180,13 @@ static int __init smsgiucv_app_init(void) | |||
| 180 | goto fail_put_driver; | 180 | goto fail_put_driver; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | /* convert sender to uppercase characters */ | ||
| 184 | if (sender) { | ||
| 185 | int len = strlen(sender); | ||
| 186 | while (len--) | ||
| 187 | sender[len] = toupper(sender[len]); | ||
| 188 | } | ||
| 189 | |||
| 183 | /* register with the smsgiucv device driver */ | 190 | /* register with the smsgiucv device driver */ |
| 184 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); | 191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); |
| 185 | if (rc) { | 192 | if (rc) { |
