Commit 665745f2 authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by Bjorn Helgaas
Browse files

PCI/bwctrl: Re-add BW notification portdrv as PCIe BW controller

This mostly reverts the commit b4c7d207 ("PCI/LINK: Remove bandwidth
notification"). An upcoming commit extends this driver building PCIe
bandwidth controller on top of it.

PCIe bandwidth notifications were first added in the commit e8303bb7
("PCI/LINK: Report degraded links via link bandwidth notification") but
later had to be removed. The significant changes compared with the old
bandwidth notification driver include:

1) Don't print the notifications into kernel log, just keep the Link
   Speed cached in struct pci_bus updated. While somewhat unfortunate,
   the log spam was the source of complaints that eventually lead to
   the removal of the bandwidth notifications driver (see the links
   below for further information).

2) Besides the Link Bandwidth Management Interrupt, also enable Link
   Autonomous Bandwidth Interrupt to cover the other source of bandwidth
   changes.

3) Handle Link Speed updates robustly. Refresh the cached Link Speed
   when enabling Bandwidth Notification Interrupts, and solve the race
   between Link Speed read and LBMS/LABS update in
   pcie_bwnotif_irq_thread().

4) Use concurrency safe LNKCTL RMW operations.

5) The driver is now called PCIe bwctrl (bandwidth controller) instead
   of just bandwidth notifications because of increased scope and
   functionality within the driver.

6) Coexist with the Target Link Speed quirk in pcie_failed_link_retrain().
   Provide LBMS counting API for it.

7) Tweaks to variable/functions names for consistency and length reasons.

Bandwidth Notifications enable the cur_bus_speed in the struct pci_bus to
keep track PCIe Link Speed changes.

[bhelgaas: This is based on previous work by Alexandru Gagniuc
<mr.nuke.me@gmail.com>; see e8303bb7 ("PCI/LINK: Report degraded links
via link bandwidth notification")]

Link: https://lore.kernel.org/r/20241018144755.7875-7-ilpo.jarvinen@linux.intel.com
Link: https://lore.kernel.org/all/20190429185611.121751-1-helgaas@kernel.org/
Link: https://lore.kernel.org/linux-pci/20190501142942.26972-1-keith.busch@intel.com/
Link: https://lore.kernel.org/linux-pci/20200115221008.GA191037@google.com/


Suggested-by: Lukas Wunner <lukas@wunner.de> # Building bwctrl on top of bwnotif
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
[bhelgaas: squash fix to drop IRQF_ONESHOT and convert to hardirq handler:
https://lore.kernel.org/r/20241115165717.15233-1-ilpo.jarvinen@linux.intel.com

]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Tested-by: default avatarStefan Wahren <wahrenst@gmx.net>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 3491f509
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -17933,6 +17933,12 @@ F: include/linux/of_pci.h
F:	include/linux/pci*
F:	include/uapi/linux/pci*
PCIE BANDWIDTH CONTROLLER
M:	Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
L:	linux-pci@vger.kernel.org
S:	Supported
F:	drivers/pci/pcie/bwctrl.c
PCIE DRIVER FOR AMAZON ANNAPURNA LABS
M:	Jonathan Chocron <jonnyc@amazon.com>
L:	linux-pci@vger.kernel.org
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#include <linux/types.h>
#include <linux/pm_runtime.h>
#include <linux/pci.h>

#include "../pci.h"
#include "pciehp.h"

/* The following routines constitute the bulk of the
@@ -127,6 +129,9 @@ static void remove_board(struct controller *ctrl, bool safe_removal)

	pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
			      INDICATOR_NOOP);

	/* Don't carry LBMS indications across */
	pcie_reset_lbms_count(ctrl->pcie->port);
}

static int pciehp_enable_slot(struct controller *ctrl);
+1 −1
Original line number Diff line number Diff line
@@ -4740,7 +4740,7 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
	 * to track link speed or width changes made by hardware itself
	 * in attempt to correct unreliable link operation.
	 */
	pcie_capability_write_word(pdev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS);
	pcie_reset_lbms_count(pdev);
	return rc;
}

+11 −0
Original line number Diff line number Diff line
@@ -698,6 +698,17 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
static inline void pcie_ecrc_get_policy(char *str) { }
#endif

#ifdef CONFIG_PCIEPORTBUS
void pcie_reset_lbms_count(struct pci_dev *port);
int pcie_lbms_count(struct pci_dev *port, unsigned long *val);
#else
static inline void pcie_reset_lbms_count(struct pci_dev *port) {}
static inline int pcie_lbms_count(struct pci_dev *port, unsigned long *val)
{
	return -EOPNOTSUPP;
}
#endif

struct pci_dev_reset_methods {
	u16 vendor;
	u16 device;
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

pcieportdrv-y			:= portdrv.o rcec.o

obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o bwctrl.o

obj-y				+= aspm.o
obj-$(CONFIG_PCIEAER)		+= aer.o err.o
Loading