Fwd: [PATCH] ahci: enable pmp but connected to HDD issue fixed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Since more than one controllers has software reset failed problem when PMP
enabled, I think it would be better to move ahci_sb600_softreset() from ahci.c
to libahci.c and rename it, let's say: ahci_pmpenable_softreset() .
(Just arbitrary
name, please someone may give a better function name)
Controller that has software reset problem when PMP enable may point its
softreset and pmp_softreset call back function of struct ata_port_operations to
ahci_pmpenable_softreset(). Regardless of PCI or Platform based AHCI controller.
(ahci.c or ahci_platform.c)
Regards,
BingJiun
On Tue, Jun 14, 2011 at 1:48 PM, Yuan-Hsin Chen <yuanlmm@xxxxxxxxx> wrote:
>
> From: Yuan-Hsin Chen <yhchen@xxxxxxxxxxxxxxxx>
>
> When enabling both port multiplier and platform ahci sata, ahci
> times out while connecting to HDD directly. This is because soft
> reset fails with IPMS set. Do soft reset again to port 0.
>
> The soft reset sequence is copied from ahci.c.
>
> Signed-off-by: Yuan-Hsin Chen <yhchen@xxxxxxxxxxxxxxxx>
> ---
>  drivers/ata/ahci_platform.c |   62 ++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 61 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
> index 6fef1fa..6eab716 100644
> --- a/drivers/ata/ahci_platform.c
> +++ b/drivers/ata/ahci_platform.c
> @@ -27,6 +27,66 @@ static struct scsi_host_template ahci_platform_sht = {
>        AHCI_SHT("ahci_platform"),
>  };
>
> +static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
> +                         unsigned long deadline);
> +
> +static struct ata_port_operations ahci_pmp_ops = {
> +       .inherits               = &ahci_ops,
> +       .softreset              = ahci_pmp_softreset,
> +       .pmp_softreset          = ahci_pmp_softreset,
> +};
> +
> +static int ahci_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;
> +
> +       printk("%s:TFT 0x%x\n", __func__, status);
> +       return ata_check_ready(status);
> +}
> +
> +static int ahci_pmp_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_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 __init ahci_probe(struct platform_device *pdev)
>  {
>        struct device *dev = &pdev->dev;
> @@ -35,7 +95,7 @@ static int __init ahci_probe(struct platform_device *pdev)
>                .flags          = AHCI_FLAG_COMMON,
>                .pio_mask       = ATA_PIO4,
>                .udma_mask      = ATA_UDMA6,
> -               .port_ops       = &ahci_ops,
> +               .port_ops       = &ahci_pmp_ops,
>        };
>        const struct ata_port_info *ppi[] = { &pi, NULL };
>        struct ahci_host_priv *hpriv;
> --
> 1.7.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ide" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux