mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
VT-d, tools: Intel IGD passthrough 1/2: vendor-specific FLR
Due to FLR capability of IGD is not exposed on some platforms, this patch uses vendor specific FLR to reset those IGDs. Signed-off-by: Weidong Han <weidong.han@intel.com>
This commit is contained in:
1 parent
22cce0547c
commit
3c29b3fd3c
1 file changed
+76
-7
@@ -19,6 +19,7 @@ from xen.xend import uuid
|
||||
from xen.xend import sxp
|
||||
from xen.xend.XendConstants import AUTO_PHP_SLOT
|
||||
from xen.xend.XendSXPDev import dev_dict_to_sxp
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
# for 2.3 compatibility
|
||||
try:
|
||||
@@ -94,6 +95,21 @@ PCI_CAP_ID_VENDOR_SPECIFIC_CAP = 0x09
|
||||
PCI_CLASS_ID_USB = 0x0c03
|
||||
PCI_USB_FLRCTRL = 0x4
|
||||
|
||||
PCI_DEVICE_ID = 0x02
|
||||
PCI_COMMAND = 0x04
|
||||
PCI_CLASS_ID_VGA = 0x0300
|
||||
|
||||
PCI_DEVICE_ID_IGFX_GM45 = 0x2a42
|
||||
PCI_DEVICE_ID_IGFX_EAGLELAKE = 0x2e02
|
||||
PCI_DEVICE_ID_IGFX_Q45 = 0x2e12
|
||||
PCI_DEVICE_ID_IGFX_G45 = 0x2e22
|
||||
PCI_DEVICE_ID_IGFX_G41 = 0x2e32
|
||||
|
||||
PCI_CAP_IGFX_CAP09_OFFSET = 0xa4
|
||||
PCI_CAP_IGFX_CAP13_OFFSET = 0xa4
|
||||
PCI_CAP_IGFX_GDRST = 0X0d
|
||||
PCI_CAP_IGFX_GDRST_OFFSET = 0xc0
|
||||
|
||||
# The VF of Intel 82599 10GbE Controller
|
||||
# See http://download.intel.com/design/network/datashts/82599_datasheet.pdf
|
||||
# For 'VF PCIe Configuration Space', see its Table 9.7.
|
||||
@@ -831,6 +847,45 @@ class PciDevice:
|
||||
if not self.do_Dstate_transition():
|
||||
self.do_vendor_specific_FLR_method()
|
||||
|
||||
def do_AF_FLR(self, af_pos):
|
||||
''' use PCI Advanced Capability to do FLR
|
||||
'''
|
||||
(pci_list, cfg_list) = save_pci_conf_space([self.name])
|
||||
self.pci_conf_write8(af_pos + PCI_AF_CTL, PCI_AF_CTL_FLR)
|
||||
time.sleep(0.100)
|
||||
restore_pci_conf_space((pci_list, cfg_list))
|
||||
|
||||
def do_FLR_for_intel_4Series_iGFX(self):
|
||||
af_pos = PCI_CAP_IGFX_CAP13_OFFSET
|
||||
self.do_AF_FLR(af_pos)
|
||||
log.debug("Intel 4 Series iGFX FLR done")
|
||||
|
||||
def do_FLR_for_GM45_iGFX(self):
|
||||
reg32 = self.pci_conf_read32(PCI_CAP_IGFX_CAP09_OFFSET)
|
||||
if ((reg32 >> 16) & 0x000000FF) != 0x06 or \
|
||||
((reg32 >> 24) & 0x000000F0) != 0x20:
|
||||
return
|
||||
|
||||
self.pci_conf_write8(PCI_CAP_IGFX_GDRST_OFFSET, PCI_CAP_IGFX_GDRST)
|
||||
for i in range(0, 10):
|
||||
time.sleep(0.100)
|
||||
reg8 = self.pci_conf_read8(PCI_CAP_IGFX_GDRST_OFFSET)
|
||||
if (reg8 & 0x01) == 0:
|
||||
break
|
||||
if i == 10:
|
||||
log.debug("Intel iGFX FLR fail on GM45")
|
||||
return
|
||||
|
||||
# This specific reset will hang if the command register does not have
|
||||
# memory space access enabled
|
||||
cmd = self.pci_conf_read16(PCI_COMMAND)
|
||||
self.pci_conf_write16(PCI_COMMAND, (cmd | 0x02))
|
||||
af_pos = PCI_CAP_IGFX_CAP09_OFFSET
|
||||
self.do_AF_FLR(af_pos)
|
||||
self.pci_conf_write16(PCI_COMMAND, cmd)
|
||||
|
||||
log.debug("Intel iGFX FLR on GM45 done")
|
||||
|
||||
def find_all_the_multi_functions(self):
|
||||
sysfs_mnt = find_sysfs_mnt()
|
||||
parentdict = self.find_parent()
|
||||
@@ -1104,15 +1159,29 @@ class PciDevice:
|
||||
else:
|
||||
# For PCI device on host bus, we test "PCI Advanced Capabilities".
|
||||
if self.bus == 0 and self.pci_af_flr:
|
||||
(pci_list, cfg_list) = save_pci_conf_space([self.name])
|
||||
# We use Advanced Capability to do FLR.
|
||||
pos = self.find_cap_offset(PCI_CAP_ID_AF)
|
||||
self.pci_conf_write8(pos + PCI_AF_CTL, PCI_AF_CTL_FLR)
|
||||
time.sleep(0.100)
|
||||
restore_pci_conf_space((pci_list, cfg_list))
|
||||
af_pos = self.find_cap_offset(PCI_CAP_ID_AF)
|
||||
self.do_AF_FLR(af_pos)
|
||||
else:
|
||||
if self.bus == 0:
|
||||
self.do_FLR_for_integrated_device()
|
||||
if self.slot == 0x02 and self.func == 0x0:
|
||||
vendor_id = self.pci_conf_read16(PCI_VENDOR_ID)
|
||||
if vendor_id != VENDOR_INTEL:
|
||||
return
|
||||
class_id = self.pci_conf_read16(PCI_CLASS_DEVICE)
|
||||
if class_id != PCI_CLASS_ID_VGA:
|
||||
return
|
||||
device_id = self.pci_conf_read16(PCI_DEVICE_ID)
|
||||
if device_id == PCI_DEVICE_ID_IGFX_GM45:
|
||||
self.do_FLR_for_GM45_iGFX()
|
||||
elif device_id == PCI_DEVICE_ID_IGFX_EAGLELAKE or \
|
||||
device_id == PCI_DEVICE_ID_IGFX_Q45 or \
|
||||
device_id == PCI_DEVICE_ID_IGFX_G45 or \
|
||||
device_id == PCI_DEVICE_ID_IGFX_G41:
|
||||
self.do_FLR_for_intel_4Series_iGFX()
|
||||
else:
|
||||
log.debug("Unknown iGFX device_id:%x", device_id)
|
||||
else:
|
||||
self.do_FLR_for_integrated_device()
|
||||
else:
|
||||
devs = self.find_coassigned_pci_devices(False)
|
||||
# Remove the element 0 which is a bridge
|
||||
|
||||