Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9936328b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull PCI fixes from Bjorn Helgaas:
 "PCI fixes:

   - Clear level-triggered interrupts for the bandwidth notification
     supported added for v5.1 (Alexandru Gagniuc)

   - Clear bandwidth notification interrupts before enabling them (Lukas
     Wunner)

   - Report post-enumeration bandwidth changes only once for
     multi-function devices (Lukas Wunner)"

* tag 'pci-v5.1-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  PCI/LINK: Deduplicate bandwidth reports for multi-function devices
  PCI/LINK: Clear bandwidth notification interrupt before enabling it
  PCI/LINK: Supply IRQ handler so level-triggered IRQs are acked
parents 8c7ae38d 0fa635ae
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev);
u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed,
			   enum pcie_link_width *width);
void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
void pcie_report_downtraining(struct pci_dev *dev);

/* Single Root I/O Virtualization */
struct pci_sriov {
+17 −6
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ static void pcie_enable_link_bandwidth_notification(struct pci_dev *dev)
{
	u16 lnk_ctl;

	pcie_capability_write_word(dev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS);

	pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &lnk_ctl);
	lnk_ctl |= PCI_EXP_LNKCTL_LBMIE;
	pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnk_ctl);
@@ -44,11 +46,10 @@ static void pcie_disable_link_bandwidth_notification(struct pci_dev *dev)
	pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnk_ctl);
}

static irqreturn_t pcie_bw_notification_handler(int irq, void *context)
static irqreturn_t pcie_bw_notification_irq(int irq, void *context)
{
	struct pcie_device *srv = context;
	struct pci_dev *port = srv->port;
	struct pci_dev *dev;
	u16 link_status, events;
	int ret;

@@ -58,17 +59,26 @@ static irqreturn_t pcie_bw_notification_handler(int irq, void *context)
	if (ret != PCIBIOS_SUCCESSFUL || !events)
		return IRQ_NONE;

	pcie_capability_write_word(port, PCI_EXP_LNKSTA, events);
	pcie_update_link_speed(port->subordinate, link_status);
	return IRQ_WAKE_THREAD;
}

static irqreturn_t pcie_bw_notification_handler(int irq, void *context)
{
	struct pcie_device *srv = context;
	struct pci_dev *port = srv->port;
	struct pci_dev *dev;

	/*
	 * Print status from downstream devices, not this root port or
	 * downstream switch port.
	 */
	down_read(&pci_bus_sem);
	list_for_each_entry(dev, &port->subordinate->devices, bus_list)
		__pcie_print_link_status(dev, false);
		pcie_report_downtraining(dev);
	up_read(&pci_bus_sem);

	pcie_update_link_speed(port->subordinate, link_status);
	pcie_capability_write_word(port, PCI_EXP_LNKSTA, events);
	return IRQ_HANDLED;
}

@@ -80,7 +90,8 @@ static int pcie_bandwidth_notification_probe(struct pcie_device *srv)
	if (!pcie_link_bandwidth_notification_supported(srv->port))
		return -ENODEV;

	ret = request_threaded_irq(srv->irq, NULL, pcie_bw_notification_handler,
	ret = request_threaded_irq(srv->irq, pcie_bw_notification_irq,
				   pcie_bw_notification_handler,
				   IRQF_SHARED, "PCIe BW notif", srv);
	if (ret)
		return ret;
+1 −1
Original line number Diff line number Diff line
@@ -2388,7 +2388,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
	return dev;
}

static void pcie_report_downtraining(struct pci_dev *dev)
void pcie_report_downtraining(struct pci_dev *dev)
{
	if (!pci_is_pcie(dev))
		return;