From 0c247c559cd70f85ba9f0764ce13ae00e20fcad8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:19 +0900 Subject: [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 --- drivers/scsi/libata-eh.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 0803231f6577..71ad18b7cff6 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -46,6 +46,51 @@ static void __ata_port_freeze(struct ata_port *ap); +static void ata_ering_record(struct ata_ering *ering, int is_io, + unsigned int err_mask) +{ + struct ata_ering_entry *ent; + + WARN_ON(!err_mask); + + ering->cursor++; + ering->cursor %= ATA_ERING_SIZE; + + ent = &ering->ring[ering->cursor]; + ent->is_io = is_io; + ent->err_mask = err_mask; + ent->timestamp = get_jiffies_64(); +} + +static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering) +{ + struct ata_ering_entry *ent = &ering->ring[ering->cursor]; + if (!ent->err_mask) + return NULL; + return ent; +} + +static int ata_ering_map(struct ata_ering *ering, + int (*map_fn)(struct ata_ering_entry *, void *), + void *arg) +{ + int idx, rc = 0; + struct ata_ering_entry *ent; + + idx = ering->cursor; + do { + ent = &ering->ring[idx]; + if (!ent->err_mask) + break; + rc = map_fn(ent, arg); + if (rc) + break; + idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE; + } while (idx != ering->cursor); + + return rc; +} + /** * ata_scsi_timed_out - SCSI layer time out callback * @cmd: timed out SCSI command -- cgit v1.2.3