ahci: move ahci_sb600_softreset to libahci.c and rename it
ahci_sb600_softreset was in ahci.c. This function is used to fix soft reset failure and renames as ahci_pmp_retry_softreset in libahci.c. Signed-off-by: Yuan-Hsin Chen <yhchen@faraday-tech.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
8ea7645c5a
commit
345347c5d7
|
@ -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_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,
|
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline);
|
unsigned long deadline);
|
||||||
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
|
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
|
||||||
|
@ -104,12 +102,6 @@ static struct ata_port_operations ahci_p5wdh_ops = {
|
||||||
.hardreset = ahci_p5wdh_hardreset,
|
.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)
|
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
|
||||||
|
|
||||||
static const struct ata_port_info ahci_port_info[] = {
|
static const struct ata_port_info ahci_port_info[] = {
|
||||||
|
@ -188,7 +180,7 @@ static const struct ata_port_info ahci_port_info[] = {
|
||||||
.flags = AHCI_FLAG_COMMON,
|
.flags = AHCI_FLAG_COMMON,
|
||||||
.pio_mask = ATA_PIO4,
|
.pio_mask = ATA_PIO4,
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
.port_ops = &ahci_sb600_ops,
|
.port_ops = &ahci_pmp_retry_srst_ops,
|
||||||
},
|
},
|
||||||
[board_ahci_sb700] = /* for SB700 and SB800 */
|
[board_ahci_sb700] = /* for SB700 and SB800 */
|
||||||
{
|
{
|
||||||
|
@ -196,7 +188,7 @@ static const struct ata_port_info ahci_port_info[] = {
|
||||||
.flags = AHCI_FLAG_COMMON,
|
.flags = AHCI_FLAG_COMMON,
|
||||||
.pio_mask = ATA_PIO4,
|
.pio_mask = ATA_PIO4,
|
||||||
.udma_mask = ATA_UDMA6,
|
.udma_mask = ATA_UDMA6,
|
||||||
.port_ops = &ahci_sb600_ops,
|
.port_ops = &ahci_pmp_retry_srst_ops,
|
||||||
},
|
},
|
||||||
[board_ahci_vt8251] =
|
[board_ahci_vt8251] =
|
||||||
{
|
{
|
||||||
|
@ -502,54 +494,6 @@ static void ahci_pci_init_controller(struct ata_host *host)
|
||||||
ahci_init_controller(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,
|
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline)
|
unsigned long deadline)
|
||||||
{
|
{
|
||||||
|
|
|
@ -312,6 +312,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
|
||||||
.sdev_attrs = ahci_sdev_attrs
|
.sdev_attrs = ahci_sdev_attrs
|
||||||
|
|
||||||
extern struct ata_port_operations ahci_ops;
|
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,
|
void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
|
||||||
u32 opts);
|
u32 opts);
|
||||||
|
|
|
@ -82,6 +82,8 @@ static void ahci_pmp_attach(struct ata_port *ap);
|
||||||
static void ahci_pmp_detach(struct ata_port *ap);
|
static void ahci_pmp_detach(struct ata_port *ap);
|
||||||
static int ahci_softreset(struct ata_link *link, unsigned int *class,
|
static int ahci_softreset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline);
|
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,
|
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline);
|
unsigned long deadline);
|
||||||
static void ahci_postreset(struct ata_link *link, unsigned int *class);
|
static void ahci_postreset(struct ata_link *link, unsigned int *class);
|
||||||
|
@ -178,6 +180,12 @@ struct ata_port_operations ahci_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(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;
|
int ahci_em_messages = 1;
|
||||||
EXPORT_SYMBOL_GPL(ahci_em_messages);
|
EXPORT_SYMBOL_GPL(ahci_em_messages);
|
||||||
module_param(ahci_em_messages, int, 0444);
|
module_param(ahci_em_messages, int, 0444);
|
||||||
|
@ -1319,6 +1327,55 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ahci_do_softreset);
|
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,
|
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline)
|
unsigned long deadline)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue