diff options
-rw-r--r-- | drivers/pci/iov.c | 31 | ||||
-rw-r--r-- | drivers/pci/pci.h | 1 |
2 files changed, 28 insertions, 4 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index a8752c2c2b53..2ae921f84bd3 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -46,6 +46,30 @@ static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn) | |||
46 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &iov->stride); | 46 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &iov->stride); |
47 | } | 47 | } |
48 | 48 | ||
49 | /* | ||
50 | * The PF consumes one bus number. NumVFs, First VF Offset, and VF Stride | ||
51 | * determine how many additional bus numbers will be consumed by VFs. | ||
52 | * | ||
53 | * Iterate over all valid NumVFs and calculate the maximum number of bus | ||
54 | * numbers that could ever be required. | ||
55 | */ | ||
56 | static inline u8 virtfn_max_buses(struct pci_dev *dev) | ||
57 | { | ||
58 | struct pci_sriov *iov = dev->sriov; | ||
59 | int nr_virtfn; | ||
60 | u8 max = 0; | ||
61 | u8 busnr; | ||
62 | |||
63 | for (nr_virtfn = 1; nr_virtfn <= iov->total_VFs; nr_virtfn++) { | ||
64 | pci_iov_set_numvfs(dev, nr_virtfn); | ||
65 | busnr = virtfn_bus(dev, nr_virtfn - 1); | ||
66 | if (busnr > max) | ||
67 | max = busnr; | ||
68 | } | ||
69 | |||
70 | return max; | ||
71 | } | ||
72 | |||
49 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) | 73 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) |
50 | { | 74 | { |
51 | struct pci_bus *child; | 75 | struct pci_bus *child; |
@@ -427,6 +451,7 @@ found: | |||
427 | 451 | ||
428 | dev->sriov = iov; | 452 | dev->sriov = iov; |
429 | dev->is_physfn = 1; | 453 | dev->is_physfn = 1; |
454 | iov->max_VF_buses = virtfn_max_buses(dev); | ||
430 | 455 | ||
431 | return 0; | 456 | return 0; |
432 | 457 | ||
@@ -556,15 +581,13 @@ void pci_restore_iov_state(struct pci_dev *dev) | |||
556 | int pci_iov_bus_range(struct pci_bus *bus) | 581 | int pci_iov_bus_range(struct pci_bus *bus) |
557 | { | 582 | { |
558 | int max = 0; | 583 | int max = 0; |
559 | u8 busnr; | ||
560 | struct pci_dev *dev; | 584 | struct pci_dev *dev; |
561 | 585 | ||
562 | list_for_each_entry(dev, &bus->devices, bus_list) { | 586 | list_for_each_entry(dev, &bus->devices, bus_list) { |
563 | if (!dev->is_physfn) | 587 | if (!dev->is_physfn) |
564 | continue; | 588 | continue; |
565 | busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1); | 589 | if (dev->sriov->max_VF_buses > max) |
566 | if (busnr > max) | 590 | max = dev->sriov->max_VF_buses; |
567 | max = busnr; | ||
568 | } | 591 | } |
569 | 592 | ||
570 | return max ? max - bus->number : 0; | 593 | return max ? max - bus->number : 0; |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 57329645dd01..bae593c04541 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -243,6 +243,7 @@ struct pci_sriov { | |||
243 | u16 stride; /* following VF stride */ | 243 | u16 stride; /* following VF stride */ |
244 | u32 pgsz; /* page size for BAR alignment */ | 244 | u32 pgsz; /* page size for BAR alignment */ |
245 | u8 link; /* Function Dependency Link */ | 245 | u8 link; /* Function Dependency Link */ |
246 | u8 max_VF_buses; /* max buses consumed by VFs */ | ||
246 | u16 driver_max_VFs; /* max num VFs driver supports */ | 247 | u16 driver_max_VFs; /* max num VFs driver supports */ |
247 | struct pci_dev *dev; /* lowest numbered PF */ | 248 | struct pci_dev *dev; /* lowest numbered PF */ |
248 | struct pci_dev *self; /* this PF */ | 249 | struct pci_dev *self; /* this PF */ |