diff options
-rw-r--r-- | drivers/ata/Makefile | 3 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 11 | ||||
-rw-r--r-- | drivers/ata/libata-pmp.c | 1182 | ||||
-rw-r--r-- | drivers/ata/libata.h | 5 | ||||
-rw-r--r-- | include/linux/libata.h | 19 |
5 files changed, 1219 insertions, 1 deletions
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 56bf13cbd198..7e937519a930 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
@@ -71,5 +71,6 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o | |||
71 | # Should be last libata driver | 71 | # Should be last libata driver |
72 | obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o | 72 | obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o |
73 | 73 | ||
74 | libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o | 74 | libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o \ |
75 | libata-pmp.o | ||
75 | libata-$(CONFIG_ATA_ACPI) += libata-acpi.o | 76 | libata-$(CONFIG_ATA_ACPI) += libata-acpi.o |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index eb9709864a21..9e7f55b71044 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -3865,6 +3865,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
3865 | { "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */ | 3865 | { "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */ |
3866 | { "IOMEGA ZIP 250 ATAPI Floppy", | 3866 | { "IOMEGA ZIP 250 ATAPI Floppy", |
3867 | NULL, ATA_HORKAGE_NODMA }, | 3867 | NULL, ATA_HORKAGE_NODMA }, |
3868 | /* Odd clown on sil3726/4726 PMPs */ | ||
3869 | { "Config Disk", NULL, ATA_HORKAGE_NODMA | | ||
3870 | ATA_HORKAGE_SKIP_PM }, | ||
3868 | 3871 | ||
3869 | /* Weird ATAPI devices */ | 3872 | /* Weird ATAPI devices */ |
3870 | { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, | 3873 | { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, |
@@ -7251,6 +7254,14 @@ EXPORT_SYMBOL_GPL(ata_pci_default_filter); | |||
7251 | EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); | 7254 | EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); |
7252 | #endif /* CONFIG_PCI */ | 7255 | #endif /* CONFIG_PCI */ |
7253 | 7256 | ||
7257 | EXPORT_SYMBOL_GPL(sata_pmp_read_init_tf); | ||
7258 | EXPORT_SYMBOL_GPL(sata_pmp_read_val); | ||
7259 | EXPORT_SYMBOL_GPL(sata_pmp_write_init_tf); | ||
7260 | EXPORT_SYMBOL_GPL(sata_pmp_std_prereset); | ||
7261 | EXPORT_SYMBOL_GPL(sata_pmp_std_hardreset); | ||
7262 | EXPORT_SYMBOL_GPL(sata_pmp_std_postreset); | ||
7263 | EXPORT_SYMBOL_GPL(sata_pmp_do_eh); | ||
7264 | |||
7254 | EXPORT_SYMBOL_GPL(__ata_ehi_push_desc); | 7265 | EXPORT_SYMBOL_GPL(__ata_ehi_push_desc); |
7255 | EXPORT_SYMBOL_GPL(ata_ehi_push_desc); | 7266 | EXPORT_SYMBOL_GPL(ata_ehi_push_desc); |
7256 | EXPORT_SYMBOL_GPL(ata_ehi_clear_desc); | 7267 | EXPORT_SYMBOL_GPL(ata_ehi_clear_desc); |
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c new file mode 100644 index 000000000000..671d171055a3 --- /dev/null +++ b/drivers/ata/libata-pmp.c | |||
@@ -0,0 +1,1182 @@ | |||
1 | /* | ||
2 | * libata-pmp.c - libata port multiplier support | ||
3 | * | ||
4 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
5 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/libata.h> | ||
12 | #include "libata.h" | ||
13 | |||
14 | /** | ||
15 | * sata_pmp_read - read PMP register | ||
16 | * @link: link to read PMP register for | ||
17 | * @reg: register to read | ||
18 | * @r_val: resulting value | ||
19 | * | ||
20 | * Wrapper around ap->ops->pmp_read to make it easier to call and | ||
21 | * nomarlize error return value. | ||
22 | * | ||
23 | * LOCKING: | ||
24 | * Kernel thread context (may sleep). | ||
25 | * | ||
26 | * RETURNS: | ||
27 | * 0 on success, -errno on failure. | ||
28 | */ | ||
29 | static int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val) | ||
30 | { | ||
31 | struct ata_port *ap = link->ap; | ||
32 | struct ata_device *pmp_dev = ap->link.device; | ||
33 | int rc; | ||
34 | |||
35 | might_sleep(); | ||
36 | |||
37 | rc = ap->ops->pmp_read(pmp_dev, link->pmp, reg, r_val); | ||
38 | if (rc) | ||
39 | rc = -EIO; | ||
40 | return rc; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * sata_pmp_write - write PMP register | ||
45 | * @link: link to write PMP register for | ||
46 | * @reg: register to write | ||
47 | * @r_val: value to write | ||
48 | * | ||
49 | * Wrapper around ap->ops->pmp_write to make it easier to call | ||
50 | * and nomarlize error return value. | ||
51 | * | ||
52 | * LOCKING: | ||
53 | * Kernel thread context (may sleep). | ||
54 | * | ||
55 | * RETURNS: | ||
56 | * 0 on success, -errno on failure. | ||
57 | */ | ||
58 | static int sata_pmp_write(struct ata_link *link, int reg, u32 val) | ||
59 | { | ||
60 | struct ata_port *ap = link->ap; | ||
61 | struct ata_device *pmp_dev = ap->link.device; | ||
62 | int rc; | ||
63 | |||
64 | might_sleep(); | ||
65 | |||
66 | rc = ap->ops->pmp_write(pmp_dev, link->pmp, reg, val); | ||
67 | if (rc) | ||
68 | rc = -EIO; | ||
69 | return rc; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * sata_pmp_read_init_tf - initialize TF for PMP read | ||
74 | * @tf: taskfile to initialize | ||
75 | * @dev: PMP dev | ||
76 | * @pmp: port multiplier port number | ||
77 | * @reg: register to read | ||
78 | * | ||
79 | * Initialize @tf for PMP read command. | ||
80 | * | ||
81 | * LOCKING: | ||
82 | * None. | ||
83 | */ | ||
84 | void sata_pmp_read_init_tf(struct ata_taskfile *tf, | ||
85 | struct ata_device *dev, int pmp, int reg) | ||
86 | { | ||
87 | ata_tf_init(dev, tf); | ||
88 | tf->command = ATA_CMD_PMP_READ; | ||
89 | tf->protocol = ATA_PROT_NODATA; | ||
90 | tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
91 | tf->feature = reg; | ||
92 | tf->device = pmp; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * sata_pmp_read_val - extract PMP read result from TF | ||
97 | * @tf: target TF | ||
98 | * | ||
99 | * Determine PMP read result from @tf. | ||
100 | * | ||
101 | * LOCKING: | ||
102 | * None. | ||
103 | */ | ||
104 | u32 sata_pmp_read_val(const struct ata_taskfile *tf) | ||
105 | { | ||
106 | return tf->nsect | tf->lbal << 8 | tf->lbam << 16 | tf->lbah << 24; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * sata_pmp_read_init_tf - initialize TF for PMP write | ||
111 | * @tf: taskfile to initialize | ||
112 | * @dev: PMP dev | ||
113 | * @pmp: port multiplier port number | ||
114 | * @reg: register to read | ||
115 | * @val: value to write | ||
116 | * | ||
117 | * Initialize @tf for PMP write command. | ||
118 | * | ||
119 | * LOCKING: | ||
120 | * None. | ||
121 | */ | ||
122 | void sata_pmp_write_init_tf(struct ata_taskfile *tf, | ||
123 | struct ata_device *dev, int pmp, int reg, u32 val) | ||
124 | { | ||
125 | ata_tf_init(dev, tf); | ||
126 | tf->command = ATA_CMD_PMP_WRITE; | ||
127 | tf->protocol = ATA_PROT_NODATA; | ||
128 | tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
129 | tf->feature = reg; | ||
130 | tf->device = pmp; | ||
131 | tf->nsect = val & 0xff; | ||
132 | tf->lbal = (val >> 8) & 0xff; | ||
133 | tf->lbam = (val >> 16) & 0xff; | ||
134 | tf->lbah = (val >> 24) & 0xff; | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * sata_pmp_scr_read - read PSCR | ||
139 | * @link: ATA link to read PSCR for | ||
140 | * @reg: PSCR to read | ||
141 | * @r_val: resulting value | ||
142 | * | ||
143 | * Read PSCR @reg into @r_val for @link, to be called from | ||
144 | * ata_scr_read(). | ||
145 | * | ||
146 | * LOCKING: | ||
147 | * Kernel thread context (may sleep). | ||
148 | * | ||
149 | * RETURNS: | ||
150 | * 0 on success, -errno on failure. | ||
151 | */ | ||
152 | int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val) | ||
153 | { | ||
154 | if (reg > SATA_PMP_PSCR_CONTROL) | ||
155 | return -EINVAL; | ||
156 | |||
157 | return sata_pmp_read(link, reg, r_val); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * sata_pmp_scr_write - write PSCR | ||
162 | * @link: ATA link to write PSCR for | ||
163 | * @reg: PSCR to write | ||
164 | * @val: value to be written | ||
165 | * | ||
166 | * Write @val to PSCR @reg for @link, to be called from | ||
167 | * ata_scr_write() and ata_scr_write_flush(). | ||
168 | * | ||
169 | * LOCKING: | ||
170 | * Kernel thread context (may sleep). | ||
171 | * | ||
172 | * RETURNS: | ||
173 | * 0 on success, -errno on failure. | ||
174 | */ | ||
175 | int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val) | ||
176 | { | ||
177 | if (reg > SATA_PMP_PSCR_CONTROL) | ||
178 | return -EINVAL; | ||
179 | |||
180 | return sata_pmp_write(link, reg, val); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * sata_pmp_std_prereset - prepare PMP link for reset | ||
185 | * @link: link to be reset | ||
186 | * @deadline: deadline jiffies for the operation | ||
187 | * | ||
188 | * @link is about to be reset. Initialize it. | ||
189 | * | ||
190 | * LOCKING: | ||
191 | * Kernel thread context (may sleep) | ||
192 | * | ||
193 | * RETURNS: | ||
194 | * 0 on success, -errno otherwise. | ||
195 | */ | ||
196 | int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline) | ||
197 | { | ||
198 | struct ata_eh_context *ehc = &link->eh_context; | ||
199 | const unsigned long *timing = sata_ehc_deb_timing(ehc); | ||
200 | int rc; | ||
201 | |||
202 | /* force HRST? */ | ||
203 | if (link->flags & ATA_LFLAG_NO_SRST) | ||
204 | ehc->i.action |= ATA_EH_HARDRESET; | ||
205 | |||
206 | /* handle link resume */ | ||
207 | if ((ehc->i.flags & ATA_EHI_RESUME_LINK) && | ||
208 | (link->flags & ATA_LFLAG_HRST_TO_RESUME)) | ||
209 | ehc->i.action |= ATA_EH_HARDRESET; | ||
210 | |||
211 | /* if we're about to do hardreset, nothing more to do */ | ||
212 | if (ehc->i.action & ATA_EH_HARDRESET) | ||
213 | return 0; | ||
214 | |||
215 | /* resume link */ | ||
216 | rc = sata_link_resume(link, timing, deadline); | ||
217 | if (rc) { | ||
218 | /* phy resume failed */ | ||
219 | ata_link_printk(link, KERN_WARNING, "failed to resume link " | ||
220 | "for reset (errno=%d)\n", rc); | ||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | /* clear SError bits including .X which blocks the port when set */ | ||
225 | rc = sata_scr_write(link, SCR_ERROR, 0xffffffff); | ||
226 | if (rc) { | ||
227 | ata_link_printk(link, KERN_ERR, | ||
228 | "failed to clear SError (errno=%d)\n", rc); | ||
229 | return rc; | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * sata_pmp_std_hardreset - standard hardreset method for PMP link | ||
237 | * @link: link to be reset | ||
238 | * @class: resulting class of attached device | ||
239 | * @deadline: deadline jiffies for the operation | ||
240 | * | ||
241 | * Hardreset PMP port @link. Note that this function doesn't | ||
242 | * wait for BSY clearance. There simply isn't a generic way to | ||
243 | * wait the event. Instead, this function return -EAGAIN thus | ||
244 | * telling libata-EH to followup with softreset. | ||
245 | * | ||
246 | * LOCKING: | ||
247 | * Kernel thread context (may sleep) | ||
248 | * | ||
249 | * RETURNS: | ||
250 | * 0 on success, -errno otherwise. | ||
251 | */ | ||
252 | int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class, | ||
253 | unsigned long deadline) | ||
254 | { | ||
255 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); | ||
256 | u32 tmp; | ||
257 | int rc; | ||
258 | |||
259 | DPRINTK("ENTER\n"); | ||
260 | |||
261 | /* do hardreset */ | ||
262 | rc = sata_link_hardreset(link, timing, deadline); | ||
263 | if (rc) { | ||
264 | ata_link_printk(link, KERN_ERR, | ||
265 | "COMRESET failed (errno=%d)\n", rc); | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | /* clear SError bits including .X which blocks the port when set */ | ||
270 | rc = sata_scr_write(link, SCR_ERROR, 0xffffffff); | ||
271 | if (rc) { | ||
272 | ata_link_printk(link, KERN_ERR, "failed to clear SError " | ||
273 | "during hardreset (errno=%d)\n", rc); | ||
274 | goto out; | ||
275 | } | ||
276 | |||
277 | /* if device is present, follow up with srst to wait for !BSY */ | ||
278 | if (ata_link_online(link)) | ||
279 | rc = -EAGAIN; | ||
280 | out: | ||
281 | /* if SCR isn't accessible, we need to reset the PMP */ | ||
282 | if (rc && rc != -EAGAIN && sata_scr_read(link, SCR_STATUS, &tmp)) | ||
283 | rc = -ERESTART; | ||
284 | |||
285 | DPRINTK("EXIT, rc=%d\n", rc); | ||
286 | return rc; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * ata_std_postreset - standard postreset method for PMP link | ||
291 | * @link: the target ata_link | ||
292 | * @classes: classes of attached devices | ||
293 | * | ||
294 | * This function is invoked after a successful reset. Note that | ||
295 | * the device might have been reset more than once using | ||
296 | * different reset methods before postreset is invoked. | ||
297 | * | ||
298 | * LOCKING: | ||
299 | * Kernel thread context (may sleep) | ||
300 | */ | ||
301 | void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class) | ||
302 | { | ||
303 | u32 serror; | ||
304 | |||
305 | DPRINTK("ENTER\n"); | ||
306 | |||
307 | /* clear SError */ | ||
308 | if (sata_scr_read(link, SCR_ERROR, &serror) == 0) | ||
309 | sata_scr_write(link, SCR_ERROR, serror); | ||
310 | |||
311 | /* print link status */ | ||
312 | sata_print_link_status(link); | ||
313 | |||
314 | DPRINTK("EXIT\n"); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * sata_pmp_read_gscr - read GSCR block of SATA PMP | ||
319 | * @dev: PMP device | ||
320 | * @gscr: buffer to read GSCR block into | ||
321 | * | ||
322 | * Read selected PMP GSCRs from the PMP at @dev. This will serve | ||
323 | * as configuration and identification info for the PMP. | ||
324 | * | ||
325 | * LOCKING: | ||
326 | * Kernel thread context (may sleep). | ||
327 | * | ||
328 | * RETURNS: | ||
329 | * 0 on success, -errno on failure. | ||
330 | */ | ||
331 | static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr) | ||
332 | { | ||
333 | static const int gscr_to_read[] = { 0, 1, 2, 32, 33, 64, 96 }; | ||
334 | int i, rc; | ||
335 | |||
336 | for (i = 0; i < ARRAY_SIZE(gscr_to_read); i++) { | ||
337 | int reg = gscr_to_read[i]; | ||
338 | |||
339 | rc = sata_pmp_read(dev->link, reg, &gscr[reg]); | ||
340 | if (rc) { | ||
341 | ata_dev_printk(dev, KERN_ERR, "failed to read " | ||
342 | "PMP GSCR[%d] (errno=%d)\n", reg, rc); | ||
343 | return rc; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static const char *sata_pmp_spec_rev_str(const u32 *gscr) | ||
351 | { | ||
352 | u32 rev = gscr[SATA_PMP_GSCR_REV]; | ||
353 | |||
354 | if (rev & (1 << 2)) | ||
355 | return "1.1"; | ||
356 | if (rev & (1 << 1)) | ||
357 | return "1.0"; | ||
358 | return "<unknown>"; | ||
359 | } | ||
360 | |||
361 | static int sata_pmp_configure(struct ata_device *dev, int print_info) | ||
362 | { | ||
363 | struct ata_port *ap = dev->link->ap; | ||
364 | u32 *gscr = dev->gscr; | ||
365 | const char *reason; | ||
366 | int nr_ports, rc; | ||
367 | |||
368 | nr_ports = sata_pmp_gscr_ports(gscr); | ||
369 | |||
370 | if (nr_ports <= 0 || nr_ports > SATA_PMP_MAX_PORTS) { | ||
371 | rc = -EINVAL; | ||
372 | reason = "invalid nr_ports"; | ||
373 | goto fail; | ||
374 | } | ||
375 | |||
376 | if ((ap->flags & ATA_FLAG_AN) && | ||
377 | (gscr[SATA_PMP_GSCR_FEAT] & SATA_PMP_FEAT_NOTIFY)) | ||
378 | dev->flags |= ATA_DFLAG_AN; | ||
379 | |||
380 | /* monitor SERR_PHYRDY_CHG on fan-out ports */ | ||
381 | rc = sata_pmp_write(dev->link, SATA_PMP_GSCR_ERROR_EN, SERR_PHYRDY_CHG); | ||
382 | if (rc) { | ||
383 | reason = "failed to write GSCR_ERROR_EN"; | ||
384 | goto fail; | ||
385 | } | ||
386 | |||
387 | /* turn off notification till fan-out ports are reset and configured */ | ||
388 | if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) { | ||
389 | gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY; | ||
390 | |||
391 | rc = sata_pmp_write(dev->link, SATA_PMP_GSCR_FEAT_EN, | ||
392 | gscr[SATA_PMP_GSCR_FEAT_EN]); | ||
393 | if (rc) { | ||
394 | reason = "failed to write GSCR_FEAT_EN"; | ||
395 | goto fail; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | if (print_info) { | ||
400 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " | ||
401 | "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", | ||
402 | sata_pmp_spec_rev_str(gscr), | ||
403 | sata_pmp_gscr_vendor(gscr), | ||
404 | sata_pmp_gscr_devid(gscr), | ||
405 | sata_pmp_gscr_rev(gscr), | ||
406 | nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], | ||
407 | gscr[SATA_PMP_GSCR_FEAT]); | ||
408 | |||
409 | if (!(dev->flags & ATA_DFLAG_AN)) | ||
410 | ata_dev_printk(dev, KERN_INFO, | ||
411 | "Asynchronous notification not supported, " | ||
412 | "hotplug won't\n work on fan-out " | ||
413 | "ports. Use warm-plug instead.\n"); | ||
414 | } | ||
415 | |||
416 | return 0; | ||
417 | |||
418 | fail: | ||
419 | ata_dev_printk(dev, KERN_ERR, | ||
420 | "failed to configure Port Multiplier (%s)\n", reason); | ||
421 | return rc; | ||
422 | } | ||
423 | |||
424 | static int sata_pmp_init_links(struct ata_port *ap, int nr_ports) | ||
425 | { | ||
426 | struct ata_link *pmp_link = ap->pmp_link; | ||
427 | int i; | ||
428 | |||
429 | if (!pmp_link) { | ||
430 | pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS, | ||
431 | GFP_NOIO); | ||
432 | if (!pmp_link) | ||
433 | return -ENOMEM; | ||
434 | |||
435 | for (i = 0; i < SATA_PMP_MAX_PORTS; i++) | ||
436 | ata_link_init(ap, &pmp_link[i], i); | ||
437 | |||
438 | ap->pmp_link = pmp_link; | ||
439 | } | ||
440 | |||
441 | for (i = 0; i < nr_ports; i++) { | ||
442 | struct ata_link *link = &pmp_link[i]; | ||
443 | struct ata_eh_context *ehc = &link->eh_context; | ||
444 | |||
445 | link->flags = 0; | ||
446 | ehc->i.probe_mask |= 1; | ||
447 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
448 | ehc->i.flags |= ATA_EHI_RESUME_LINK; | ||
449 | } | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static void sata_pmp_quirks(struct ata_port *ap) | ||
455 | { | ||
456 | u32 *gscr = ap->link.device->gscr; | ||
457 | u16 vendor = sata_pmp_gscr_vendor(gscr); | ||
458 | u16 devid = sata_pmp_gscr_devid(gscr); | ||
459 | struct ata_link *link; | ||
460 | |||
461 | if (vendor == 0x1095 && devid == 0x3726) { | ||
462 | /* sil3726 quirks */ | ||
463 | ata_port_for_each_link(link, ap) { | ||
464 | /* SError.N need a kick in the ass to get working */ | ||
465 | link->flags |= ATA_LFLAG_HRST_TO_RESUME; | ||
466 | |||
467 | /* class code report is unreliable */ | ||
468 | if (link->pmp < 5) | ||
469 | link->flags |= ATA_LFLAG_ASSUME_ATA; | ||
470 | |||
471 | /* port 5 is for SEMB device and it doesn't like SRST */ | ||
472 | if (link->pmp == 5) | ||
473 | link->flags |= ATA_LFLAG_NO_SRST | | ||
474 | ATA_LFLAG_ASSUME_SEMB; | ||
475 | } | ||
476 | } else if (vendor == 0x1095 && devid == 0x4723) { | ||
477 | /* sil4723 quirks */ | ||
478 | ata_port_for_each_link(link, ap) { | ||
479 | /* SError.N need a kick in the ass to get working */ | ||
480 | link->flags |= ATA_LFLAG_HRST_TO_RESUME; | ||
481 | |||
482 | /* class code report is unreliable */ | ||
483 | if (link->pmp < 2) | ||
484 | link->flags |= ATA_LFLAG_ASSUME_ATA; | ||
485 | |||
486 | /* the config device at port 2 locks up on SRST */ | ||
487 | if (link->pmp == 2) | ||
488 | link->flags |= ATA_LFLAG_NO_SRST | | ||
489 | ATA_LFLAG_ASSUME_ATA; | ||
490 | } | ||
491 | } else if (vendor == 0x1095 && devid == 0x4726) { | ||
492 | /* sil4726 quirks */ | ||
493 | ata_port_for_each_link(link, ap) { | ||
494 | /* SError.N need a kick in the ass to get working */ | ||
495 | link->flags |= ATA_LFLAG_HRST_TO_RESUME; | ||
496 | |||
497 | /* class code report is unreliable */ | ||
498 | if (link->pmp < 5) | ||
499 | link->flags |= ATA_LFLAG_ASSUME_ATA; | ||
500 | |||
501 | /* The config device, which can be either at | ||
502 | * port 0 or 5, locks up on SRST. | ||
503 | */ | ||
504 | if (link->pmp == 0 || link->pmp == 5) | ||
505 | link->flags |= ATA_LFLAG_NO_SRST | | ||
506 | ATA_LFLAG_ASSUME_ATA; | ||
507 | |||
508 | /* Port 6 is for SEMB device which doesn't | ||
509 | * like SRST either. | ||
510 | */ | ||
511 | if (link->pmp == 6) | ||
512 | link->flags |= ATA_LFLAG_NO_SRST | | ||
513 | ATA_LFLAG_ASSUME_SEMB; | ||
514 | } | ||
515 | } else if (vendor == 0x1095 && (devid == 0x5723 || devid == 0x5733 || | ||
516 | devid == 0x5734 || devid == 0x5744)) { | ||
517 | /* sil5723/5744 quirks */ | ||
518 | |||
519 | /* sil5723/5744 has either two or three downstream | ||
520 | * ports depending on operation mode. The last port | ||
521 | * is empty if any actual IO device is available or | ||
522 | * occupied by a pseudo configuration device | ||
523 | * otherwise. Don't try hard to recover it. | ||
524 | */ | ||
525 | ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY; | ||
526 | } else if (vendor == 0x11ab && devid == 0x4140) { | ||
527 | /* Marvell 88SM4140 quirks. Fan-out ports require PHY | ||
528 | * reset to work; other than that, it behaves very | ||
529 | * nicely. | ||
530 | */ | ||
531 | ata_port_for_each_link(link, ap) | ||
532 | link->flags |= ATA_LFLAG_HRST_TO_RESUME; | ||
533 | } | ||
534 | } | ||
535 | |||
536 | /** | ||
537 | * sata_pmp_attach - attach a SATA PMP device | ||
538 | * @dev: SATA PMP device to attach | ||
539 | * | ||
540 | * Configure and attach SATA PMP device @dev. This function is | ||
541 | * also responsible for allocating and initializing PMP links. | ||
542 | * | ||
543 | * LOCKING: | ||
544 | * Kernel thread context (may sleep). | ||
545 | * | ||
546 | * RETURNS: | ||
547 | * 0 on success, -errno on failure. | ||
548 | */ | ||
549 | int sata_pmp_attach(struct ata_device *dev) | ||
550 | { | ||
551 | struct ata_link *link = dev->link; | ||
552 | struct ata_port *ap = link->ap; | ||
553 | unsigned long flags; | ||
554 | struct ata_link *tlink; | ||
555 | int rc; | ||
556 | |||
557 | /* is it hanging off the right place? */ | ||
558 | if (!(ap->flags & ATA_FLAG_PMP)) { | ||
559 | ata_dev_printk(dev, KERN_ERR, | ||
560 | "host does not support Port Multiplier\n"); | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | |||
564 | if (!ata_is_host_link(link)) { | ||
565 | ata_dev_printk(dev, KERN_ERR, | ||
566 | "Port Multipliers cannot be nested\n"); | ||
567 | return -EINVAL; | ||
568 | } | ||
569 | |||
570 | if (dev->devno) { | ||
571 | ata_dev_printk(dev, KERN_ERR, | ||
572 | "Port Multiplier must be the first device\n"); | ||
573 | return -EINVAL; | ||
574 | } | ||
575 | |||
576 | WARN_ON(link->pmp != 0); | ||
577 | link->pmp = SATA_PMP_CTRL_PORT; | ||
578 | |||
579 | /* read GSCR block */ | ||
580 | rc = sata_pmp_read_gscr(dev, dev->gscr); | ||
581 | if (rc) | ||
582 | goto fail; | ||
583 | |||
584 | /* config PMP */ | ||
585 | rc = sata_pmp_configure(dev, 1); | ||
586 | if (rc) | ||
587 | goto fail; | ||
588 | |||
589 | rc = sata_pmp_init_links(ap, sata_pmp_gscr_ports(dev->gscr)); | ||
590 | if (rc) { | ||
591 | ata_dev_printk(dev, KERN_INFO, | ||
592 | "failed to initialize PMP links\n"); | ||
593 | goto fail; | ||
594 | } | ||
595 | |||
596 | /* attach it */ | ||
597 | spin_lock_irqsave(ap->lock, flags); | ||
598 | WARN_ON(ap->nr_pmp_links); | ||
599 | ap->nr_pmp_links = sata_pmp_gscr_ports(dev->gscr); | ||
600 | spin_unlock_irqrestore(ap->lock, flags); | ||
601 | |||
602 | sata_pmp_quirks(ap); | ||
603 | |||
604 | if (ap->ops->pmp_attach) | ||
605 | ap->ops->pmp_attach(ap); | ||
606 | |||
607 | ata_port_for_each_link(tlink, ap) | ||
608 | sata_link_init_spd(tlink); | ||
609 | |||
610 | return 0; | ||
611 | |||
612 | fail: | ||
613 | link->pmp = 0; | ||
614 | return rc; | ||
615 | } | ||
616 | |||
617 | /** | ||
618 | * sata_pmp_detach - detach a SATA PMP device | ||
619 | * @dev: SATA PMP device to detach | ||
620 | * | ||
621 | * Detach SATA PMP device @dev. This function is also | ||
622 | * responsible for deconfiguring PMP links. | ||
623 | * | ||
624 | * LOCKING: | ||
625 | * Kernel thread context (may sleep). | ||
626 | */ | ||
627 | static void sata_pmp_detach(struct ata_device *dev) | ||
628 | { | ||
629 | struct ata_link *link = dev->link; | ||
630 | struct ata_port *ap = link->ap; | ||
631 | struct ata_link *tlink; | ||
632 | unsigned long flags; | ||
633 | |||
634 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier detaching\n"); | ||
635 | |||
636 | WARN_ON(!ata_is_host_link(link) || dev->devno || | ||
637 | link->pmp != SATA_PMP_CTRL_PORT); | ||
638 | |||
639 | if (ap->ops->pmp_detach) | ||
640 | ap->ops->pmp_detach(ap); | ||
641 | |||
642 | ata_port_for_each_link(tlink, ap) | ||
643 | ata_eh_detach_dev(tlink->device); | ||
644 | |||
645 | spin_lock_irqsave(ap->lock, flags); | ||
646 | ap->nr_pmp_links = 0; | ||
647 | link->pmp = 0; | ||
648 | spin_unlock_irqrestore(ap->lock, flags); | ||
649 | } | ||
650 | |||
651 | /** | ||
652 | * sata_pmp_same_pmp - does new GSCR matches the configured PMP? | ||
653 | * @dev: PMP device to compare against | ||
654 | * @new_gscr: GSCR block of the new device | ||
655 | * | ||
656 | * Compare @new_gscr against @dev and determine whether @dev is | ||
657 | * the PMP described by @new_gscr. | ||
658 | * | ||
659 | * LOCKING: | ||
660 | * None. | ||
661 | * | ||
662 | * RETURNS: | ||
663 | * 1 if @dev matches @new_gscr, 0 otherwise. | ||
664 | */ | ||
665 | static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr) | ||
666 | { | ||
667 | const u32 *old_gscr = dev->gscr; | ||
668 | u16 old_vendor, new_vendor, old_devid, new_devid; | ||
669 | int old_nr_ports, new_nr_ports; | ||
670 | |||
671 | old_vendor = sata_pmp_gscr_vendor(old_gscr); | ||
672 | new_vendor = sata_pmp_gscr_vendor(new_gscr); | ||
673 | old_devid = sata_pmp_gscr_devid(old_gscr); | ||
674 | new_devid = sata_pmp_gscr_devid(new_gscr); | ||
675 | old_nr_ports = sata_pmp_gscr_ports(old_gscr); | ||
676 | new_nr_ports = sata_pmp_gscr_ports(new_gscr); | ||
677 | |||
678 | if (old_vendor != new_vendor) { | ||
679 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier " | ||
680 | "vendor mismatch '0x%x' != '0x%x'\n", | ||
681 | old_vendor, new_vendor); | ||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | if (old_devid != new_devid) { | ||
686 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier " | ||
687 | "device ID mismatch '0x%x' != '0x%x'\n", | ||
688 | old_devid, new_devid); | ||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | if (old_nr_ports != new_nr_ports) { | ||
693 | ata_dev_printk(dev, KERN_INFO, "Port Multiplier " | ||
694 | "nr_ports mismatch '0x%x' != '0x%x'\n", | ||
695 | old_nr_ports, new_nr_ports); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | return 1; | ||
700 | } | ||
701 | |||
702 | /** | ||
703 | * sata_pmp_revalidate - revalidate SATA PMP | ||
704 | * @dev: PMP device to revalidate | ||
705 | * @new_class: new class code | ||
706 | * | ||
707 | * Re-read GSCR block and make sure @dev is still attached to the | ||
708 | * port and properly configured. | ||
709 | * | ||
710 | * LOCKING: | ||
711 | * Kernel thread context (may sleep). | ||
712 | * | ||
713 | * RETURNS: | ||
714 | * 0 on success, -errno otherwise. | ||
715 | */ | ||
716 | static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class) | ||
717 | { | ||
718 | struct ata_link *link = dev->link; | ||
719 | struct ata_port *ap = link->ap; | ||
720 | u32 *gscr = (void *)ap->sector_buf; | ||
721 | int rc; | ||
722 | |||
723 | DPRINTK("ENTER\n"); | ||
724 | |||
725 | ata_eh_about_to_do(link, NULL, ATA_EH_REVALIDATE); | ||
726 | |||
727 | if (!ata_dev_enabled(dev)) { | ||
728 | rc = -ENODEV; | ||
729 | goto fail; | ||
730 | } | ||
731 | |||
732 | /* wrong class? */ | ||
733 | if (ata_class_enabled(new_class) && new_class != ATA_DEV_PMP) { | ||
734 | rc = -ENODEV; | ||
735 | goto fail; | ||
736 | } | ||
737 | |||
738 | /* read GSCR */ | ||
739 | rc = sata_pmp_read_gscr(dev, gscr); | ||
740 | if (rc) | ||
741 | goto fail; | ||
742 | |||
743 | /* is the pmp still there? */ | ||
744 | if (!sata_pmp_same_pmp(dev, gscr)) { | ||
745 | rc = -ENODEV; | ||
746 | goto fail; | ||
747 | } | ||
748 | |||
749 | memcpy(dev->gscr, gscr, sizeof(gscr[0]) * SATA_PMP_GSCR_DWORDS); | ||
750 | |||
751 | rc = sata_pmp_configure(dev, 0); | ||
752 | if (rc) | ||
753 | goto fail; | ||
754 | |||
755 | ata_eh_done(link, NULL, ATA_EH_REVALIDATE); | ||
756 | |||
757 | DPRINTK("EXIT, rc=0\n"); | ||
758 | return 0; | ||
759 | |||
760 | fail: | ||
761 | ata_dev_printk(dev, KERN_ERR, | ||
762 | "PMP revalidation failed (errno=%d)\n", rc); | ||
763 | DPRINTK("EXIT, rc=%d\n", rc); | ||
764 | return rc; | ||
765 | } | ||
766 | |||
767 | /** | ||
768 | * sata_pmp_revalidate_quick - revalidate SATA PMP quickly | ||
769 | * @dev: PMP device to revalidate | ||
770 | * | ||
771 | * Make sure the attached PMP is accessible. | ||
772 | * | ||
773 | * LOCKING: | ||
774 | * Kernel thread context (may sleep). | ||
775 | * | ||
776 | * RETURNS: | ||
777 | * 0 on success, -errno otherwise. | ||
778 | */ | ||
779 | static int sata_pmp_revalidate_quick(struct ata_device *dev) | ||
780 | { | ||
781 | u32 prod_id; | ||
782 | int rc; | ||
783 | |||
784 | rc = sata_pmp_read(dev->link, SATA_PMP_GSCR_PROD_ID, &prod_id); | ||
785 | if (rc) { | ||
786 | ata_dev_printk(dev, KERN_ERR, "failed to read PMP product ID\n"); | ||
787 | return rc; | ||
788 | } | ||
789 | |||
790 | if (prod_id != dev->gscr[SATA_PMP_GSCR_PROD_ID]) { | ||
791 | ata_dev_printk(dev, KERN_ERR, "PMP product ID mismatch\n"); | ||
792 | /* something weird is going on, request full PMP recovery */ | ||
793 | return -EIO; | ||
794 | } | ||
795 | |||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * sata_pmp_eh_recover_pmp - recover PMP | ||
801 | * @ap: ATA port PMP is attached to | ||
802 | * @prereset: prereset method (can be NULL) | ||
803 | * @softreset: softreset method | ||
804 | * @hardreset: hardreset method | ||
805 | * @postreset: postreset method (can be NULL) | ||
806 | * | ||
807 | * Recover PMP attached to @ap. Recovery procedure is somewhat | ||
808 | * similar to that of ata_eh_recover() except that reset should | ||
809 | * always be performed in hard->soft sequence and recovery | ||
810 | * failure results in PMP detachment. | ||
811 | * | ||
812 | * LOCKING: | ||
813 | * Kernel thread context (may sleep). | ||
814 | * | ||
815 | * RETURNS: | ||
816 | * 0 on success, -errno on failure. | ||
817 | */ | ||
818 | static int sata_pmp_eh_recover_pmp(struct ata_port *ap, | ||
819 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | ||
820 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) | ||
821 | { | ||
822 | struct ata_link *link = &ap->link; | ||
823 | struct ata_eh_context *ehc = &link->eh_context; | ||
824 | struct ata_device *dev = link->device; | ||
825 | int tries = ATA_EH_PMP_TRIES; | ||
826 | int detach = 0, rc = 0; | ||
827 | int reval_failed = 0; | ||
828 | |||
829 | DPRINTK("ENTER\n"); | ||
830 | |||
831 | if (dev->flags & ATA_DFLAG_DETACH) { | ||
832 | detach = 1; | ||
833 | goto fail; | ||
834 | } | ||
835 | |||
836 | retry: | ||
837 | ehc->classes[0] = ATA_DEV_UNKNOWN; | ||
838 | |||
839 | if (ehc->i.action & ATA_EH_RESET_MASK) { | ||
840 | struct ata_link *tlink; | ||
841 | |||
842 | ata_eh_freeze_port(ap); | ||
843 | |||
844 | /* reset */ | ||
845 | ehc->i.action = ATA_EH_HARDRESET; | ||
846 | rc = ata_eh_reset(link, 0, prereset, softreset, hardreset, | ||
847 | postreset); | ||
848 | if (rc) { | ||
849 | ata_link_printk(link, KERN_ERR, | ||
850 | "failed to reset PMP, giving up\n"); | ||
851 | goto fail; | ||
852 | } | ||
853 | |||
854 | ata_eh_thaw_port(ap); | ||
855 | |||
856 | /* PMP is reset, SErrors cannot be trusted, scan all */ | ||
857 | ata_port_for_each_link(tlink, ap) | ||
858 | ata_ehi_schedule_probe(&tlink->eh_context.i); | ||
859 | } | ||
860 | |||
861 | /* If revalidation is requested, revalidate and reconfigure; | ||
862 | * otherwise, do quick revalidation. | ||
863 | */ | ||
864 | if (ehc->i.action & ATA_EH_REVALIDATE) | ||
865 | rc = sata_pmp_revalidate(dev, ehc->classes[0]); | ||
866 | else | ||
867 | rc = sata_pmp_revalidate_quick(dev); | ||
868 | |||
869 | if (rc) { | ||
870 | tries--; | ||
871 | |||
872 | if (rc == -ENODEV) { | ||
873 | ehc->i.probe_mask |= 1; | ||
874 | detach = 1; | ||
875 | /* give it just two more chances */ | ||
876 | tries = min(tries, 2); | ||
877 | } | ||
878 | |||
879 | if (tries) { | ||
880 | int sleep = ehc->i.flags & ATA_EHI_DID_RESET; | ||
881 | |||
882 | /* consecutive revalidation failures? speed down */ | ||
883 | if (reval_failed) | ||
884 | sata_down_spd_limit(link); | ||
885 | else | ||
886 | reval_failed = 1; | ||
887 | |||
888 | ata_dev_printk(dev, KERN_WARNING, | ||
889 | "retrying hardreset%s\n", | ||
890 | sleep ? " in 5 secs" : ""); | ||
891 | if (sleep) | ||
892 | ssleep(5); | ||
893 | ehc->i.action |= ATA_EH_HARDRESET; | ||
894 | goto retry; | ||
895 | } else { | ||
896 | ata_dev_printk(dev, KERN_ERR, "failed to recover PMP " | ||
897 | "after %d tries, giving up\n", | ||
898 | ATA_EH_PMP_TRIES); | ||
899 | goto fail; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | /* okay, PMP resurrected */ | ||
904 | ehc->i.flags = 0; | ||
905 | |||
906 | DPRINTK("EXIT, rc=0\n"); | ||
907 | return 0; | ||
908 | |||
909 | fail: | ||
910 | sata_pmp_detach(dev); | ||
911 | if (detach) | ||
912 | ata_eh_detach_dev(dev); | ||
913 | else | ||
914 | ata_dev_disable(dev); | ||
915 | |||
916 | DPRINTK("EXIT, rc=%d\n", rc); | ||
917 | return rc; | ||
918 | } | ||
919 | |||
920 | static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) | ||
921 | { | ||
922 | struct ata_link *link; | ||
923 | unsigned long flags; | ||
924 | int rc; | ||
925 | |||
926 | spin_lock_irqsave(ap->lock, flags); | ||
927 | |||
928 | ata_port_for_each_link(link, ap) { | ||
929 | if (!(link->flags & ATA_LFLAG_DISABLED)) | ||
930 | continue; | ||
931 | |||
932 | spin_unlock_irqrestore(ap->lock, flags); | ||
933 | |||
934 | /* Some PMPs require hardreset sequence to get | ||
935 | * SError.N working. | ||
936 | */ | ||
937 | if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) && | ||
938 | (link->eh_context.i.flags & ATA_EHI_RESUME_LINK)) | ||
939 | sata_link_hardreset(link, sata_deb_timing_normal, | ||
940 | jiffies + ATA_TMOUT_INTERNAL_QUICK); | ||
941 | |||
942 | /* unconditionally clear SError.N */ | ||
943 | rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG); | ||
944 | if (rc) { | ||
945 | ata_link_printk(link, KERN_ERR, "failed to clear " | ||
946 | "SError.N (errno=%d)\n", rc); | ||
947 | return rc; | ||
948 | } | ||
949 | |||
950 | spin_lock_irqsave(ap->lock, flags); | ||
951 | } | ||
952 | |||
953 | spin_unlock_irqrestore(ap->lock, flags); | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries) | ||
959 | { | ||
960 | struct ata_port *ap = link->ap; | ||
961 | unsigned long flags; | ||
962 | |||
963 | if (link_tries[link->pmp] && --link_tries[link->pmp]) | ||
964 | return 1; | ||
965 | |||
966 | /* disable this link */ | ||
967 | if (!(link->flags & ATA_LFLAG_DISABLED)) { | ||
968 | ata_link_printk(link, KERN_WARNING, | ||
969 | "failed to recover link after %d tries, disabling\n", | ||
970 | ATA_EH_PMP_LINK_TRIES); | ||
971 | |||
972 | spin_lock_irqsave(ap->lock, flags); | ||
973 | link->flags |= ATA_LFLAG_DISABLED; | ||
974 | spin_unlock_irqrestore(ap->lock, flags); | ||
975 | } | ||
976 | |||
977 | ata_dev_disable(link->device); | ||
978 | link->eh_context.i.action = 0; | ||
979 | |||
980 | return 0; | ||
981 | } | ||
982 | |||
983 | /** | ||
984 | * sata_pmp_eh_recover - recover PMP-enabled port | ||
985 | * @ap: ATA port to recover | ||
986 | * @prereset: prereset method (can be NULL) | ||
987 | * @softreset: softreset method | ||
988 | * @hardreset: hardreset method | ||
989 | * @postreset: postreset method (can be NULL) | ||
990 | * @pmp_prereset: PMP prereset method (can be NULL) | ||
991 | * @pmp_softreset: PMP softreset method (can be NULL) | ||
992 | * @pmp_hardreset: PMP hardreset method (can be NULL) | ||
993 | * @pmp_postreset: PMP postreset method (can be NULL) | ||
994 | * | ||
995 | * Drive EH recovery operation for PMP enabled port @ap. This | ||
996 | * function recovers host and PMP ports with proper retrials and | ||
997 | * fallbacks. Actual recovery operations are performed using | ||
998 | * ata_eh_recover() and sata_pmp_eh_recover_pmp(). | ||
999 | * | ||
1000 | * LOCKING: | ||
1001 | * Kernel thread context (may sleep). | ||
1002 | * | ||
1003 | * RETURNS: | ||
1004 | * 0 on success, -errno on failure. | ||
1005 | */ | ||
1006 | static int sata_pmp_eh_recover(struct ata_port *ap, | ||
1007 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | ||
1008 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, | ||
1009 | ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset, | ||
1010 | ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset) | ||
1011 | { | ||
1012 | int pmp_tries, link_tries[SATA_PMP_MAX_PORTS]; | ||
1013 | struct ata_link *pmp_link = &ap->link; | ||
1014 | struct ata_device *pmp_dev = pmp_link->device; | ||
1015 | struct ata_eh_context *pmp_ehc = &pmp_link->eh_context; | ||
1016 | struct ata_link *link; | ||
1017 | struct ata_device *dev; | ||
1018 | u32 gscr_error, sntf; | ||
1019 | int cnt, rc; | ||
1020 | |||
1021 | pmp_tries = ATA_EH_PMP_TRIES; | ||
1022 | ata_port_for_each_link(link, ap) | ||
1023 | link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES; | ||
1024 | |||
1025 | retry: | ||
1026 | /* PMP attached? */ | ||
1027 | if (!ap->nr_pmp_links) { | ||
1028 | rc = ata_eh_recover(ap, prereset, softreset, hardreset, | ||
1029 | postreset, NULL); | ||
1030 | if (rc) { | ||
1031 | ata_link_for_each_dev(dev, &ap->link) | ||
1032 | ata_dev_disable(dev); | ||
1033 | return rc; | ||
1034 | } | ||
1035 | |||
1036 | if (pmp_dev->class != ATA_DEV_PMP) | ||
1037 | return 0; | ||
1038 | |||
1039 | /* new PMP online */ | ||
1040 | ata_port_for_each_link(link, ap) | ||
1041 | link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES; | ||
1042 | |||
1043 | /* fall through */ | ||
1044 | } | ||
1045 | |||
1046 | /* recover pmp */ | ||
1047 | rc = sata_pmp_eh_recover_pmp(ap, prereset, softreset, hardreset, | ||
1048 | postreset); | ||
1049 | if (rc) | ||
1050 | goto pmp_fail; | ||
1051 | |||
1052 | /* handle disabled links */ | ||
1053 | rc = sata_pmp_eh_handle_disabled_links(ap); | ||
1054 | if (rc) | ||
1055 | goto pmp_fail; | ||
1056 | |||
1057 | /* recover links */ | ||
1058 | rc = ata_eh_recover(ap, pmp_prereset, pmp_softreset, pmp_hardreset, | ||
1059 | pmp_postreset, &link); | ||
1060 | if (rc) | ||
1061 | goto link_fail; | ||
1062 | |||
1063 | /* Connection status might have changed while resetting other | ||
1064 | * links, check SATA_PMP_GSCR_ERROR before returning. | ||
1065 | */ | ||
1066 | |||
1067 | /* clear SNotification */ | ||
1068 | rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf); | ||
1069 | if (rc == 0) | ||
1070 | sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf); | ||
1071 | |||
1072 | /* enable notification */ | ||
1073 | if (pmp_dev->flags & ATA_DFLAG_AN) { | ||
1074 | pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY; | ||
1075 | |||
1076 | rc = sata_pmp_write(pmp_dev->link, SATA_PMP_GSCR_FEAT_EN, | ||
1077 | pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN]); | ||
1078 | if (rc) { | ||
1079 | ata_dev_printk(pmp_dev, KERN_ERR, | ||
1080 | "failed to write PMP_FEAT_EN\n"); | ||
1081 | goto pmp_fail; | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | /* check GSCR_ERROR */ | ||
1086 | rc = sata_pmp_read(pmp_link, SATA_PMP_GSCR_ERROR, &gscr_error); | ||
1087 | if (rc) { | ||
1088 | ata_dev_printk(pmp_dev, KERN_ERR, | ||
1089 | "failed to read PMP_GSCR_ERROR\n"); | ||
1090 | goto pmp_fail; | ||
1091 | } | ||
1092 | |||
1093 | cnt = 0; | ||
1094 | ata_port_for_each_link(link, ap) { | ||
1095 | if (!(gscr_error & (1 << link->pmp))) | ||
1096 | continue; | ||
1097 | |||
1098 | if (sata_pmp_handle_link_fail(link, link_tries)) { | ||
1099 | ata_ehi_hotplugged(&link->eh_context.i); | ||
1100 | cnt++; | ||
1101 | } else { | ||
1102 | ata_link_printk(link, KERN_WARNING, | ||
1103 | "PHY status changed but maxed out on retries, " | ||
1104 | "giving up\n"); | ||
1105 | ata_link_printk(link, KERN_WARNING, | ||
1106 | "Manully issue scan to resume this link\n"); | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | if (cnt) { | ||
1111 | ata_port_printk(ap, KERN_INFO, "PMP SError.N set for some " | ||
1112 | "ports, repeating recovery\n"); | ||
1113 | goto retry; | ||
1114 | } | ||
1115 | |||
1116 | return 0; | ||
1117 | |||
1118 | link_fail: | ||
1119 | if (sata_pmp_handle_link_fail(link, link_tries)) { | ||
1120 | pmp_ehc->i.action |= ATA_EH_HARDRESET; | ||
1121 | goto retry; | ||
1122 | } | ||
1123 | |||
1124 | /* fall through */ | ||
1125 | pmp_fail: | ||
1126 | /* Control always ends up here after detaching PMP. Shut up | ||
1127 | * and return if we're unloading. | ||
1128 | */ | ||
1129 | if (ap->pflags & ATA_PFLAG_UNLOADING) | ||
1130 | return rc; | ||
1131 | |||
1132 | if (!ap->nr_pmp_links) | ||
1133 | goto retry; | ||
1134 | |||
1135 | if (--pmp_tries) { | ||
1136 | ata_port_printk(ap, KERN_WARNING, | ||
1137 | "failed to recover PMP, retrying in 5 secs\n"); | ||
1138 | pmp_ehc->i.action |= ATA_EH_HARDRESET; | ||
1139 | ssleep(5); | ||
1140 | goto retry; | ||
1141 | } | ||
1142 | |||
1143 | ata_port_printk(ap, KERN_ERR, | ||
1144 | "failed to recover PMP after %d tries, giving up\n", | ||
1145 | ATA_EH_PMP_TRIES); | ||
1146 | sata_pmp_detach(pmp_dev); | ||
1147 | ata_dev_disable(pmp_dev); | ||
1148 | |||
1149 | return rc; | ||
1150 | } | ||
1151 | |||
1152 | /** | ||
1153 | * sata_pmp_do_eh - do standard error handling for PMP-enabled host | ||
1154 | * @ap: host port to handle error for | ||
1155 | * @prereset: prereset method (can be NULL) | ||
1156 | * @softreset: softreset method | ||
1157 | * @hardreset: hardreset method | ||
1158 | * @postreset: postreset method (can be NULL) | ||
1159 | * @pmp_prereset: PMP prereset method (can be NULL) | ||
1160 | * @pmp_softreset: PMP softreset method (can be NULL) | ||
1161 | * @pmp_hardreset: PMP hardreset method (can be NULL) | ||
1162 | * @pmp_postreset: PMP postreset method (can be NULL) | ||
1163 | * | ||
1164 | * Perform standard error handling sequence for PMP-enabled host | ||
1165 | * @ap. | ||
1166 | * | ||
1167 | * LOCKING: | ||
1168 | * Kernel thread context (may sleep). | ||
1169 | */ | ||
1170 | void sata_pmp_do_eh(struct ata_port *ap, | ||
1171 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | ||
1172 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, | ||
1173 | ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset, | ||
1174 | ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset) | ||
1175 | { | ||
1176 | ata_eh_autopsy(ap); | ||
1177 | ata_eh_report(ap); | ||
1178 | sata_pmp_eh_recover(ap, prereset, softreset, hardreset, postreset, | ||
1179 | pmp_prereset, pmp_softreset, pmp_hardreset, | ||
1180 | pmp_postreset); | ||
1181 | ata_eh_finish(ap); | ||
1182 | } | ||
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index ebe22982e80c..a9b9c9e1e105 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -153,6 +153,11 @@ extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); | |||
153 | extern void ata_scsi_dev_rescan(struct work_struct *work); | 153 | extern void ata_scsi_dev_rescan(struct work_struct *work); |
154 | extern int ata_bus_probe(struct ata_port *ap); | 154 | extern int ata_bus_probe(struct ata_port *ap); |
155 | 155 | ||
156 | /* libata-pmp.c */ | ||
157 | extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val); | ||
158 | extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val); | ||
159 | extern int sata_pmp_attach(struct ata_device *dev); | ||
160 | |||
156 | /* libata-eh.c */ | 161 | /* libata-eh.c */ |
157 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | 162 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); |
158 | extern void ata_scsi_error(struct Scsi_Host *host); | 163 | extern void ata_scsi_error(struct Scsi_Host *host); |
diff --git a/include/linux/libata.h b/include/linux/libata.h index f9ed198e4fcd..3cfdb5f67621 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -945,6 +945,25 @@ extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long); | |||
945 | #endif /* CONFIG_PCI */ | 945 | #endif /* CONFIG_PCI */ |
946 | 946 | ||
947 | /* | 947 | /* |
948 | * PMP | ||
949 | */ | ||
950 | extern void sata_pmp_read_init_tf(struct ata_taskfile *tf, | ||
951 | struct ata_device *dev, int pmp, int reg); | ||
952 | extern u32 sata_pmp_read_val(const struct ata_taskfile *tf); | ||
953 | extern void sata_pmp_write_init_tf(struct ata_taskfile *tf, | ||
954 | struct ata_device *dev, | ||
955 | int pmp, int reg, u32 val); | ||
956 | extern int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline); | ||
957 | extern int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class, | ||
958 | unsigned long deadline); | ||
959 | extern void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class); | ||
960 | extern void sata_pmp_do_eh(struct ata_port *ap, | ||
961 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | ||
962 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, | ||
963 | ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset, | ||
964 | ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset); | ||
965 | |||
966 | /* | ||
948 | * EH | 967 | * EH |
949 | */ | 968 | */ |
950 | extern void ata_eng_timeout(struct ata_port *ap); | 969 | extern void ata_eng_timeout(struct ata_port *ap); |