libata-5.5-20191226
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAl4E+S0QHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgptfiEAC8w1WnAkB4SkSzcex7TjxRcmBHHAB6rWbb Myf0GiAj6rvC+8KW91SOgxIF2xTlvgwEcY4v0mIHCy0Lb2SSeEg74X9OmhAGVTNI WXeHWeV7zDVUU5DePKt/3Mkt3qIalTUzhmxM3erJmgj3LuJQWOXDpW/YGKVwULJG V7PnEcVrlolZ+WLfEY1NvZ9+gwgp6GkG7vuN7QYCFqpVnLxxtxVA7qx4azNGzt8M 1KFtL8S7yUpAw3z3J/77DDigi//VSLabdyLnBOLQ5KJJpO/Qjr8+5GGWSmAQFQYQ t6et4DtLqIuJOq3y8kx5aUwLHdLfwWDIGE1AoY+kHToYbGcCTAe7HXLUJMgjwfEe +nLgtrRD1OhOe5zON1C3MI2tbqBJjdKYabUHCWzUWz1IO8d4JN4bOv1KkquaeFep te/GjQ/86kvX12uF87lrlcaslJu5TBLnD7vd+pj+1AOdFEjNX+WY0NljZRIWtbHA 2N5V8WhpW08jL4Hr/86oq1uNNc6cfBd5d16JiDbLnxJoulfhQGr0oV8T+lq9s4l8 txJy8oDlhE5CU80a/8UhsZTasfa3Vg37xL71uZtCz7dWEfkq4ZPGKJHoa9DGUd9l tXa+04bxg+sAwyFH+RWmxulQEdvF4+4H4lEbHah+UuMUukgYo1i86ao+R6DTiVx+ AVsawlrW+Q== =IO44 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
0f710a5572
|
@ -76,8 +76,7 @@ enum brcm_ahci_version {
|
|||
};
|
||||
|
||||
enum brcm_ahci_quirks {
|
||||
BRCM_AHCI_QUIRK_NO_NCQ = BIT(0),
|
||||
BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1),
|
||||
BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(0),
|
||||
};
|
||||
|
||||
struct brcm_ahci_priv {
|
||||
|
@ -213,19 +212,12 @@ static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
|
|||
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)
|
||||
{
|
||||
void __iomem *ahci;
|
||||
struct resource *res;
|
||||
u32 impl;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
|
||||
ahci = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(ahci))
|
||||
return 0;
|
||||
|
||||
impl = readl(ahci + HOST_PORTS_IMPL);
|
||||
impl = readl(hpriv->mmio + HOST_PORTS_IMPL);
|
||||
|
||||
if (fls(impl) > SATA_TOP_MAX_PHYS)
|
||||
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,
|
|||
else if (!impl)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -285,6 +274,13 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev,
|
|||
/* Perform the SATA PHY reset sequence */
|
||||
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 */
|
||||
brcm_sata_phy_enable(priv, ap->port_no);
|
||||
|
||||
|
@ -347,11 +343,10 @@ static int brcm_ahci_suspend(struct device *dev)
|
|||
struct ata_host *host = dev_get_drvdata(dev);
|
||||
struct ahci_host_priv *hpriv = host->private_data;
|
||||
struct brcm_ahci_priv *priv = hpriv->plat_data;
|
||||
int ret;
|
||||
|
||||
ret = ahci_platform_suspend(dev);
|
||||
brcm_sata_phys_disable(priv);
|
||||
return ret;
|
||||
|
||||
return ahci_platform_suspend(dev);
|
||||
}
|
||||
|
||||
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 ahci_host_priv *hpriv = host->private_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_phys_enable(priv);
|
||||
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
|
||||
|
||||
|
@ -410,44 +438,71 @@ static int brcm_ahci_probe(struct platform_device *pdev)
|
|||
if (!IS_ERR_OR_NULL(priv->rcdev))
|
||||
reset_control_deassert(priv->rcdev);
|
||||
|
||||
if ((priv->version == BRCM_SATA_BCM7425) ||
|
||||
(priv->version == BRCM_SATA_NSP)) {
|
||||
priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ;
|
||||
priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
|
||||
hpriv = ahci_platform_get_resources(pdev, 0);
|
||||
if (IS_ERR(hpriv)) {
|
||||
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;
|
||||
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);
|
||||
|
||||
priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
|
||||
if (!priv->port_mask)
|
||||
return -ENODEV;
|
||||
/* Initializes priv->port_mask which is used below */
|
||||
priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
|
||||
if (!priv->port_mask) {
|
||||
ret = -ENODEV;
|
||||
goto out_disable_clks;
|
||||
}
|
||||
|
||||
/* Must be done before ahci_platform_enable_phys() */
|
||||
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);
|
||||
|
||||
ret = ahci_platform_enable_resources(hpriv);
|
||||
ret = ahci_platform_enable_phys(hpriv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
|
||||
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
|
||||
hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
|
||||
goto out_disable_phys;
|
||||
|
||||
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
|
||||
&ahci_platform_sht);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_disable_platform_phys;
|
||||
|
||||
dev_info(dev, "Broadcom AHCI SATA3 registered\n");
|
||||
|
||||
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)
|
||||
|
@ -457,12 +512,12 @@ static int brcm_ahci_remove(struct platform_device *pdev)
|
|||
struct brcm_ahci_priv *priv = hpriv->plat_data;
|
||||
int ret;
|
||||
|
||||
brcm_sata_phys_disable(priv);
|
||||
|
||||
ret = ata_platform_remove_one(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
brcm_sata_phys_disable(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_ops);
|
|||
* RETURNS:
|
||||
* 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;
|
||||
|
||||
|
@ -74,6 +74,7 @@ disable_phys:
|
|||
}
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
|
||||
|
||||
/**
|
||||
* ahci_platform_disable_phys - Disable PHYs
|
||||
|
@ -81,7 +82,7 @@ disable_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;
|
||||
|
||||
|
@ -90,6 +91,7 @@ static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
|
|||
phy_exit(hpriv->phys[i]);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
|
||||
|
||||
/**
|
||||
* ahci_platform_enable_clks - Enable platform clocks
|
||||
|
|
|
@ -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
|
||||
* @ap: port in question
|
||||
|
|
|
@ -1280,7 +1280,7 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
|||
i, ioread32(hcr_base + CC),
|
||||
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;
|
||||
|
||||
} 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
|
|||
}
|
||||
|
||||
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 */
|
||||
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)
|
|||
check_commands = 0;
|
||||
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;
|
|||
struct platform_device;
|
||||
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);
|
||||
void ahci_platform_disable_clks(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,
|
|||
struct ata_taskfile *tf, u16 *id);
|
||||
extern void ata_qc_complete(struct ata_queued_cmd *qc);
|
||||
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 int ata_std_bios_param(struct scsi_device *sdev,
|
||||
struct block_device *bdev,
|
||||
|
|
Loading…
Reference in New Issue