Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 258415
b: refs/heads/master
c: 345347c
h: refs/heads/master
i:
  258413: 543839e
  258411: 4ef2e87
  258407: dcd1dd4
  258399: 6370d93
v: v3
  • Loading branch information
Yuan-Hsin Chen authored and Jeff Garzik committed Jul 23, 2011
1 parent 8df0920 commit 25e601a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 59 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8ea7645c5a949f9d0ea86edc0778713b5e63ab74
refs/heads/master: 345347c5d767332d7352f220808fe9b5e4af8c6b
60 changes: 2 additions & 58 deletions trunk/drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ enum board_ids {
};

static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
Expand All @@ -104,12 +102,6 @@ static struct ata_port_operations ahci_p5wdh_ops = {
.hardreset = ahci_p5wdh_hardreset,
};

static struct ata_port_operations ahci_sb600_ops = {
.inherits = &ahci_ops,
.softreset = ahci_sb600_softreset,
.pmp_softreset = ahci_sb600_softreset,
};

#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)

static const struct ata_port_info ahci_port_info[] = {
Expand Down Expand Up @@ -188,15 +180,15 @@ static const struct ata_port_info ahci_port_info[] = {
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_sb600_ops,
.port_ops = &ahci_pmp_retry_srst_ops,
},
[board_ahci_sb700] = /* for SB700 and SB800 */
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_sb600_ops,
.port_ops = &ahci_pmp_retry_srst_ops,
},
[board_ahci_vt8251] =
{
Expand Down Expand Up @@ -502,54 +494,6 @@ static void ahci_pci_init_controller(struct ata_host *host)
ahci_init_controller(host);
}

static int ahci_sb600_check_ready(struct ata_link *link)
{
void __iomem *port_mmio = ahci_port_base(link->ap);
u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);

/*
* There is no need to check TFDATA if BAD PMP is found due to HW bug,
* which can save timeout delay.
*/
if (irq_status & PORT_IRQ_BAD_PMP)
return -EIO;

return ata_check_ready(status);
}

static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
struct ata_port *ap = link->ap;
void __iomem *port_mmio = ahci_port_base(ap);
int pmp = sata_srst_pmp(link);
int rc;
u32 irq_sts;

DPRINTK("ENTER\n");

rc = ahci_do_softreset(link, class, pmp, deadline,
ahci_sb600_check_ready);

/*
* Soft reset fails on some ATI chips with IPMS set when PMP
* is enabled but SATA HDD/ODD is connected to SATA port,
* do soft reset again to port 0.
*/
if (rc == -EIO) {
irq_sts = readl(port_mmio + PORT_IRQ_STAT);
if (irq_sts & PORT_IRQ_BAD_PMP) {
ata_link_warn(link,
"applying SB600 PMP SRST workaround and retrying\n");
rc = ahci_do_softreset(link, class, 0, deadline,
ahci_check_ready);
}
}

return rc;
}

static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/ata/ahci.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
.sdev_attrs = ahci_sdev_attrs

extern struct ata_port_operations ahci_ops;
extern struct ata_port_operations ahci_pmp_retry_srst_ops;

void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts);
Expand Down
57 changes: 57 additions & 0 deletions trunk/drivers/ata/libahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_detach(struct ata_port *ap);
static int ahci_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static void ahci_postreset(struct ata_link *link, unsigned int *class);
Expand Down Expand Up @@ -178,6 +180,12 @@ struct ata_port_operations ahci_ops = {
};
EXPORT_SYMBOL_GPL(ahci_ops);

struct ata_port_operations ahci_pmp_retry_srst_ops = {
.inherits = &ahci_ops,
.softreset = ahci_pmp_retry_softreset,
};
EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);

int ahci_em_messages = 1;
EXPORT_SYMBOL_GPL(ahci_em_messages);
module_param(ahci_em_messages, int, 0444);
Expand Down Expand Up @@ -1319,6 +1327,55 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
}
EXPORT_SYMBOL_GPL(ahci_do_softreset);

static int ahci_bad_pmp_check_ready(struct ata_link *link)
{
void __iomem *port_mmio = ahci_port_base(link->ap);
u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);

/*
* There is no need to check TFDATA if BAD PMP is found due to HW bug,
* which can save timeout delay.
*/
if (irq_status & PORT_IRQ_BAD_PMP)
return -EIO;

return ata_check_ready(status);
}

int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
struct ata_port *ap = link->ap;
void __iomem *port_mmio = ahci_port_base(ap);
int pmp = sata_srst_pmp(link);
int rc;
u32 irq_sts;

DPRINTK("ENTER\n");

rc = ahci_do_softreset(link, class, pmp, deadline,
ahci_bad_pmp_check_ready);

/*
* Soft reset fails with IPMS set when PMP is enabled but
* SATA HDD/ODD is connected to SATA port, do soft reset
* again to port 0.
*/
if (rc == -EIO) {
irq_sts = readl(port_mmio + PORT_IRQ_STAT);
if (irq_sts & PORT_IRQ_BAD_PMP) {
ata_link_printk(link, KERN_WARNING,
"applying PMP SRST workaround "
"and retrying\n");
rc = ahci_do_softreset(link, class, 0, deadline,
ahci_check_ready);
}
}

return rc;
}

static int ahci_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
Expand Down

0 comments on commit 25e601a

Please sign in to comment.