diff options
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/hotplug/pcihp_slot.c | 4 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 6 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 59 | ||||
| -rw-r--r-- | drivers/pci/xen-pcifront.c | 5 | 
4 files changed, 46 insertions, 28 deletions
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index 753b21aaea6..3ffd9c1acc0 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c @@ -169,7 +169,9 @@ void pci_configure_slot(struct pci_dev *dev)  			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))  		return; -	pcie_bus_configure_settings(dev->bus, dev->bus->self->pcie_mpss); +	if (dev->bus && dev->bus->self) +		pcie_bus_configure_settings(dev->bus, +					    dev->bus->self->pcie_mpss);  	memset(&hpp, 0, sizeof(hpp));  	ret = pci_get_hp_params(dev, &hpp); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0ce67423a0a..e9651f0a881 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -77,7 +77,7 @@ 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; +enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;  /*   * The default CLS is used if arch didn't set CLS explicitly and not @@ -3568,10 +3568,14 @@ 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_tune_off", 17)) { +				pcie_bus_config = PCIE_BUS_TUNE_OFF;  			} 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 if (!strncmp(str, "pcie_bus_peer2peer", 18)) { +				pcie_bus_config = PCIE_BUS_PEER2PEER;  			} else {  				printk(KERN_ERR "PCI: Unknown option `%s'\n",  						str); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8473727b29f..6ab6bd3df4b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1351,7 +1351,8 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data)  	 * will occur as normal.  	 */  	if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || -	    dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT)) +	     (dev->bus->self && +	      dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT)))  		*smpss = 0;  	if (*smpss > dev->pcie_mpss) @@ -1396,34 +1397,37 @@ static void pcie_write_mps(struct pci_dev *dev, int mps)  static void pcie_write_mrrs(struct pci_dev *dev, int mps)  { -	int rc, mrrs; +	int rc, mrrs, dev_mpss; -	if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { -		int dev_mpss = 128 << dev->pcie_mpss; +	/* In the "safe" case, do not configure the MRRS.  There appear to be +	 * issues with setting MRRS to 0 on a number of devices. +	 */ -		/* For Max performance, the MRRS must be set to the largest -		 * supported value.  However, it cannot be configured larger -		 * than the MPS the device or the bus can support.  This assumes -		 * that the largest MRRS available on the device cannot be -		 * smaller than the device MPSS. -		 */ -		mrrs = mps < dev_mpss ? mps : dev_mpss; -	} else -		/* In the "safe" case, configure the MRRS for fairness on the -		 * bus by making all devices have the same size -		 */ -		mrrs = mps; +	if (pcie_bus_config != PCIE_BUS_PERFORMANCE) +		return; +	dev_mpss = 128 << dev->pcie_mpss; + +	/* For Max performance, the MRRS must be set to the largest supported +	 * value.  However, it cannot be configured larger than the MPS the +	 * device or the bus can support.  This assumes that the largest MRRS +	 * available on the device cannot be smaller than the device MPSS. +	 */ +	mrrs = min(mps, dev_mpss);  	/* MRRS is a R/W register.  Invalid values can be written, but a -	 * subsiquent read will verify if the value is acceptable or not. +	 * subsequent read will verify if the value is acceptable or not.  	 * If the MRRS value provided is not acceptable (e.g., too large),  	 * shrink the value until it is acceptable to the HW.   	 */  	while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) { +		dev_warn(&dev->dev, "Attempting to modify the PCI-E MRRS value" +			 " to %d.  If any issues are encountered, please try " +			 "running with pci=pcie_bus_safe\n", mrrs);  		rc = pcie_set_readrq(dev, mrrs);  		if (rc) -			dev_err(&dev->dev, "Failed attempting to set the MRRS\n"); +			dev_err(&dev->dev, +				"Failed attempting to set the MRRS\n");  		mrrs /= 2;  	} @@ -1436,13 +1440,13 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)  	if (!pci_is_pcie(dev))  		return 0; -	dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n", +	dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",  		 pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));  	pcie_write_mps(dev, mps);  	pcie_write_mrrs(dev, mps); -	dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n", +	dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",  		 pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));  	return 0; @@ -1454,15 +1458,24 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)   */  void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)  { -	u8 smpss = mpss; +	u8 smpss; -	if (!bus->self) +	if (!pci_is_pcie(bus->self))  		return; -	if (!pci_is_pcie(bus->self)) +	if (pcie_bus_config == PCIE_BUS_TUNE_OFF)  		return; +	/* FIXME - Peer to peer DMA is possible, though the endpoint would need +	 * to be aware to the MPS of the destination.  To work around this, +	 * simply force the MPS of the entire system to the smallest possible. +	 */ +	if (pcie_bus_config == PCIE_BUS_PEER2PEER) +		smpss = 0; +  	if (pcie_bus_config == PCIE_BUS_SAFE) { +		smpss = mpss; +  		pcie_find_smpss(bus->self, &smpss);  		pci_walk_bus(bus, pcie_find_smpss, &smpss);  	} diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 6fa215a3861..90832a95599 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -400,9 +400,8 @@ static int pcifront_claim_resource(struct pci_dev *dev, void *data)  			dev_info(&pdev->xdev->dev, "claiming resource %s/%d\n",  				pci_name(dev), i);  			if (pci_claim_resource(dev, i)) { -				dev_err(&pdev->xdev->dev, "Could not claim " -					"resource %s/%d! Device offline. Try " -					"giving less than 4GB to domain.\n", +				dev_err(&pdev->xdev->dev, "Could not claim resource %s/%d! " +					"Device offline. Try using e820_host=1 in the guest config.\n",  					pci_name(dev), i);  			}  		}  |