diff options
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 78 |
1 files changed, 51 insertions, 27 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 4305c23c57a4..5b1cd8d6e971 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid) | |||
692 | /* | 692 | /* |
693 | * Generate device unique id that specifies the physical device. | 693 | * Generate device unique id that specifies the physical device. |
694 | */ | 694 | */ |
695 | static int dasd_eckd_generate_uid(struct dasd_device *device, | 695 | static int dasd_eckd_generate_uid(struct dasd_device *device) |
696 | struct dasd_uid *uid) | ||
697 | { | 696 | { |
698 | struct dasd_eckd_private *private; | 697 | struct dasd_eckd_private *private; |
698 | struct dasd_uid *uid; | ||
699 | int count; | 699 | int count; |
700 | unsigned long flags; | ||
700 | 701 | ||
701 | private = (struct dasd_eckd_private *) device->private; | 702 | private = (struct dasd_eckd_private *) device->private; |
702 | if (!private) | 703 | if (!private) |
703 | return -ENODEV; | 704 | return -ENODEV; |
704 | if (!private->ned || !private->gneq) | 705 | if (!private->ned || !private->gneq) |
705 | return -ENODEV; | 706 | return -ENODEV; |
706 | 707 | uid = &private->uid; | |
708 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
707 | memset(uid, 0, sizeof(struct dasd_uid)); | 709 | memset(uid, 0, sizeof(struct dasd_uid)); |
708 | memcpy(uid->vendor, private->ned->HDA_manufacturer, | 710 | memcpy(uid->vendor, private->ned->HDA_manufacturer, |
709 | sizeof(uid->vendor) - 1); | 711 | sizeof(uid->vendor) - 1); |
@@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device, | |||
726 | private->vdsneq->uit[count]); | 728 | private->vdsneq->uit[count]); |
727 | } | 729 | } |
728 | } | 730 | } |
731 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
729 | return 0; | 732 | return 0; |
730 | } | 733 | } |
731 | 734 | ||
735 | static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) | ||
736 | { | ||
737 | struct dasd_eckd_private *private; | ||
738 | unsigned long flags; | ||
739 | |||
740 | if (device->private) { | ||
741 | private = (struct dasd_eckd_private *)device->private; | ||
742 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
743 | *uid = private->uid; | ||
744 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
745 | return 0; | ||
746 | } | ||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
732 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, | 750 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, |
733 | void *rcd_buffer, | 751 | void *rcd_buffer, |
734 | struct ciw *ciw, __u8 lpm) | 752 | struct ciw *ciw, __u8 lpm) |
@@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1088 | { | 1106 | { |
1089 | struct dasd_eckd_private *private; | 1107 | struct dasd_eckd_private *private; |
1090 | struct dasd_block *block; | 1108 | struct dasd_block *block; |
1109 | struct dasd_uid temp_uid; | ||
1091 | int is_known, rc; | 1110 | int is_known, rc; |
1092 | int readonly; | 1111 | int readonly; |
1093 | 1112 | ||
@@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1124 | if (rc) | 1143 | if (rc) |
1125 | goto out_err1; | 1144 | goto out_err1; |
1126 | 1145 | ||
1127 | /* Generate device unique id and register in devmap */ | 1146 | /* Generate device unique id */ |
1128 | rc = dasd_eckd_generate_uid(device, &private->uid); | 1147 | rc = dasd_eckd_generate_uid(device); |
1129 | if (rc) | 1148 | if (rc) |
1130 | goto out_err1; | 1149 | goto out_err1; |
1131 | dasd_set_uid(device->cdev, &private->uid); | ||
1132 | 1150 | ||
1133 | if (private->uid.type == UA_BASE_DEVICE) { | 1151 | dasd_eckd_get_uid(device, &temp_uid); |
1152 | if (temp_uid.type == UA_BASE_DEVICE) { | ||
1134 | block = dasd_alloc_block(); | 1153 | block = dasd_alloc_block(); |
1135 | if (IS_ERR(block)) { | 1154 | if (IS_ERR(block)) { |
1136 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | 1155 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
@@ -3305,15 +3324,16 @@ static int dasd_eckd_restore_device(struct dasd_device *device) | |||
3305 | if (rc) | 3324 | if (rc) |
3306 | goto out_err; | 3325 | goto out_err; |
3307 | 3326 | ||
3308 | /* Generate device unique id and register in devmap */ | 3327 | dasd_eckd_get_uid(device, &temp_uid); |
3309 | rc = dasd_eckd_generate_uid(device, &private->uid); | 3328 | /* Generate device unique id */ |
3310 | dasd_get_uid(device->cdev, &temp_uid); | 3329 | rc = dasd_eckd_generate_uid(device); |
3330 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
3311 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) | 3331 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) |
3312 | dev_err(&device->cdev->dev, "The UID of the DASD has " | 3332 | dev_err(&device->cdev->dev, "The UID of the DASD has " |
3313 | "changed\n"); | 3333 | "changed\n"); |
3334 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
3314 | if (rc) | 3335 | if (rc) |
3315 | goto out_err; | 3336 | goto out_err; |
3316 | dasd_set_uid(device->cdev, &private->uid); | ||
3317 | 3337 | ||
3318 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 3338 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
3319 | is_known = dasd_alias_make_device_known_to_lcu(device); | 3339 | is_known = dasd_alias_make_device_known_to_lcu(device); |
@@ -3358,42 +3378,45 @@ static int dasd_eckd_reload_device(struct dasd_device *device) | |||
3358 | { | 3378 | { |
3359 | struct dasd_eckd_private *private; | 3379 | struct dasd_eckd_private *private; |
3360 | int rc, old_base; | 3380 | int rc, old_base; |
3361 | char uid[60]; | 3381 | char print_uid[60]; |
3382 | struct dasd_uid uid; | ||
3383 | unsigned long flags; | ||
3362 | 3384 | ||
3363 | private = (struct dasd_eckd_private *) device->private; | 3385 | private = (struct dasd_eckd_private *) device->private; |
3386 | |||
3387 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
3364 | old_base = private->uid.base_unit_addr; | 3388 | old_base = private->uid.base_unit_addr; |
3389 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
3390 | |||
3365 | /* Read Configuration Data */ | 3391 | /* Read Configuration Data */ |
3366 | rc = dasd_eckd_read_conf(device); | 3392 | rc = dasd_eckd_read_conf(device); |
3367 | if (rc) | 3393 | if (rc) |
3368 | goto out_err; | 3394 | goto out_err; |
3369 | 3395 | ||
3370 | rc = dasd_eckd_generate_uid(device, &private->uid); | 3396 | rc = dasd_eckd_generate_uid(device); |
3371 | if (rc) | 3397 | if (rc) |
3372 | goto out_err; | 3398 | goto out_err; |
3373 | |||
3374 | dasd_set_uid(device->cdev, &private->uid); | ||
3375 | |||
3376 | /* | 3399 | /* |
3377 | * update unit address configuration and | 3400 | * update unit address configuration and |
3378 | * add device to alias management | 3401 | * add device to alias management |
3379 | */ | 3402 | */ |
3380 | dasd_alias_update_add_device(device); | 3403 | dasd_alias_update_add_device(device); |
3381 | 3404 | ||
3382 | if (old_base != private->uid.base_unit_addr) { | 3405 | dasd_eckd_get_uid(device, &uid); |
3383 | if (strlen(private->uid.vduit) > 0) | 3406 | |
3384 | snprintf(uid, 60, "%s.%s.%04x.%02x.%s", | 3407 | if (old_base != uid.base_unit_addr) { |
3385 | private->uid.vendor, private->uid.serial, | 3408 | if (strlen(uid.vduit) > 0) |
3386 | private->uid.ssid, private->uid.base_unit_addr, | 3409 | snprintf(print_uid, sizeof(print_uid), |
3387 | private->uid.vduit); | 3410 | "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial, |
3411 | uid.ssid, uid.base_unit_addr, uid.vduit); | ||
3388 | else | 3412 | else |
3389 | snprintf(uid, 60, "%s.%s.%04x.%02x", | 3413 | snprintf(print_uid, sizeof(print_uid), |
3390 | private->uid.vendor, private->uid.serial, | 3414 | "%s.%s.%04x.%02x", uid.vendor, uid.serial, |
3391 | private->uid.ssid, | 3415 | uid.ssid, uid.base_unit_addr); |
3392 | private->uid.base_unit_addr); | ||
3393 | 3416 | ||
3394 | dev_info(&device->cdev->dev, | 3417 | dev_info(&device->cdev->dev, |
3395 | "An Alias device was reassigned to a new base device " | 3418 | "An Alias device was reassigned to a new base device " |
3396 | "with UID: %s\n", uid); | 3419 | "with UID: %s\n", print_uid); |
3397 | } | 3420 | } |
3398 | return 0; | 3421 | return 0; |
3399 | 3422 | ||
@@ -3455,6 +3478,7 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
3455 | .freeze = dasd_eckd_pm_freeze, | 3478 | .freeze = dasd_eckd_pm_freeze, |
3456 | .restore = dasd_eckd_restore_device, | 3479 | .restore = dasd_eckd_restore_device, |
3457 | .reload = dasd_eckd_reload_device, | 3480 | .reload = dasd_eckd_reload_device, |
3481 | .get_uid = dasd_eckd_get_uid, | ||
3458 | }; | 3482 | }; |
3459 | 3483 | ||
3460 | static int __init | 3484 | static int __init |