diff options
| -rw-r--r-- | arch/s390/include/asm/dasd.h | 40 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 69 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.h | 1 |
3 files changed, 92 insertions, 18 deletions
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index 218bce81ec70..b604a9186f8e 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h | |||
| @@ -217,6 +217,25 @@ typedef struct dasd_symmio_parms { | |||
| 217 | int rssd_result_len; | 217 | int rssd_result_len; |
| 218 | } __attribute__ ((packed)) dasd_symmio_parms_t; | 218 | } __attribute__ ((packed)) dasd_symmio_parms_t; |
| 219 | 219 | ||
| 220 | /* | ||
| 221 | * Data returned by Sense Path Group ID (SNID) | ||
| 222 | */ | ||
| 223 | struct dasd_snid_data { | ||
| 224 | struct { | ||
| 225 | __u8 group:2; | ||
| 226 | __u8 reserve:2; | ||
| 227 | __u8 mode:1; | ||
| 228 | __u8 res:3; | ||
| 229 | } __attribute__ ((packed)) path_state; | ||
| 230 | __u8 pgid[11]; | ||
| 231 | } __attribute__ ((packed)); | ||
| 232 | |||
| 233 | struct dasd_snid_ioctl_data { | ||
| 234 | struct dasd_snid_data data; | ||
| 235 | __u8 path_mask; | ||
| 236 | } __attribute__ ((packed)); | ||
| 237 | |||
| 238 | |||
| 220 | /******************************************************************************** | 239 | /******************************************************************************** |
| 221 | * SECTION: Definition of IOCTLs | 240 | * SECTION: Definition of IOCTLs |
| 222 | * | 241 | * |
| @@ -261,25 +280,10 @@ typedef struct dasd_symmio_parms { | |||
| 261 | /* Set Attributes (cache operations) */ | 280 | /* Set Attributes (cache operations) */ |
| 262 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) | 281 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) |
| 263 | 282 | ||
| 283 | /* Get Sense Path Group ID (SNID) data */ | ||
| 284 | #define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) | ||
| 285 | |||
| 264 | #define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) | 286 | #define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) |
| 265 | 287 | ||
| 266 | #endif /* DASD_H */ | 288 | #endif /* DASD_H */ |
| 267 | 289 | ||
| 268 | /* | ||
| 269 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 270 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 271 | * adjust the settings for this buffer only. This must remain at the end | ||
| 272 | * of the file. | ||
| 273 | * --------------------------------------------------------------------------- | ||
| 274 | * Local variables: | ||
| 275 | * c-indent-level: 4 | ||
| 276 | * c-brace-imaginary-offset: 0 | ||
| 277 | * c-brace-offset: -4 | ||
| 278 | * c-argdecl-indent: 4 | ||
| 279 | * c-label-offset: -4 | ||
| 280 | * c-continued-statement-offset: 4 | ||
| 281 | * c-continued-brace-offset: 0 | ||
| 282 | * indent-tabs-mode: nil | ||
| 283 | * tab-width: 8 | ||
| 284 | * End: | ||
| 285 | */ | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 50cf96389d2c..bf61274af3bb 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -2802,6 +2802,73 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
| 2802 | } | 2802 | } |
| 2803 | 2803 | ||
| 2804 | /* | 2804 | /* |
| 2805 | * SNID - Sense Path Group ID | ||
| 2806 | * This ioctl may be used in situations where I/O is stalled due to | ||
| 2807 | * a reserve, so if the normal dasd_smalloc_request fails, we use the | ||
| 2808 | * preallocated dasd_reserve_req. | ||
| 2809 | */ | ||
| 2810 | static int dasd_eckd_snid(struct dasd_device *device, | ||
| 2811 | void __user *argp) | ||
| 2812 | { | ||
| 2813 | struct dasd_ccw_req *cqr; | ||
| 2814 | int rc; | ||
| 2815 | struct ccw1 *ccw; | ||
| 2816 | int useglobal; | ||
| 2817 | struct dasd_snid_ioctl_data usrparm; | ||
| 2818 | |||
| 2819 | if (!capable(CAP_SYS_ADMIN)) | ||
| 2820 | return -EACCES; | ||
| 2821 | |||
| 2822 | if (copy_from_user(&usrparm, argp, sizeof(usrparm))) | ||
| 2823 | return -EFAULT; | ||
| 2824 | |||
| 2825 | useglobal = 0; | ||
| 2826 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, | ||
| 2827 | sizeof(struct dasd_snid_data), device); | ||
| 2828 | if (IS_ERR(cqr)) { | ||
| 2829 | mutex_lock(&dasd_reserve_mutex); | ||
| 2830 | useglobal = 1; | ||
| 2831 | cqr = &dasd_reserve_req->cqr; | ||
| 2832 | memset(cqr, 0, sizeof(*cqr)); | ||
| 2833 | memset(&dasd_reserve_req->ccw, 0, | ||
| 2834 | sizeof(dasd_reserve_req->ccw)); | ||
| 2835 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
| 2836 | cqr->data = &dasd_reserve_req->data; | ||
| 2837 | cqr->magic = DASD_ECKD_MAGIC; | ||
| 2838 | } | ||
| 2839 | ccw = cqr->cpaddr; | ||
| 2840 | ccw->cmd_code = DASD_ECKD_CCW_SNID; | ||
| 2841 | ccw->flags |= CCW_FLAG_SLI; | ||
| 2842 | ccw->count = 12; | ||
| 2843 | ccw->cda = (__u32)(addr_t) cqr->data; | ||
| 2844 | cqr->startdev = device; | ||
| 2845 | cqr->memdev = device; | ||
| 2846 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | ||
| 2847 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | ||
| 2848 | cqr->retries = 5; | ||
| 2849 | cqr->expires = 10 * HZ; | ||
| 2850 | cqr->buildclk = get_clock(); | ||
| 2851 | cqr->status = DASD_CQR_FILLED; | ||
| 2852 | cqr->lpm = usrparm.path_mask; | ||
| 2853 | |||
| 2854 | rc = dasd_sleep_on_immediatly(cqr); | ||
| 2855 | /* verify that I/O processing didn't modify the path mask */ | ||
| 2856 | if (!rc && usrparm.path_mask && (cqr->lpm != usrparm.path_mask)) | ||
| 2857 | rc = -EIO; | ||
| 2858 | if (!rc) { | ||
| 2859 | usrparm.data = *((struct dasd_snid_data *)cqr->data); | ||
| 2860 | if (copy_to_user(argp, &usrparm, sizeof(usrparm))) | ||
| 2861 | rc = -EFAULT; | ||
| 2862 | } | ||
| 2863 | |||
| 2864 | if (useglobal) | ||
| 2865 | mutex_unlock(&dasd_reserve_mutex); | ||
| 2866 | else | ||
| 2867 | dasd_sfree_request(cqr, cqr->memdev); | ||
| 2868 | return rc; | ||
| 2869 | } | ||
| 2870 | |||
| 2871 | /* | ||
| 2805 | * Read performance statistics | 2872 | * Read performance statistics |
| 2806 | */ | 2873 | */ |
| 2807 | static int | 2874 | static int |
| @@ -3036,6 +3103,8 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) | |||
| 3036 | return dasd_eckd_reserve(device); | 3103 | return dasd_eckd_reserve(device); |
| 3037 | case BIODASDSLCK: | 3104 | case BIODASDSLCK: |
| 3038 | return dasd_eckd_steal_lock(device); | 3105 | return dasd_eckd_steal_lock(device); |
| 3106 | case BIODASDSNID: | ||
| 3107 | return dasd_eckd_snid(device, argp); | ||
| 3039 | case BIODASDSYMMIO: | 3108 | case BIODASDSYMMIO: |
| 3040 | return dasd_symm_io(device, argp); | 3109 | return dasd_symm_io(device, argp); |
| 3041 | default: | 3110 | default: |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 0eb49655a6cd..12097c24f2f5 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #define DASD_ECKD_CCW_WRITE_CKD 0x1d | 27 | #define DASD_ECKD_CCW_WRITE_CKD 0x1d |
| 28 | #define DASD_ECKD_CCW_READ_CKD 0x1e | 28 | #define DASD_ECKD_CCW_READ_CKD 0x1e |
| 29 | #define DASD_ECKD_CCW_PSF 0x27 | 29 | #define DASD_ECKD_CCW_PSF 0x27 |
| 30 | #define DASD_ECKD_CCW_SNID 0x34 | ||
| 30 | #define DASD_ECKD_CCW_RSSD 0x3e | 31 | #define DASD_ECKD_CCW_RSSD 0x3e |
| 31 | #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 | 32 | #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 |
| 32 | #define DASD_ECKD_CCW_SNSS 0x54 | 33 | #define DASD_ECKD_CCW_SNSS 0x54 |
