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

Commit a63ab613 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/gavin-window-alignment' into next

* pci/gavin-window-alignment:
  powerpc/powernv: I/O and memory alignment for P2P bridges
  powerpc/PCI: Override pcibios_window_alignment()
  PCI: Refactor pbus_size_mem()
  PCI: Align P2P windows using pcibios_window_alignment()
  PCI: Add weak pcibios_window_alignment() interface
parents a690a4cb 271fd03a
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -214,6 +214,9 @@ struct machdep_calls {
	/* Called after scan and before resource survey */
	/* Called after scan and before resource survey */
	void (*pcibios_fixup_phb)(struct pci_controller *hose);
	void (*pcibios_fixup_phb)(struct pci_controller *hose);


	/* Called during PCI resource reassignment */
	resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type);

	/* Called to shutdown machine specific hardware not already controlled
	/* Called to shutdown machine specific hardware not already controlled
	 * by other drivers.
	 * by other drivers.
	 */
	 */
+20 −0
Original line number Original line Diff line number Diff line
@@ -99,6 +99,26 @@ void pcibios_free_controller(struct pci_controller *phb)
		kfree(phb);
		kfree(phb);
}
}


/*
 * The function is used to return the minimal alignment
 * for memory or I/O windows of the associated P2P bridge.
 * By default, 4KiB alignment for I/O windows and 1MiB for
 * memory windows.
 */
resource_size_t pcibios_window_alignment(struct pci_bus *bus,
					 unsigned long type)
{
	if (ppc_md.pcibios_window_alignment)
		return ppc_md.pcibios_window_alignment(bus, type);

	/*
	 * PCI core will figure out the default
	 * alignment: 4KiB for I/O and 1MiB for
	 * memory window.
	 */
	return 1;
}

static resource_size_t pcibios_io_size(const struct pci_controller *hose)
static resource_size_t pcibios_io_size(const struct pci_controller *hose)
{
{
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
+39 −0
Original line number Original line Diff line number Diff line
@@ -1139,6 +1139,44 @@ static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose)
	}
	}
}
}


/*
 * Returns the alignment for I/O or memory windows for P2P
 * bridges. That actually depends on how PEs are segmented.
 * For now, we return I/O or M32 segment size for PE sensitive
 * P2P bridges. Otherwise, the default values (4KiB for I/O,
 * 1MiB for memory) will be returned.
 *
 * The current PCI bus might be put into one PE, which was
 * create against the parent PCI bridge. For that case, we
 * needn't enlarge the alignment so that we can save some
 * resources.
 */
static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
						unsigned long type)
{
	struct pci_dev *bridge;
	struct pci_controller *hose = pci_bus_to_host(bus);
	struct pnv_phb *phb = hose->private_data;
	int num_pci_bridges = 0;

	bridge = bus->self;
	while (bridge) {
		if (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) {
			num_pci_bridges++;
			if (num_pci_bridges >= 2)
				return 1;
		}

		bridge = bridge->bus->self;
	}

	/* We need support prefetchable memory window later */
	if (type & IORESOURCE_MEM)
		return phb->ioda.m32_segsize;

	return phb->ioda.io_segsize;
}

/* Prevent enabling devices for which we couldn't properly
/* Prevent enabling devices for which we couldn't properly
 * assign a PE
 * assign a PE
 */
 */
@@ -1306,6 +1344,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
	 */
	 */
	ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb;
	ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb;
	ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
	ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
	ppc_md.pcibios_window_alignment = pnv_pci_window_alignment;
	pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC);
	pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC);


	/* Reset IODA tables to a clean state */
	/* Reset IODA tables to a clean state */
+60 −21
Original line number Original line Diff line number Diff line
@@ -697,6 +697,38 @@ static resource_size_t calculate_memsize(resource_size_t size,
	return size;
	return size;
}
}


resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
						unsigned long type)
{
	return 1;
}

#define PCI_P2P_DEFAULT_MEM_ALIGN	0x100000	/* 1MiB */
#define PCI_P2P_DEFAULT_IO_ALIGN	0x1000		/* 4KiB */
#define PCI_P2P_DEFAULT_IO_ALIGN_1K	0x400		/* 1KiB */

