From nobody Thu Apr 2 14:10:31 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 652BE331A57 for ; Fri, 27 Mar 2026 21:17:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774646222; cv=none; b=SMW1hK+q9RnjYLvhqoulWrLtYnAUJ/QJ0yVu6NtWjydmFEE39d6RpwbMPApoSQ+IEx86iO7L5zUeSh+Y/urH8n1AEkGi6a/cBI3HSa3ho+/mBAGpG4P2S8vBlx74NjIaQlghvwvMSgoT4VxI+WzxC8I1yoesN10BDO/uU3dtPYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774646222; c=relaxed/simple; bh=GsELgrNxz8NysXFVGpuJJb49OBemyS6+o7WjbjUqBrQ=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=ZAad4l8fnjiMN9RkDoZG3AI9f20H3CZNU2iibHxIJTYMF7cWGBDvYtm2fjJXzYw47MipXx6vQwjNSTJgGpBNcO8ZiaSHKgaUfRaHh1DMH5ZFD4OZ//SSdoz3JCi5KyJI9dMTjaxkKJNpKKjuh7ZqXIWmS+rSYI0Et/NQFO1RVv4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=jerDzyr8; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jerDzyr8" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-35c0bd3a968so2508438a91.0 for ; Fri, 27 Mar 2026 14:17:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774646220; x=1775251020; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=trO8rmzZPr0RQOymFCLZQOIxeJZ/gPQu+3jTXW69zB0=; b=jerDzyr8g1/PV3aJWcODRsQNtUbIg8oGt2n+6fr8SH6Hf8BPdCZwNUQ1aMMPtfdEyK FyEfAqAUbYaBZ6yztd/MscakCNR0Z1QGP1oLXmtDtQziASzCawx+zUHo9PqfatBj69+w Z+S6UNVtM3BeOLmLFuohDBrlLg0CgfvlB13yOGzEYTSHnL7Ccnklv6gW6eFQq2MiyV3h iYu060dZls0BwXizp3cpCrk6qg7sXTJkzF7kDe16idjvX5vNFXcmFablAcFQ+HN7UZ6B EbsObRyCDPbh6dk3X/EO9nu0QC9tqsKgWO8+ZNeo+wz161l1iqv+l049BLOmh9SZUIvL fkbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774646220; x=1775251020; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=trO8rmzZPr0RQOymFCLZQOIxeJZ/gPQu+3jTXW69zB0=; b=jbR+VxHhiPewpiZmNBZBJ1bibFNNsE/lSYugUbVWdf+91NT95SrH8emq5WPraA3GJa UlsqxVk8u1DZE9ZWIpR7NedSlnKkGEaLn7VpT7faexK1J1cmjmTAD3lrZt/yFp5JV0i3 cR1Lj7AWteID63qPdxWhl1YeiYPBx6NikRM2sEi2Db3yy7qTLHxkIBHYMe8TgH9DlpJ7 Ayg92QZDYnbvCmsvy/OR77U7lBQy2DsYofR68KKkTXQicOaoScgs5T+7EvKwvNkUqkd1 poVBQS1SLXuOIEr9f/GB42wLHGY2GQN07MB/adVuSpATK4p3t74Eudfd7m3BE0Y1N2VB 0/pg== X-Forwarded-Encrypted: i=1; AJvYcCVi/Mp/0uUOfJxCDRQXT9EKLz22KInEz35mijmWlVefu8iyTCtvg58B2wqSbj4Ona3egD+F+327g1pylak=@vger.kernel.org X-Gm-Message-State: AOJu0YzhWhRGfuQdb64fuDkbxUcDC9azTdqVKi3/Qcrzda6/PPeJsDRd GdP+7ChE+1G8kYnQrPwOT4P267r+rp6LaruHrGo2SalQ7llKdB0INpFjg6XolA5aLhbZg3k3tCR V3qwdyuc1P5V9pg== X-Received: from pjbpv14.prod.google.com ([2002:a17:90b:3c8e:b0:35c:2b6d:7890]) (user=dmatlack job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4cc6:b0:35b:e4f8:7cb0 with SMTP id 98e67ed59e1d1-35c300c19c4mr3887836a91.21.1774646220375; Fri, 27 Mar 2026 14:17:00 -0700 (PDT) Date: Fri, 27 Mar 2026 21:16:40 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327211649.3816010-1-dmatlack@google.com> Subject: [PATCH v2] PCI: Disable ATS via quirk before notifying IOMMU drivers From: David Matlack To: Bjorn Helgaas Cc: Alexander Lobakin , Andy Shevchenko , Bartosz Pawlowski , David Woodhouse , linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, Lu Baolu , Raghavendra Rao Ananta , David Matlack Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Ensure that PCI devices with ATS disabled via quirk have it disabled before IOMMU drivers are notified about the device rather than after. Fix this by converting the existing quirks from final to early fixups and changing the quirk logic to set a new no_ats bit in struct pci_dev that prevents pci_dev.ats_cap from ever gettting set. This change ensures that pci_ats_supported() takes quirks into account during iommu_ops.probe_device(), when IOMMU drivers are first notified about devices. It also ensures that pci_ats_supported() returns the same value when the device is released in iommu_ops.release_device(). Notably, the Intel IOMMU driver uses pci_ats_supported() in probe/release to determine whether to add/remove a device from a data structure, which easily leads to a use-after-free without this fix. This change also makes disabling ATS via quirk behave the same way as the pci=3Dnoats command line option, in that pci_ats_init() bails immediately and never intializes pci_dev.ats_cap. Fixes: a18615b1cfc0 ("PCI: Disable ATS for specific Intel IPU E2000 devices= ") Closes: https://lore.kernel.org/linux-iommu/aYUQ_HkDJU9kjsUl@google.com/ Signed-off-by: David Matlack --- v2: - Update the commit message with reasons why this is being fixed in the PCI core, rather than applying a point fix to the Intel IOMMU driver (Andy) - Condense the pci_ats_disabled() and dev->no_ats checks into a single line in pci_ats_init() - Reorder the no_ats bitfield to be after ats_stu since there is likely u8-sized gap there for alignment purposes v1: https://lore.kernel.org/linux-pci/20260223184017.688212-1-dmatlack@goog= le.com/ Cc: Raghavendra Rao Ananta Cc: David Woodhouse Cc: Lu Baolu Cc: Andy Shevchenko drivers/pci/ats.c | 2 +- drivers/pci/quirks.c | 50 ++++++++++++++++++++++---------------------- include/linux/pci.h | 1 + 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index ec6c8dbdc5e9..ceb6f5d3cb10 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -21,7 +21,7 @@ void pci_ats_init(struct pci_dev *dev) { int pos; =20 - if (pci_ats_disabled()) + if (pci_ats_disabled() || dev->no_ats) return; =20 pos =3D pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 48946cca4be7..2c7e11830e45 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -5653,7 +5653,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x= 0422, quirk_no_ext_tags); static void quirk_no_ats(struct pci_dev *pdev) { pci_info(pdev, "disabling ATS\n"); - pdev->ats_cap =3D 0; + pdev->no_ats =3D 1; } =20 /* @@ -5676,25 +5676,25 @@ static void quirk_amd_harvest_no_ats(struct pci_dev= *pdev) } =20 /* AMD Stoney platform GPU */ -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x98e4, quirk_amd_harvest_no_at= s); /* AMD Iceland dGPU */ -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x6900, quirk_amd_harvest_no_at= s); /* AMD Navi10 dGPU */ -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7310, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7312, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7318, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7319, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731a, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731b, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731e, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x731f, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7310, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7312, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7318, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7319, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x731a, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x731b, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x731e, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x731f, quirk_amd_harvest_no_at= s); /* AMD Navi14 dGPU */ -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7340, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7341, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7347, quirk_amd_harvest_no_at= s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x734f, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7340, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7341, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7347, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x734f, quirk_amd_harvest_no_at= s); /* AMD Raven platform iGPU */ -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x15d8, quirk_amd_harvest_no_at= s); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x15d8, quirk_amd_harvest_no_at= s); =20 /* * Intel IPU E2000 revisions before C0 implement incorrect endianness @@ -5705,15 +5705,15 @@ static void quirk_intel_e2000_no_ats(struct pci_dev= *pdev) if (pdev->revision < 0x20) quirk_no_ats(pdev); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1451, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1452, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1453, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1454, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1455, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1457, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1459, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145a, quirk_intel_e2000_no_= ats); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145c, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1451, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1452, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1453, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1454, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1455, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1457, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1459, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x145a, quirk_intel_e2000_no_= ats); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x145c, quirk_intel_e2000_no_= ats); #endif /* CONFIG_PCI_ATS */ =20 /* Freescale PCIe doesn't support MSI in RC mode */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 1c270f1d5123..850100f209e3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -539,6 +539,7 @@ struct pci_dev { }; u16 ats_cap; /* ATS Capability offset */ u8 ats_stu; /* ATS Smallest Translation Unit */ + unsigned int no_ats:1; /* ATS disabled via quirk */ #endif #ifdef CONFIG_PCI_PRI u16 pri_cap; /* PRI Capability offset */ base-commit: 7df48e36313029e4c0907b2023905dd7213fd678 --=20 2.53.0.1018.g2bb0e51243-goog