FAILED: patch "[PATCH] PCI: Restore original INTX_DISABLE bit by pcim_intx()" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x d555ed45a5a10a813528c7685f432369d536ae3d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025021022-broadness-afflicted-47d6@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d555ed45a5a10a813528c7685f432369d536ae3d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <[email protected]>
Date: Thu, 31 Oct 2024 14:42:56 +0100
Subject: [PATCH] PCI: Restore original INTX_DISABLE bit by pcim_intx()
pcim_intx() tries to restore the INTx bit at removal via devres, but there is a chance that it restores a wrong value.
Because the value to be restored is blindly assumed to be the negative of the enable argument, when a driver calls pcim_intx() unnecessarily for the already enabled state, it'll restore to the disabled state in turn. That is, the function assumes the case like:
// INTx == 1
pcim_intx(pdev, 0); // old INTx value assumed to be 1 -> correct
but it might be like the following, too:
// INTx == 0
pcim_intx(pdev, 0); // old INTx value assumed to be 1 -> wrong
Also, when a driver calls pcim_intx() multiple times with different enable argument values, the last one will win no matter what value it is. This can lead to inconsistency, e.g.
// INTx == 1
pcim_intx(pdev, 0); // OK
...
pcim_intx(pdev, 1); // now old INTx wrongly assumed to be 0
This patch addresses those inconsistencies by saving the original INTx state at the first pcim_intx() call. For that, get_or_create_intx_devres() is folded into pcim_intx() caller side; it allows us to simply check the already allocated devres and record the original INTx along with the devres_alloc() call.
drivers/pci/devres.c +19 -15
@@ -419,19 +419,12 @@ static void pcim_intx_restore(struct device *dev, void *data)pci_intx (pdev, res->orig_intx); } -static struct pcim_intx_devres *get_or_create_intx_devres (struct device *dev) +static void save_orig_intx (struct pci_dev *pdev,struct pcim_intx_devres *res) { -struct pcim_intx_devres *res; +u16 pci_command; - res =devres_find (dev, pcim_intx_restore,NULL ,NULL ); -if (res) -return res; - - res =devres_alloc (pcim_intx_restore,sizeof (*res),GFP_KERNEL ); -if (res) -devres_add (dev, res); - -return res; +pci_read_config_word (pdev,PCI_COMMAND , &pci_command); + res->orig_intx = !(pci_command &PCI_COMMAND_INTX_DISABLE ); }/**
@@ -447,12 +440,23 @@ static struct pcim_intx_devres *get_or_create_intx_devres(struct device *dev)int pcim_intx (struct pci_dev *pdev,int enable) {struct pcim_intx_devres *res; +struct device *dev = &pdev->dev; - res =get_or_create_intx_devres (&pdev->dev); -if (!res) -return -ENOMEM ; +/* +* pcim_intx() must only restore the INTx value that existed before the +* driver was loaded, i.e., before it called pcim_intx() for the +* first time. +*/ + res =devres_find (dev, pcim_intx_restore,NULL ,NULL ); +if (!res) { + res =devres_alloc (pcim_intx_restore,sizeof (*res),GFP_KERNEL ); +if (!res) +return -ENOMEM ; + +save_orig_intx (pdev, res); +devres_add (dev, res); + } - res->orig_intx = !enable;pci_intx (pdev, enable);return 0 ;