linux/include
Taisuke Yamada 97b697a11b [libata] LBA28/LBA48 off-by-one bug in ata.h
I recently bought 3 HGST P7K500-series 500GB SATA drives and
had trouble accessing the block right on the LBA28-LBA48 border.
Here's how it fails (same for all 3 drives):

  # dd if=/dev/sdc bs=512 count=1 skip=268435455 > /dev/null
  dd: reading `/dev/sdc': Input/output error
  0+0 records in
  0+0 records out
  0 bytes (0 B) copied, 0.288033 seconds, 0.0 kB/s
  # dmesg
  ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
  ata1.00: BMDMA stat 0x25
  ata1.00: cmd c8/00:08:f8:ff:ff/00:00:00:00:00/ef tag 0 dma 4096 in
  res 51/04:08:f8:ff:ff/00:00:00:00:00/ef Emask 0x1 (device error)
  ata1.00: status: { DRDY ERR }
  ata1.00: error: { ABRT }
  ata1.00: configured for UDMA/33
  ata1: EH complete
  ...

After some investigations, it turned out this seems to be caused
by misinterpretation of the ATA specification on LBA28 access.
Following part is the code in question:

  === include/linux/ata.h ===
  static inline int lba_28_ok(u64 block, u32 n_block)
  {
    /* check the ending block number */
    return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
  }

HGST drive (sometimes) fails with LBA28 access of {block = 0xfffffff,
n_block = 1}, and this behavior seems to be comformant. Other drives,
including other HGST drives are not that strict, through.

>From the ATA specification:
(http://www.t13.org/Documents/UploadedDocuments/project/d1410r3b-ATA-ATAPI-6.pdf)

  8.15.29  Word (61:60): Total number of user addressable sectors
  This field contains a value that is one greater than the total number
  of user addressable sectors (see 6.2). The maximum value that shall
  be placed in this field is 0FFFFFFFh.

So the driver shouldn't use the value of 0xfffffff for LBA28 request
as this exceeds maximum user addressable sector. The logical maximum
value for LBA28 is 0xffffffe.

The obvious fix is to cut "- 1" part, and the patch attached just do
that. I've been using the patched kernel for about a month now, and
the same fix is also floating on the net for some time. So I believe
this fix works reliably.

Just FYI, many Windows/Intel platform users also seems to be struck
by this, and HGST has issued a note pointing to Intel ICH8/9 driver.

  "28-bit LBA command is being used to access LBAs 29-bits in length"
http://www.hitachigst.com/hddt/knowtree.nsf/cffe836ed7c12018862565b000530c74/b531b8bce8745fb78825740f00580e23

Also, *BSDs seems to have similar fix included sometime around ~2004,
through I have not checked out exact portion of the code.

Signed-off-by: Taisuke Yamada <tai@rakugaki.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
2008-09-13 16:46:15 -04:00
..
acpi ACPICA: Additional error checking for pathname utilities 2008-08-15 02:12:16 +02:00
asm-arm [ARM] 5191/1: ARM: remove CVS keywords 2008-08-16 20:01:18 +01:00
asm-cris Reduce brokenness of CRIS headers_install 2008-08-20 13:19:51 -07:00
asm-frv FRV: Provide ioremap_wc() for FRV 2008-08-20 13:19:52 -07:00
asm-generic lib: Correct printk %pF to work on all architectures 2008-09-09 11:51:15 -07:00
asm-m32r [PATCH] kill altroot 2008-07-26 20:53:20 -04:00
asm-m68k m68k{,nommu}: Wire up new system calls 2008-08-11 10:37:34 -07:00
asm-mips [MIPS] Fix WARNING: at kernel/smp.c:290 2008-09-05 21:24:11 +01:00
asm-mn10300 MN10300: Supply ioremap_wc() for MN10300 2008-08-20 13:19:51 -07:00
asm-parisc lib: Correct printk %pF to work on all architectures 2008-09-09 11:51:15 -07:00
asm-um [PATCH] kill altroot 2008-07-26 20:53:20 -04:00
asm-x86 x86: add NOPL as a synthetic CPU feature bit 2008-09-05 16:13:52 -07:00
asm-xtensa [PATCH] kill altroot 2008-07-26 20:53:20 -04:00
crypto crypto: hash - Add missing top-level functions 2008-08-13 20:08:44 +10:00
drm
keys
linux [libata] LBA28/LBA48 off-by-one bug in ata.h 2008-09-13 16:46:15 -04:00
math-emu
media V4L/DVB (8610): Add suspend/resume capabilities to soc_camera. 2008-08-06 06:57:32 -03:00
mtd
net Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6 2008-09-09 02:11:11 -07:00
pcmcia
rdma RDMA/cma: Remove padding arrays by using struct sockaddr_storage 2008-08-04 11:02:14 -07:00
rxrpc
scsi [SCSI] fix check of PQ and PDT bits for WLUNs 2008-08-29 09:19:11 -05:00
sound ALSA: ASoC: Export dapm_reg_event() fully 2008-07-29 16:00:33 +02:00
video atmel_lcdfb: add board parameter specify framebuffer memory size 2008-08-12 16:07:29 -07:00
xen
Kbuild kbuild: only one call for include/ in make headers_* 2008-07-25 22:11:44 +02:00