diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2007-05-04 12:47:51 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-05-04 12:48:26 -0400 |
commit | 17283b56eceb6b7d9cc48dc74759a2450699c22a (patch) | |
tree | ded19dee693d1b712c0f5117610b21eb4761d017 /drivers/s390/block/dasd_eckd.c | |
parent | 52706ec903dcc7679acf5b93400d68fbc5384553 (diff) |
[S390] dasd: New read device characteristics and read configuration data.
Instead of the deprecated read_dev_chars() and read_conf_data_lpm(),
implement dasd_generic_read_dev_chars() and dasd_eckd_read_conf_lpm().
These should even recover better from error than the original cio
functions.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 81 |
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 | ||
453 | struct 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 | |||
483 | static 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; | ||
521 | out_error: | ||
522 | kfree(rcd_buf); | ||
523 | *rcd_buffer = NULL; | ||
524 | *rcd_buffer_size = 0; | ||
525 | return ret; | ||
526 | } | ||
527 | |||
453 | static int | 528 | static int |
454 | dasd_eckd_read_conf(struct dasd_device *device) | 529 | dasd_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 " |