diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-scsi.c | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 86c2663e00e6..67d23bd87950 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -2205,9 +2205,33 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf) | |||
2205 | } | 2205 | } |
2206 | 2206 | ||
2207 | /** | 2207 | /** |
2208 | * modecpy - Prepare response for MODE SENSE | ||
2209 | * @dest: output buffer | ||
2210 | * @src: data being copied | ||
2211 | * @n: length of mode page | ||
2212 | * @changeable: whether changeable parameters are requested | ||
2213 | * | ||
2214 | * Generate a generic MODE SENSE page for either current or changeable | ||
2215 | * parameters. | ||
2216 | * | ||
2217 | * LOCKING: | ||
2218 | * None. | ||
2219 | */ | ||
2220 | static void modecpy(u8 *dest, const u8 *src, int n, bool changeable) | ||
2221 | { | ||
2222 | if (changeable) { | ||
2223 | memcpy(dest, src, 2); | ||
2224 | memset(dest + 2, 0, n - 2); | ||
2225 | } else { | ||
2226 | memcpy(dest, src, n); | ||
2227 | } | ||
2228 | } | ||
2229 | |||
2230 | /** | ||
2208 | * ata_msense_caching - Simulate MODE SENSE caching info page | 2231 | * ata_msense_caching - Simulate MODE SENSE caching info page |
2209 | * @id: device IDENTIFY data | 2232 | * @id: device IDENTIFY data |
2210 | * @buf: output buffer | 2233 | * @buf: output buffer |
2234 | * @changeable: whether changeable parameters are requested | ||
2211 | * | 2235 | * |
2212 | * Generate a caching info page, which conditionally indicates | 2236 | * Generate a caching info page, which conditionally indicates |
2213 | * write caching to the SCSI layer, depending on device | 2237 | * write caching to the SCSI layer, depending on device |
@@ -2216,12 +2240,12 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf) | |||
2216 | * LOCKING: | 2240 | * LOCKING: |
2217 | * None. | 2241 | * None. |
2218 | */ | 2242 | */ |
2219 | static unsigned int ata_msense_caching(u16 *id, u8 *buf) | 2243 | static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) |
2220 | { | 2244 | { |
2221 | memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage)); | 2245 | modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable); |
2222 | if (ata_id_wcache_enabled(id)) | 2246 | if (!changeable && ata_id_wcache_enabled(id)) |
2223 | buf[2] |= (1 << 2); /* write cache enable */ | 2247 | buf[2] |= (1 << 2); /* write cache enable */ |
2224 | if (!ata_id_rahead_enabled(id)) | 2248 | if (!changeable && !ata_id_rahead_enabled(id)) |
2225 | buf[12] |= (1 << 5); /* disable read ahead */ | 2249 | buf[12] |= (1 << 5); /* disable read ahead */ |
2226 | return sizeof(def_cache_mpage); | 2250 | return sizeof(def_cache_mpage); |
2227 | } | 2251 | } |
@@ -2229,30 +2253,33 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf) | |||
2229 | /** | 2253 | /** |
2230 | * ata_msense_ctl_mode - Simulate MODE SENSE control mode page | 2254 | * ata_msense_ctl_mode - Simulate MODE SENSE control mode page |
2231 | * @buf: output buffer | 2255 | * @buf: output buffer |
2256 | * @changeable: whether changeable parameters are requested | ||
2232 | * | 2257 | * |
2233 | * Generate a generic MODE SENSE control mode page. | 2258 | * Generate a generic MODE SENSE control mode page. |
2234 | * | 2259 | * |
2235 | * LOCKING: | 2260 | * LOCKING: |
2236 | * None. | 2261 | * None. |
2237 | */ | 2262 | */ |
2238 | static unsigned int ata_msense_ctl_mode(u8 *buf) | 2263 | static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable) |
2239 | { | 2264 | { |
2240 | memcpy(buf, def_control_mpage, sizeof(def_control_mpage)); | 2265 | modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); |
2241 | return sizeof(def_control_mpage); | 2266 | return sizeof(def_control_mpage); |
2242 | } | 2267 | } |
2243 | 2268 | ||
2244 | /** | 2269 | /** |
2245 | * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page | 2270 | * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page |
2246 | * @buf: output buffer | 2271 | * @buf: output buffer |
2272 | * @changeable: whether changeable parameters are requested | ||
2247 | * | 2273 | * |
2248 | * Generate a generic MODE SENSE r/w error recovery page. | 2274 | * Generate a generic MODE SENSE r/w error recovery page. |
2249 | * | 2275 | * |
2250 | * LOCKING: | 2276 | * LOCKING: |
2251 | * None. | 2277 | * None. |
2252 | */ | 2278 | */ |
2253 | static unsigned int ata_msense_rw_recovery(u8 *buf) | 2279 | static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable) |
2254 | { | 2280 | { |
2255 | memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage)); | 2281 | modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage), |
2282 | changeable); | ||
2256 | return sizeof(def_rw_recovery_mpage); | 2283 | return sizeof(def_rw_recovery_mpage); |
2257 | } | 2284 | } |
2258 | 2285 | ||
@@ -2316,11 +2343,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) | |||
2316 | page_control = scsicmd[2] >> 6; | 2343 | page_control = scsicmd[2] >> 6; |
2317 | switch (page_control) { | 2344 | switch (page_control) { |
2318 | case 0: /* current */ | 2345 | case 0: /* current */ |
2346 | case 1: /* changeable */ | ||
2347 | case 2: /* defaults */ | ||
2319 | break; /* supported */ | 2348 | break; /* supported */ |
2320 | case 3: /* saved */ | 2349 | case 3: /* saved */ |
2321 | goto saving_not_supp; | 2350 | goto saving_not_supp; |
2322 | case 1: /* changeable */ | ||
2323 | case 2: /* defaults */ | ||
2324 | default: | 2351 | default: |
2325 | goto invalid_fld; | 2352 | goto invalid_fld; |
2326 | } | 2353 | } |
@@ -2341,21 +2368,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) | |||
2341 | 2368 | ||
2342 | switch(pg) { | 2369 | switch(pg) { |
2343 | case RW_RECOVERY_MPAGE: | 2370 | case RW_RECOVERY_MPAGE: |
2344 | p += ata_msense_rw_recovery(p); | 2371 | p += ata_msense_rw_recovery(p, page_control == 1); |
2345 | break; | 2372 | break; |
2346 | 2373 | ||
2347 | case CACHE_MPAGE: | 2374 | case CACHE_MPAGE: |
2348 | p += ata_msense_caching(args->id, p); | 2375 | p += ata_msense_caching(args->id, p, page_control == 1); |
2349 | break; | 2376 | break; |
2350 | 2377 | ||
2351 | case CONTROL_MPAGE: | 2378 | case CONTROL_MPAGE: |
2352 | p += ata_msense_ctl_mode(p); | 2379 | p += ata_msense_ctl_mode(p, page_control == 1); |
2353 | break; | 2380 | break; |
2354 | 2381 | ||
2355 | case ALL_MPAGES: | 2382 | case ALL_MPAGES: |
2356 | p += ata_msense_rw_recovery(p); | 2383 | p += ata_msense_rw_recovery(p, page_control == 1); |
2357 | p += ata_msense_caching(args->id, p); | 2384 | p += ata_msense_caching(args->id, p, page_control == 1); |
2358 | p += ata_msense_ctl_mode(p); | 2385 | p += ata_msense_ctl_mode(p, page_control == 1); |
2359 | break; | 2386 | break; |
2360 | 2387 | ||
2361 | default: /* invalid page code */ | 2388 | default: /* invalid page code */ |