ata fixes for 7.2-rc4

- Interrupt initialization and handling Fixes for the Designware
    ahci_dwc driver (Rosen)
 
  - Avoid possible infinite loop when scanning completion in the
    Designware ahci_dwc driver (Rosen)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQSRPv8tYSvhwAzJdzjdoc3SxdoYdgUCalrPMQAKCRDdoc3SxdoY
 dnQ3AP9NaxQu5xoACQtFtNPb8CyY35CRclAKZsKk+/clCNAVwwEAuUo2rgw/eAfP
 w98ZEvN1HMRqW4dbatv2d3zNw2L8Iw8=
 =9+gW
 -----END PGP SIGNATURE-----

Merge tag 'ata-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull ata fixes from Damien Le Moal:

 - Interrupt initialization and handling fixes for the Designware
   ahci_dwc driver (Rosen)

 - Avoid possible infinite loop when scanning completion in the
   Designware ahci_dwc driver (Rosen)

* tag 'ata-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning
  ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts
  ata: sata_dwc_460ex: use platform_get_irq()
  ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered
This commit is contained in:
Linus Torvalds 2026-07-17 17:58:57 -07:00
commit 94dc07d6d9

View File

@ -19,7 +19,6 @@
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include <linux/libata.h>
@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
struct sata_dwc_device *hsdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL);
if (!hsdev->dma)
@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
hsdev->dma->id = pdev->id;
/* Get SATA DMA interrupt number */
hsdev->dma->irq = irq_of_parse_and_map(np, 1);
if (!hsdev->dma->irq) {
dev_err(dev, "no SATA DMA irq\n");
return -ENODEV;
}
hsdev->dma->irq = platform_get_irq(pdev, 1);
if (hsdev->dma->irq < 0)
return hsdev->dma->irq;
/* Get physical SATA DMA register base address */
hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1);
@ -398,8 +394,7 @@ static void clear_serror(struct ata_port *ap)
static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
{
sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit);
}
static u32 qcmd_tag_to_mask(u8 tag)
@ -612,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
status = ap->ops->sff_check_status(ap);
dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
tag = 0;
while (tag_mask) {
while (!(tag_mask & 0x00000001)) {
tag++;
tag_mask <<= 1;
}
tag_mask &= (~0x00000001);
tag = __ffs(tag_mask);
tag_mask &= ~(1U << tag);
qc = ata_qc_from_tag(ap, tag);
if (unlikely(!qc)) {
dev_err(ap->dev, "failed to get qc");
@ -1126,7 +1116,6 @@ static const struct ata_port_info sata_dwc_port_info[] = {
static int sata_dwc_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct device_node *np = dev->of_node;
struct sata_dwc_device *hsdev;
u32 idr, versionr;
char *ver = (char *)&versionr;
@ -1169,18 +1158,13 @@ static int sata_dwc_probe(struct platform_device *ofdev)
/* Save dev for later use in dev_xxx() routines */
hsdev->dev = dev;
/* Enable SATA Interrupts */
sata_dwc_enable_interrupts(hsdev);
/* Get SATA interrupt number */
irq = irq_of_parse_and_map(np, 0);
if (!irq) {
dev_err(dev, "no SATA DMA irq\n");
return -ENODEV;
}
irq = platform_get_irq(ofdev, 0);
if (irq < 0)
return irq;
#ifdef CONFIG_SATA_DWC_OLD_DMA
if (!of_property_present(np, "dmas")) {
if (!of_property_present(dev->of_node, "dmas")) {
err = sata_dwc_dma_init_old(ofdev, hsdev);
if (err)
return err;
@ -1204,6 +1188,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
if (err)
dev_err(dev, "failed to activate host");
/* Enable SATA Interrupts */
sata_dwc_enable_interrupts(hsdev);
return 0;
error_out: