提交 ae01b249 编写于 作者: T Tejun Heo 提交者: Jeff Garzik

libata: Implement ATA_FLAG_NO_DIPM and apply it to mcp65

NVIDIA mcp65 familiy of controllers cause command timeouts when DIPM
is used.  Implement ATA_FLAG_NO_DIPM and apply it.

This problem was reported by Stefan Bader in the following thread.

 http://thread.gmane.org/gmane.linux.ide/48841

stable: applicable to 2.6.37 and 38.
Signed-off-by: NTejun Heo <tj@kernel.org>
Reported-by: NStefan Bader <stefan.bader@canonical.com>
Cc: stable@kernel.org
Signed-off-by: NJeff Garzik <jgarzik@pobox.com>
上级 3f7ac1d6
...@@ -150,7 +150,7 @@ static const struct ata_port_info ahci_port_info[] = { ...@@ -150,7 +150,7 @@ static const struct ata_port_info ahci_port_info[] = {
{ {
AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
AHCI_HFLAG_YES_NCQ), AHCI_HFLAG_YES_NCQ),
.flags = AHCI_FLAG_COMMON, .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
......
...@@ -3316,6 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, ...@@ -3316,6 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
struct ata_eh_context *ehc = &link->eh_context; struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
enum ata_lpm_policy old_policy = link->lpm_policy; enum ata_lpm_policy old_policy = link->lpm_policy;
bool no_dipm = ap->flags & ATA_FLAG_NO_DIPM;
unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM; unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
unsigned int err_mask; unsigned int err_mask;
int rc; int rc;
...@@ -3332,7 +3333,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, ...@@ -3332,7 +3333,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
*/ */
ata_for_each_dev(dev, link, ENABLED) { ata_for_each_dev(dev, link, ENABLED) {
bool hipm = ata_id_has_hipm(dev->id); bool hipm = ata_id_has_hipm(dev->id);
bool dipm = ata_id_has_dipm(dev->id); bool dipm = ata_id_has_dipm(dev->id) && !no_dipm;
/* find the first enabled and LPM enabled devices */ /* find the first enabled and LPM enabled devices */
if (!link_dev) if (!link_dev)
...@@ -3389,7 +3390,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, ...@@ -3389,7 +3390,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
/* host config updated, enable DIPM if transitioning to MIN_POWER */ /* host config updated, enable DIPM if transitioning to MIN_POWER */
ata_for_each_dev(dev, link, ENABLED) { ata_for_each_dev(dev, link, ENABLED) {
if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) { if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
ata_id_has_dipm(dev->id)) {
err_mask = ata_dev_set_feature(dev, err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE, SATA_DIPM); SETFEATURES_SATA_ENABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) { if (err_mask && err_mask != AC_ERR_DEV) {
......
...@@ -196,6 +196,7 @@ enum { ...@@ -196,6 +196,7 @@ enum {
* management */ * management */
ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity
* led */ * led */
ATA_FLAG_NO_DIPM = (1 << 23), /* host not happy with DIPM */
/* bits 24:31 of ap->flags are reserved for LLD specific flags */ /* bits 24:31 of ap->flags are reserved for LLD specific flags */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册