Skip to content

Commit 18d6624

Browse files
stefan-haberlandMartin Schwidefsky
authored andcommitted
s390/dasd: check for availability of prefix command during format
The prefix command is used instead of a define extent to make use of PAV alias devices during format. On some older storage servers the prefix command may not be available and the IO request will fail. Check for availability of prefix command and use define extent if not available. Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
1 parent af0ebc4 commit 18d6624

File tree

1 file changed

+71
-27
lines changed

1 file changed

+71
-27
lines changed

drivers/s390/block/dasd_eckd.c

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,7 @@ dasd_eckd_build_format(struct dasd_device *base,
20772077
int intensity = 0;
20782078
int r0_perm;
20792079
int nr_tracks;
2080+
int use_prefix;
20802081

20812082
startdev = dasd_alias_get_start_dev(base);
20822083
if (!startdev)
@@ -2106,28 +2107,46 @@ dasd_eckd_build_format(struct dasd_device *base,
21062107
intensity = fdata->intensity;
21072108
}
21082109

2110+
use_prefix = base_priv->features.feature[8] & 0x01;
2111+
21092112
switch (intensity) {
21102113
case 0x00: /* Normal format */
21112114
case 0x08: /* Normal format, use cdl. */
21122115
cplength = 2 + (rpt*nr_tracks);
2113-
datasize = sizeof(struct PFX_eckd_data) +
2114-
sizeof(struct LO_eckd_data) +
2115-
rpt * nr_tracks * sizeof(struct eckd_count);
2116+
if (use_prefix)
2117+
datasize = sizeof(struct PFX_eckd_data) +
2118+
sizeof(struct LO_eckd_data) +
2119+
rpt * nr_tracks * sizeof(struct eckd_count);
2120+
else
2121+
datasize = sizeof(struct DE_eckd_data) +
2122+
sizeof(struct LO_eckd_data) +
2123+
rpt * nr_tracks * sizeof(struct eckd_count);
21162124
break;
21172125
case 0x01: /* Write record zero and format track. */
21182126
case 0x09: /* Write record zero and format track, use cdl. */
21192127
cplength = 2 + rpt * nr_tracks;
2120-
datasize = sizeof(struct PFX_eckd_data) +
2121-
sizeof(struct LO_eckd_data) +
2122-
sizeof(struct eckd_count) +
2123-
rpt * nr_tracks * sizeof(struct eckd_count);
2128+
if (use_prefix)
2129+
datasize = sizeof(struct PFX_eckd_data) +
2130+
sizeof(struct LO_eckd_data) +
2131+
sizeof(struct eckd_count) +
2132+
rpt * nr_tracks * sizeof(struct eckd_count);
2133+
else
2134+
datasize = sizeof(struct DE_eckd_data) +
2135+
sizeof(struct LO_eckd_data) +
2136+
sizeof(struct eckd_count) +
2137+
rpt * nr_tracks * sizeof(struct eckd_count);
21242138
break;
21252139
case 0x04: /* Invalidate track. */
21262140
case 0x0c: /* Invalidate track, use cdl. */
21272141
cplength = 3;
2128-
datasize = sizeof(struct PFX_eckd_data) +
2129-
sizeof(struct LO_eckd_data) +
2130-
sizeof(struct eckd_count);
2142+
if (use_prefix)
2143+
datasize = sizeof(struct PFX_eckd_data) +
2144+
sizeof(struct LO_eckd_data) +
2145+
sizeof(struct eckd_count);
2146+
else
2147+
datasize = sizeof(struct DE_eckd_data) +
2148+
sizeof(struct LO_eckd_data) +
2149+
sizeof(struct eckd_count);
21312150
break;
21322151
default:
21332152
dev_warn(&startdev->cdev->dev,
@@ -2147,14 +2166,25 @@ dasd_eckd_build_format(struct dasd_device *base,
21472166

21482167
switch (intensity & ~0x08) {
21492168
case 0x00: /* Normal format. */
2150-
prefix(ccw++, (struct PFX_eckd_data *) data,
2151-
fdata->start_unit, fdata->stop_unit,
2152-
DASD_ECKD_CCW_WRITE_CKD, base, startdev);
2153-
/* grant subsystem permission to format R0 */
2154-
if (r0_perm)
2155-
((struct PFX_eckd_data *)data)
2156-
->define_extent.ga_extended |= 0x04;
2157-
data += sizeof(struct PFX_eckd_data);
2169+
if (use_prefix) {
2170+
prefix(ccw++, (struct PFX_eckd_data *) data,
2171+
fdata->start_unit, fdata->stop_unit,
2172+
DASD_ECKD_CCW_WRITE_CKD, base, startdev);
2173+
/* grant subsystem permission to format R0 */
2174+
if (r0_perm)
2175+
((struct PFX_eckd_data *)data)
2176+
->define_extent.ga_extended |= 0x04;
2177+
data += sizeof(struct PFX_eckd_data);
2178+
} else {
2179+
define_extent(ccw++, (struct DE_eckd_data *) data,
2180+
fdata->start_unit, fdata->stop_unit,
2181+
DASD_ECKD_CCW_WRITE_CKD, startdev);
2182+
/* grant subsystem permission to format R0 */
2183+
if (r0_perm)
2184+
((struct DE_eckd_data *) data)
2185+
->ga_extended |= 0x04;
2186+
data += sizeof(struct DE_eckd_data);
2187+
}
21582188
ccw[-1].flags |= CCW_FLAG_CC;
21592189
locate_record(ccw++, (struct LO_eckd_data *) data,
21602190
fdata->start_unit, 0, rpt*nr_tracks,
@@ -2163,11 +2193,18 @@ dasd_eckd_build_format(struct dasd_device *base,
21632193
data += sizeof(struct LO_eckd_data);
21642194
break;
21652195
case 0x01: /* Write record zero + format track. */
2166-
prefix(ccw++, (struct PFX_eckd_data *) data,
2167-
fdata->start_unit, fdata->stop_unit,
2168-
DASD_ECKD_CCW_WRITE_RECORD_ZERO,
2169-
base, startdev);
2170-
data += sizeof(struct PFX_eckd_data);
2196+
if (use_prefix) {
2197+
prefix(ccw++, (struct PFX_eckd_data *) data,
2198+
fdata->start_unit, fdata->stop_unit,
2199+
DASD_ECKD_CCW_WRITE_RECORD_ZERO,
2200+
base, startdev);
2201+
data += sizeof(struct PFX_eckd_data);
2202+
} else {
2203+
define_extent(ccw++, (struct DE_eckd_data *) data,
2204+
fdata->start_unit, fdata->stop_unit,
2205+
DASD_ECKD_CCW_WRITE_RECORD_ZERO, startdev);
2206+
data += sizeof(struct DE_eckd_data);
2207+
}
21712208
ccw[-1].flags |= CCW_FLAG_CC;
21722209
locate_record(ccw++, (struct LO_eckd_data *) data,
21732210
fdata->start_unit, 0, rpt * nr_tracks + 1,
@@ -2176,10 +2213,17 @@ dasd_eckd_build_format(struct dasd_device *base,
21762213
data += sizeof(struct LO_eckd_data);
21772214
break;
21782215
case 0x04: /* Invalidate track. */
2179-
prefix(ccw++, (struct PFX_eckd_data *) data,
2180-
fdata->start_unit, fdata->stop_unit,
2181-
DASD_ECKD_CCW_WRITE_CKD, base, startdev);
2182-
data += sizeof(struct PFX_eckd_data);
2216+
if (use_prefix) {
2217+
prefix(ccw++, (struct PFX_eckd_data *) data,
2218+
fdata->start_unit, fdata->stop_unit,
2219+
DASD_ECKD_CCW_WRITE_CKD, base, startdev);
2220+
data += sizeof(struct PFX_eckd_data);
2221+
} else {
2222+
define_extent(ccw++, (struct DE_eckd_data *) data,
2223+
fdata->start_unit, fdata->stop_unit,
2224+
DASD_ECKD_CCW_WRITE_CKD, startdev);
2225+
data += sizeof(struct DE_eckd_data);
2226+
}
21832227
ccw[-1].flags |= CCW_FLAG_CC;
21842228
locate_record(ccw++, (struct LO_eckd_data *) data,
21852229
fdata->start_unit, 0, 1,

0 commit comments

Comments
 (0)