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