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

Commit 0c3bef61 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
  PCI: OF: Don't crash when bridge parent is NULL.
  PCI: export pcie_bus_configure_settings symbol
  PCI: code and comments cleanup
  PCI: make cardbus-bridge resources optional
  PCI: make SRIOV resources optional
  PCI : ability to relocate assigned pci-resources
  PCI: honor child buses add_size in hot plug configuration
  PCI: Set PCI-E Max Payload Size on fabric
parents 01b88335 69566dd8
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -360,6 +360,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
		}
	}

	/* After the PCI-E bus has been walked and all devices discovered,
	 * configure any settings of the fabric that might be necessary.
	 */
	if (bus) {
		struct pci_bus *child;
		list_for_each_entry(child, &bus->children, node)
			pcie_bus_configure_settings(child, child->self->pcie_mpss);
	}

	if (!bus)
		kfree(sd);

+1 −44
Original line number Diff line number Diff line
@@ -158,47 +158,6 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
	 */
}

/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
static int pci_set_payload(struct pci_dev *dev)
{
       int pos, ppos;
       u16 pctl, psz;
       u16 dctl, dsz, dcap, dmax;
       struct pci_dev *parent;

       parent = dev->bus->self;
       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
       if (!pos)
               return 0;

       /* Read Device MaxPayload capability and setting */
       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
       pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
       dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
       dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);

       /* Read Parent MaxPayload setting */
       ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
       if (!ppos)
               return 0;
       pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
       psz = (pctl &  PCI_EXP_DEVCTL_PAYLOAD) >> 5;

       /* If parent payload > device max payload -> error
        * If parent payload > device payload -> set speed
        * If parent payload <= device payload -> do nothing
        */
       if (psz > dmax)
               return -1;
       else if (psz > dsz) {
               dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
                                     (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
                                     (psz << 5));
       }
       return 0;
}

void pci_configure_slot(struct pci_dev *dev)
{
	struct pci_dev *cdev;
@@ -210,9 +169,7 @@ void pci_configure_slot(struct pci_dev *dev)
			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
		return;

       ret = pci_set_payload(dev);
       if (ret)
               dev_warn(&dev->dev, "could not set device max payload\n");
	pcie_bus_configure_settings(dev->bus, dev->bus->self->pcie_mpss);

	memset(&hpp, 0, sizeof(hpp));
	ret = pci_get_hp_params(dev, &hpp);
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
	 */
	if (bus->bridge->of_node)
		return of_node_get(bus->bridge->of_node);
	if (bus->bridge->parent->of_node)
	if (bus->bridge->parent && bus->bridge->parent->of_node)
		return of_node_get(bus->bridge->parent->of_node);
	return NULL;
}
+67 −0
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;

enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;

/*
 * The default CLS is used if arch didn't set CLS explicitly and not
 * all pci devices agree on the same value.  Arch can override either
@@ -3222,6 +3224,67 @@ out:
}
EXPORT_SYMBOL(pcie_set_readrq);

/**
 * pcie_get_mps - get PCI Express maximum payload size
 * @dev: PCI device to query
 *
 * Returns maximum payload size in bytes
 *    or appropriate error value.
 */
int pcie_get_mps(struct pci_dev *dev)
{
	int ret, cap;
	u16 ctl;

	cap = pci_pcie_cap(dev);
	if (!cap)
		return -EINVAL;

	ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
	if (!ret)
		ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);

	return ret;
}

/**
 * pcie_set_mps - set PCI Express maximum payload size
 * @dev: PCI device to query
 * @rq: maximum payload size in bytes
 *    valid values are 128, 256, 512, 1024, 2048, 4096
 *
 * If possible sets maximum payload size
 */
int pcie_set_mps(struct pci_dev *dev, int mps)
{
	int cap, err = -EINVAL;
	u16 ctl, v;

	if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
		goto out;

	v = ffs(mps) - 8;
	if (v > dev->pcie_mpss) 
		goto out;
	v <<= 5;

	cap = pci_pcie_cap(dev);
	if (!cap)
		goto out;

	err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
	if (err)
		goto out;

	if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
		ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
		ctl |= v;
		err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
	}
out:
	return err;
}

/**
 * pci_select_bars - Make BAR mask from the type of resource
 * @dev: the PCI device for which BAR mask is made
@@ -3505,6 +3568,10 @@ static int __init pci_setup(char *str)
				pci_hotplug_io_size = memparse(str + 9, &str);
			} else if (!strncmp(str, "hpmemsize=", 10)) {
				pci_hotplug_mem_size = memparse(str + 10, &str);
			} else if (!strncmp(str, "pcie_bus_safe", 13)) {
				pcie_bus_config = PCIE_BUS_SAFE;
			} else if (!strncmp(str, "pcie_bus_perf", 13)) {
				pcie_bus_config = PCIE_BUS_PERFORMANCE;
			} else {
				printk(KERN_ERR "PCI: Unknown option `%s'\n",
						str);
+4 −0
Original line number Diff line number Diff line
@@ -283,6 +283,8 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)

#endif /* CONFIG_PCI_IOV */

extern unsigned long pci_cardbus_resource_alignment(struct resource *);

static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
					 struct resource *res)
{
@@ -292,6 +294,8 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
	if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
		return pci_sriov_resource_alignment(dev, resno);
#endif
	if (dev->class >> 8  == PCI_CLASS_BRIDGE_CARDBUS)
		return pci_cardbus_resource_alignment(res);
	return resource_alignment(res);
}

Loading