diff options
| -rw-r--r-- | drivers/pci/pci.c | 62 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 5 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 3 | ||||
| -rw-r--r-- | drivers/pci/quirks.c | 63 | ||||
| -rw-r--r-- | drivers/pci/setup-res.c | 4 | 
5 files changed, 66 insertions, 71 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e9f9dc183cf..b832f0fece9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3694,6 +3694,68 @@ int pci_is_reassigndev(struct pci_dev *dev)  	return (pci_specified_resource_alignment(dev) != 0);  } +/* + * This function disables memory decoding and releases memory resources + * of the device specified by kernel's boot parameter 'pci=resource_alignment='. + * It also rounds up size to specified alignment. + * Later on, the kernel will assign page-aligned memory resource back + * to the device. + */ +void pci_reassigndev_resource_alignment(struct pci_dev *dev) +{ +	int i; +	struct resource *r; +	resource_size_t align, size; +	u16 command; + +	if (!pci_is_reassigndev(dev)) +		return; + +	if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && +	    (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { +		dev_warn(&dev->dev, +			"Can't reassign resources to host bridge.\n"); +		return; +	} + +	dev_info(&dev->dev, +		"Disabling memory decoding and releasing memory resources.\n"); +	pci_read_config_word(dev, PCI_COMMAND, &command); +	command &= ~PCI_COMMAND_MEMORY; +	pci_write_config_word(dev, PCI_COMMAND, command); + +	align = pci_specified_resource_alignment(dev); +	for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { +		r = &dev->resource[i]; +		if (!(r->flags & IORESOURCE_MEM)) +			continue; +		size = resource_size(r); +		if (size < align) { +			size = align; +			dev_info(&dev->dev, +				"Rounding up size of resource #%d to %#llx.\n", +				i, (unsigned long long)size); +		} +		r->end = size - 1; +		r->start = 0; +	} +	/* Need to disable bridge's resource window, +	 * to enable the kernel to reassign new resource +	 * window later on. +	 */ +	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && +	    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { +		for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { +			r = &dev->resource[i]; +			if (!(r->flags & IORESOURCE_MEM)) +				continue; +			r->end = resource_size(r) - 1; +			r->start = 0; +		} +		pci_disable_bridge_window(dev); +	} +} +  ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)  {  	if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 1fc63b39f83..e4943479b23 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -228,11 +228,8 @@ static inline int pci_ari_enabled(struct pci_bus *bus)  	return bus->self && bus->self->ari_enabled;  } -#ifdef CONFIG_PCI_QUIRKS -extern int pci_is_reassigndev(struct pci_dev *dev); -resource_size_t pci_specified_resource_alignment(struct pci_dev *dev); +void pci_reassigndev_resource_alignment(struct pci_dev *dev);  extern void pci_disable_bridge_window(struct pci_dev *dev); -#endif  /* Single Root I/O Virtualization */  struct pci_sriov { diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 36c22032ea1..944e05a66b9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1325,6 +1325,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)  	/* Fix up broken headers */  	pci_fixup_device(pci_fixup_header, dev); +	/* moved out from quirk header fixup code */ +	pci_reassigndev_resource_alignment(dev); +  	/* Clear the state_saved flag. */  	dev->state_saved = false; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e198589d099..f8f81d4f29f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -32,69 +32,6 @@  #include "pci.h"  /* - * This quirk function disables memory decoding and releases memory resources - * of the device specified by kernel's boot parameter 'pci=resource_alignment='. - * It also rounds up size to specified alignment. - * Later on, the kernel will assign page-aligned memory resource back - * to the device. - */ -static void __devinit quirk_resource_alignment(struct pci_dev *dev) -{ -	int i; -	struct resource *r; -	resource_size_t align, size; -	u16 command; - -	if (!pci_is_reassigndev(dev)) -		return; - -	if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && -	    (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { -		dev_warn(&dev->dev, -			"Can't reassign resources to host bridge.\n"); -		return; -	} - -	dev_info(&dev->dev, -		"Disabling memory decoding and releasing memory resources.\n"); -	pci_read_config_word(dev, PCI_COMMAND, &command); -	command &= ~PCI_COMMAND_MEMORY; -	pci_write_config_word(dev, PCI_COMMAND, command); - -	align = pci_specified_resource_alignment(dev); -	for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { -		r = &dev->resource[i]; -		if (!(r->flags & IORESOURCE_MEM)) -			continue; -		size = resource_size(r); -		if (size < align) { -			size = align; -			dev_info(&dev->dev, -				"Rounding up size of resource #%d to %#llx.\n", -				i, (unsigned long long)size); -		} -		r->end = size - 1; -		r->start = 0; -	} -	/* Need to disable bridge's resource window, -	 * to enable the kernel to reassign new resource -	 * window later on. -	 */ -	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && -	    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { -		for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { -			r = &dev->resource[i]; -			if (!(r->flags & IORESOURCE_MEM)) -				continue; -			r->end = resource_size(r) - 1; -			r->start = 0; -		} -		pci_disable_bridge_window(dev); -	} -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); - -/*   * Decoding should be disabled for a PCI device during BAR sizing to avoid   * conflict. But doing so may cause problems on host bridge and perhaps other   * key system devices. For devices that need to have mmio decoding always-on, diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index f968185aa19..eea85dafc76 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -114,7 +114,6 @@ int pci_claim_resource(struct pci_dev *dev, int resource)  }  EXPORT_SYMBOL(pci_claim_resource); -#ifdef CONFIG_PCI_QUIRKS  void pci_disable_bridge_window(struct pci_dev *dev)  {  	dev_info(&dev->dev, "disabling bridge mem windows\n"); @@ -127,9 +126,6 @@ void pci_disable_bridge_window(struct pci_dev *dev)  	pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);  	pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);  } -#endif	/* CONFIG_PCI_QUIRKS */ - -  static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,  		int resno, resource_size_t size, resource_size_t align)  |