diff options
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 98 |
1 files changed, 71 insertions, 27 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 5adb2042e824..cee7e2708a1f 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -2077,6 +2077,7 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2077 | int intensity = 0; | 2077 | int intensity = 0; |
| 2078 | int r0_perm; | 2078 | int r0_perm; |
| 2079 | int nr_tracks; | 2079 | int nr_tracks; |
| 2080 | int use_prefix; | ||
| 2080 | 2081 | ||
| 2081 | startdev = dasd_alias_get_start_dev(base); | 2082 | startdev = dasd_alias_get_start_dev(base); |
| 2082 | if (!startdev) | 2083 | if (!startdev) |
| @@ -2106,28 +2107,46 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2106 | intensity = fdata->intensity; | 2107 | intensity = fdata->intensity; |
| 2107 | } | 2108 | } |
| 2108 | 2109 | ||
| 2110 | use_prefix = base_priv->features.feature[8] & 0x01; | ||
| 2111 | |||
| 2109 | switch (intensity) { | 2112 | switch (intensity) { |
| 2110 | case 0x00: /* Normal format */ | 2113 | case 0x00: /* Normal format */ |
| 2111 | case 0x08: /* Normal format, use cdl. */ | 2114 | case 0x08: /* Normal format, use cdl. */ |
| 2112 | cplength = 2 + (rpt*nr_tracks); | 2115 | cplength = 2 + (rpt*nr_tracks); |
| 2113 | datasize = sizeof(struct PFX_eckd_data) + | 2116 | if (use_prefix) |
| 2114 | sizeof(struct LO_eckd_data) + | 2117 | datasize = sizeof(struct PFX_eckd_data) + |
| 2115 | rpt * nr_tracks * sizeof(struct eckd_count); | 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); | ||
| 2116 | break; | 2124 | break; |
| 2117 | case 0x01: /* Write record zero and format track. */ | 2125 | case 0x01: /* Write record zero and format track. */ |
| 2118 | case 0x09: /* Write record zero and format track, use cdl. */ | 2126 | case 0x09: /* Write record zero and format track, use cdl. */ |
| 2119 | cplength = 2 + rpt * nr_tracks; | 2127 | cplength = 2 + rpt * nr_tracks; |
| 2120 | datasize = sizeof(struct PFX_eckd_data) + | 2128 | if (use_prefix) |
| 2121 | sizeof(struct LO_eckd_data) + | 2129 | datasize = sizeof(struct PFX_eckd_data) + |
| 2122 | sizeof(struct eckd_count) + | 2130 | sizeof(struct LO_eckd_data) + |
| 2123 | rpt * nr_tracks * sizeof(struct eckd_count); | 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); | ||
| 2124 | break; | 2138 | break; |
| 2125 | case 0x04: /* Invalidate track. */ | 2139 | case 0x04: /* Invalidate track. */ |
| 2126 | case 0x0c: /* Invalidate track, use cdl. */ | 2140 | case 0x0c: /* Invalidate track, use cdl. */ |
| 2127 | cplength = 3; | 2141 | cplength = 3; |
| 2128 | datasize = sizeof(struct PFX_eckd_data) + | 2142 | if (use_prefix) |
| 2129 | sizeof(struct LO_eckd_data) + | 2143 | datasize = sizeof(struct PFX_eckd_data) + |
| 2130 | sizeof(struct eckd_count); | 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); | ||
| 2131 | break; | 2150 | break; |
| 2132 | default: | 2151 | default: |
| 2133 | dev_warn(&startdev->cdev->dev, | 2152 | dev_warn(&startdev->cdev->dev, |
| @@ -2147,14 +2166,25 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2147 | 2166 | ||
| 2148 | switch (intensity & ~0x08) { | 2167 | switch (intensity & ~0x08) { |
| 2149 | case 0x00: /* Normal format. */ | 2168 | case 0x00: /* Normal format. */ |
| 2150 | prefix(ccw++, (struct PFX_eckd_data *) data, | 2169 | if (use_prefix) { |
| 2151 | fdata->start_unit, fdata->stop_unit, | 2170 | prefix(ccw++, (struct PFX_eckd_data *) data, |
| 2152 | DASD_ECKD_CCW_WRITE_CKD, base, startdev); | 2171 | fdata->start_unit, fdata->stop_unit, |
| 2153 | /* grant subsystem permission to format R0 */ | 2172 | DASD_ECKD_CCW_WRITE_CKD, base, startdev); |
| 2154 | if (r0_perm) | 2173 | /* grant subsystem permission to format R0 */ |
| 2155 | ((struct PFX_eckd_data *)data) | 2174 | if (r0_perm) |
| 2156 | ->define_extent.ga_extended |= 0x04; | 2175 | ((struct PFX_eckd_data *)data) |
| 2157 | data += sizeof(struct PFX_eckd_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 | } | ||
| 2158 | ccw[-1].flags |= CCW_FLAG_CC; | 2188 | ccw[-1].flags |= CCW_FLAG_CC; |
| 2159 | locate_record(ccw++, (struct LO_eckd_data *) data, | 2189 | locate_record(ccw++, (struct LO_eckd_data *) data, |
| 2160 | fdata->start_unit, 0, rpt*nr_tracks, | 2190 | fdata->start_unit, 0, rpt*nr_tracks, |
| @@ -2163,11 +2193,18 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2163 | data += sizeof(struct LO_eckd_data); | 2193 | data += sizeof(struct LO_eckd_data); |
| 2164 | break; | 2194 | break; |
| 2165 | case 0x01: /* Write record zero + format track. */ | 2195 | case 0x01: /* Write record zero + format track. */ |
| 2166 | prefix(ccw++, (struct PFX_eckd_data *) data, | 2196 | if (use_prefix) { |
| 2167 | fdata->start_unit, fdata->stop_unit, | 2197 | prefix(ccw++, (struct PFX_eckd_data *) data, |
| 2168 | DASD_ECKD_CCW_WRITE_RECORD_ZERO, | 2198 | fdata->start_unit, fdata->stop_unit, |
| 2169 | base, startdev); | 2199 | DASD_ECKD_CCW_WRITE_RECORD_ZERO, |
| 2170 | data += sizeof(struct PFX_eckd_data); | 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 | } | ||
| 2171 | ccw[-1].flags |= CCW_FLAG_CC; | 2208 | ccw[-1].flags |= CCW_FLAG_CC; |
| 2172 | locate_record(ccw++, (struct LO_eckd_data *) data, | 2209 | locate_record(ccw++, (struct LO_eckd_data *) data, |
| 2173 | fdata->start_unit, 0, rpt * nr_tracks + 1, | 2210 | fdata->start_unit, 0, rpt * nr_tracks + 1, |
| @@ -2176,10 +2213,17 @@ dasd_eckd_build_format(struct dasd_device *base, | |||
| 2176 | data += sizeof(struct LO_eckd_data); | 2213 | data += sizeof(struct LO_eckd_data); |
| 2177 | break; | 2214 | break; |
| 2178 | case 0x04: /* Invalidate track. */ | 2215 | case 0x04: /* Invalidate track. */ |
| 2179 | prefix(ccw++, (struct PFX_eckd_data *) data, | 2216 | if (use_prefix) { |
| 2180 | fdata->start_unit, fdata->stop_unit, | 2217 | prefix(ccw++, (struct PFX_eckd_data *) data, |
| 2181 | DASD_ECKD_CCW_WRITE_CKD, base, startdev); | 2218 | fdata->start_unit, fdata->stop_unit, |
| 2182 | data += sizeof(struct PFX_eckd_data); | 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 | } | ||
| 2183 | ccw[-1].flags |= CCW_FLAG_CC; | 2227 | ccw[-1].flags |= CCW_FLAG_CC; |
| 2184 | locate_record(ccw++, (struct LO_eckd_data *) data, | 2228 | locate_record(ccw++, (struct LO_eckd_data *) data, |
| 2185 | fdata->start_unit, 0, 1, | 2229 | fdata->start_unit, 0, 1, |
