diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-05-15 16:06:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-18 00:32:21 -0400 |
commit | e9a1c52c7b19d10342226c12f170d7ab644427e2 (patch) | |
tree | 231d00c761444c650e527d048aab0776bd135fb5 | |
parent | 24d3bf884e093f9de52d31c97187f4b9b4ad7dcb (diff) |
[PATCH] sbp2: add read_capacity workaround for iPod
Apple decided to copy some USB stupidity over to FireWire.
The sector number returned by iPods from read_capacity is one too many.
This may cause I/O errors, especially if the kernel is configured for EFI
partition support. We use the same workaround as usb-storage but have to
check for different model IDs.
http://marc.theaimsgroup.com/?t=114233262300001
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=187409
Acknowledgements:
Diagnosis and therapy by Mathieu Chouquet-Stringer <ml2news@free.fr>,
additional data about affected and unaffected Apple hardware from
Vladimir Kotal, Sander De Graaf, Bryan Olmstead and Hugh Dixon.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/ieee1394/sbp2.c | 49 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.h | 1 |
2 files changed, 46 insertions, 4 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index ecd59ef8c8a3..09e9291f1848 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -151,6 +151,11 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)" | |||
151 | * - skip mode page 8 | 151 | * - skip mode page 8 |
152 | * Suppress sending of mode_sense for mode page 8 if the device pretends to | 152 | * Suppress sending of mode_sense for mode page 8 if the device pretends to |
153 | * support the SCSI Primary Block commands instead of Reduced Block Commands. | 153 | * support the SCSI Primary Block commands instead of Reduced Block Commands. |
154 | * | ||
155 | * - fix capacity | ||
156 | * Tell sd_mod to correct the last sector number reported by read_capacity. | ||
157 | * Avoids access beyond actual disk limits on devices with an off-by-one bug. | ||
158 | * Don't use this with devices which don't have this bug. | ||
154 | */ | 159 | */ |
155 | static int sbp2_default_workarounds; | 160 | static int sbp2_default_workarounds; |
156 | module_param_named(workarounds, sbp2_default_workarounds, int, 0644); | 161 | module_param_named(workarounds, sbp2_default_workarounds, int, 0644); |
@@ -158,6 +163,7 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" | |||
158 | ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) | 163 | ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) |
159 | ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) | 164 | ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) |
160 | ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) | 165 | ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) |
166 | ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) | ||
161 | ", or a combination)"); | 167 | ", or a combination)"); |
162 | 168 | ||
163 | /* legacy parameter */ | 169 | /* legacy parameter */ |
@@ -291,6 +297,7 @@ static struct hpsb_protocol_driver sbp2_driver = { | |||
291 | */ | 297 | */ |
292 | static const struct { | 298 | static const struct { |
293 | u32 firmware_revision; | 299 | u32 firmware_revision; |
300 | u32 model_id; | ||
294 | unsigned workarounds; | 301 | unsigned workarounds; |
295 | } sbp2_workarounds_table[] = { | 302 | } sbp2_workarounds_table[] = { |
296 | /* TSB42AA9 */ { | 303 | /* TSB42AA9 */ { |
@@ -305,6 +312,31 @@ static const struct { | |||
305 | /* Symbios bridge */ { | 312 | /* Symbios bridge */ { |
306 | .firmware_revision = 0xa0b800, | 313 | .firmware_revision = 0xa0b800, |
307 | .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, | 314 | .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, |
315 | }, | ||
316 | /* | ||
317 | * Note about the following Apple iPod blacklist entries: | ||
318 | * | ||
319 | * There are iPods (2nd gen, 3rd gen) with model_id==0. Since our | ||
320 | * matching logic treats 0 as a wildcard, we cannot match this ID | ||
321 | * without rewriting the matching routine. Fortunately these iPods | ||
322 | * do not feature the read_capacity bug according to one report. | ||
323 | * Read_capacity behaviour as well as model_id could change due to | ||
324 | * Apple-supplied firmware updates though. | ||
325 | */ | ||
326 | /* iPod 4th generation */ { | ||
327 | .firmware_revision = 0x0a2700, | ||
328 | .model_id = 0x000021, | ||
329 | .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, | ||
330 | }, | ||
331 | /* iPod mini */ { | ||
332 | .firmware_revision = 0x0a2700, | ||
333 | .model_id = 0x000023, | ||
334 | .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, | ||
335 | }, | ||
336 | /* iPod Photo */ { | ||
337 | .firmware_revision = 0x0a2700, | ||
338 | .model_id = 0x00007e, | ||
339 | .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, | ||
308 | } | 340 | } |
309 | }; | 341 | }; |
310 | 342 | ||
@@ -1556,18 +1588,25 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, | |||
1556 | } | 1588 | } |
1557 | 1589 | ||
1558 | for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { | 1590 | for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { |
1559 | if (sbp2_workarounds_table[i].firmware_revision != | 1591 | if (sbp2_workarounds_table[i].firmware_revision && |
1592 | sbp2_workarounds_table[i].firmware_revision != | ||
1560 | (firmware_revision & 0xffff00)) | 1593 | (firmware_revision & 0xffff00)) |
1561 | continue; | 1594 | continue; |
1595 | if (sbp2_workarounds_table[i].model_id && | ||
1596 | sbp2_workarounds_table[i].model_id != ud->model_id) | ||
1597 | continue; | ||
1562 | workarounds |= sbp2_workarounds_table[i].workarounds; | 1598 | workarounds |= sbp2_workarounds_table[i].workarounds; |
1563 | break; | 1599 | break; |
1564 | } | 1600 | } |
1565 | 1601 | ||
1566 | if (workarounds) | 1602 | if (workarounds) |
1567 | SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": " | 1603 | SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x " |
1568 | "0x%x (firmware_revision 0x%x)", | 1604 | "(firmware_revision 0x%06x, vendor_id 0x%06x," |
1605 | " model_id 0x%06x)", | ||
1569 | NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), | 1606 | NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), |
1570 | workarounds, firmware_revision); | 1607 | workarounds, firmware_revision, |
1608 | ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id, | ||
1609 | ud->model_id); | ||
1571 | 1610 | ||
1572 | /* We would need one SCSI host template for each target to adjust | 1611 | /* We would need one SCSI host template for each target to adjust |
1573 | * max_sectors on the fly, therefore warn only. */ | 1612 | * max_sectors on the fly, therefore warn only. */ |
@@ -2488,6 +2527,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) | |||
2488 | if (sdev->type == TYPE_DISK && | 2527 | if (sdev->type == TYPE_DISK && |
2489 | scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) | 2528 | scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) |
2490 | sdev->skip_ms_page_8 = 1; | 2529 | sdev->skip_ms_page_8 = 1; |
2530 | if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) | ||
2531 | sdev->fix_capacity = 1; | ||
2491 | return 0; | 2532 | return 0; |
2492 | } | 2533 | } |
2493 | 2534 | ||
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index e40caf5d61ac..3af2710f1858 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
@@ -238,6 +238,7 @@ struct sbp2_status_block { | |||
238 | #define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 | 238 | #define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 |
239 | #define SBP2_WORKAROUND_INQUIRY_36 0x2 | 239 | #define SBP2_WORKAROUND_INQUIRY_36 0x2 |
240 | #define SBP2_WORKAROUND_MODE_SENSE_8 0x4 | 240 | #define SBP2_WORKAROUND_MODE_SENSE_8 0x4 |
241 | #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 | ||
241 | 242 | ||
242 | /* This is the two dma types we use for cmd_dma below */ | 243 | /* This is the two dma types we use for cmd_dma below */ |
243 | enum cmd_dma_types { | 244 | enum cmd_dma_types { |