diff options
Diffstat (limited to 'drivers/pci/setup-res.c')
| -rw-r--r-- | drivers/pci/setup-res.c | 48 | 
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 9526e341988b..4bc589ee78d0 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -25,21 +25,18 @@  #include <linux/slab.h>  #include "pci.h" - -void pci_update_resource(struct pci_dev *dev, int resno) +static void pci_std_update_resource(struct pci_dev *dev, int resno)  {  	struct pci_bus_region region;  	bool disable;  	u16 cmd;  	u32 new, check, mask;  	int reg; -	enum pci_bar_type type;  	struct resource *res = dev->resource + resno; -	if (dev->is_virtfn) { -		dev_warn(&dev->dev, "can't update VF BAR%d\n", resno); +	/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */ +	if (dev->is_virtfn)  		return; -	}  	/*  	 * Ignore resources for unimplemented BARs and unused resource slots @@ -60,21 +57,34 @@ void pci_update_resource(struct pci_dev *dev, int resno)  		return;  	pcibios_resource_to_bus(dev->bus, ®ion, res); +	new = region.start; -	new = region.start | (res->flags & PCI_REGION_FLAG_MASK); -	if (res->flags & IORESOURCE_IO) +	if (res->flags & IORESOURCE_IO) {  		mask = (u32)PCI_BASE_ADDRESS_IO_MASK; -	else +		new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK; +	} else if (resno == PCI_ROM_RESOURCE) { +		mask = (u32)PCI_ROM_ADDRESS_MASK; +	} else {  		mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; +		new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK; +	} -	reg = pci_resource_bar(dev, resno, &type); -	if (!reg) -		return; -	if (type != pci_bar_unknown) { +	if (resno < PCI_ROM_RESOURCE) { +		reg = PCI_BASE_ADDRESS_0 + 4 * resno; +	} else if (resno == PCI_ROM_RESOURCE) { + +		/* +		 * Apparently some Matrox devices have ROM BARs that read +		 * as zero when disabled, so don't update ROM BARs unless +		 * they're enabled.  See https://lkml.org/lkml/2005/8/30/138. +		 */  		if (!(res->flags & IORESOURCE_ROM_ENABLE))  			return; + +		reg = dev->rom_base_reg;  		new |= PCI_ROM_ADDRESS_ENABLE; -	} +	} else +		return;  	/*  	 * We can't update a 64-bit BAR atomically, so when possible, @@ -110,6 +120,16 @@ void pci_update_resource(struct pci_dev *dev, int resno)  		pci_write_config_word(dev, PCI_COMMAND, cmd);  } +void pci_update_resource(struct pci_dev *dev, int resno) +{ +	if (resno <= PCI_ROM_RESOURCE) +		pci_std_update_resource(dev, resno); +#ifdef CONFIG_PCI_IOV +	else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) +		pci_iov_update_resource(dev, resno); +#endif +} +  int pci_claim_resource(struct pci_dev *dev, int resource)  {  	struct resource *res = &dev->resource[resource];  |