Bug 187269

Summary: AF-4Kn SATA drives have mis-interpreted sector sizes
Product: Base System Reporter: Ravi Pokala <rpokala>
Component: kernAssignee: Alexander Motin <mav>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Ravi Pokala 2014-03-05 04:20:00 UTC
AF-4Kn SATA drives (4KB logical sector size, 4KB physical sector size) are being identified as having 2KB logical sectors and 512-byte physical sectors. This leads to data access timing out, the GPT being unreadable, and general uselessness.

The drive that I was using when I discovered this problem is an engineering sample under NDA, so I have obscured the model/firmware/serial/WWN; sorry about that. The label states that the capacity is 5.0TB and that there are 1220942646 LBAs.


/var/run/dmesg.boot (comments indented):
----------------------------------------------------------------
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
ada0: Serial Number DRIVE-SERIAL-NUMBER
ada0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 4096bytes)
ada0: Command Queueing enabled
ada0: 2384653MB (1220942646 2048 byte sectors: 16H 63S/T 16383C)
        Incorrect capacity
        Correct number of logical sectors, but incorrect sector size
ada0: Previously was known as ad4
(ada0:ahcich0:0:0:0): READ_DMA48. ACB: 25 00 f7 1a c6 40 48 00 00 00 04 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
GEOM: ada0: corrupt or invalid GPT detected.
GEOM: ada0: GPT rejected -- may not be recoverable.
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 20 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 20 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 04 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 04 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 00 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 00 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 80 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 80 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 20 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 20 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 04 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 04 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 00 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 00 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 80 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 80 00 00 00 00 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 f7 1a c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 f7 1a c6 00 48 00 00 00 00
        5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
----------------------------------------------------------------

`camcontrol identify ada0' (comments indented):
----------------------------------------------------------------
pass0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
pass0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 4096bytes)

protocol              ATA/ATAPI-9 SATA 3.x
device model          DRIVE-MODEL
firmware revision     DRIVE-FW
serial number         DRIVE-SERIAL-NUMBER
WWN                   DRIVE-WWN
cylinders             16383
heads                 16
sectors/track         63
sector size           logical 2048, physical 512, offset 0
        Incorrect sector sizes
LBA supported         268435455 sectors
LBA48 supported       1220942646 sectors
PIO supported         PIO4
DMA supported         WDMA2 UDMA6 
media RPM             7200

Feature                      Support  Enabled   Value           Vendor
read ahead                     yes	yes
write cache                    yes	yes
flush cache                    yes	yes
overlap                        no
Tagged Command Queuing (TCQ)   no	no
Native Command Queuing (NCQ)   yes		32 tags
SMART                          yes	yes
microcode download             yes	yes
security                       yes	no
power management               yes	yes
advanced power management      yes	yes	128/0x80
automatic acoustic management  no	no
media status notification      no	no
power-up in Standby            yes	no
write-read-verify              no	no
unload                         no	no
free-fall                      no	no
Data Set Management (DSM/TRIM) no
Host Protected Area (HPA)      no
----------------------------------------------------------------

I looked at the code, and discovered two issues:

(1) sys/cam/ata/ata_all.c::ata_logical_sector_size()

The function returns the LSS in bytes. If IDENTIFY_DEVICE word 'pss' indicates that the LSS is larger than 512 bytes, it concatenates words 'lss_1' and 'lss_2' into a 'u_int32_t' and returns it. However, the ATA specs define that value as the number of *words* in a logical sector, not the number of bytes. Thus, it returns 2048 instead of 4096 as the LSS.

----------------------------------------------------------------

(2) sys/cam/ata/ata_all.c::ata_physical_sector_size()

The function returns the PSS in bytes. If IDENTIFY_DEVICE word 'pss' indicates that there are multiple logical sectors per physical sector, it extracts the scaling factor, multiplies it by the LSS, and returns the result; otherwise, it returns a PSS of 512 bytes. The problem here is that, if there is only one logical sector per physical sector, the logical sector size is completely ignored.

Fix: The attached patch fixes both of the problems (I also took the liberty of replacing a few magic constants (a bitmask and value used for validation) with '#define's.)

(1) sys/cam/ata/ata_all.c::ata_logical_sector_size()

After concatenating 'lss_1' and 'lss_2', convert from words to bytes by left-shifting one bit.

----------------------------------------------------------------

(2) sys/cam/ata/ata_all.c::ata_physical_sector_size()

If there is only a single logical sector per physical sector, then the physical sector size is equal to the logical sector size, so return that value.

----------------------------------------------------------------

/var/run/dmesg.boot (comments indented):
----------------------------------------------------------------
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
ada0: Serial Number DRIVE-SERIAL-NUMBER
ada0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 4769307MB (1220942646 4096 byte sectors: 16H 63S/T 16383C)
        Correct capacity
        Correct number of logical sectors, and correct sector size
ada0: Previously was known as ad4
        No errors; GPT was read and parsed correctly
----------------------------------------------------------------

`gpart show ada0':
----------------------------------------------------------------
=>         6  1220942635  ada0  GPT  (4.5T)
           6     3969000     2  freebsd-ufs  (15G)
     3969006  1216973635        - free -  (4.5T)
