From cd7e93afb0edd654fe220261ce9a1597999e3ffb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 May 2006 20:58:19 +0900 Subject: [PATCH] --- yaml --- r: 29311 b: refs/heads/master c: 0c247c559cd70f85ba9f0764ce13ae00e20fcad8 h: refs/heads/master i: 29309: 64adc489d466daf83baed5e753cc84bc7e637af1 29307: f0153d56682e129fec7c625c255ac76683978b5f 29303: 5467ae4cf77abc8b01e9ca0f419865e06d0777f4 29295: 6c06e0fbf0f21c97defb9e3c4b1d5714744130c2 29279: b8b5e900d86281030d4c58026309693ffe9da65f 29247: cbd4c3d71a2c9fda46b91d7ac71a7173282dbc7d 29183: abd228295c198bf53d6215ade6d8ea92636507c5 v: v3 --- [refs] | 2 +- trunk/drivers/scsi/libata-eh.c | 45 ++++++++++++++++++++++++++++++++++ trunk/include/linux/libata.h | 17 +++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 10e8a36de9ce..824089490d53 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9be1e979f2e1e57a091a658fa88dac266f9fd6fe +refs/heads/master: 0c247c559cd70f85ba9f0764ce13ae00e20fcad8 diff --git a/trunk/drivers/scsi/libata-eh.c b/trunk/drivers/scsi/libata-eh.c index 0803231f6577..71ad18b7cff6 100644 --- a/trunk/drivers/scsi/libata-eh.c +++ b/trunk/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 diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index 6fe5ed8eabf5..f5cea13599c3 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -226,6 +226,9 @@ enum { ATA_PORT_PRIMARY = (1 << 0), ATA_PORT_SECONDARY = (1 << 1), + /* ering size */ + ATA_ERING_SIZE = 32, + /* reset / recovery action types */ ATA_EH_REVALIDATE = (1 << 0), ATA_EH_SOFTRESET = (1 << 1), @@ -375,6 +378,17 @@ struct ata_host_stats { unsigned long rw_reqbuf; }; +struct ata_ering_entry { + int is_io; + unsigned int err_mask; + u64 timestamp; +}; + +struct ata_ering { + int cursor; + struct ata_ering_entry ring[ATA_ERING_SIZE]; +}; + struct ata_device { struct ata_port *ap; u64 n_sectors; /* size of device, if ATA */ @@ -401,6 +415,9 @@ struct ata_device { u16 cylinders; /* Number of cylinders */ u16 heads; /* Number of heads */ u16 sectors; /* Number of sectors per track */ + + /* error history */ + struct ata_ering ering; }; struct ata_port {