ide-disk: workaround for buggy HPA support on ST340823A (take 3)

This disk reports total number of sectors instead of maximum sector address
in response to READ_NATIVE_MAX_ADDRESS command and also happily accepts
SET_MAX_ADDRESS command with the bogus value.  This results in +1 sector
capacity being used and errors on attempts to use the last sector.

...
hdd: Host Protected Area detected.
        current capacity is 78165360 sectors (40020 MB)
        native  capacity is 78165361 sectors (40020 MB)
hdd: Host Protected Area disabled.
...
hdd: reading: block=78165360, sectors=1, buffer=0xc1e63000
hdd: dma_intr: status=0x51 { DriveReady SeekComplete Error }
hdd: dma_intr: error=0x10 { SectorIdNotFound }, LBAsect=78165360, sector=78165360
...

Add hpa_list[] table and workaround the issue in idedisk_check_hpa().

v2:
* Add missing export and improve patch description a bit.

v3:
* Add list termination.  (From Mikko)

Fixes kernel bugzilla bug #8816.

Thanks to Mikko for investigating the issue and helping with this patch.

Cc: Mikko Rapeli <mikko.rapeli@iki.fi>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: NBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
上级 76e1faa7
...@@ -481,6 +481,15 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) ...@@ -481,6 +481,15 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id)
&& id->lba_capacity_2; && id->lba_capacity_2;
} }
/*
* Some disks report total number of sectors instead of
* maximum sector address. We list them here.
*/
static const struct drive_list_entry hpa_list[] = {
{ "ST340823A", NULL },
{ NULL, NULL }
};
static void idedisk_check_hpa(ide_drive_t *drive) static void idedisk_check_hpa(ide_drive_t *drive)
{ {
unsigned long long capacity, set_max; unsigned long long capacity, set_max;
...@@ -492,6 +501,15 @@ static void idedisk_check_hpa(ide_drive_t *drive) ...@@ -492,6 +501,15 @@ static void idedisk_check_hpa(ide_drive_t *drive)
else else
set_max = idedisk_read_native_max_address(drive); set_max = idedisk_read_native_max_address(drive);
if (ide_in_drive_list(drive->id, hpa_list)) {
/*
* Since we are inclusive wrt to firmware revisions do this
* extra check and apply the workaround only when needed.
*/
if (set_max == capacity + 1)
set_max--;
}
if (set_max <= capacity) if (set_max <= capacity)
return; return;
......
...@@ -584,6 +584,8 @@ int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *driv ...@@ -584,6 +584,8 @@ int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *driv
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ide_in_drive_list);
/* /*
* Early UDMA66 devices don't set bit14 to 1, only bit13 is valid. * Early UDMA66 devices don't set bit14 to 1, only bit13 is valid.
* We list them here and depend on the device side cable detection for them. * We list them here and depend on the device side cable detection for them.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册