mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
PCI/IOV: Read VF config values that need not match PF
Per PCIe r7.0, sec 7.5.1.1.5 and 7.5.1.2.3, VF Revision IDs and Subsystem
IDs may differ from the PF's. Read these values from VF config space
instead of using cached values from VF 0.
Per 7.5.1.1.6 and 7.5.1.2.3, VF Class Codes and Subsystem Vendor IDs must
be the same as the PF's. Use the PF's value instead of reading from VF
config space.
Per 7.5.1.1.9, the Header Type for a VF must be 0, so hardcode that
assignment.
Fixes: cf0921bea6 ("PCI/IOV: Use VF0 cached config registers for other VFs")
Signed-off-by: Logan Odell <loganodell@google.com>
[bhelgaas: commit log, move "rev" decl inside block that uses it]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260910173648.1304517-1-loganodell@google.com
This commit is contained in:
parent
7bff67d3d6
commit
ae43799529
|
|
@ -179,29 +179,6 @@ bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev)
|
|||
return cmd & PCI_SRIOV_CTRL_MSE;
|
||||
}
|
||||
|
||||
static void pci_read_vf_config_common(struct pci_dev *virtfn)
|
||||
{
|
||||
struct pci_dev *physfn = virtfn->physfn;
|
||||
|
||||
/*
|
||||
* Some config registers are the same across all associated VFs.
|
||||
* Read them once from VF0 so we can skip reading them from the
|
||||
* other VFs.
|
||||
*
|
||||
* PCIe r4.0, sec 9.3.4.1, technically doesn't require all VFs to
|
||||
* have the same Revision ID and Subsystem ID, but we assume they
|
||||
* do.
|
||||
*/
|
||||
pci_read_config_dword(virtfn, PCI_CLASS_REVISION,
|
||||
&physfn->sriov->class);
|
||||
pci_read_config_byte(virtfn, PCI_HEADER_TYPE,
|
||||
&physfn->sriov->hdr_type);
|
||||
pci_read_config_word(virtfn, PCI_SUBSYSTEM_VENDOR_ID,
|
||||
&physfn->sriov->subsystem_vendor);
|
||||
pci_read_config_word(virtfn, PCI_SUBSYSTEM_ID,
|
||||
&physfn->sriov->subsystem_device);
|
||||
}
|
||||
|
||||
int pci_iov_sysfs_link(struct pci_dev *dev,
|
||||
struct pci_dev *virtfn, int id)
|
||||
{
|
||||
|
|
@ -329,8 +306,6 @@ static struct pci_dev *pci_iov_scan_device(struct pci_dev *dev, int id,
|
|||
virtfn->physfn = pci_dev_get(dev);
|
||||
virtfn->no_command_memory = 1;
|
||||
|
||||
if (id == 0)
|
||||
pci_read_vf_config_common(virtfn);
|
||||
|
||||
rc = pci_setup_device(virtfn);
|
||||
if (rc) {
|
||||
|
|
|
|||
|
|
@ -711,10 +711,6 @@ struct pci_sriov {
|
|||
u16 driver_max_VFs; /* Max num VFs driver supports */
|
||||
struct pci_dev *dev; /* Lowest numbered PF */
|
||||
struct pci_dev *self; /* This PF */
|
||||
u32 class; /* VF device */
|
||||
u8 hdr_type; /* VF header type */
|
||||
u16 subsystem_vendor; /* VF subsystem vendor */
|
||||
u16 subsystem_device; /* VF subsystem device */
|
||||
resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
|
||||
u16 vf_rebar_cap; /* VF Resizable BAR capability offset */
|
||||
bool drivers_autoprobe; /* Auto probing of VFs by driver */
|
||||
|
|
|
|||
|
|
@ -1890,8 +1890,13 @@ static u32 pci_class(struct pci_dev *dev)
|
|||
u32 class;
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (dev->is_virtfn)
|
||||
return dev->physfn->sriov->class;
|
||||
if (dev->is_virtfn) {
|
||||
u8 rev;
|
||||
|
||||
if (pci_read_config_byte(dev, PCI_REVISION_ID, &rev))
|
||||
rev = 0;
|
||||
return (dev->physfn->class << 8) | rev;
|
||||
}
|
||||
#endif
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
|
||||
return class;
|
||||
|
|
@ -1901,8 +1906,8 @@ static void pci_subsystem_ids(struct pci_dev *dev, u16 *vendor, u16 *device)
|
|||
{
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (dev->is_virtfn) {
|
||||
*vendor = dev->physfn->sriov->subsystem_vendor;
|
||||
*device = dev->physfn->sriov->subsystem_device;
|
||||
*vendor = dev->physfn->subsystem_vendor;
|
||||
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, device);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1916,7 +1921,7 @@ static u8 pci_hdr_type(struct pci_dev *dev)
|
|||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (dev->is_virtfn)
|
||||
return dev->physfn->sriov->hdr_type;
|
||||
return 0;
|
||||
#endif
|
||||
pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type);
|
||||
return hdr_type;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user