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

Commit dad32bbf authored by John Rose's avatar John Rose Committed by Paul Mackerras
Browse files

[PATCH] pSeries - read irqs dynamically



For I/O DLPAR to work properly, the kernel needs to allow for dynamic
assignment of the irq field of the pci_dev structure upon dynamic bus
addition.  This patch moves the assignment of that field from
pSeries_final_fixup() to pcibios_fixup_bus(), which enables dynamic
assignment for the children of a newly added bus.

Currently, pci_devs receive their irq numbers in one of two ways.  The
irq line is either read at boot for all pci_devs, or read by the rpaphp
module at slot enable time.  The latter is no longer sufficient for
DLPAR addition of slots that don't qualify as PCI-hotplug capable.
This solution handles the cases of boot and dynamic add.

Signed-off-by: default avatarJohn Rose <johnrose@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 8f586b22
Loading
Loading
Loading
Loading
+20 −15
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@

#include "pci.h"

static int __initdata s7a_workaround;
static int __initdata s7a_workaround = -1;

#if 0
void pcibios_name_device(struct pci_dev *dev)
@@ -65,6 +65,7 @@ static void __init check_s7a(void)
	struct device_node *root;
	char *model;

	s7a_workaround = 0;
	root = of_find_node_by_path("/");
	if (root) {
		model = get_property(root, "model", NULL);
@@ -74,6 +75,24 @@ static void __init check_s7a(void)
	}
}

void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
{
	struct pci_dev *dev;

	if (s7a_workaround < 0)
		check_s7a();
	list_for_each_entry(dev, &bus->devices, bus_list) {
		pci_read_irq_line(dev);
		if (s7a_workaround) {
			if (dev->irq > 16) {
				dev->irq -= 3;
				pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
					dev->irq);
			}
		}
	}
}

static void __init pSeries_request_regions(void)
{
	if (!isa_io_base)
@@ -89,20 +108,6 @@ static void __init pSeries_request_regions(void)

void __init pSeries_final_fixup(void)
{
	struct pci_dev *dev = NULL;

	check_s7a();

	for_each_pci_dev(dev) {
		pci_read_irq_line(dev);
		if (s7a_workaround) {
			if (dev->irq > 16) {
				dev->irq -= 3;
				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
			}
		}
	}

	phbs_remap_io();
	pSeries_request_regions();

+1 −2
Original line number Diff line number Diff line
@@ -71,8 +71,6 @@
#define DBG(fmt...)
#endif

extern void pSeries_final_fixup(void);

extern void find_udbg_vterm(void);
extern void system_reset_fwnmi(void);	/* from head.S */
extern void machine_check_fwnmi(void);	/* from head.S */
@@ -425,6 +423,7 @@ struct machdep_calls __initdata pSeries_md = {
	.get_cpuinfo		= pSeries_get_cpuinfo,
	.log_error		= pSeries_log_error,
	.pcibios_fixup		= pSeries_final_fixup,
	.irq_bus_setup		= pSeries_irq_bus_setup,
	.restart		= rtas_restart,
	.power_off		= rtas_power_off,
	.halt			= rtas_halt,
+3 −0
Original line number Diff line number Diff line
@@ -902,6 +902,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
	list_for_each_entry(dev, &bus->devices, bus_list)
		ppc_md.iommu_dev_setup(dev);

	if (ppc_md.irq_bus_setup)
		ppc_md.irq_bus_setup(bus);

	if (!pci_probe_only)
		return;

+5 −1
Original line number Diff line number Diff line
@@ -40,10 +40,14 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev);
void pci_addr_cache_insert_device(struct pci_dev *dev);
void pci_addr_cache_remove_device(struct pci_dev *dev);

/* From pSeries_pci.h */
/* From rtas_pci.h */
void init_pci_config_tokens (void);
unsigned long get_phb_buid (struct device_node *);

/* From pSeries_pci.h */
extern void pSeries_final_fixup(void);
extern void pSeries_irq_bus_setup(struct pci_bus *bus);

extern unsigned long pci_probe_only;
extern unsigned long pci_assign_all_buses;
extern int pci_read_irq_line(struct pci_dev *pci_dev);
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ struct machdep_calls {
	void		(*tce_flush)(struct iommu_table *tbl);
	void		(*iommu_dev_setup)(struct pci_dev *dev);
	void		(*iommu_bus_setup)(struct pci_bus *bus);
	void		(*irq_bus_setup)(struct pci_bus *bus);

	int		(*probe)(int platform);
	void		(*setup_arch)(void);