aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2009-05-15 00:40:35 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-05-15 14:14:56 -0400
commit4bca3286433585b5f1c3e7d8ac37a2f4b3def9ca (patch)
tree54188630bb30858acf409df5bd07b7f31bf575ec
parent61d79a8eb362f826a002d3d14c4f9a070a818542 (diff)
libata: Media rotation rate and form factor heuristics
This patch provides new heuristics for parsing both the form factor and media rotation rate ATA IDENFITY words. The reported ATA version must be 7 or greater and the device must return values defined as valid in the standard. Only then are the characteristics reported to SCSI via the VPD B1 page. This seems like a reasonable compromise to me considering that we have been shipping several kernel releases that key off the rotation rate bit without any version checking whatsoever. With no complaints so far. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/libata-scsi.c11
-rw-r--r--include/linux/ata.h28
2 files changed, 34 insertions, 5 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d1718a1f278a..342316064e9f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2142,13 +2142,14 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
2142 2142
2143static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf) 2143static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
2144{ 2144{
2145 int form_factor = ata_id_form_factor(args->id);
2146 int media_rotation_rate = ata_id_rotation_rate(args->id);
2147
2145 rbuf[1] = 0xb1; 2148 rbuf[1] = 0xb1;
2146 rbuf[3] = 0x3c; 2149 rbuf[3] = 0x3c;
2147 if (ata_id_major_version(args->id) > 7) { 2150 rbuf[4] = media_rotation_rate >> 8;
2148 rbuf[4] = args->id[217] >> 8; 2151 rbuf[5] = media_rotation_rate;
2149 rbuf[5] = args->id[217]; 2152 rbuf[7] = form_factor;
2150 rbuf[7] = args->id[168] & 0xf;
2151 }
2152 2153
2153 return 0; 2154 return 0;
2154} 2155}
diff --git a/include/linux/ata.h b/include/linux/ata.h
index cb79b7a208e1..915da43edee1 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -730,6 +730,34 @@ static inline int ata_id_has_unload(const u16 *id)
730 return 0; 730 return 0;
731} 731}
732 732
733static inline int ata_id_form_factor(const u16 *id)
734{
735 u16 val = id[168];
736
737 if (ata_id_major_version(id) < 7 || val == 0 || val == 0xffff)
738 return 0;
739
740 val &= 0xf;
741
742 if (val > 5)
743 return 0;
744
745 return val;
746}
747
748static inline int ata_id_rotation_rate(const u16 *id)
749{
750 u16 val = id[217];
751
752 if (ata_id_major_version(id) < 7 || val == 0 || val == 0xffff)
753 return 0;
754
755 if (val > 1 && val < 0x401)
756 return 0;
757
758 return val;
759}
760
733static inline int ata_id_has_trim(const u16 *id) 761static inline int ata_id_has_trim(const u16 *id)
734{ 762{
735 if (ata_id_major_version(id) >= 7 && 763 if (ata_id_major_version(id) >= 7 &&