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

Commit a4ac9fea authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes
Browse files

PCI : Calculate right add_size



During debug of one SRIOV enabled hotplug device, we found found that
add_size is not passed properly.

The device has devices under two level bridges:

 +-[0000:80]-+-00.0-[81-8f]--
 |           +-01.0-[90-9f]--
 |           +-02.0-[a0-af]----00.0-[a1-a3]--+-02.0-[a2]--+-00.0  Oracle Corporation Device
 |           |                               \-03.0-[a3]--+-00.0  Oracle Corporation Device

Which means later the parent bridge will not try to add a big enough range:

[  557.455077] pci 0000:a0:00.0: BAR 14: assigned [mem 0xf9000000-0xf93fffff]
[  557.461974] pci 0000:a0:00.0: BAR 15: assigned [mem 0xf6000000-0xf61fffff pref]
[  557.469340] pci 0000:a1:02.0: BAR 14: assigned [mem 0xf9000000-0xf91fffff]
[  557.476231] pci 0000:a1:02.0: BAR 15: assigned [mem 0xf6000000-0xf60fffff pref]
[  557.483582] pci 0000:a1:03.0: BAR 14: assigned [mem 0xf9200000-0xf93fffff]
[  557.490468] pci 0000:a1:03.0: BAR 15: assigned [mem 0xf6100000-0xf61fffff pref]
[  557.497833] pci 0000:a1:03.0: BAR 14: can't assign mem (size 0x200000)
[  557.504378] pci 0000:a1:03.0: failed to add optional resources res=[mem 0xf9200000-0xf93fffff]
[  557.513026] pci 0000:a1:02.0: BAR 14: can't assign mem (size 0x200000)
[  557.519578] pci 0000:a1:02.0: failed to add optional resources res=[mem 0xf9000000-0xf91fffff]

It turns out we did not calculate size1 properly.

static resource_size_t calculate_memsize(resource_size_t size,
                resource_size_t min_size,
                resource_size_t size1,
                resource_size_t old_size,
                resource_size_t align)
{
        if (size < min_size)
                size = min_size;
        if (old_size == 1 )
                old_size = 0;
        if (size < old_size)
                size = old_size;
        size = ALIGN(size + size1, align);
        return size;
}

We should not pass add_size with min_size in calculate_memsize since
that will make add_size not contribute final add_size.

So just pass add_size with size1 to calculate_memsize().

With this change, we should have chance to remove extra addon in
pci_reassign_resource.

Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 0dea210b
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -612,7 +612,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
	if (children_add_size > add_size)
	if (children_add_size > add_size)
		add_size = children_add_size;
		add_size = children_add_size;
	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
		calculate_iosize(size, min_size+add_size, size1,
		calculate_iosize(size, min_size, add_size + size1,
			resource_size(b_res), 4096);
			resource_size(b_res), 4096);
	if (!size0 && !size1) {
	if (!size0 && !size1) {
		if (b_res->start || b_res->end)
		if (b_res->start || b_res->end)
@@ -726,7 +726,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
	if (children_add_size > add_size)
	if (children_add_size > add_size)
		add_size = children_add_size;
		add_size = children_add_size;
	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
		calculate_memsize(size, min_size+add_size, 0,
		calculate_memsize(size, min_size, add_size,
				resource_size(b_res), min_align);
				resource_size(b_res), min_align);
	if (!size0 && !size1) {
	if (!size0 && !size1) {
		if (b_res->start || b_res->end)
		if (b_res->start || b_res->end)
+3 −2
Original line number Original line Diff line number Diff line
@@ -255,11 +255,12 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
		return -EINVAL;
		return -EINVAL;
	}
	}


	new_size = resource_size(res) + addsize + min_align;
	/* already aligned with min_align */
	new_size = resource_size(res) + addsize;
	ret = _pci_assign_resource(dev, resno, new_size, min_align);
	ret = _pci_assign_resource(dev, resno, new_size, min_align);
	if (!ret) {
	if (!ret) {
		res->flags &= ~IORESOURCE_STARTALIGN;
		res->flags &= ~IORESOURCE_STARTALIGN;
		dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
		dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
		if (resno < PCI_BRIDGE_RESOURCES)
		if (resno < PCI_BRIDGE_RESOURCES)
			pci_update_resource(dev, resno);
			pci_update_resource(dev, resno);
	}
	}