From nobody Thu Oct 2 19:30:10 2025 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (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 745EB27D771 for ; Fri, 12 Sep 2025 23:09:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757718596; cv=none; b=WMw2plzI4kss7RPDpW4d1EFUBBQ0jIv3aqxCqR+Anr3UIiRoP+gw6un8pLcgSf+gHiUIMU5/+RvBZkz2FtUPfhYef9DUDOK4P7N9JOzYhW9H9XBhUQpz+Oop5QJmKHsEPIjw2iVvm9eK5R4ZEdHfWIiUQ4dOQd4vCjS+wVyWMpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757718596; c=relaxed/simple; bh=sXvBWDb9hTBPsLaRegbOtBiO673LvoBjYekcWqme0qY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KFt1tI1tY4tNiCjqjen7I0A1LNDc0lObLR0r5LKIITR31QAAQ47UEFY5+Zj1HJYjdvSNnxW9khvoBbG86R274Bi2CC6LskihYJK5/osrMxsFQOdQdE0kbjoHjr0eng6PlKZ/TBBoY0duIr6kFSu4X0Rrf7i4Oegb+wvvatTos3Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=A5EqVE9p; arc=none smtp.client-ip=209.85.210.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="A5EqVE9p" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-76e4f2e4c40so2220337b3a.2 for ; Fri, 12 Sep 2025 16:09:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1757718594; x=1758323394; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3dwNY0wU9h+Jp/qHmj3QCzMa4YfF1MmR36mm3/7OnW8=; b=A5EqVE9pmugzFbDWRw9h5yEqB1aD+F0NpX/kb+FCZLiOR8ng8+zTLThkd6E99KifsL oGgKnE62y6iDS+uoxPXQTFMLKbajfOcFmT/qg6H3cIj349iifoNMkK+dVjdrx//e6/Wu gbsBm1UaHa3qcZuVb5w8WUXEYHhW+FpMGu0tI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757718594; x=1758323394; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3dwNY0wU9h+Jp/qHmj3QCzMa4YfF1MmR36mm3/7OnW8=; b=Y9iaLpyFijAZ9ER9Nc09rRzP6DlhXBjPy/JcL29R4FRYBVzB4SKJLvgyWSdwHd8pNe nHc+MC0As3hj+dpL2ajMZYfeN2nGZ5r2UDd77b3ZSoVXpy5chbdd5bVu1/D+xD3ngG5d d7uj/mKcJ37eImOBtyvX1qOKRiFe2t70TYV96YX+efj4qaMfoBk9Jcpt81cnHJl87ntI EMVkZ7seY0kl8wMlvY8XgEmZju1aPRLVaN+E+Co9L5rtd6FpxUmgtmSM156CEXRy//Kj BGlZynYa6BGSyapnwQI6ouLD3nGoWSgKdCngAmAAogNbND6EQmpGMf47K8vOOnErpJMT CQbQ== X-Forwarded-Encrypted: i=1; AJvYcCUedRwvBQzhZBSML5jQsAwETtg6vh5GEzVWaGp5lPS75uMwSqTPC8H92j7K1isqnxRzQoiVrmSiwZzOSzM=@vger.kernel.org X-Gm-Message-State: AOJu0Ywuew1QJsTQEwW9fimJz83r9s11bUm0yhFFXrivAImdtVLSOb2s dAEfLkXvXsjzuJ6rPSJCBNgHKUcq5x3+H/hAPrqm3N8wPz8exaKYhcU5Ht+VlVkQ3w== X-Gm-Gg: ASbGncvMfHxCKeMOn6Jhllaq2VJ2qEurRr4XvcS15eZSSxF+Rsu4+mKSRRgX9Wwvp1D ApQatVKuC47gJ9HbaMhVedksiI2fzCZJEWak/G55z9YcHtvH/fNhrBjkkyUaBw7T61fkgtfrBD7 uv9MI1gysp/gyy6YSBuIaGQnzTwVNJ2jt4eVjPeIGu14ekmJcOFI5Qqp8XEyWr+xSqovqA4osrc U4zZwtfJ2QTQ2WqeTB/Mz0VahkxOf1MKswU4//mY3C1bRPiXj1vsJbZ5/M8bP+dnlS5desZiwxg UcZQ2kLJ8fr+hpMsRGkjgzIAGztS5/sn4qW2heKegLxdFQzESzNxG9RHmL6qFwdx6F4cUC2KuDk /xmHDS+yP/tDbCTX+dIOMpRXDMAleJF4rnqSIdGRyq8M50J2Qf3x1llq8JQQ= X-Google-Smtp-Source: AGHT+IFFuttMHqLS1NzNjjaUsptJHeOjOLiy3J4IGiKbJXBfuhvPakuAU9nJRFZCTzUYWTGc4g8XAg== X-Received: by 2002:a05:6a21:339c:b0:244:21:b477 with SMTP id adf61e73a8af0-2602a59371fmr5525527637.16.1757718593795; Fri, 12 Sep 2025 16:09:53 -0700 (PDT) Received: from localhost ([2a00:79e0:2e14:7:e464:c3f:39d8:1bab]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-77607c473b9sm6643028b3a.93.2025.09.12.16.09.52 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 12 Sep 2025 16:09:53 -0700 (PDT) From: Brian Norris To: Bjorn Helgaas , Luis Chamberlain , Petr Pavlu , Daniel Gomez Cc: linux-pci@vger.kernel.org, David Gow , Rae Moar , linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, Johannes Berg , Sami Tolvanen , Richard Weinberger , Wei Liu , Brendan Higgins , kunit-dev@googlegroups.com, Anton Ivanov , linux-um@lists.infradead.org, Brian Norris Subject: [PATCH 1/4] PCI: Support FIXUP quirks in modules Date: Fri, 12 Sep 2025 15:59:32 -0700 Message-ID: <20250912230208.967129-2-briannorris@chromium.org> X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog In-Reply-To: <20250912230208.967129-1-briannorris@chromium.org> References: <20250912230208.967129-1-briannorris@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The PCI framework supports "quirks" for PCI devices via several DECLARE_PCI_FIXUP_*() macros. These macros allow arch or driver code to match device IDs to provide customizations or workarounds for broken devices. This mechanism is generally used in code that can only be built into the kernel, but there are a few occasions where this mechanism is used in drivers that can be modules. For example, see commit 574f29036fce ("PCI: iproc: Apply quirk_paxc_bridge() for module as well as built-in"). The PCI fixup mechanism only works for built-in code, however, because pci_fixup_device() only scans the ".pci_fixup_*" linker sections found in the main kernel; it never touches modules. Extend the fixup approach to modules. I don't attempt to be clever here; the algorithm here scales with the number of modules in the system. Signed-off-by: Brian Norris --- drivers/pci/quirks.c | 62 ++++++++++++++++++++++++++++++++++++++++++ include/linux/module.h | 18 ++++++++++++ kernel/module/main.c | 26 ++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d97335a40193..db5e0ac82ed7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -207,6 +207,62 @@ extern struct pci_fixup __end_pci_fixups_suspend_late[= ]; =20 static bool pci_apply_fixup_final_quirks; =20 +struct pci_fixup_arg { + struct pci_dev *dev; + enum pci_fixup_pass pass; +}; + +static int pci_module_fixup(struct module *mod, void *parm) +{ + struct pci_fixup_arg *arg =3D parm; + void *start; + unsigned int size; + + switch (arg->pass) { + case pci_fixup_early: + start =3D mod->pci_fixup_early; + size =3D mod->pci_fixup_early_size; + break; + case pci_fixup_header: + start =3D mod->pci_fixup_header; + size =3D mod->pci_fixup_header_size; + break; + case pci_fixup_final: + start =3D mod->pci_fixup_final; + size =3D mod->pci_fixup_final_size; + break; + case pci_fixup_enable: + start =3D mod->pci_fixup_enable; + size =3D mod->pci_fixup_enable_size; + break; + case pci_fixup_resume: + start =3D mod->pci_fixup_resume; + size =3D mod->pci_fixup_resume_size; + break; + case pci_fixup_suspend: + start =3D mod->pci_fixup_suspend; + size =3D mod->pci_fixup_suspend_size; + break; + case pci_fixup_resume_early: + start =3D mod->pci_fixup_resume_early; + size =3D mod->pci_fixup_resume_early_size; + break; + case pci_fixup_suspend_late: + start =3D mod->pci_fixup_suspend_late; + size =3D mod->pci_fixup_suspend_late_size; + break; + default: + return 0; + } + + if (!size) + return 0; + + pci_do_fixups(arg->dev, start, start + size); + + return 0; +} + void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { struct pci_fixup *start, *end; @@ -259,6 +315,12 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct= pci_dev *dev) return; } pci_do_fixups(dev, start, end); + + struct pci_fixup_arg arg =3D { + .dev =3D dev, + .pass =3D pass, + }; + module_for_each_mod(pci_module_fixup, &arg); } EXPORT_SYMBOL(pci_fixup_device); =20 diff --git a/include/linux/module.h b/include/linux/module.h index 3319a5269d28..7faa8987b9eb 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -539,6 +539,24 @@ struct module { int num_kunit_suites; struct kunit_suite **kunit_suites; #endif +#ifdef CONFIG_PCI_QUIRKS + void *pci_fixup_early; + unsigned int pci_fixup_early_size; + void *pci_fixup_header; + unsigned int pci_fixup_header_size; + void *pci_fixup_final; + unsigned int pci_fixup_final_size; + void *pci_fixup_enable; + unsigned int pci_fixup_enable_size; + void *pci_fixup_resume; + unsigned int pci_fixup_resume_size; + void *pci_fixup_suspend; + unsigned int pci_fixup_suspend_size; + void *pci_fixup_resume_early; + unsigned int pci_fixup_resume_early_size; + void *pci_fixup_suspend_late; + unsigned int pci_fixup_suspend_late_size; +#endif =20 =20 #ifdef CONFIG_LIVEPATCH diff --git a/kernel/module/main.c b/kernel/module/main.c index c66b26184936..50a80c875adc 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2702,6 +2702,32 @@ static int find_module_sections(struct module *mod, = struct load_info *info) sizeof(*mod->kunit_init_suites), &mod->num_kunit_init_suites); #endif +#ifdef CONFIG_PCI_QUIRKS + mod->pci_fixup_early =3D section_objs(info, ".pci_fixup_early", + sizeof(*mod->pci_fixup_early), + &mod->pci_fixup_early_size); + mod->pci_fixup_header =3D section_objs(info, ".pci_fixup_header", + sizeof(*mod->pci_fixup_header), + &mod->pci_fixup_header_size); + mod->pci_fixup_final =3D section_objs(info, ".pci_fixup_final", + sizeof(*mod->pci_fixup_final), + &mod->pci_fixup_final_size); + mod->pci_fixup_enable =3D section_objs(info, ".pci_fixup_enable", + sizeof(*mod->pci_fixup_enable), + &mod->pci_fixup_enable_size); + mod->pci_fixup_resume =3D section_objs(info, ".pci_fixup_resume", + sizeof(*mod->pci_fixup_resume), + &mod->pci_fixup_resume_size); + mod->pci_fixup_suspend =3D section_objs(info, ".pci_fixup_suspend", + sizeof(*mod->pci_fixup_suspend), + &mod->pci_fixup_suspend_size); + mod->pci_fixup_resume_early =3D section_objs(info, ".pci_fixup_resume_ear= ly", + sizeof(*mod->pci_fixup_resume_early), + &mod->pci_fixup_resume_early_size); + mod->pci_fixup_suspend_late =3D section_objs(info, ".pci_fixup_suspend_la= te", + sizeof(*mod->pci_fixup_suspend_late), + &mod->pci_fixup_suspend_late_size); +#endif =20 mod->extable =3D section_objs(info, "__ex_table", sizeof(*mod->extable), &mod->num_exentries); --=20 2.51.0.384.g4c02a37b29-goog