diff options
Diffstat (limited to 'drivers/pci/controller/vmd.c')
| -rw-r--r-- | drivers/pci/controller/vmd.c | 44 | 
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index ebec0a6e77ed..f69ef8c89f72 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -40,13 +40,19 @@ enum vmd_features {  	 * membars, in order to allow proper address translation during  	 * resource assignment to enable guest virtualization  	 */ -	VMD_FEAT_HAS_MEMBAR_SHADOW	= (1 << 0), +	VMD_FEAT_HAS_MEMBAR_SHADOW		= (1 << 0),  	/*  	 * Device may provide root port configuration information which limits  	 * bus numbering  	 */ -	VMD_FEAT_HAS_BUS_RESTRICTIONS	= (1 << 1), +	VMD_FEAT_HAS_BUS_RESTRICTIONS		= (1 << 1), + +	/* +	 * Device contains physical location shadow registers in +	 * vendor-specific capability space +	 */ +	VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP	= (1 << 2),  };  /* @@ -454,6 +460,28 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)  		}  	} +	if (features & VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP) { +		int pos = pci_find_capability(vmd->dev, PCI_CAP_ID_VNDR); +		u32 reg, regu; + +		pci_read_config_dword(vmd->dev, pos + 4, ®); + +		/* "SHDW" */ +		if (pos && reg == 0x53484457) { +			pci_read_config_dword(vmd->dev, pos + 8, ®); +			pci_read_config_dword(vmd->dev, pos + 12, ®u); +			offset[0] = vmd->dev->resource[VMD_MEMBAR1].start - +					(((u64) regu << 32 | reg) & +					 PCI_BASE_ADDRESS_MEM_MASK); + +			pci_read_config_dword(vmd->dev, pos + 16, ®); +			pci_read_config_dword(vmd->dev, pos + 20, ®u); +			offset[1] = vmd->dev->resource[VMD_MEMBAR2].start - +					(((u64) regu << 32 | reg) & +					 PCI_BASE_ADDRESS_MEM_MASK); +		} +	} +  	/*  	 * Certain VMD devices may have a root port configuration option which  	 * limits the bus range to between 0-127, 128-255, or 224-255 @@ -720,16 +748,20 @@ static int vmd_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume);  static const struct pci_device_id vmd_ids[] = { -	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D),}, +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D), +		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP,},  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),  		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |  				VMD_FEAT_HAS_BUS_RESTRICTIONS,},  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f), -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, +		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | +				VMD_FEAT_HAS_BUS_RESTRICTIONS,},  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d), -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, +		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | +				VMD_FEAT_HAS_BUS_RESTRICTIONS,},  	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B), -		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,}, +		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | +				VMD_FEAT_HAS_BUS_RESTRICTIONS,},  	{0,}  };  MODULE_DEVICE_TABLE(pci, vmd_ids);  | 
