mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
IOMMU: add option to specify devices behaving like ones using phantom functions
At least certain Marvell SATA controllers are known to issue bus master requests with a non-zero function as origin, despite themselves being single function devices. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
This commit is contained in:
1 parent
c9af51eb96
commit
4e3c592c93
2 files changed
+67
No files matched your search
@@ -703,6 +703,16 @@ Defaults to booting secondary processors.
|
||||
|
||||
Default: `on`
|
||||
|
||||
### pci-phantom
|
||||
> `=[<seg>:]<bus>:<device>,<stride>`
|
||||
|
||||
Mark a group of PCI devices as using phantom functions without actually
|
||||
advertising so, so the IOMMU can create translation contexts for them.
|
||||
|
||||
All numbers specified must be hexadecimal ones.
|
||||
|
||||
This option can be specified more than once (up to 8 times at present).
|
||||
|
||||
### ple\_gap
|
||||
> `= <integer>`
|
||||
|
||||
|
||||
@@ -121,6 +121,49 @@ const unsigned long *pci_get_ro_map(u16 seg)
|
||||
return pseg ? pseg->ro_map : NULL;
|
||||
}
|
||||
|
||||
static struct phantom_dev {
|
||||
u16 seg;
|
||||
u8 bus, slot, stride;
|
||||
} phantom_devs[8];
|
||||
static unsigned int nr_phantom_devs;
|
||||
|
||||
static void __init parse_phantom_dev(char *str) {
|
||||
const char *s = str;
|
||||
struct phantom_dev phantom;
|
||||
|
||||
if ( !s || !*s || nr_phantom_devs >= ARRAY_SIZE(phantom_devs) )
|
||||
return;
|
||||
|
||||
phantom.seg = simple_strtol(s, &s, 16);
|
||||
if ( *s != ':' )
|
||||
return;
|
||||
|
||||
phantom.bus = simple_strtol(s + 1, &s, 16);
|
||||
if ( *s == ',' )
|
||||
{
|
||||
phantom.slot = phantom.bus;
|
||||
phantom.bus = phantom.seg;
|
||||
phantom.seg = 0;
|
||||
}
|
||||
else if ( *s == ':' )
|
||||
phantom.slot = simple_strtol(s + 1, &s, 16);
|
||||
else
|
||||
return;
|
||||
|
||||
if ( *s != ',' )
|
||||
return;
|
||||
switch ( phantom.stride = simple_strtol(s + 1, &s, 0) )
|
||||
{
|
||||
case 1: case 2: case 4:
|
||||
if ( *s )
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
phantom_devs[nr_phantom_devs++] = phantom;
|
||||
}
|
||||
custom_param("pci-phantom", parse_phantom_dev);
|
||||
|
||||
static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
@@ -181,6 +224,20 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
|
||||
if ( PCI_FUNC(devfn) >= pdev->phantom_stride )
|
||||
pdev->phantom_stride = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0; i < nr_phantom_devs; ++i )
|
||||
if ( phantom_devs[i].seg == pseg->nr &&
|
||||
phantom_devs[i].bus == bus &&
|
||||
phantom_devs[i].slot == PCI_SLOT(devfn) &&
|
||||
phantom_devs[i].stride > PCI_FUNC(devfn) )
|
||||
{
|
||||
pdev->phantom_stride = phantom_devs[i].stride;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DEV_TYPE_PCI:
|
||||
|
||||