Commit 0f710a55 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'libata-5.5-20191226' of git://git.kernel.dk/linux-block

Pull libata fixes from Jens Axboe:
 "Two things in here:

   - First half of a series that fixes ahci_brcm, also marked for
     stable. The other part of the series is going into 5.6 (Florian)

   - sata_nv regression fix that is also marked for stable (Sascha)"

* tag 'libata-5.5-20191226' of git://git.kernel.dk/linux-block:
  ata: ahci_brcm: Add missing clock management during recovery
  ata: ahci_brcm: BCM7425 AHCI requires AHCI_HFLAG_DELAY_ENGINE
  ata: ahci_brcm: Fix AHCI resources management
  ata: libahci_platform: Export again ahci_platform_<en/dis>able_phys()
  libata: Fix retrieving of active qcs
parents 8ae40a69 bf0e5013
...@@ -76,8 +76,7 @@ enum brcm_ahci_version { ...@@ -76,8 +76,7 @@ enum brcm_ahci_version {
}; };
enum brcm_ahci_quirks { enum brcm_ahci_quirks {
BRCM_AHCI_QUIRK_NO_NCQ = BIT(0), BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(0),
BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1),
}; };
struct brcm_ahci_priv { struct brcm_ahci_priv {
...@@ -213,19 +212,12 @@ static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv) ...@@ -213,19 +212,12 @@ static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
brcm_sata_phy_disable(priv, i); brcm_sata_phy_disable(priv, i);
} }
static u32 brcm_ahci_get_portmask(struct platform_device *pdev, static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv,
struct brcm_ahci_priv *priv) struct brcm_ahci_priv *priv)
{ {
void __iomem *ahci;
struct resource *res;
u32 impl; u32 impl;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"); impl = readl(hpriv->mmio + HOST_PORTS_IMPL);
ahci = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ahci))
return 0;
impl = readl(ahci + HOST_PORTS_IMPL);
if (fls(impl) > SATA_TOP_MAX_PHYS) if (fls(impl) > SATA_TOP_MAX_PHYS)
dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n", dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
...@@ -233,9 +225,6 @@ static u32 brcm_ahci_get_portmask(struct platform_device *pdev, ...@@ -233,9 +225,6 @@ static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
else if (!impl) else if (!impl)
dev_info(priv->dev, "no ports found\n"); dev_info(priv->dev, "no ports found\n");
devm_iounmap(&pdev->dev, ahci);
devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
return impl; return impl;
} }
...@@ -285,6 +274,13 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev, ...@@ -285,6 +274,13 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev,
/* Perform the SATA PHY reset sequence */ /* Perform the SATA PHY reset sequence */
brcm_sata_phy_disable(priv, ap->port_no); brcm_sata_phy_disable(priv, ap->port_no);
/* Reset the SATA clock */
ahci_platform_disable_clks(hpriv);
msleep(10);
ahci_platform_enable_clks(hpriv);
msleep(10);
/* Bring the PHY back on */ /* Bring the PHY back on */
brcm_sata_phy_enable(priv, ap->port_no); brcm_sata_phy_enable(priv, ap->port_no);
...@@ -347,11 +343,10 @@ static int brcm_ahci_suspend(struct device *dev) ...@@ -347,11 +343,10 @@ static int brcm_ahci_suspend(struct device *dev)
struct ata_host *host = dev_get_drvdata(dev); struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data; struct ahci_host_priv *hpriv = host->private_data;
struct brcm_ahci_priv *priv = hpriv->plat_data; struct brcm_ahci_priv *priv = hpriv->plat_data;
int ret;
ret = ahci_platform_suspend(dev);
brcm_sata_phys_disable(priv); brcm_sata_phys_disable(priv);
return ret;
return ahci_platform_suspend(dev);
} }
static int brcm_ahci_resume(struct device *dev) static int brcm_ahci_resume(struct device *dev)
...@@ -359,11 +354,44 @@ static int brcm_ahci_resume(struct device *dev) ...@@ -359,11 +354,44 @@ static int brcm_ahci_resume(struct device *dev)
struct ata_host *host = dev_get_drvdata(dev); struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data; struct ahci_host_priv *hpriv = host->private_data;
struct brcm_ahci_priv *priv = hpriv->plat_data; struct brcm_ahci_priv *priv = hpriv->plat_data;
int ret;
/* Make sure clocks are turned on before re-configuration */
ret = ahci_platform_enable_clks(hpriv);
if (ret)
return ret;
brcm_sata_init(priv); brcm_sata_init(priv);
brcm_sata_phys_enable(priv); brcm_sata_phys_enable(priv);
brcm_sata_alpm_init(hpriv); brcm_sata_alpm_init(hpriv);
return ahci_platform_resume(dev);
/* Since we had to enable clocks earlier on, we cannot use
* ahci_platform_resume() as-is since a second call to
* ahci_platform_enable_resources() would bump up the resources
* (regulators, clocks, PHYs) count artificially so we copy the part
* after ahci_platform_enable_resources().
*/
ret = ahci_platform_enable_phys(hpriv);
if (ret)
goto out_disable_phys;
ret = ahci_platform_resume_host(dev);
if (ret)
goto out_disable_platform_phys;
/* We resumed so update PM runtime state */
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
out_disable_platform_phys:
ahci_platform_disable_phys(hpriv);
out_disable_phys:
brcm_sata_phys_disable(priv);
ahci_platform_disable_clks(hpriv);
return ret;
} }
#endif #endif
...@@ -410,44 +438,71 @@ static int brcm_ahci_probe(struct platform_device *pdev) ...@@ -410,44 +438,71 @@ static int brcm_ahci_probe(struct platform_device *pdev)
if (!IS_ERR_OR_NULL(priv->rcdev)) if (!IS_ERR_OR_NULL(priv->rcdev))
reset_control_deassert(priv->rcdev); reset_control_deassert(priv->rcdev);
if ((priv->version == BRCM_SATA_BCM7425) || hpriv = ahci_platform_get_resources(pdev, 0);
(priv->version == BRCM_SATA_NSP)) { if (IS_ERR(hpriv)) {
priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ; ret = PTR_ERR(hpriv);
goto out_reset;
}
hpriv->plat_data = priv;
hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
switch (priv->version) {
case BRCM_SATA_BCM7425:
hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
/* fall through */
case BRCM_SATA_NSP:
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
break;
default:
break;
} }
ret = ahci_platform_enable_clks(hpriv);
if (ret)
goto out_reset;
/* Must be first so as to configure endianness including that
* of the standard AHCI register space.
*/
brcm_sata_init(priv); brcm_sata_init(priv);
priv->port_mask = brcm_ahci_get_portmask(pdev, priv); /* Initializes priv->port_mask which is used below */
if (!priv->port_mask) priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
return -ENODEV; if (!priv->port_mask) {
ret = -ENODEV;
goto out_disable_clks;
}
/* Must be done before ahci_platform_enable_phys() */
brcm_sata_phys_enable(priv); brcm_sata_phys_enable(priv);
hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
hpriv->plat_data = priv;
hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;
brcm_sata_alpm_init(hpriv); brcm_sata_alpm_init(hpriv);
ret = ahci_platform_enable_resources(hpriv); ret = ahci_platform_enable_phys(hpriv);
if (ret) if (ret)
return ret; goto out_disable_phys;
if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info, ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
&ahci_platform_sht); &ahci_platform_sht);
if (ret) if (ret)
return ret; goto out_disable_platform_phys;
dev_info(dev, "Broadcom AHCI SATA3 registered\n"); dev_info(dev, "Broadcom AHCI SATA3 registered\n");
return 0; return 0;
out_disable_platform_phys:
ahci_platform_disable_phys(hpriv);
out_disable_phys:
brcm_sata_phys_disable(priv);
out_disable_clks:
ahci_platform_disable_clks(hpriv);
out_reset:
if (!IS_ERR_OR_NULL(priv->rcdev))
reset_control_assert(priv->rcdev);
return ret;
} }
static int brcm_ahci_remove(struct platform_device *pdev) static int brcm_ahci_remove(struct platform_device *pdev)
...@@ -457,12 +512,12 @@ static int brcm_ahci_remove(struct platform_device *pdev) ...@@ -457,12 +512,12 @@ static int brcm_ahci_remove(struct platform_device *pdev)
struct brcm_ahci_priv *priv = hpriv->plat_data; struct brcm_ahci_priv *priv = hpriv->plat_data;
int ret; int ret;
brcm_sata_phys_disable(priv);
ret = ata_platform_remove_one(pdev); ret = ata_platform_remove_one(pdev);
if (ret) if (ret)
return ret; return ret;
brcm_sata_phys_disable(priv);
return 0; return 0;
} }
......
...@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_ops); ...@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_ops);
* RETURNS: * RETURNS:
* 0 on success otherwise a negative error code * 0 on success otherwise a negative error code
*/ */
static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
{ {
int rc, i; int rc, i;
...@@ -74,6 +74,7 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) ...@@ -74,6 +74,7 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
} }
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
/** /**
* ahci_platform_disable_phys - Disable PHYs * ahci_platform_disable_phys - Disable PHYs
...@@ -81,7 +82,7 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) ...@@ -81,7 +82,7 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
* *
* This function disables all PHYs found in hpriv->phys. * This function disables all PHYs found in hpriv->phys.
*/ */
static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
{ {
int i; int i;
...@@ -90,6 +91,7 @@ static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) ...@@ -90,6 +91,7 @@ static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
phy_exit(hpriv->phys[i]); phy_exit(hpriv->phys[i]);
} }
} }
EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
/** /**
* ahci_platform_enable_clks - Enable platform clocks * ahci_platform_enable_clks - Enable platform clocks
......
...@@ -5328,6 +5328,30 @@ void ata_qc_complete(struct ata_queued_cmd *qc) ...@@ -5328,6 +5328,30 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
} }
} }
/**
* ata_qc_get_active - get bitmask of active qcs
* @ap: port in question
*
* LOCKING:
* spin_lock_irqsave(host lock)
*
* RETURNS:
* Bitmask of active qcs
*/
u64 ata_qc_get_active(struct ata_port *ap)
{
u64 qc_active = ap->qc_active;
/* ATA_TAG_INTERNAL is sent to hw as tag 0 */
if (qc_active & (1ULL << ATA_TAG_INTERNAL)) {
qc_active |= (1 << 0);
qc_active &= ~(1ULL << ATA_TAG_INTERNAL);
}
return qc_active;
}
EXPORT_SYMBOL_GPL(ata_qc_get_active);
/** /**
* ata_qc_complete_multiple - Complete multiple qcs successfully * ata_qc_complete_multiple - Complete multiple qcs successfully
* @ap: port in question * @ap: port in question
......
...@@ -1280,7 +1280,7 @@ static void sata_fsl_host_intr(struct ata_port *ap) ...@@ -1280,7 +1280,7 @@ static void sata_fsl_host_intr(struct ata_port *ap)
i, ioread32(hcr_base + CC), i, ioread32(hcr_base + CC),
ioread32(hcr_base + CA)); ioread32(hcr_base + CA));
} }
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask); ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
return; return;
} else if ((ap->qc_active & (1ULL << ATA_TAG_INTERNAL))) { } else if ((ap->qc_active & (1ULL << ATA_TAG_INTERNAL))) {
......
...@@ -2829,7 +2829,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp ...@@ -2829,7 +2829,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
} }
if (work_done) { if (work_done) {
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask); ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
/* Update the software queue position index in hardware */ /* Update the software queue position index in hardware */
writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
......
...@@ -984,7 +984,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) ...@@ -984,7 +984,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
check_commands = 0; check_commands = 0;
check_commands &= ~(1 << pos); check_commands &= ~(1 << pos);
} }
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask); ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
} }
} }
......
...@@ -19,6 +19,8 @@ struct ahci_host_priv; ...@@ -19,6 +19,8 @@ struct ahci_host_priv;
struct platform_device; struct platform_device;
struct scsi_host_template; struct scsi_host_template;
int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv); int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv);
......
...@@ -1175,6 +1175,7 @@ extern unsigned int ata_do_dev_read_id(struct ata_device *dev, ...@@ -1175,6 +1175,7 @@ extern unsigned int ata_do_dev_read_id(struct ata_device *dev,
struct ata_taskfile *tf, u16 *id); struct ata_taskfile *tf, u16 *id);
extern void ata_qc_complete(struct ata_queued_cmd *qc); extern void ata_qc_complete(struct ata_queued_cmd *qc);
extern int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active); extern int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active);
extern u64 ata_qc_get_active(struct ata_port *ap);
extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd); extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd);
extern int ata_std_bios_param(struct scsi_device *sdev, extern int ata_std_bios_param(struct scsi_device *sdev,
struct block_device *bdev, struct block_device *bdev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment