From 9977126c4b65c1396b665f7a0eeb8c7dede336f9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:38 +0900 Subject: libata: add @is_cmd to ata_tf_to_fis() Add @is_cmd to ata_tf_to_fis(). This controls bit 7 of the second byte which tells the device whether this H2D FIS is for a command or not. This cleans up ahci a bit and will be used by PMP. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 47cd2a1c5544..5d3df6cde272 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -764,7 +764,8 @@ extern unsigned int ata_dev_try_classify(struct ata_port *, unsigned int, u8 *); */ extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf); -extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp); +extern void ata_tf_to_fis(const struct ata_taskfile *tf, + u8 pmp, int is_cmd, u8 *fis); extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf); extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device); extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); -- cgit v1.2.3 From b64bbc39f2122a2276578e40144af69ef01decd4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:39 +0900 Subject: libata: improve EH report formatting Requiring LLDs to format multiple error description messages properly doesn't work too well. Help LLDs a bit by making ata_ehi_push_desc() insert ", " on each invocation. __ata_ehi_push_desc() is the raw version without the automatic separator. While at it, make ehi_desc interface proper functions instead of macros. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 5d3df6cde272..94b37d180680 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -910,16 +910,9 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, /* * ata_eh_info helpers */ -#define ata_ehi_push_desc(ehi, fmt, args...) do { \ - (ehi)->desc_len += scnprintf((ehi)->desc + (ehi)->desc_len, \ - ATA_EH_DESC_LEN - (ehi)->desc_len, \ - fmt , ##args); \ -} while (0) - -#define ata_ehi_clear_desc(ehi) do { \ - (ehi)->desc[0] = '\0'; \ - (ehi)->desc_len = 0; \ -} while (0) +extern void __ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...); +extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...); +extern void ata_ehi_clear_desc(struct ata_eh_info *ehi); static inline void __ata_ehi_hotplugged(struct ata_eh_info *ehi) { -- cgit v1.2.3 From 5335b729064e03319cd2d5219770451dbb1d7f67 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:40 +0900 Subject: libata: implement AC_ERR_NCQ When an NCQ command fails, all commands in flight are aborted and the offending one is reported using log page 10h. Depending on controller characteristics and LLD implementation, all commands may appear as having a device error due to shared TF status making it hard to determine what's actually going on. This patch adds AC_ERR_NCQ, marks the command reported by log page 10h with it and print extra "" after the error report for the command to help distinguishing the offending command. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 94b37d180680..cb181713d9b5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -323,6 +323,7 @@ enum ata_completion_errors { AC_ERR_INVALID = (1 << 7), /* invalid argument */ AC_ERR_OTHER = (1 << 8), /* unknown */ AC_ERR_NODEV_HINT = (1 << 9), /* polling device detection hint */ + AC_ERR_NCQ = (1 << 10), /* marker for offending NCQ qc */ }; /* forward declarations */ -- cgit v1.2.3 From da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:40 +0900 Subject: libata: make ->scr_read/write callbacks return error code Convert ->scr_read/write callbacks to return error code to better indicate failure. This will help handling of SCR_NOTIFICATION. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index cb181713d9b5..c732b3e78e28 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -620,9 +620,8 @@ struct ata_port_operations { u8 (*irq_on) (struct ata_port *); u8 (*irq_ack) (struct ata_port *ap, unsigned int chk_drq); - u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); - void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, - u32 val); + int (*scr_read) (struct ata_port *ap, unsigned int sc_reg, u32 *val); + int (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 val); int (*port_suspend) (struct ata_port *ap, pm_message_t mesg); int (*port_resume) (struct ata_port *ap); -- cgit v1.2.3 From 008a78961ec72990d09d7625ef9499d7317d040d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:40 +0900 Subject: libata: improve SATA PHY speed down logic sata_down_spd_limit() first reads the current SPD from SStatus and limit the speed to the lower one of one below the current limit or one below the current SPD in SStatus. SPD may not be accessible or valid when SPD down is requested making sata_down_spd_limit() fail when it's most needed. This patch makes the current SPD cached after each successful reset and forces GEN I speed (1.5Gbps) if neither of SStatus or the cached value is valid, so sata_down_spd_limit() is now guaranteed to lower the speed limit if lower speed is available. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index c732b3e78e28..16ebdf152c75 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -531,6 +531,7 @@ struct ata_port { unsigned int cbl; /* cable type; ATA_CBL_xxx */ unsigned int hw_sata_spd_limit; unsigned int sata_spd_limit; /* SATA PHY speed limit */ + unsigned int sata_spd; /* current SATA PHY speed */ /* record runtime error info, protected by host lock */ struct ata_eh_info eh_info; -- cgit v1.2.3 From f8f1e1cc0cd4d75c73e9a55a0ede8958e4fa14f1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:40 +0900 Subject: libata: reorganize ata_ehi_hotplugged() __ata_ehi_hotplugged() now has no users. Regorganize ata_ehi_hotplugged() such that a new function ata_ehi_schedule_probe() deals with scheduling probing. ata_ehi_hotplugged() calls it and additionally marks hotplug specific flags. ata_ehi_schedule_probe() will be used laster. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 16ebdf152c75..74800ad6d81f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -915,16 +915,17 @@ extern void __ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...); extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...); extern void ata_ehi_clear_desc(struct ata_eh_info *ehi); -static inline void __ata_ehi_hotplugged(struct ata_eh_info *ehi) +static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi) { - ehi->flags |= ATA_EHI_HOTPLUGGED | ATA_EHI_RESUME_LINK; + ehi->flags |= ATA_EHI_RESUME_LINK; ehi->action |= ATA_EH_SOFTRESET; ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1; } static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi) { - __ata_ehi_hotplugged(ehi); + ata_ehi_schedule_probe(ehi); + ehi->flags |= ATA_EHI_HOTPLUGGED; ehi->err_mask |= AC_ERR_ATA_BUS; } -- cgit v1.2.3 From 5ddf24c5ea9d715dc4f5d5d5dd1c9337d90466dc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jul 2007 14:29:41 +0900 Subject: libata: implement EH fast drain In most cases, when EH is scheduled, all in-flight commands are aborted causing EH to kick in immediately. However, in some cases (especially with PMP), it's unclear which commands are affected by the error condition and although aborting all in-flight commands work, it isn't optimal and may cause unnecessary disruption. On the other hand, waiting for in-flight commands to drain themselves can take up to 30seconds. This patch implements EH fast drain to handle such situations. It gives in-flight commands some time to finish up but doesn't wait for too long. After EH is scheduled, fast drain timer is started and if no other completion occurs in ATA_EH_FASTDRAIN_INTERVAL all in-flight commands are aborted. If any completion occurred in the interval, the port is given another interval to finish up itself. Currently ATA_EH_FASTDRAIN_INTERVAL is 3 secs which should be enough for finishing up most commands. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 74800ad6d81f..be5a43928c84 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -565,6 +565,9 @@ struct ata_port { pm_message_t pm_mesg; int *pm_result; + struct timer_list fastdrain_timer; + unsigned long fastdrain_cnt; + void *private_data; #ifdef CONFIG_ATA_ACPI -- cgit v1.2.3