1 | Hi, | 1 | Hi, |
---|---|---|---|
2 | 2 | ||
3 | Next relatively small update - now that the PCI cap for regular | 3 | Another revision after the feedback from Ilpo. |
4 | resizable BAR is cached, we're following suit with VF rebar cap. | 4 | Few tweaks here and there, the biggest change is the removal of the |
5 | loop in pci_iov_vf_bar_get_sizes(). | ||
5 | 6 | ||
6 | v5 can be found here: | 7 | v6 can be found here: |
7 | https://lore.kernel.org/linux-pci/20250312225949.969716-1-michal.winiarski@intel.com/ | 8 | https://lore.kernel.org/linux-pci/20250320110854.3866284-1-michal.winiarski@intel.com/ |
8 | 9 | ||
9 | For regular BAR, drivers can use pci_resize_resource to resize it to the | 10 | For regular BAR, drivers can use pci_resize_resource to resize it to the |
10 | desired size provided that it is supported by the hardware, which the | 11 | desired size provided that it is supported by the hardware, which the |
11 | driver can query using pci_rebar_get_possible_sizes. | 12 | driver can query using pci_rebar_get_possible_sizes. |
12 | This series expands the API to work with IOV BAR as well. | 13 | This series expands the API to work with IOV BAR as well. |
13 | It also adds the additional API for drivers to change the VF BAR size | 14 | It also adds the additional API for drivers to change the VF BAR size |
14 | without resizing the entire underlying reservation (within the original | 15 | without resizing the entire underlying reservation (within the original |
15 | resource boundary). | 16 | resource boundary). |
16 | 17 | ||
17 | Thanks, | 18 | Thanks, |
18 | -Michał | 19 | -Michał |
20 | |||
21 | v6 -> v7: | ||
22 | - Eliminate the loop in pci_iov_vf_bar_get_sizes() (Ilpo) | ||
23 | - Use helper variable for indexes (Ilpo) | ||
24 | - Kerneldoc formatting (Ilpo) | ||
25 | - Refer to latest PCI spec (Ilpo) | ||
26 | - Commit message wording (Ilpo) | ||
19 | 27 | ||
20 | v5 -> v6: | 28 | v5 -> v6: |
21 | - Rebased on latest pci/next | 29 | - Rebased on latest pci/next |
22 | - Cache the VF resizable BAR capability position to avoid multiple | 30 | - Cache the VF resizable BAR capability position to avoid multiple |
23 | lookups (Ilpo) | 31 | lookups (Ilpo) |
... | ... | ||
59 | PCI: Allow drivers to control VF BAR size | 67 | PCI: Allow drivers to control VF BAR size |
60 | drm/xe/pf: Set VF LMEM BAR size | 68 | drm/xe/pf: Set VF LMEM BAR size |
61 | 69 | ||
62 | drivers/gpu/drm/xe/regs/xe_bars.h | 1 + | 70 | drivers/gpu/drm/xe/regs/xe_bars.h | 1 + |
63 | drivers/gpu/drm/xe/xe_pci_sriov.c | 22 +++++ | 71 | drivers/gpu/drm/xe/xe_pci_sriov.c | 22 +++++ |
64 | drivers/pci/iov.c | 156 +++++++++++++++++++++++++++--- | 72 | drivers/pci/iov.c | 149 +++++++++++++++++++++++++++--- |
65 | drivers/pci/pci.c | 8 +- | 73 | drivers/pci/pci.c | 10 +- |
66 | drivers/pci/pci.h | 29 ++++++ | 74 | drivers/pci/pci.h | 29 ++++++ |
67 | drivers/pci/setup-bus.c | 3 +- | 75 | drivers/pci/setup-bus.c | 3 +- |
68 | drivers/pci/setup-res.c | 35 ++++++- | 76 | drivers/pci/setup-res.c | 35 ++++++- |
69 | include/linux/pci.h | 6 ++ | 77 | include/linux/pci.h | 6 ++ |
70 | include/uapi/linux/pci_regs.h | 1 + | 78 | include/uapi/linux/pci_regs.h | 9 ++ |
71 | 9 files changed, 243 insertions(+), 18 deletions(-) | 79 | 9 files changed, 246 insertions(+), 18 deletions(-) |
72 | 80 | ||
73 | -- | 81 | -- |
74 | 2.49.0 | 82 | 2.49.0 |
75 | 83 | diff view generated by jsdifflib |
1 | Similar to regular resizable BAR, VF BAR can also be resized, e.g. by | 1 | Similar to regular resizable BAR, VF BAR can also be resized, e.g. by |
---|---|---|---|
2 | the system firmware or the PCI subsystem itself. | 2 | the system firmware or the PCI subsystem itself. |
3 | 3 | ||
4 | The capability layout is the same as PCI_EXT_CAP_ID_REBAR. | ||
5 | |||
4 | Add the capability ID and restore it as a part of IOV state. | 6 | Add the capability ID and restore it as a part of IOV state. |
5 | 7 | ||
6 | See PCIe r4.0, sec 9.3.7.4. | 8 | See PCIe r6.2, sec 7.8.7. |
7 | 9 | ||
8 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> | 10 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> |
9 | Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | 11 | Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> |
10 | Reviewed-by: Christian König <christian.koenig@amd.com> | 12 | Reviewed-by: Christian König <christian.koenig@amd.com> |
11 | --- | 13 | --- |
12 | drivers/pci/iov.c | 30 +++++++++++++++++++++++++++++- | 14 | drivers/pci/iov.c | 30 +++++++++++++++++++++++++++++- |
13 | drivers/pci/pci.h | 1 + | 15 | drivers/pci/pci.h | 1 + |
14 | include/uapi/linux/pci_regs.h | 1 + | 16 | include/uapi/linux/pci_regs.h | 9 +++++++++ |
15 | 3 files changed, 31 insertions(+), 1 deletion(-) | 17 | 3 files changed, 39 insertions(+), 1 deletion(-) |
16 | 18 | ||
17 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c | 19 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c |
18 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/drivers/pci/iov.c | 21 | --- a/drivers/pci/iov.c |
20 | +++ b/drivers/pci/iov.c | 22 | +++ b/drivers/pci/iov.c |
... | ... | ||
45 | + | 47 | + |
46 | + pos = dev->sriov->vf_rebar_cap; | 48 | + pos = dev->sriov->vf_rebar_cap; |
47 | + if (!pos) | 49 | + if (!pos) |
48 | + return; | 50 | + return; |
49 | + | 51 | + |
50 | + pci_read_config_dword(dev, pos + PCI_REBAR_CTRL, &ctrl); | 52 | + pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl); |
51 | + nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl); | 53 | + nbars = FIELD_GET(PCI_VF_REBAR_CTRL_NBAR_MASK, ctrl); |
52 | + | 54 | + |
53 | + for (i = 0; i < nbars; i++, pos += 8) { | 55 | + for (i = 0; i < nbars; i++, pos += 8) { |
54 | + int bar_idx, size; | 56 | + int bar_idx, size; |
55 | + | 57 | + |
56 | + pci_read_config_dword(dev, pos + PCI_REBAR_CTRL, &ctrl); | 58 | + pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl); |
57 | + bar_idx = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, ctrl); | 59 | + bar_idx = FIELD_GET(PCI_VF_REBAR_CTRL_BAR_IDX, ctrl); |
58 | + size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]); | 60 | + size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]); |
59 | + ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; | 61 | + ctrl &= ~PCI_VF_REBAR_CTRL_BAR_SIZE; |
60 | + ctrl |= FIELD_PREP(PCI_REBAR_CTRL_BAR_SIZE, size); | 62 | + ctrl |= FIELD_PREP(PCI_VF_REBAR_CTRL_BAR_SIZE, size); |
61 | + pci_write_config_dword(dev, pos + PCI_REBAR_CTRL, ctrl); | 63 | + pci_write_config_dword(dev, pos + PCI_VF_REBAR_CTRL, ctrl); |
62 | + } | 64 | + } |
63 | +} | 65 | +} |
64 | + | 66 | + |
65 | static void sriov_restore_state(struct pci_dev *dev) | 67 | static void sriov_restore_state(struct pci_dev *dev) |
66 | { | 68 | { |
... | ... | ||
99 | #define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */ | 101 | #define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */ |
100 | +#define PCI_EXT_CAP_ID_VF_REBAR 0x24 /* VF Resizable BAR */ | 102 | +#define PCI_EXT_CAP_ID_VF_REBAR 0x24 /* VF Resizable BAR */ |
101 | #define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */ | 103 | #define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */ |
102 | #define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */ | 104 | #define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */ |
103 | #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ | 105 | #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ |
106 | @@ -XXX,XX +XXX,XX @@ | ||
107 | #define PCI_DVSEC_HEADER2 0x8 /* Designated Vendor-Specific Header2 */ | ||
108 | #define PCI_DVSEC_HEADER2_ID(x) ((x) & 0xffff) | ||
109 | |||
110 | +/* VF Resizable BARs, same layout as PCI_REBAR */ | ||
111 | +#define PCI_VF_REBAR_CAP PCI_REBAR_CAP | ||
112 | +#define PCI_VF_REBAR_CAP_SIZES PCI_REBAR_CAP_SIZES | ||
113 | +#define PCI_VF_REBAR_CTRL PCI_REBAR_CTRL | ||
114 | +#define PCI_VF_REBAR_CTRL_BAR_IDX PCI_REBAR_CTRL_BAR_IDX | ||
115 | +#define PCI_VF_REBAR_CTRL_NBAR_MASK PCI_REBAR_CTRL_NBAR_MASK | ||
116 | +#define PCI_VF_REBAR_CTRL_BAR_SIZE PCI_REBAR_CTRL_BAR_SIZE | ||
117 | + | ||
118 | /* Data Link Feature */ | ||
119 | #define PCI_DLF_CAP 0x04 /* Capabilities Register */ | ||
120 | #define PCI_DLF_EXCHANGE_ENABLE 0x80000000 /* Data Link Feature Exchange Enable */ | ||
104 | -- | 121 | -- |
105 | 2.49.0 | 122 | 2.49.0 |
106 | 123 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
6 | 6 | ||
7 | Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | 7 | Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> |
8 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> | 8 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> |
9 | Acked-by: Christian König <christian.koenig@amd.com> | 9 | Acked-by: Christian König <christian.koenig@amd.com> |
10 | --- | 10 | --- |
11 | drivers/pci/iov.c | 22 ++++++++++++---------- | 11 | drivers/pci/iov.c | 26 ++++++++++++++++---------- |
12 | drivers/pci/pci.h | 19 +++++++++++++++++++ | 12 | drivers/pci/pci.h | 19 +++++++++++++++++++ |
13 | drivers/pci/setup-bus.c | 3 ++- | 13 | drivers/pci/setup-bus.c | 3 ++- |
14 | 3 files changed, 33 insertions(+), 11 deletions(-) | 14 | 3 files changed, 37 insertions(+), 11 deletions(-) |
15 | 15 | ||
16 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c | 16 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c |
17 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/drivers/pci/iov.c | 18 | --- a/drivers/pci/iov.c |
19 | +++ b/drivers/pci/iov.c | 19 | +++ b/drivers/pci/iov.c |
... | ... | ||
29 | @@ -XXX,XX +XXX,XX @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id) | 29 | @@ -XXX,XX +XXX,XX @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id) |
30 | virtfn->multifunction = 0; | 30 | virtfn->multifunction = 0; |
31 | 31 | ||
32 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 32 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
33 | - res = &dev->resource[i + PCI_IOV_RESOURCES]; | 33 | - res = &dev->resource[i + PCI_IOV_RESOURCES]; |
34 | + res = &dev->resource[pci_resource_num_from_vf_bar(i)]; | 34 | + int idx = pci_resource_num_from_vf_bar(i); |
35 | + | ||
36 | + res = &dev->resource[idx]; | ||
35 | if (!res->parent) | 37 | if (!res->parent) |
36 | continue; | 38 | continue; |
37 | virtfn->resource[i].name = pci_name(virtfn); | 39 | virtfn->resource[i].name = pci_name(virtfn); |
38 | virtfn->resource[i].flags = res->flags; | 40 | virtfn->resource[i].flags = res->flags; |
39 | - size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES); | 41 | - size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES); |
40 | + size = pci_iov_resource_size(dev, | 42 | + size = pci_iov_resource_size(dev, idx); |
41 | + pci_resource_num_from_vf_bar(i)); | ||
42 | resource_set_range(&virtfn->resource[i], | 43 | resource_set_range(&virtfn->resource[i], |
43 | res->start + size * id, size); | 44 | res->start + size * id, size); |
44 | rc = request_resource(res, &virtfn->resource[i]); | 45 | rc = request_resource(res, &virtfn->resource[i]); |
45 | @@ -XXX,XX +XXX,XX @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | 46 | @@ -XXX,XX +XXX,XX @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) |
46 | 47 | ||
47 | nres = 0; | 48 | nres = 0; |
48 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 49 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
49 | - bars |= (1 << (i + PCI_IOV_RESOURCES)); | 50 | - bars |= (1 << (i + PCI_IOV_RESOURCES)); |
50 | - res = &dev->resource[i + PCI_IOV_RESOURCES]; | 51 | - res = &dev->resource[i + PCI_IOV_RESOURCES]; |
51 | + bars |= (1 << pci_resource_num_from_vf_bar(i)); | 52 | + int idx = pci_resource_num_from_vf_bar(i); |
52 | + res = &dev->resource[pci_resource_num_from_vf_bar(i)]; | 53 | + |
54 | + bars |= (1 << idx); | ||
55 | + res = &dev->resource[idx]; | ||
53 | if (res->parent) | 56 | if (res->parent) |
54 | nres++; | 57 | nres++; |
55 | } | 58 | } |
56 | @@ -XXX,XX +XXX,XX @@ static int sriov_init(struct pci_dev *dev, int pos) | 59 | @@ -XXX,XX +XXX,XX @@ static int sriov_init(struct pci_dev *dev, int pos) |
57 | 60 | ||
58 | nres = 0; | 61 | nres = 0; |
59 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 62 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
60 | - res = &dev->resource[i + PCI_IOV_RESOURCES]; | 63 | - res = &dev->resource[i + PCI_IOV_RESOURCES]; |
61 | - res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES); | 64 | - res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES); |
62 | + res = &dev->resource[pci_resource_num_from_vf_bar(i)]; | 65 | + int idx = pci_resource_num_from_vf_bar(i); |
63 | + res_name = pci_resource_name(dev, | 66 | + |
64 | + pci_resource_num_from_vf_bar(i)); | 67 | + res = &dev->resource[idx]; |
68 | + res_name = pci_resource_name(dev, idx); | ||
65 | 69 | ||
66 | /* | 70 | /* |
67 | * If it is already FIXED, don't change it, something | 71 | * If it is already FIXED, don't change it, something |
68 | @@ -XXX,XX +XXX,XX @@ static int sriov_init(struct pci_dev *dev, int pos) | 72 | @@ -XXX,XX +XXX,XX @@ static int sriov_init(struct pci_dev *dev, int pos) |
69 | dev->is_physfn = 0; | 73 | dev->is_physfn = 0; |
... | ... | ||
136 | @@ -XXX,XX +XXX,XX @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data) | 140 | @@ -XXX,XX +XXX,XX @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data) |
137 | bool *unassigned = data; | 141 | bool *unassigned = data; |
138 | 142 | ||
139 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 143 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
140 | - struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES]; | 144 | - struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES]; |
141 | + struct resource *r = | 145 | + int idx = pci_resource_num_from_vf_bar(i); |
142 | + &dev->resource[pci_resource_num_from_vf_bar(i)]; | 146 | + struct resource *r = &dev->resource[idx]; |
143 | struct pci_bus_region region; | 147 | struct pci_bus_region region; |
144 | 148 | ||
145 | /* Not assigned or rejected by kernel? */ | 149 | /* Not assigned or rejected by kernel? */ |
146 | -- | 150 | -- |
147 | 2.49.0 | 151 | 2.49.0 |
148 | 152 | diff view generated by jsdifflib |
1 | Similar to regular resizable BAR, VF BAR can also be resized. | 1 | Similar to regular resizable BAR, VF BAR can also be resized. |
---|---|---|---|
2 | 2 | ||
3 | The structures are very similar, which means we can reuse most of the | 3 | The capability layout is the same as PCI_EXT_CAP_ID_REBAR, which means |
4 | implementation. | 4 | we can reuse most of the implementation, the only difference being |
5 | resource size calculation (which is multiplied by total VFs) and memory | ||
6 | decoding (which is controlled by a separate VF MSE field in SR-IOV cap). | ||
5 | 7 | ||
6 | Extend the pci_resize_resource() function to accept IOV resources. | 8 | Extend the pci_resize_resource() function to accept IOV resources. |
7 | 9 | ||
8 | See PCIe r4.0, sec 9.3.7.4. | 10 | See PCIe r6.2, sec 7.8.7. |
9 | 11 | ||
10 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> | 12 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> |
11 | --- | 13 | --- |
12 | drivers/pci/iov.c | 21 +++++++++++++++++++++ | 14 | drivers/pci/iov.c | 21 +++++++++++++++++++++ |
13 | drivers/pci/pci.c | 8 +++++++- | 15 | drivers/pci/pci.c | 10 +++++++++- |
14 | drivers/pci/pci.h | 9 +++++++++ | 16 | drivers/pci/pci.h | 9 +++++++++ |
15 | drivers/pci/setup-res.c | 35 ++++++++++++++++++++++++++++++----- | 17 | drivers/pci/setup-res.c | 35 ++++++++++++++++++++++++++++++----- |
16 | 4 files changed, 67 insertions(+), 6 deletions(-) | 18 | 4 files changed, 69 insertions(+), 6 deletions(-) |
17 | 19 | ||
18 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c | 20 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c |
19 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/drivers/pci/iov.c | 22 | --- a/drivers/pci/iov.c |
21 | +++ b/drivers/pci/iov.c | 23 | +++ b/drivers/pci/iov.c |
... | ... | ||
55 | unsigned int pos, nbars, i; | 57 | unsigned int pos, nbars, i; |
56 | u32 ctrl; | 58 | u32 ctrl; |
57 | 59 | ||
58 | - pos = pdev->rebar_cap; | 60 | - pos = pdev->rebar_cap; |
59 | + if (pci_resource_is_iov(bar)) { | 61 | + if (pci_resource_is_iov(bar)) { |
60 | + pos = pdev->physfn ? pdev->sriov->vf_rebar_cap : 0; | 62 | + if (!pdev->physfn) |
63 | + return -ENOTSUPP; | ||
64 | + pos = pdev->sriov->vf_rebar_cap; | ||
61 | + bar = pci_resource_num_to_vf_bar(bar); | 65 | + bar = pci_resource_num_to_vf_bar(bar); |
62 | + } else { | 66 | + } else { |
63 | + pos = pdev->rebar_cap; | 67 | + pos = pdev->rebar_cap; |
64 | + } | 68 | + } |
65 | + | 69 | + |
... | ... | diff view generated by jsdifflib |
1 | When the resource representing VF MMIO BAR reservation is created, its | 1 | When the resource representing VF MMIO BAR reservation is created, its |
---|---|---|---|
2 | size is always large enough to accommodate the BAR of all SR-IOV Virtual | 2 | size is always large enough to accommodate the BAR of all SR-IOV Virtual |
3 | Functions that can potentially be created (total VFs). If for whatever | 3 | Functions that can potentially be created (total VFs). If for whatever |
4 | reason it's not possible to accommodate all VFs - the resource is not | 4 | reason it's not possible to accommodate all VFs - the resource is not |
5 | assigned and no VFs can be created. | 5 | assigned and no VFs can be created. |
6 | 6 | ||
7 | The following patch will allow VF BAR size to be modified by drivers at | 7 | An upcoming change will allow VF BAR size to be modified by drivers at |
8 | a later point in time, which means that the check for resource | 8 | a later point in time, which means that the check for resource |
9 | assignment is no longer sufficient. | 9 | assignment is no longer sufficient. |
10 | 10 | ||
11 | Add an additional check that verifies that VF BAR for all enabled VFs | 11 | Add an additional check that verifies that VF BAR for all enabled VFs |
12 | fits within the underlying reservation resource. | 12 | fits within the underlying reservation resource. |
13 | 13 | ||
14 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> | 14 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> |
15 | --- | 15 | --- |
16 | drivers/pci/iov.c | 5 +++++ | 16 | drivers/pci/iov.c | 3 +++ |
17 | 1 file changed, 5 insertions(+) | 17 | 1 file changed, 3 insertions(+) |
18 | 18 | ||
19 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c | 19 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c |
20 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/drivers/pci/iov.c | 21 | --- a/drivers/pci/iov.c |
22 | +++ b/drivers/pci/iov.c | 22 | +++ b/drivers/pci/iov.c |
23 | @@ -XXX,XX +XXX,XX @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | 23 | @@ -XXX,XX +XXX,XX @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) |
24 | |||
25 | nres = 0; | 24 | nres = 0; |
26 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 25 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
27 | + resource_size_t vf_bar_sz = | 26 | int idx = pci_resource_num_from_vf_bar(i); |
28 | + pci_iov_resource_size(dev, | 27 | + resource_size_t vf_bar_sz = pci_iov_resource_size(dev, idx); |
29 | + pci_resource_num_from_vf_bar(i)); | 28 | |
30 | bars |= (1 << pci_resource_num_from_vf_bar(i)); | 29 | bars |= (1 << idx); |
31 | res = &dev->resource[pci_resource_num_from_vf_bar(i)]; | 30 | res = &dev->resource[idx]; |
32 | + if (vf_bar_sz * nr_virtfn > resource_size(res)) | 31 | + if (vf_bar_sz * nr_virtfn > resource_size(res)) |
33 | + continue; | 32 | + continue; |
34 | if (res->parent) | 33 | if (res->parent) |
35 | nres++; | 34 | nres++; |
36 | } | 35 | } |
37 | -- | 36 | -- |
38 | 2.49.0 | 37 | 2.49.0 |
39 | 38 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
7 | allow up to num_vfs to be successfully enabled with the current | 7 | allow up to num_vfs to be successfully enabled with the current |
8 | underlying reservation size. | 8 | underlying reservation size. |
9 | 9 | ||
10 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> | 10 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> |
11 | --- | 11 | --- |
12 | drivers/pci/iov.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ | 12 | drivers/pci/iov.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ |
13 | include/linux/pci.h | 6 ++++ | 13 | include/linux/pci.h | 6 ++++ |
14 | 2 files changed, 84 insertions(+) | 14 | 2 files changed, 75 insertions(+) |
15 | 15 | ||
16 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c | 16 | diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c |
17 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/drivers/pci/iov.c | 18 | --- a/drivers/pci/iov.c |
19 | +++ b/drivers/pci/iov.c | 19 | +++ b/drivers/pci/iov.c |
... | ... | ||
32 | + * Unlike pci_resize_resource(), this does not cause the resource that | 32 | + * Unlike pci_resize_resource(), this does not cause the resource that |
33 | + * reserves the MMIO space (originally up to total_VFs) to be resized, which | 33 | + * reserves the MMIO space (originally up to total_VFs) to be resized, which |
34 | + * means that following calls to pci_enable_sriov() can fail if the resources | 34 | + * means that following calls to pci_enable_sriov() can fail if the resources |
35 | + * no longer fit. | 35 | + * no longer fit. |
36 | + * | 36 | + * |
37 | + * Returns 0 on success, or negative on failure. | 37 | + * Return: 0 on success, or negative on failure. |
38 | + */ | 38 | + */ |
39 | +int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size) | 39 | +int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size) |
40 | +{ | 40 | +{ |
41 | + int ret; | 41 | + int ret; |
42 | + u32 sizes; | 42 | + u32 sizes; |
... | ... | ||
68 | + * pci_iov_vf_bar_get_sizes - get VF BAR sizes allowing to create up to num_vfs | 68 | + * pci_iov_vf_bar_get_sizes - get VF BAR sizes allowing to create up to num_vfs |
69 | + * @dev: the PCI device | 69 | + * @dev: the PCI device |
70 | + * @resno: the resource number | 70 | + * @resno: the resource number |
71 | + * @num_vfs: number of VFs | 71 | + * @num_vfs: number of VFs |
72 | + * | 72 | + * |
73 | + * Get the sizes of a VF resizable BAR that can be accommodated within the | 73 | + * Get the sizes of a VF resizable BAR that can accommodate @num_vfs within |
74 | + * resource that reserves the MMIO space if num_vfs are enabled. | 74 | + * the currently assigned size of the resource @resno. |
75 | + * | 75 | + * |
76 | + * Returns 0 if BAR isn't resizable, otherwise returns a bitmask in format | 76 | + * Return: A bitmask of sizes in format defined in the spec (bit 0=1MB, |
77 | + * defined in the spec (bit 0=1MB, bit 31=128TB). | 77 | + * bit 31=128TB). |
78 | + */ | 78 | + */ |
79 | +u32 pci_iov_vf_bar_get_sizes(struct pci_dev *dev, int resno, int num_vfs) | 79 | +u32 pci_iov_vf_bar_get_sizes(struct pci_dev *dev, int resno, int num_vfs) |
80 | +{ | 80 | +{ |
81 | + resource_size_t size; | 81 | + resource_size_t vf_len = pci_resource_len(dev, resno); |
82 | + u32 sizes; | 82 | + u32 sizes; |
83 | + int i; | ||
84 | + | 83 | + |
85 | + sizes = pci_rebar_get_possible_sizes(dev, resno); | 84 | + if (!num_vfs) |
86 | + if (!sizes) | ||
87 | + return 0; | 85 | + return 0; |
88 | + | 86 | + |
89 | + while (sizes > 0) { | 87 | + do_div(vf_len, num_vfs); |
90 | + i = __fls(sizes); | 88 | + sizes = (roundup_pow_of_two(vf_len + 1) - 1) >> ilog2(SZ_1M); |
91 | + size = pci_rebar_size_to_bytes(i); | ||
92 | + | 89 | + |
93 | + if (size * num_vfs <= pci_resource_len(dev, resno)) | 90 | + return sizes & pci_rebar_get_possible_sizes(dev, resno); |
94 | + break; | ||
95 | + | ||
96 | + sizes &= ~BIT(i); | ||
97 | + } | ||
98 | + | ||
99 | + return sizes; | ||
100 | +} | 91 | +} |
101 | +EXPORT_SYMBOL_GPL(pci_iov_vf_bar_get_sizes); | 92 | +EXPORT_SYMBOL_GPL(pci_iov_vf_bar_get_sizes); |
102 | diff --git a/include/linux/pci.h b/include/linux/pci.h | 93 | diff --git a/include/linux/pci.h b/include/linux/pci.h |
103 | index XXXXXXX..XXXXXXX 100644 | 94 | index XXXXXXX..XXXXXXX 100644 |
104 | --- a/include/linux/pci.h | 95 | --- a/include/linux/pci.h |
... | ... | diff view generated by jsdifflib |
1 | LMEM is partitioned between multiple VFs and we expect that the more | 1 | LMEM is partitioned between multiple VFs and we expect that the more |
---|---|---|---|
2 | VFs we have, the less LMEM is assigned to each VF. | 2 | VFs we have, the less LMEM is assigned to each VF. |
3 | This means that we can achieve full LMEM BAR access without the need to | 3 | This means that we can achieve full LMEM BAR access without the need to |
4 | attempt full VF LMEM BAR resize via pci_resize_resource(). | 4 | attempt full VF LMEM BAR resize via pci_resize_resource(). |
5 | 5 | ||
6 | Always set the largest possible BAR size that allows to fit the number | 6 | Always try to set the largest possible BAR size that allows to fit the |
7 | of enabled VFs. | 7 | number of enabled VFs and inform the user in case the resize attempt is |
8 | not successful. | ||
8 | 9 | ||
9 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> | 10 | Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> |
11 | Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | ||
10 | --- | 12 | --- |
11 | drivers/gpu/drm/xe/regs/xe_bars.h | 1 + | 13 | drivers/gpu/drm/xe/regs/xe_bars.h | 1 + |
12 | drivers/gpu/drm/xe/xe_pci_sriov.c | 22 ++++++++++++++++++++++ | 14 | drivers/gpu/drm/xe/xe_pci_sriov.c | 22 ++++++++++++++++++++++ |
13 | 2 files changed, 23 insertions(+) | 15 | 2 files changed, 23 insertions(+) |
14 | 16 | ||
... | ... | ||
36 | + | 38 | + |
37 | +#include "regs/xe_bars.h" | 39 | +#include "regs/xe_bars.h" |
38 | #include "xe_assert.h" | 40 | #include "xe_assert.h" |
39 | #include "xe_device.h" | 41 | #include "xe_device.h" |
40 | #include "xe_gt_sriov_pf_config.h" | 42 | #include "xe_gt_sriov_pf_config.h" |
41 | @@ -XXX,XX +XXX,XX @@ static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) | 43 | @@ -XXX,XX +XXX,XX @@ static void pf_link_vfs(struct xe_device *xe, int num_vfs) |
42 | xe_gt_sriov_pf_control_trigger_flr(gt, n); | 44 | } |
43 | } | 45 | } |
44 | 46 | ||
45 | +static int resize_vf_vram_bar(struct xe_device *xe, int num_vfs) | 47 | +static int resize_vf_vram_bar(struct xe_device *xe, int num_vfs) |
46 | +{ | 48 | +{ |
47 | + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); | 49 | + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); |
... | ... | diff view generated by jsdifflib |