[libata] More robust parsing for IDENTIFY DEVICE multi_count field

Make libata more robust when parsing the multi_count
field from a drive's identify data.  This prevents us from
attempting to use dubious multi_count values ad infinitum.

Reset dev->multi_count to zero and reprobe it each time
through this routine, as it can change on device reset.

Also ensure that the reported "maximum" value is valid
and is a power of two, and that the reported "count" value
is valid and also a power of two.  And that the "count"
value is not greater than the "maximum" value.

Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
Mark Lord 2009-03-19 13:32:21 -04:00 committed by Jeff Garzik
parent 000b344f4c
commit e18086d69c

View File

@ -57,6 +57,7 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/async.h> #include <linux/async.h>
#include <linux/log2.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
@ -2389,6 +2390,7 @@ int ata_dev_configure(struct ata_device *dev)
dev->cylinders = 0; dev->cylinders = 0;
dev->heads = 0; dev->heads = 0;
dev->sectors = 0; dev->sectors = 0;
dev->multi_count = 0;
/* /*
* common ATA, ATAPI feature tests * common ATA, ATAPI feature tests
@ -2426,8 +2428,15 @@ int ata_dev_configure(struct ata_device *dev)
dev->n_sectors = ata_id_n_sectors(id); dev->n_sectors = ata_id_n_sectors(id);
if (dev->id[59] & 0x100) /* get current R/W Multiple count setting */
dev->multi_count = dev->id[59] & 0xff; if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) {
unsigned int max = dev->id[47] & 0xff;
unsigned int cnt = dev->id[59] & 0xff;
/* only recognize/allow powers of two here */
if (is_power_of_2(max) && is_power_of_2(cnt))
if (cnt <= max)
dev->multi_count = cnt;
}
if (ata_id_has_lba(id)) { if (ata_id_has_lba(id)) {
const char *lba_desc; const char *lba_desc;