diff options
| author | Mark Lord <liml@rtr.ca> | 2009-03-19 13:32:21 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2009-03-24 22:40:05 -0400 |
| commit | e18086d69cb5bb864749a0637f6ac573aa89d5ea (patch) | |
| tree | 2d3e541787eb30743693dd45c96ebabb9be0f0a6 | |
| parent | 000b344f4ca7828ee43940255c8bbb32e2c7dbec (diff) | |
[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>
| -rw-r--r-- | drivers/ata/libata-core.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d4a7b8a96ecd..e7ea77cf6069 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #include <linux/scatterlist.h> | 57 | #include <linux/scatterlist.h> |
| 58 | #include <linux/io.h> | 58 | #include <linux/io.h> |
| 59 | #include <linux/async.h> | 59 | #include <linux/async.h> |
| 60 | #include <linux/log2.h> | ||
| 60 | #include <scsi/scsi.h> | 61 | #include <scsi/scsi.h> |
| 61 | #include <scsi/scsi_cmnd.h> | 62 | #include <scsi/scsi_cmnd.h> |
| 62 | #include <scsi/scsi_host.h> | 63 | #include <scsi/scsi_host.h> |
| @@ -2389,6 +2390,7 @@ int ata_dev_configure(struct ata_device *dev) | |||
| 2389 | dev->cylinders = 0; | 2390 | dev->cylinders = 0; |
| 2390 | dev->heads = 0; | 2391 | dev->heads = 0; |
| 2391 | dev->sectors = 0; | 2392 | dev->sectors = 0; |
| 2393 | dev->multi_count = 0; | ||
| 2392 | 2394 | ||
| 2393 | /* | 2395 | /* |
| 2394 | * common ATA, ATAPI feature tests | 2396 | * common ATA, ATAPI feature tests |
| @@ -2426,8 +2428,15 @@ int ata_dev_configure(struct ata_device *dev) | |||
| 2426 | 2428 | ||
| 2427 | dev->n_sectors = ata_id_n_sectors(id); | 2429 | dev->n_sectors = ata_id_n_sectors(id); |
| 2428 | 2430 | ||
| 2429 | if (dev->id[59] & 0x100) | 2431 | /* get current R/W Multiple count setting */ |
| 2430 | dev->multi_count = dev->id[59] & 0xff; | 2432 | if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) { |
| 2433 | unsigned int max = dev->id[47] & 0xff; | ||
| 2434 | unsigned int cnt = dev->id[59] & 0xff; | ||
| 2435 | /* only recognize/allow powers of two here */ | ||
| 2436 | if (is_power_of_2(max) && is_power_of_2(cnt)) | ||
| 2437 | if (cnt <= max) | ||
| 2438 | dev->multi_count = cnt; | ||
| 2439 | } | ||
| 2431 | 2440 | ||
| 2432 | if (ata_id_has_lba(id)) { | 2441 | if (ata_id_has_lba(id)) { |
| 2433 | const char *lba_desc; | 2442 | const char *lba_desc; |