static resource_size_t window_alignment(struct pci_bus *bus,
					unsigned long type)
{
	resource_size_t align = 1, arch_align;

	if (type & IORESOURCE_MEM)
		align = PCI_P2P_DEFAULT_MEM_ALIGN;
	else if (type & IORESOURCE_IO) {
		/*
		 * Per spec, I/O windows are 4K-aligned, but some
		 * bridges have an extension to support 1K alignment.
		 */
		if (bus->self->io_window_1k)
			align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
		else
			align = PCI_P2P_DEFAULT_IO_ALIGN;
	}

	arch_align = pcibios_window_alignment(bus, type);
	return max(align, arch_align);
}

/**
/**
 * pbus_size_io() - size the io window of a given bus
 * pbus_size_io() - size the io window of a given bus
 *
 *
@@ -717,17 +749,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
	unsigned long size = 0, size0 = 0, size1 = 0;
	unsigned long size = 0, size0 = 0, size1 = 0;
	resource_size_t children_add_size = 0;
	resource_size_t children_add_size = 0;
	resource_size_t min_align = 4096, align;
	resource_size_t min_align, io_align, align;


	if (!b_res)
	if (!b_res)
 		return;
 		return;


	/*
	io_align = min_align = window_alignment(bus, IORESOURCE_IO);
	 * Per spec, I/O windows are 4K-aligned, but some bridges have an
	 * extension to support 1K alignment.
	 */
	if (bus->self->io_window_1k)
		min_align = 1024;
	list_for_each_entry(dev, &bus->devices, bus_list) {
	list_for_each_entry(dev, &bus->devices, bus_list) {
		int i;
		int i;


@@ -754,8 +781,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
		}
		}
	}
	}


	if (min_align > 4096)
	if (min_align > io_align)
		min_align = 4096;
		min_align = io_align;


	size0 = calculate_iosize(size, min_size, size1,
	size0 = calculate_iosize(size, min_size, size1,
			resource_size(b_res), min_align);
			resource_size(b_res), min_align);
@@ -785,6 +812,28 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
	}
	}
}
}


static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
						  int max_order)
{
	resource_size_t align = 0;
	resource_size_t min_align = 0;
	int order;

	for (order = 0; order <= max_order; order++) {
		resource_size_t align1 = 1;

		align1 <<= (order + 20);

		if (!align)
			min_align = align1;
		else if (ALIGN(align + min_align, min_align) < align1)
			min_align = align1 >> 1;
		align += aligns[order];
	}

	return min_align;
}

/**
/**
 * pbus_size_mem() - size the memory window of a given bus
 * pbus_size_mem() - size the memory window of a given bus
 *
 *
@@ -864,19 +913,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
				children_add_size += get_res_add_size(realloc_head, r);
				children_add_size += get_res_add_size(realloc_head, r);
		}
		}
	}
	}
	align = 0;
	min_align = 0;
	for (order = 0; order <= max_order; order++) {
		resource_size_t align1 = 1;


		align1 <<= (order + 20);
	min_align = calculate_mem_align(aligns, max_order);

	min_align = max(min_align, window_alignment(bus, b_res->flags & mask));
		if (!align)
			min_align = align1;
		else if (ALIGN(align + min_align, min_align) < align1)
			min_align = align1 >> 1;
		align += aligns[order];
	}
	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
	if (children_add_size > add_size)
	if (children_add_size > add_size)
		add_size = children_add_size;
		add_size = children_add_size;
+2 −0
Original line number Original line Diff line number Diff line
@@ -1061,6 +1061,8 @@ int pci_cfg_space_size_ext(struct pci_dev *dev);
int pci_cfg_space_size(struct pci_dev *dev);
int pci_cfg_space_size(struct pci_dev *dev);
unsigned char pci_bus_max_busnr(struct pci_bus *bus);
unsigned char pci_bus_max_busnr(struct pci_bus *bus);
void pci_setup_bridge(struct pci_bus *bus);
void pci_setup_bridge(struct pci_bus *bus);
resource_size_t pcibios_window_alignment(struct pci_bus *bus,
					 unsigned long type);


#define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0)
#define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0)
#define PCI_VGA_STATE_CHANGE_DECODES (1 << 1)
#define PCI_VGA_STATE_CHANGE_DECODES (1 << 1)