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 */ |
