aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-pmp.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/ata/libata-pmp.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/ata/libata-pmp.c')
-rw-r--r--drivers/ata/libata-pmp.c76
1 files changed, 70 insertions, 6 deletions
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 224faabd7b7e..f06b7ea590d3 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -11,6 +11,7 @@
11#include <linux/libata.h> 11#include <linux/libata.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include "libata.h" 13#include "libata.h"
14#include "libata-transport.h"
14 15
15const struct ata_port_operations sata_pmp_port_ops = { 16const struct ata_port_operations sata_pmp_port_ops = {
16 .inherits = &sata_port_ops, 17 .inherits = &sata_port_ops,
@@ -185,6 +186,27 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
185} 186}
186 187
187/** 188/**
189 * sata_pmp_set_lpm - configure LPM for a PMP link
190 * @link: PMP link to configure LPM for
191 * @policy: target LPM policy
192 * @hints: LPM hints
193 *
194 * Configure LPM for @link. This function will contain any PMP
195 * specific workarounds if necessary.
196 *
197 * LOCKING:
198 * EH context.
199 *
200 * RETURNS:
201 * 0 on success, -errno on failure.
202 */
203int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
204 unsigned hints)
205{
206 return sata_link_scr_lpm(link, policy, true);
207}
208
209/**
188 * sata_pmp_read_gscr - read GSCR block of SATA PMP 210 * sata_pmp_read_gscr - read GSCR block of SATA PMP
189 * @dev: PMP device 211 * @dev: PMP device
190 * @gscr: buffer to read GSCR block into 212 * @gscr: buffer to read GSCR block into
@@ -312,10 +334,10 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
312 return rc; 334 return rc;
313} 335}
314 336
315static int sata_pmp_init_links(struct ata_port *ap, int nr_ports) 337static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
316{ 338{
317 struct ata_link *pmp_link = ap->pmp_link; 339 struct ata_link *pmp_link = ap->pmp_link;
318 int i; 340 int i, err;
319 341
320 if (!pmp_link) { 342 if (!pmp_link) {
321 pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS, 343 pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
@@ -327,6 +349,13 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
327 ata_link_init(ap, &pmp_link[i], i); 349 ata_link_init(ap, &pmp_link[i], i);
328 350
329 ap->pmp_link = pmp_link; 351 ap->pmp_link = pmp_link;
352
353 for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
354 err = ata_tlink_add(&pmp_link[i]);
355 if (err) {
356 goto err_tlink;
357 }
358 }
330 } 359 }
331 360
332 for (i = 0; i < nr_ports; i++) { 361 for (i = 0; i < nr_ports; i++) {
@@ -339,6 +368,12 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
339 } 368 }
340 369
341 return 0; 370 return 0;
371 err_tlink:
372 while (--i >= 0)
373 ata_tlink_delete(&pmp_link[i]);
374 kfree(pmp_link);
375 ap->pmp_link = NULL;
376 return err;
342} 377}
343 378
344static void sata_pmp_quirks(struct ata_port *ap) 379static void sata_pmp_quirks(struct ata_port *ap)
@@ -351,6 +386,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
351 if (vendor == 0x1095 && devid == 0x3726) { 386 if (vendor == 0x1095 && devid == 0x3726) {
352 /* sil3726 quirks */ 387 /* sil3726 quirks */
353 ata_for_each_link(link, ap, EDGE) { 388 ata_for_each_link(link, ap, EDGE) {
389 /* link reports offline after LPM */
390 link->flags |= ATA_LFLAG_NO_LPM;
391
354 /* Class code report is unreliable and SRST 392 /* Class code report is unreliable and SRST
355 * times out under certain configurations. 393 * times out under certain configurations.
356 */ 394 */
@@ -366,6 +404,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
366 } else if (vendor == 0x1095 && devid == 0x4723) { 404 } else if (vendor == 0x1095 && devid == 0x4723) {
367 /* sil4723 quirks */ 405 /* sil4723 quirks */
368 ata_for_each_link(link, ap, EDGE) { 406 ata_for_each_link(link, ap, EDGE) {
407 /* link reports offline after LPM */
408 link->flags |= ATA_LFLAG_NO_LPM;
409
369 /* class code report is unreliable */ 410 /* class code report is unreliable */
370 if (link->pmp < 2) 411 if (link->pmp < 2)
371 link->flags |= ATA_LFLAG_ASSUME_ATA; 412 link->flags |= ATA_LFLAG_ASSUME_ATA;
@@ -378,6 +419,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
378 } else if (vendor == 0x1095 && devid == 0x4726) { 419 } else if (vendor == 0x1095 && devid == 0x4726) {
379 /* sil4726 quirks */ 420 /* sil4726 quirks */
380 ata_for_each_link(link, ap, EDGE) { 421 ata_for_each_link(link, ap, EDGE) {
422 /* link reports offline after LPM */
423 link->flags |= ATA_LFLAG_NO_LPM;
424
381 /* Class code report is unreliable and SRST 425 /* Class code report is unreliable and SRST
382 * times out under certain configurations. 426 * times out under certain configurations.
383 * Config device can be at port 0 or 5 and 427 * Config device can be at port 0 or 5 and
@@ -405,6 +449,16 @@ static void sata_pmp_quirks(struct ata_port *ap)
405 * otherwise. Don't try hard to recover it. 449 * otherwise. Don't try hard to recover it.
406 */ 450 */
407 ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY; 451 ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
452 } else if (vendor == 0x197b && devid == 0x2352) {
453 /* chip found in Thermaltake BlackX Duet, jmicron JMB350? */
454 ata_for_each_link(link, ap, EDGE) {
455 /* SRST breaks detection and disks get misclassified
456 * LPM disabled to avoid potential problems
457 */
458 link->flags |= ATA_LFLAG_NO_LPM |
459 ATA_LFLAG_NO_SRST |
460 ATA_LFLAG_ASSUME_ATA;
461 }
408 } 462 }
409} 463}
410 464
@@ -938,15 +992,25 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
938 if (rc) 992 if (rc)
939 goto link_fail; 993 goto link_fail;
940 994
941 /* Connection status might have changed while resetting other
942 * links, check SATA_PMP_GSCR_ERROR before returning.
943 */
944
945 /* clear SNotification */ 995 /* clear SNotification */
946 rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf); 996 rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf);
947 if (rc == 0) 997 if (rc == 0)
948 sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf); 998 sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
949 999
1000 /*
1001 * If LPM is active on any fan-out port, hotplug wouldn't
1002 * work. Return w/ PHY event notification disabled.
1003 */
1004 ata_for_each_link(link, ap, EDGE)
1005 if (link->lpm_policy > ATA_LPM_MAX_POWER)
1006 return 0;
1007
1008 /*
1009 * Connection status might have changed while resetting other
1010 * links, enable notification and check SATA_PMP_GSCR_ERROR
1011 * before returning.
1012 */
1013
950 /* enable notification */ 1014 /* enable notification */
951 if (pmp_dev->flags & ATA_DFLAG_AN) { 1015 if (pmp_dev->flags & ATA_DFLAG_AN) {
952 gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY; 1016 gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;