aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-08-13 07:19:09 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-08-22 02:07:43 -0400
commit05944bdf6fadb5394710269df6770dde447b23ca (patch)
tree7dd0435f44518b01e5d3a229167e7122425e2255
parent6a55617ed5d1aa62b850de2cf66f5ede2eef4825 (diff)
libata: implement no[hs]rst force params
Implement force params nohrst, nosrst and norst. This is to work around reset related problems and ease debugging. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--Documentation/kernel-parameters.txt3
-rw-r--r--drivers/ata/libata-core.c46
-rw-r--r--drivers/ata/libata-eh.c4
-rw-r--r--include/linux/libata.h1
4 files changed, 38 insertions, 16 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index a8976467a983..1150444a21ab 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1074,6 +1074,9 @@ and is between 256 and 4096 characters. It is defined in the file
1074 1074
1075 * [no]ncq: Turn on or off NCQ. 1075 * [no]ncq: Turn on or off NCQ.
1076 1076
1077 * nohrst, nosrst, norst: suppress hard, soft
1078 and both resets.
1079
1077 If there are multiple matching configurations changing 1080 If there are multiple matching configurations changing
1078 the same attribute, the last one is used. 1081 the same attribute, the last one is used.
1079 1082
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5ba96c5052c8..dddcb9fde35a 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -104,6 +104,7 @@ struct ata_force_param {
104 unsigned long xfer_mask; 104 unsigned long xfer_mask;
105 unsigned int horkage_on; 105 unsigned int horkage_on;
106 unsigned int horkage_off; 106 unsigned int horkage_off;
107 unsigned int lflags;
107}; 108};
108 109
109struct ata_force_ent { 110struct ata_force_ent {
@@ -196,22 +197,23 @@ void ata_force_cbl(struct ata_port *ap)
196} 197}
197 198
198/** 199/**
199 * ata_force_spd_limit - force SATA spd limit according to libata.force 200 * ata_force_link_limits - force link limits according to libata.force
200 * @link: ATA link of interest 201 * @link: ATA link of interest
201 * 202 *
202 * Force SATA spd limit according to libata.force and whine about 203 * Force link flags and SATA spd limit according to libata.force
203 * it. When only the port part is specified (e.g. 1:), the limit 204 * and whine about it. When only the port part is specified
204 * applies to all links connected to both the host link and all 205 * (e.g. 1:), the limit applies to all links connected to both
205 * fan-out ports connected via PMP. If the device part is 206 * the host link and all fan-out ports connected via PMP. If the
206 * specified as 0 (e.g. 1.00:), it specifies the first fan-out 207 * device part is specified as 0 (e.g. 1.00:), it specifies the
207 * link not the host link. Device number 15 always points to the 208 * first fan-out link not the host link. Device number 15 always
208 * host link whether PMP is attached or not. 209 * points to the host link whether PMP is attached or not.
209 * 210 *
210 * LOCKING: 211 * LOCKING:
211 * EH context. 212 * EH context.
212 */ 213 */
213static void ata_force_spd_limit(struct ata_link *link) 214static void ata_force_link_limits(struct ata_link *link)
214{ 215{
216 bool did_spd = false;
215 int linkno, i; 217 int linkno, i;
216 218
217 if (ata_is_host_link(link)) 219 if (ata_is_host_link(link))
@@ -228,13 +230,22 @@ static void ata_force_spd_limit(struct ata_link *link)
228 if (fe->device != -1 && fe->device != linkno) 230 if (fe->device != -1 && fe->device != linkno)
229 continue; 231 continue;
230 232
231 if (!fe->param.spd_limit) 233 /* only honor the first spd limit */
232 continue; 234 if (!did_spd && fe->param.spd_limit) {
235 link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1;
236 ata_link_printk(link, KERN_NOTICE,
237 "FORCE: PHY spd limit set to %s\n",
238 fe->param.name);
239 did_spd = true;
240 }
233 241
234 link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; 242 /* let lflags stack */
235 ata_link_printk(link, KERN_NOTICE, 243 if (fe->param.lflags) {
236 "FORCE: PHY spd limit set to %s\n", fe->param.name); 244 link->flags |= fe->param.lflags;
237 return; 245 ata_link_printk(link, KERN_NOTICE,
246 "FORCE: link flag 0x%x forced -> 0x%x\n",
247 fe->param.lflags, link->flags);
248 }
238 } 249 }
239} 250}
240 251
@@ -5200,7 +5211,7 @@ int sata_link_init_spd(struct ata_link *link)
5200 if (spd) 5211 if (spd)
5201 link->hw_sata_spd_limit &= (1 << spd) - 1; 5212 link->hw_sata_spd_limit &= (1 << spd) - 1;
5202 5213
5203 ata_force_spd_limit(link); 5214 ata_force_link_limits(link);
5204 5215
5205 link->sata_spd_limit = link->hw_sata_spd_limit; 5216 link->sata_spd_limit = link->hw_sata_spd_limit;
5206 5217
@@ -5991,6 +6002,9 @@ static int __init ata_parse_force_one(char **cur,
5991 { "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, 6002 { "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
5992 { "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, 6003 { "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
5993 { "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) }, 6004 { "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) },
6005 { "nohrst", .lflags = ATA_LFLAG_NO_HRST },
6006 { "nosrst", .lflags = ATA_LFLAG_NO_SRST },
6007 { "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
5994 }; 6008 };
5995 char *start = *cur, *p = *cur; 6009 char *start = *cur, *p = *cur;
5996 char *id, *val, *endp; 6010 char *id, *val, *endp;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 58bdc538d229..a570ca47e239 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2210,6 +2210,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
2210 */ 2210 */
2211 while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX) 2211 while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX)
2212 max_tries++; 2212 max_tries++;
2213 if (link->flags & ATA_LFLAG_NO_HRST)
2214 hardreset = NULL;
2215 if (link->flags & ATA_LFLAG_NO_SRST)
2216 softreset = NULL;
2213 2217
2214 now = jiffies; 2218 now = jiffies;
2215 deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); 2219 deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 06b80337303b..5340d4c83fd9 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -163,6 +163,7 @@ enum {
163 ATA_DEV_NONE = 9, /* no device */ 163 ATA_DEV_NONE = 9, /* no device */
164 164
165 /* struct ata_link flags */ 165 /* struct ata_link flags */
166 ATA_LFLAG_NO_HRST = (1 << 1), /* avoid hardreset */
166 ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */ 167 ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */
167 ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */ 168 ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */
168 ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */ 169 ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */