diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:58:19 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:58:19 -0400 |
commit | 0c247c559cd70f85ba9f0764ce13ae00e20fcad8 (patch) | |
tree | 9b0d00b300ad9178438b9c7feba95ed62f540c1a /drivers/scsi/libata-eh.c | |
parent | 9be1e979f2e1e57a091a658fa88dac266f9fd6fe (diff) |
[PATCH] libata-eh: implement dev->ering
This patch implements ata_ering and uses it to define dev->ering.
ata_ering is a ring buffer which records libata errors - whether a
command was for normar IO request, err_mask and timestamp. Errors are
recorded per-device in dev->ering. This will be used by EH to
determine recovery actions.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/scsi/libata-eh.c')
-rw-r--r-- | drivers/scsi/libata-eh.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 0803231f657..71ad18b7cff 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -46,6 +46,51 @@ | |||
46 | 46 | ||
47 | static void __ata_port_freeze(struct ata_port *ap); | 47 | static void __ata_port_freeze(struct ata_port *ap); |
48 | 48 | ||
49 | static void ata_ering_record(struct ata_ering *ering, int is_io, | ||
50 | unsigned int err_mask) | ||
51 | { | ||
52 | struct ata_ering_entry *ent; | ||
53 | |||
54 | WARN_ON(!err_mask); | ||
55 | |||
56 | ering->cursor++; | ||
57 | ering->cursor %= ATA_ERING_SIZE; | ||
58 | |||
59 | ent = &ering->ring[ering->cursor]; | ||
60 | ent->is_io = is_io; | ||
61 | ent->err_mask = err_mask; | ||
62 | ent->timestamp = get_jiffies_64(); | ||
63 | } | ||
64 | |||
65 | static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering) | ||
66 | { | ||
67 | struct ata_ering_entry *ent = &ering->ring[ering->cursor]; | ||
68 | if (!ent->err_mask) | ||
69 | return NULL; | ||
70 | return ent; | ||
71 | } | ||
72 | |||
73 | static int ata_ering_map(struct ata_ering *ering, | ||
74 | int (*map_fn)(struct ata_ering_entry *, void *), | ||
75 | void *arg) | ||
76 | { | ||
77 | int idx, rc = 0; | ||
78 | struct ata_ering_entry *ent; | ||
79 | |||
80 | idx = ering->cursor; | ||
81 | do { | ||
82 | ent = &ering->ring[idx]; | ||
83 | if (!ent->err_mask) | ||
84 | break; | ||
85 | rc = map_fn(ent, arg); | ||
86 | if (rc) | ||
87 | break; | ||
88 | idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE; | ||
89 | } while (idx != ering->cursor); | ||
90 | |||
91 | return rc; | ||
92 | } | ||
93 | |||
49 | /** | 94 | /** |
50 | * ata_scsi_timed_out - SCSI layer time out callback | 95 | * ata_scsi_timed_out - SCSI layer time out callback |
51 | * @cmd: timed out SCSI command | 96 | * @cmd: timed out SCSI command |