----------------------------------------------------------------

`camcontrol identify ada0' (comments indented):
----------------------------------------------------------------
pass0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
pass0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 8192bytes)

protocol              ATA/ATAPI-9 SATA 3.x
device model          DRIVE-MODEL
firmware revision     DRIVE-FW
serial number         DRIVE-SERIAL-NUMBER
WWN                   DRIVE-WWN
cylinders             16383
heads                 16
sectors/track         63
sector size           logical 4096, physical 4096, offset 0
        Correct sector sizes
LBA supported         268435455 sectors
LBA48 supported       1220942646 sectors
PIO supported         PIO4
DMA supported         WDMA2 UDMA6 
media RPM             7200

Feature                      Support  Enabled   Value           Vendor
read ahead                     yes	yes
write cache                    yes	yes
flush cache                    yes	yes
overlap                        no
Tagged Command Queuing (TCQ)   no	no
Native Command Queuing (NCQ)   yes		32 tags
SMART                          yes	yes
microcode download             yes	yes
security                       yes	no
power management               yes	yes
advanced power management      yes	yes	128/0x80
automatic acoustic management  no	no
media status notification      no	no
power-up in Standby            yes	no
write-read-verify              no	no
unload                         no	no
free-fall                      no	no
Data Set Management (DSM/TRIM) no
Host Protected Area (HPA)      no
----------------------------------------------------------------


Patch attached with submission follows:
How-To-Repeat: Boot with an AF-4Kn SATA drive attached.
Comment 1 dfilter service freebsd_committer freebsd_triage 2014-03-07 09:45:54 UTC
Author: mav
Date: Fri Mar  7 09:45:40 2014
New Revision: 262886
URL: http://svnweb.freebsd.org/changeset/base/262886

Log:
  Fix support for increased logical sector size (4K-native drives).
  
  - Logical sector size is measured in words, not bytes.
  - If physical sector is not bigger then logical sector, it does not mean
  it should be set equal to 512 bytes, but set to logical sector.
  
  PR:		misc/187269
  Submitted by:	Ravi Pokala <rpokala@panasas.com>
  MFC after:	1 week

Modified:
  head/sys/cam/ata/ata_all.c
  head/sys/sys/ata.h

Modified: head/sys/cam/ata/ata_all.c
==============================================================================
--- head/sys/cam/ata/ata_all.c	Fri Mar  7 07:06:36 2014	(r262885)
+++ head/sys/cam/ata/ata_all.c	Fri Mar  7 09:45:40 2014	(r262886)
@@ -338,10 +338,10 @@ semb_print_ident_short(struct sep_identi
 uint32_t
 ata_logical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE &&
 	    (ident_data->pss & ATA_PSS_LSSABOVE512)) {
-		return ((u_int32_t)ident_data->lss_1 |
-		    ((u_int32_t)ident_data->lss_2 << 16));
+		return (((u_int32_t)ident_data->lss_1 |
+		    ((u_int32_t)ident_data->lss_2 << 16)) * 2);
 	}
 	return (512);
 }
@@ -349,10 +349,13 @@ ata_logical_sector_size(struct ata_param
 uint64_t
 ata_physical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
-	    (ident_data->pss & ATA_PSS_MULTLS)) {
-		return ((uint64_t)ata_logical_sector_size(ident_data) *
-		    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) {
+		if (ident_data->pss & ATA_PSS_MULTLS) {
+			return ((uint64_t)ata_logical_sector_size(ident_data) *
+			    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+		} else {
+			return (uint64_t)ata_logical_sector_size(ident_data);
+		}
 	}
 	return (512);
 }

Modified: head/sys/sys/ata.h
==============================================================================
--- head/sys/sys/ata.h	Fri Mar  7 07:06:36 2014	(r262885)
+++ head/sys/sys/ata.h	Fri Mar  7 09:45:40 2014	(r262886)
@@ -214,6 +214,8 @@ struct ata_params {
 #define ATA_PSS_LSPPS			0x000F
 #define ATA_PSS_LSSABOVE512		0x1000
 #define ATA_PSS_MULTLS			0x2000
+#define ATA_PSS_VALID_MASK		0xC000
+#define ATA_PSS_VALID_VALUE		0x4000
 /*107*/ u_int16_t       isd;
 /*108*/ u_int16_t       wwn[4];
 	u_int16_t       reserved112[5];
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 2 dfilter service freebsd_committer freebsd_triage 2014-03-14 07:47:50 UTC
Author: mav
Date: Fri Mar 14 07:47:28 2014
New Revision: 263156
URL: http://svnweb.freebsd.org/changeset/base/263156

Log:
  MFC r262886:
  Fix support for increased logical sector size (4K-native drives).
  
  - Logical sector size is measured in words, not bytes.
  - If physical sector is not bigger then logical sector, it does not mean
  it should be set equal to 512 bytes, but set to logical sector.
  
  PR:		misc/187269
  Submitted by:	Ravi Pokala <rpokala@panasas.com>

Modified:
  stable/10/sys/cam/ata/ata_all.c
  stable/10/sys/sys/ata.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/ata/ata_all.c
==============================================================================
--- stable/10/sys/cam/ata/ata_all.c	Fri Mar 14 07:11:33 2014	(r263155)
+++ stable/10/sys/cam/ata/ata_all.c	Fri Mar 14 07:47:28 2014	(r263156)
@@ -338,10 +338,10 @@ semb_print_ident_short(struct sep_identi
 uint32_t
 ata_logical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE &&
 	    (ident_data->pss & ATA_PSS_LSSABOVE512)) {
-		return ((u_int32_t)ident_data->lss_1 |
-		    ((u_int32_t)ident_data->lss_2 << 16));
+		return (((u_int32_t)ident_data->lss_1 |
+		    ((u_int32_t)ident_data->lss_2 << 16)) * 2);
 	}
 	return (512);
 }
@@ -349,10 +349,13 @@ ata_logical_sector_size(struct ata_param
 uint64_t
 ata_physical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
-	    (ident_data->pss & ATA_PSS_MULTLS)) {
-		return ((uint64_t)ata_logical_sector_size(ident_data) *
-		    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) {
+		if (ident_data->pss & ATA_PSS_MULTLS) {
+			return ((uint64_t)ata_logical_sector_size(ident_data) *
+			    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+		} else {
+			return (uint64_t)ata_logical_sector_size(ident_data);
+		}
 	}
 	return (512);
 }

Modified: stable/10/sys/sys/ata.h
==============================================================================
--- stable/10/sys/sys/ata.h	Fri Mar 14 07:11:33 2014	(r263155)
+++ stable/10/sys/sys/ata.h	Fri Mar 14 07:47:28 2014	(r263156)
@@ -214,6 +214,8 @@ struct ata_params {
 #define ATA_PSS_LSPPS			0x000F
 #define ATA_PSS_LSSABOVE512		0x1000
 #define ATA_PSS_MULTLS			0x2000
+#define ATA_PSS_VALID_MASK		0xC000
+#define ATA_PSS_VALID_VALUE		0x4000
 /*107*/ u_int16_t       isd;
 /*108*/ u_int16_t       wwn[4];
 	u_int16_t       reserved112[5];
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 3 dfilter service freebsd_committer freebsd_triage 2014-03-14 07:48:42 UTC
Author: mav
Date: Fri Mar 14 07:48:35 2014
New Revision: 263157
URL: http://svnweb.freebsd.org/changeset/base/263157

Log:
  MFC r262886:
  Fix support for increased logical sector size (4K-native drives).
  
  - Logical sector size is measured in words, not bytes.
  - If physical sector is not bigger then logical sector, it does not mean
  it should be set equal to 512 bytes, but set to logical sector.
  
  PR:             misc/187269
  Submitted by:   Ravi Pokala <rpokala@panasas.com>

Modified:
  stable/9/sys/cam/ata/ata_all.c
  stable/9/sys/sys/ata.h
Directory Properties:
  stable/9/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/sys/   (props changed)

Modified: stable/9/sys/cam/ata/ata_all.c
==============================================================================
--- stable/9/sys/cam/ata/ata_all.c	Fri Mar 14 07:47:28 2014	(r263156)
+++ stable/9/sys/cam/ata/ata_all.c	Fri Mar 14 07:48:35 2014	(r263157)
@@ -338,10 +338,10 @@ semb_print_ident_short(struct sep_identi
 uint32_t
 ata_logical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE &&
 	    (ident_data->pss & ATA_PSS_LSSABOVE512)) {
-		return ((u_int32_t)ident_data->lss_1 |
-		    ((u_int32_t)ident_data->lss_2 << 16));
+		return (((u_int32_t)ident_data->lss_1 |
+		    ((u_int32_t)ident_data->lss_2 << 16)) * 2);
 	}
 	return (512);
 }
@@ -349,10 +349,13 @@ ata_logical_sector_size(struct ata_param
 uint64_t
 ata_physical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
-	    (ident_data->pss & ATA_PSS_MULTLS)) {
-		return ((uint64_t)ata_logical_sector_size(ident_data) *
-		    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) {
+		if (ident_data->pss & ATA_PSS_MULTLS) {
+			return ((uint64_t)ata_logical_sector_size(ident_data) *
+			    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+		} else {
+			return (uint64_t)ata_logical_sector_size(ident_data);
+		}
 	}
 	return (512);
 }

Modified: stable/9/sys/sys/ata.h
==============================================================================
--- stable/9/sys/sys/ata.h	Fri Mar 14 07:47:28 2014	(r263156)
+++ stable/9/sys/sys/ata.h	Fri Mar 14 07:48:35 2014	(r263157)
@@ -214,6 +214,8 @@ struct ata_params {
 #define ATA_PSS_LSPPS			0x000F
 #define ATA_PSS_LSSABOVE512		0x1000
 #define ATA_PSS_MULTLS			0x2000
+#define ATA_PSS_VALID_MASK		0xC000
+#define ATA_PSS_VALID_VALUE		0x4000
 /*107*/ u_int16_t       isd;
 /*108*/ u_int16_t       wwn[4];
 	u_int16_t       reserved112[5];
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 4 dfilter service freebsd_committer freebsd_triage 2014-03-14 07:58:18 UTC
Author: mav
Date: Fri Mar 14 07:58:11 2014
New Revision: 263158
URL: http://svnweb.freebsd.org/changeset/base/263158

Log:
  MFC r262886:
  Fix support for increased logical sector size (4K-native drives).
  
  - Logical sector size is measured in words, not bytes.
  - If physical sector is not bigger then logical sector, it does not mean
  it should be set equal to 512 bytes, but set to logical sector.
  
  PR:             misc/187269
  Submitted by:   Ravi Pokala <rpokala@panasas.com>

Modified:
  stable/8/sys/cam/ata/ata_all.c
  stable/8/sys/sys/ata.h
Directory Properties:
  stable/8/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/cam/   (props changed)
  stable/8/sys/sys/   (props changed)

Modified: stable/8/sys/cam/ata/ata_all.c
==============================================================================
--- stable/8/sys/cam/ata/ata_all.c	Fri Mar 14 07:48:35 2014	(r263157)
+++ stable/8/sys/cam/ata/ata_all.c	Fri Mar 14 07:58:11 2014	(r263158)
@@ -289,10 +289,10 @@ ata_print_ident(struct ata_params *ident
 uint32_t
 ata_logical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE &&
 	    (ident_data->pss & ATA_PSS_LSSABOVE512)) {
-		return ((u_int32_t)ident_data->lss_1 |
-		    ((u_int32_t)ident_data->lss_2 << 16));
+		return (((u_int32_t)ident_data->lss_1 |
+		    ((u_int32_t)ident_data->lss_2 << 16)) * 2);
 	}
 	return (512);
 }
@@ -300,10 +300,13 @@ ata_logical_sector_size(struct ata_param
 uint64_t
 ata_physical_sector_size(struct ata_params *ident_data)
 {
-	if ((ident_data->pss & 0xc000) == 0x4000 &&
-	    (ident_data->pss & ATA_PSS_MULTLS)) {
-		return ((uint64_t)ata_logical_sector_size(ident_data) *
-		    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+	if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) {
+		if (ident_data->pss & ATA_PSS_MULTLS) {
+			return ((uint64_t)ata_logical_sector_size(ident_data) *
+			    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+		} else {
+			return (uint64_t)ata_logical_sector_size(ident_data);
+		}
 	}
 	return (512);
 }

Modified: stable/8/sys/sys/ata.h
==============================================================================
--- stable/8/sys/sys/ata.h	Fri Mar 14 07:48:35 2014	(r263157)
+++ stable/8/sys/sys/ata.h	Fri Mar 14 07:58:11 2014	(r263158)
@@ -214,6 +214,8 @@ struct ata_params {
 #define ATA_PSS_LSPPS			0x000F
 #define ATA_PSS_LSSABOVE512		0x1000
 #define ATA_PSS_MULTLS			0x2000
+#define ATA_PSS_VALID_MASK		0xC000
+#define ATA_PSS_VALID_VALUE		0x4000
 /*107*/ u_int16_t       isd;
 /*108*/ u_int16_t       wwn[4];
 	u_int16_t       reserved112[5];
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 5 Alexander Motin freebsd_committer freebsd_triage 2014-06-01 08:08:00 UTC
State Changed
From-To: open->patched

Patch committed to FreeBSD head and will be merged in a week. 


Comment 6 Alexander Motin freebsd_committer freebsd_triage 2014-06-01 08:08:00 UTC
Responsible Changed
From-To: freebsd-bugs->mav

Patch committed to FreeBSD head and will be merged in a week.
Comment 7 Alexander Motin freebsd_committer freebsd_triage 2014-06-01 08:08:00 UTC
State Changed
From-To: patched->closed

Patch merged to stable/10, stable/9 and stable/8.