diff options
-rw-r--r-- | drivers/firewire/fw-sbp2.c | 25 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.c | 22 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.h | 1 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 5 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 1 |
5 files changed, 50 insertions, 4 deletions
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 227d2e036cd8..53fc5a641e6d 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
@@ -86,6 +86,11 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " | |||
86 | * - delay inquiry | 86 | * - delay inquiry |
87 | * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. | 87 | * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. |
88 | * | 88 | * |
89 | * - power condition | ||
90 | * Set the power condition field in the START STOP UNIT commands sent by | ||
91 | * sd_mod on suspend, resume, and shutdown (if manage_start_stop is on). | ||
92 | * Some disks need this to spin down or to resume properly. | ||
93 | * | ||
89 | * - override internal blacklist | 94 | * - override internal blacklist |
90 | * Instead of adding to the built-in blacklist, use only the workarounds | 95 | * Instead of adding to the built-in blacklist, use only the workarounds |
91 | * specified in the module load parameter. | 96 | * specified in the module load parameter. |
@@ -97,6 +102,7 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " | |||
97 | #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 | 102 | #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 |
98 | #define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 | 103 | #define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 |
99 | #define SBP2_INQUIRY_DELAY 12 | 104 | #define SBP2_INQUIRY_DELAY 12 |
105 | #define SBP2_WORKAROUND_POWER_CONDITION 0x20 | ||
100 | #define SBP2_WORKAROUND_OVERRIDE 0x100 | 106 | #define SBP2_WORKAROUND_OVERRIDE 0x100 |
101 | 107 | ||
102 | static int sbp2_param_workarounds; | 108 | static int sbp2_param_workarounds; |
@@ -107,6 +113,8 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" | |||
107 | ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) | 113 | ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) |
108 | ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) | 114 | ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) |
109 | ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) | 115 | ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) |
116 | ", set power condition in start stop unit = " | ||
117 | __stringify(SBP2_WORKAROUND_POWER_CONDITION) | ||
110 | ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) | 118 | ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) |
111 | ", or a combination)"); | 119 | ", or a combination)"); |
112 | 120 | ||
@@ -310,18 +318,25 @@ static const struct { | |||
310 | .firmware_revision = 0x002800, | 318 | .firmware_revision = 0x002800, |
311 | .model = 0x001010, | 319 | .model = 0x001010, |
312 | .workarounds = SBP2_WORKAROUND_INQUIRY_36 | | 320 | .workarounds = SBP2_WORKAROUND_INQUIRY_36 | |
313 | SBP2_WORKAROUND_MODE_SENSE_8, | 321 | SBP2_WORKAROUND_MODE_SENSE_8 | |
322 | SBP2_WORKAROUND_POWER_CONDITION, | ||
314 | }, | 323 | }, |
315 | /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { | 324 | /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { |
316 | .firmware_revision = 0x002800, | 325 | .firmware_revision = 0x002800, |
317 | .model = 0x000000, | 326 | .model = 0x000000, |
318 | .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY, | 327 | .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY | |
328 | SBP2_WORKAROUND_POWER_CONDITION, | ||
319 | }, | 329 | }, |
320 | /* Initio bridges, actually only needed for some older ones */ { | 330 | /* Initio bridges, actually only needed for some older ones */ { |
321 | .firmware_revision = 0x000200, | 331 | .firmware_revision = 0x000200, |
322 | .model = ~0, | 332 | .model = ~0, |
323 | .workarounds = SBP2_WORKAROUND_INQUIRY_36, | 333 | .workarounds = SBP2_WORKAROUND_INQUIRY_36, |
324 | }, | 334 | }, |
335 | /* PL-3507 bridge with Prolific firmware */ { | ||
336 | .firmware_revision = 0x012800, | ||
337 | .model = ~0, | ||
338 | .workarounds = SBP2_WORKAROUND_POWER_CONDITION, | ||
339 | }, | ||
325 | /* Symbios bridge */ { | 340 | /* Symbios bridge */ { |
326 | .firmware_revision = 0xa0b800, | 341 | .firmware_revision = 0xa0b800, |
327 | .model = ~0, | 342 | .model = ~0, |
@@ -1530,6 +1545,9 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) | |||
1530 | 1545 | ||
1531 | sdev->use_10_for_rw = 1; | 1546 | sdev->use_10_for_rw = 1; |
1532 | 1547 | ||
1548 | if (sbp2_param_exclusive_login) | ||
1549 | sdev->manage_start_stop = 1; | ||
1550 | |||
1533 | if (sdev->type == TYPE_ROM) | 1551 | if (sdev->type == TYPE_ROM) |
1534 | sdev->use_10_for_ms = 1; | 1552 | sdev->use_10_for_ms = 1; |
1535 | 1553 | ||
@@ -1540,6 +1558,9 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) | |||
1540 | if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) | 1558 | if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) |
1541 | sdev->fix_capacity = 1; | 1559 | sdev->fix_capacity = 1; |
1542 | 1560 | ||
1561 | if (lu->tgt->workarounds & SBP2_WORKAROUND_POWER_CONDITION) | ||
1562 | sdev->start_stop_pwr_cond = 1; | ||
1563 | |||
1543 | if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) | 1564 | if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) |
1544 | blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); | 1565 | blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); |
1545 | 1566 | ||
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index a5ceff287a28..9cbf3154d243 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -186,6 +186,11 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " | |||
186 | * - delay inquiry | 186 | * - delay inquiry |
187 | * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. | 187 | * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. |
188 | * | 188 | * |
189 | * - power condition | ||
190 | * Set the power condition field in the START STOP UNIT commands sent by | ||
191 | * sd_mod on suspend, resume, and shutdown (if manage_start_stop is on). | ||
192 | * Some disks need this to spin down or to resume properly. | ||
193 | * | ||
189 | * - override internal blacklist | 194 | * - override internal blacklist |
190 | * Instead of adding to the built-in blacklist, use only the workarounds | 195 | * Instead of adding to the built-in blacklist, use only the workarounds |
191 | * specified in the module load parameter. | 196 | * specified in the module load parameter. |
@@ -199,6 +204,8 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" | |||
199 | ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) | 204 | ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) |
200 | ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) | 205 | ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) |
201 | ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) | 206 | ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) |
207 | ", set power condition in start stop unit = " | ||
208 | __stringify(SBP2_WORKAROUND_POWER_CONDITION) | ||
202 | ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) | 209 | ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) |
203 | ", or a combination)"); | 210 | ", or a combination)"); |
204 | 211 | ||
@@ -359,18 +366,25 @@ static const struct { | |||
359 | .firmware_revision = 0x002800, | 366 | .firmware_revision = 0x002800, |
360 | .model_id = 0x001010, | 367 | .model_id = 0x001010, |
361 | .workarounds = SBP2_WORKAROUND_INQUIRY_36 | | 368 | .workarounds = SBP2_WORKAROUND_INQUIRY_36 | |
362 | SBP2_WORKAROUND_MODE_SENSE_8, | 369 | SBP2_WORKAROUND_MODE_SENSE_8 | |
370 | SBP2_WORKAROUND_POWER_CONDITION, | ||
363 | }, | 371 | }, |
364 | /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { | 372 | /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { |
365 | .firmware_revision = 0x002800, | 373 | .firmware_revision = 0x002800, |
366 | .model_id = 0x000000, | 374 | .model_id = 0x000000, |
367 | .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY, | 375 | .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY | |
376 | SBP2_WORKAROUND_POWER_CONDITION, | ||
368 | }, | 377 | }, |
369 | /* Initio bridges, actually only needed for some older ones */ { | 378 | /* Initio bridges, actually only needed for some older ones */ { |
370 | .firmware_revision = 0x000200, | 379 | .firmware_revision = 0x000200, |
371 | .model_id = SBP2_ROM_VALUE_WILDCARD, | 380 | .model_id = SBP2_ROM_VALUE_WILDCARD, |
372 | .workarounds = SBP2_WORKAROUND_INQUIRY_36, | 381 | .workarounds = SBP2_WORKAROUND_INQUIRY_36, |
373 | }, | 382 | }, |
383 | /* PL-3507 bridge with Prolific firmware */ { | ||
384 | .firmware_revision = 0x012800, | ||
385 | .model_id = SBP2_ROM_VALUE_WILDCARD, | ||
386 | .workarounds = SBP2_WORKAROUND_POWER_CONDITION, | ||
387 | }, | ||
374 | /* Symbios bridge */ { | 388 | /* Symbios bridge */ { |
375 | .firmware_revision = 0xa0b800, | 389 | .firmware_revision = 0xa0b800, |
376 | .model_id = SBP2_ROM_VALUE_WILDCARD, | 390 | .model_id = SBP2_ROM_VALUE_WILDCARD, |
@@ -1995,6 +2009,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) | |||
1995 | 2009 | ||
1996 | sdev->use_10_for_rw = 1; | 2010 | sdev->use_10_for_rw = 1; |
1997 | 2011 | ||
2012 | if (sbp2_exclusive_login) | ||
2013 | sdev->manage_start_stop = 1; | ||
1998 | if (sdev->type == TYPE_ROM) | 2014 | if (sdev->type == TYPE_ROM) |
1999 | sdev->use_10_for_ms = 1; | 2015 | sdev->use_10_for_ms = 1; |
2000 | if (sdev->type == TYPE_DISK && | 2016 | if (sdev->type == TYPE_DISK && |
@@ -2002,6 +2018,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) | |||
2002 | sdev->skip_ms_page_8 = 1; | 2018 | sdev->skip_ms_page_8 = 1; |
2003 | if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) | 2019 | if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) |
2004 | sdev->fix_capacity = 1; | 2020 | sdev->fix_capacity = 1; |
2021 | if (lu->workarounds & SBP2_WORKAROUND_POWER_CONDITION) | ||
2022 | sdev->start_stop_pwr_cond = 1; | ||
2005 | if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) | 2023 | if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) |
2006 | blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); | 2024 | blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); |
2007 | return 0; | 2025 | return 0; |
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 80d8e097b065..875428bc8d29 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
@@ -345,6 +345,7 @@ enum sbp2lu_state_types { | |||
345 | #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 | 345 | #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 |
346 | #define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 | 346 | #define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 |
347 | #define SBP2_INQUIRY_DELAY 12 | 347 | #define SBP2_INQUIRY_DELAY 12 |
348 | #define SBP2_WORKAROUND_POWER_CONDITION 0x20 | ||
348 | #define SBP2_WORKAROUND_OVERRIDE 0x100 | 349 | #define SBP2_WORKAROUND_OVERRIDE 0x100 |
349 | 350 | ||
350 | #endif /* SBP2_H */ | 351 | #endif /* SBP2_H */ |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 01cefbb2d539..d53312c42547 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1124,6 +1124,8 @@ sd_spinup_disk(struct scsi_disk *sdkp) | |||
1124 | cmd[1] = 1; /* Return immediately */ | 1124 | cmd[1] = 1; /* Return immediately */ |
1125 | memset((void *) &cmd[2], 0, 8); | 1125 | memset((void *) &cmd[2], 0, 8); |
1126 | cmd[4] = 1; /* Start spin cycle */ | 1126 | cmd[4] = 1; /* Start spin cycle */ |
1127 | if (sdkp->device->start_stop_pwr_cond) | ||
1128 | cmd[4] |= 1 << 4; | ||
1127 | scsi_execute_req(sdkp->device, cmd, DMA_NONE, | 1129 | scsi_execute_req(sdkp->device, cmd, DMA_NONE, |
1128 | NULL, 0, &sshdr, | 1130 | NULL, 0, &sshdr, |
1129 | SD_TIMEOUT, SD_MAX_RETRIES); | 1131 | SD_TIMEOUT, SD_MAX_RETRIES); |
@@ -1790,6 +1792,9 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) | |||
1790 | if (start) | 1792 | if (start) |
1791 | cmd[4] |= 1; /* START */ | 1793 | cmd[4] |= 1; /* START */ |
1792 | 1794 | ||
1795 | if (sdp->start_stop_pwr_cond) | ||
1796 | cmd[4] |= start ? 1 << 4 : 3 << 4; /* Active or Standby */ | ||
1797 | |||
1793 | if (!scsi_device_online(sdp)) | 1798 | if (!scsi_device_online(sdp)) |
1794 | return -ENODEV; | 1799 | return -ENODEV; |
1795 | 1800 | ||
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f6a9fe0ef09c..00b78763a1bf 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -134,6 +134,7 @@ struct scsi_device { | |||
134 | unsigned no_start_on_add:1; /* do not issue start on add */ | 134 | unsigned no_start_on_add:1; /* do not issue start on add */ |
135 | unsigned allow_restart:1; /* issue START_UNIT in error handler */ | 135 | unsigned allow_restart:1; /* issue START_UNIT in error handler */ |
136 | unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */ | 136 | unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */ |
137 | unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */ | ||
137 | unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ | 138 | unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ |
138 | unsigned select_no_atn:1; | 139 | unsigned select_no_atn:1; |
139 | unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ | 140 | unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ |