Re: [PATCH v3] PCI: Max Payload Size BIOS workaround

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I do not know, how will it be implemented as a generic for all the
architecture.
I have implemented it for SPEAr( Its an ARM based SOC). ARM architecture
provides a postinit hook. I have implemented these modifications using
this hook.
This will also not work for hotplug case.
Since patch is still to be sent to main line for review, I am posting relevant
part of code here:

static void set_readrq(struct pci_bus *bus, int rq)
{
	struct pci_dev *dev;

	list_for_each_entry(dev, &bus->devices, bus_list) {
		if (rq < pcie_get_readrq(dev))
			pcie_set_readrq(dev, rq);
		if (dev->subordinate)
			set_readrq(dev->subordinate, rq);
	}
}

static int get_max_payload(struct pci_bus *bus, int rq)
{
	struct pci_dev *dev;
	int payload;
	int max_payload = rq;

	list_for_each_entry(dev, &bus->devices, bus_list) {
		payload = pcie_get_payload(dev);
		if (payload < max_payload)
			max_payload = payload;
		if (dev->subordinate)
			max_payload = get_max_payload(dev->subordinate,
					max_payload);
	}
	return max_payload;
}

static void set_payload(struct pci_bus *bus, int rq)
{
	struct pci_dev *dev;

	list_for_each_entry(dev, &bus->devices, bus_list) {
		pcie_set_payload(dev, rq);
		if (dev->subordinate)
			set_payload(dev->subordinate, rq);
	}
}

static void __init pcie_postinit(void)
{
	struct hw_pci *hw = &pci;
	struct pci_sys_data *sys;
	struct pci_bus *bus;
	int cap, ctl, payload, readrq;
	int max_payload = 4096;
	struct pcie_port *pp;

	/*
	 * allign Max_Payload_Size for all devices to the minimum
	 * Max_Payload_Size of any of the device in tree.
	 * Max_Read_Request_Size of any of the DS device should be less
	 * than or equal to that of RC's Max_Read_Request_Size.
	 */

	list_for_each_entry(sys, &hw->buses, node) {
		bus = sys->bus;
		pp = bus_to_port(bus->number);
		if (!pp) {
			BUG();
			return;
		}
		cap = pci_find_own_capability(pp, PCI_CAP_ID_EXP);
		pp->ops.rd_own(pp, cap + PCI_EXP_DEVCTL, 2, &ctl);
		payload = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
		if (payload < max_payload)
			max_payload = payload;
		readrq = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
		max_payload = get_max_payload(bus, max_payload);
		set_payload(bus, max_payload);
		set_readrq(bus, readrq);
	}
}


static struct hw_pci pci = {
         .preinit        = pcie_preinit,
         .postinit       = pcie_postinit,
         .swizzle        = pci_std_swizzle,
         .setup          = pcie_setup,
         .scan           = pcie_scan_bus,
         .map_irq        = pcie_map_irq,
};
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux