diff options
author | Tejun Heo <tj@kernel.org> | 2009-01-29 06:31:32 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-02-02 23:03:17 -0500 |
commit | 99cf610aa4840d822cdc67d194b23b55010ca9bd (patch) | |
tree | 68bc3d6c1f13849731bb7b4b11414b4b0e5fbffb /include/linux | |
parent | 9913ff8abf1c70a8d52560dc931e1901d025ad27 (diff) |
libata: clear dev->ering in smarter way
dev->ering used to be cleared together with the rest of ata_device in
ata_dev_init() which is called whenever a probing event occurs.
dev->ering is about to be used to track probing failures so it needs
to remain persistent over multiple porbing events. This patch
achieves this by doing the following.
* Instead of CLEAR_OFFSET, define CLEAR_BEGIN and CLEAR_END and only
clear between BEGIN and END. ering is moved after END. The split
of persistent area is to allow hotter items remain at the head.
* ering is explicitly cleared on ata_dev_disable() and when device
attach succeeds. So, ering is persistent throug a device's life
time (unless explicitly cleared of course) and also through periods
inbetween disablement of an attached device and successful detection
of the next one.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/libata.h | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h index bca3ba25f52a..9dcefee5843c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -580,7 +580,7 @@ struct ata_device { | |||
580 | acpi_handle acpi_handle; | 580 | acpi_handle acpi_handle; |
581 | union acpi_object *gtf_cache; | 581 | union acpi_object *gtf_cache; |
582 | #endif | 582 | #endif |
583 | /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ | 583 | /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ |
584 | u64 n_sectors; /* size of device, if ATA */ | 584 | u64 n_sectors; /* size of device, if ATA */ |
585 | unsigned int class; /* ATA_DEV_xxx */ | 585 | unsigned int class; /* ATA_DEV_xxx */ |
586 | unsigned long unpark_deadline; | 586 | unsigned long unpark_deadline; |
@@ -605,20 +605,22 @@ struct ata_device { | |||
605 | u16 heads; /* Number of heads */ | 605 | u16 heads; /* Number of heads */ |
606 | u16 sectors; /* Number of sectors per track */ | 606 | u16 sectors; /* Number of sectors per track */ |
607 | 607 | ||
608 | /* error history */ | ||
609 | int spdn_cnt; | ||
610 | struct ata_ering ering; | ||
611 | |||
612 | union { | 608 | union { |
613 | u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ | 609 | u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ |
614 | u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ | 610 | u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ |
615 | }; | 611 | }; |
612 | |||
613 | /* error history */ | ||
614 | int spdn_cnt; | ||
615 | /* ering is CLEAR_END, read comment above CLEAR_END */ | ||
616 | struct ata_ering ering; | ||
616 | }; | 617 | }; |
617 | 618 | ||
618 | /* Offset into struct ata_device. Fields above it are maintained | 619 | /* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are |
619 | * acress device init. Fields below are zeroed. | 620 | * cleared to zero on ata_dev_init(). |
620 | */ | 621 | */ |
621 | #define ATA_DEVICE_CLEAR_OFFSET offsetof(struct ata_device, n_sectors) | 622 | #define ATA_DEVICE_CLEAR_BEGIN offsetof(struct ata_device, n_sectors) |
623 | #define ATA_DEVICE_CLEAR_END offsetof(struct ata_device, ering) | ||
622 | 624 | ||
623 | struct ata_eh_info { | 625 | struct ata_eh_info { |
624 | struct ata_device *dev; /* offending device */ | 626 | struct ata_device *dev; /* offending device */ |