aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_eckd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r--drivers/s390/block/dasd_eckd.c81
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index cecab2274a6e..c9583fbc2a7d 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -450,6 +450,81 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
450 return 0; 450 return 0;
451} 451}
452 452
453struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device,
454 void *rcd_buffer,
455 struct ciw *ciw, __u8 lpm)
456{
457 struct dasd_ccw_req *cqr;
458 struct ccw1 *ccw;
459
460 cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
461
462 if (IS_ERR(cqr)) {
463 DEV_MESSAGE(KERN_WARNING, device, "%s",
464 "Could not allocate RCD request");
465 return cqr;
466 }
467
468 ccw = cqr->cpaddr;
469 ccw->cmd_code = ciw->cmd;
470 ccw->cda = (__u32)(addr_t)rcd_buffer;
471 ccw->count = ciw->count;
472
473 cqr->device = device;
474 cqr->expires = 10*HZ;
475 cqr->lpm = lpm;
476 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
477 cqr->retries = 2;
478 cqr->buildclk = get_clock();
479 cqr->status = DASD_CQR_FILLED;
480 return cqr;
481}
482
483static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
484 void **rcd_buffer,
485 int *rcd_buffer_size, __u8 lpm)
486{
487 struct ciw *ciw;
488 char *rcd_buf = NULL;
489 int ret;
490 struct dasd_ccw_req *cqr;
491
492 /*
493 * scan for RCD command in extended SenseID data
494 */
495 ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
496 if (!ciw || ciw->cmd == 0) {
497 ret = -EOPNOTSUPP;
498 goto out_error;
499 }
500 rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
501 if (!rcd_buf) {
502 ret = -ENOMEM;
503 goto out_error;
504 }
505 cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
506 if (IS_ERR(cqr)) {
507 ret = PTR_ERR(cqr);
508 goto out_error;
509 }
510 ret = dasd_sleep_on(cqr);
511 /*
512 * on success we update the user input parms
513 */
514 dasd_sfree_request(cqr, cqr->device);
515 if (ret)
516 goto out_error;
517
518 *rcd_buffer_size = ciw->count;
519 *rcd_buffer = rcd_buf;
520 return 0;
521out_error:
522 kfree(rcd_buf);
523 *rcd_buffer = NULL;
524 *rcd_buffer_size = 0;
525 return ret;
526}
527
453static int 528static int
454dasd_eckd_read_conf(struct dasd_device *device) 529dasd_eckd_read_conf(struct dasd_device *device)
455{ 530{
@@ -469,8 +544,8 @@ dasd_eckd_read_conf(struct dasd_device *device)
469 /* get configuration data per operational path */ 544 /* get configuration data per operational path */
470 for (lpm = 0x80; lpm; lpm>>= 1) { 545 for (lpm = 0x80; lpm; lpm>>= 1) {
471 if (lpm & path_data->opm){ 546 if (lpm & path_data->opm){
472 rc = read_conf_data_lpm(device->cdev, &conf_data, 547 rc = dasd_eckd_read_conf_lpm(device, &conf_data,
473 &conf_len, lpm); 548 &conf_len, lpm);
474 if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ 549 if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */
475 MESSAGE(KERN_WARNING, 550 MESSAGE(KERN_WARNING,
476 "Read configuration data returned " 551 "Read configuration data returned "
@@ -639,7 +714,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
639 /* Read Device Characteristics */ 714 /* Read Device Characteristics */
640 rdc_data = (void *) &(private->rdc_data); 715 rdc_data = (void *) &(private->rdc_data);
641 memset(rdc_data, 0, sizeof(rdc_data)); 716 memset(rdc_data, 0, sizeof(rdc_data));
642 rc = read_dev_chars(device->cdev, &rdc_data, 64); 717 rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
643 if (rc) 718 if (rc)
644 DEV_MESSAGE(KERN_WARNING, device, 719 DEV_MESSAGE(KERN_WARNING, device,
645 "Read device characteristics returned " 720 "Read device characteristics returned "