aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-scsi.c59
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 */
2220static 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 */
2219static unsigned int ata_msense_caching(u16 *id, u8 *buf) 2243static 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 */
2238static unsigned int ata_msense_ctl_mode(u8 *buf) 2263static 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 */
2253static unsigned int ata_msense_rw_recovery(u8 *buf) 2279static 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 */