1
Hi,
1
Hi,
2
2
3
No major logic changes since v4, just a few tweaks to docs, commit
3
Another revision after the feedback from Ilpo.
4
messages and function naming.
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
v4 can be found here:
7
v6 can be found here:
7
https://lore.kernel.org/linux-pci/20241025215038.3125626-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)
27
28
v5 -> v6:
29
- Rebased on latest pci/next
30
- Cache the VF resizable BAR capability position to avoid multiple
31
lookups (Ilpo)
32
- Use pci_resource_n helper (Ilpo)
19
33
20
v4 -> v5:
34
v4 -> v5:
21
- Rename pci_resource_to/from_iov helpers and add WARN if called without
35
- Rename pci_resource_to/from_iov helpers and add WARN if called without
22
CONFIG_PCI_IOV (Ilpo)
36
CONFIG_PCI_IOV (Ilpo)
23
- Reword kerneldoc for pci_iov_vf_bar_get_sizes (Bjorn)
37
- Reword kerneldoc for pci_iov_vf_bar_get_sizes (Bjorn)
...
...
53
PCI: Allow drivers to control VF BAR size
67
PCI: Allow drivers to control VF BAR size
54
drm/xe/pf: Set VF LMEM BAR size
68
drm/xe/pf: Set VF LMEM BAR size
55
69
56
drivers/gpu/drm/xe/regs/xe_bars.h | 1 +
70
drivers/gpu/drm/xe/regs/xe_bars.h | 1 +
57
drivers/gpu/drm/xe/xe_pci_sriov.c | 22 +++++
71
drivers/gpu/drm/xe/xe_pci_sriov.c | 22 +++++
58
drivers/pci/iov.c | 155 +++++++++++++++++++++++++++---
72
drivers/pci/iov.c | 149 +++++++++++++++++++++++++++---
59
drivers/pci/pci.c | 10 +-
73
drivers/pci/pci.c | 10 +-
60
drivers/pci/pci.h | 28 ++++++
74
drivers/pci/pci.h | 29 ++++++
61
drivers/pci/setup-bus.c | 3 +-
75
drivers/pci/setup-bus.c | 3 +-
62
drivers/pci/setup-res.c | 35 ++++++-
76
drivers/pci/setup-res.c | 35 ++++++-
63
include/linux/pci.h | 6 ++
77
include/linux/pci.h | 6 ++
64
include/uapi/linux/pci_regs.h | 1 +
78
include/uapi/linux/pci_regs.h | 9 ++
65
9 files changed, 243 insertions(+), 18 deletions(-)
79
9 files changed, 246 insertions(+), 18 deletions(-)
66
80
67
--
81
--
68
2.48.1
82
2.49.0
69
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 | 29 ++++++++++++++++++++++++++++-
14
drivers/pci/iov.c | 30 +++++++++++++++++++++++++++++-
13
include/uapi/linux/pci_regs.h | 1 +
15
drivers/pci/pci.h | 1 +
14
2 files changed, 29 insertions(+), 1 deletion(-)
16
include/uapi/linux/pci_regs.h | 9 +++++++++
17
3 files changed, 39 insertions(+), 1 deletion(-)
15
18
16
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
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/drivers/pci/iov.c
21
--- a/drivers/pci/iov.c
19
+++ b/drivers/pci/iov.c
22
+++ b/drivers/pci/iov.c
...
...
23
26
24
+#include <linux/bitfield.h>
27
+#include <linux/bitfield.h>
25
#include <linux/pci.h>
28
#include <linux/pci.h>
26
#include <linux/slab.h>
29
#include <linux/slab.h>
27
#include <linux/export.h>
30
#include <linux/export.h>
31
@@ -XXX,XX +XXX,XX @@ static int sriov_init(struct pci_dev *dev, int pos)
32
    pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
33
    if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)
34
        iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link);
35
+    iov->vf_rebar_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VF_REBAR);
36
37
    if (pdev)
38
        iov->dev = pci_dev_get(pdev);
28
@@ -XXX,XX +XXX,XX @@ static void sriov_release(struct pci_dev *dev)
39
@@ -XXX,XX +XXX,XX @@ static void sriov_release(struct pci_dev *dev)
29
    dev->sriov = NULL;
40
    dev->sriov = NULL;
30
}
41
}
31
42
32
+static void sriov_restore_vf_rebar_state(struct pci_dev *dev)
43
+static void sriov_restore_vf_rebar_state(struct pci_dev *dev)
33
+{
44
+{
34
+    unsigned int pos, nbars, i;
45
+    unsigned int pos, nbars, i;
35
+    u32 ctrl;
46
+    u32 ctrl;
36
+
47
+
37
+    pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VF_REBAR);
48
+    pos = dev->sriov->vf_rebar_cap;
38
+    if (!pos)
49
+    if (!pos)
39
+        return;
50
+        return;
40
+
51
+
41
+    pci_read_config_dword(dev, pos + PCI_REBAR_CTRL, &ctrl);
52
+    pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl);
42
+    nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl);
53
+    nbars = FIELD_GET(PCI_VF_REBAR_CTRL_NBAR_MASK, ctrl);
43
+
54
+
44
+    for (i = 0; i < nbars; i++, pos += 8) {
55
+    for (i = 0; i < nbars; i++, pos += 8) {
45
+        int bar_idx, size;
56
+        int bar_idx, size;
46
+
57
+
47
+        pci_read_config_dword(dev, pos + PCI_REBAR_CTRL, &ctrl);
58
+        pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl);
48
+        bar_idx = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, ctrl);
59
+        bar_idx = FIELD_GET(PCI_VF_REBAR_CTRL_BAR_IDX, ctrl);
49
+        size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]);
60
+        size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]);
50
+        ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
61
+        ctrl &= ~PCI_VF_REBAR_CTRL_BAR_SIZE;
51
+        ctrl |= FIELD_PREP(PCI_REBAR_CTRL_BAR_SIZE, size);
62
+        ctrl |= FIELD_PREP(PCI_VF_REBAR_CTRL_BAR_SIZE, size);
52
+        pci_write_config_dword(dev, pos + PCI_REBAR_CTRL, ctrl);
63
+        pci_write_config_dword(dev, pos + PCI_VF_REBAR_CTRL, ctrl);
53
+    }
64
+    }
54
+}
65
+}
55
+
66
+
56
static void sriov_restore_state(struct pci_dev *dev)
67
static void sriov_restore_state(struct pci_dev *dev)
57
{
68
{
...
...
66
        sriov_restore_state(dev);
77
        sriov_restore_state(dev);
67
+    }
78
+    }
68
}
79
}
69
80
70
/**
81
/**
82
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
83
index XXXXXXX..XXXXXXX 100644
84
--- a/drivers/pci/pci.h
85
+++ b/drivers/pci/pci.h
86
@@ -XXX,XX +XXX,XX @@ struct pci_sriov {
87
    u16        subsystem_vendor; /* VF subsystem vendor */
88
    u16        subsystem_device; /* VF subsystem device */
89
    resource_size_t    barsz[PCI_SRIOV_NUM_BARS];    /* VF BAR size */
90
+    u16        vf_rebar_cap;    /* VF Resizable BAR capability offset */
91
    bool        drivers_autoprobe; /* Auto probing of VFs by driver */
92
};
93
71
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
94
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
72
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
73
--- a/include/uapi/linux/pci_regs.h
96
--- a/include/uapi/linux/pci_regs.h
74
+++ b/include/uapi/linux/pci_regs.h
97
+++ b/include/uapi/linux/pci_regs.h
75
@@ -XXX,XX +XXX,XX @@
98
@@ -XXX,XX +XXX,XX @@
...
...
78
#define PCI_EXT_CAP_ID_DVSEC    0x23    /* Designated Vendor-Specific */
101
#define PCI_EXT_CAP_ID_DVSEC    0x23    /* Designated Vendor-Specific */
79
+#define PCI_EXT_CAP_ID_VF_REBAR 0x24    /* VF Resizable BAR */
102
+#define PCI_EXT_CAP_ID_VF_REBAR 0x24    /* VF Resizable BAR */
80
#define PCI_EXT_CAP_ID_DLF    0x25    /* Data Link Feature */
103
#define PCI_EXT_CAP_ID_DLF    0x25    /* Data Link Feature */
81
#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 */
82
#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 */
83
--
121
--
84
2.48.1
122
2.49.0
85
123
diff view generated by jsdifflib
...
...
4
Extract the logic to pci_resource_num_from_vf_bar() and
4
Extract the logic to pci_resource_num_from_vf_bar() and
5
pci_resource_num_to_vf_bar() helpers.
5
pci_resource_num_to_vf_bar() helpers.
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
---
10
---
10
drivers/pci/iov.c | 22 ++++++++++++----------
11
drivers/pci/iov.c | 26 ++++++++++++++++----------
11
drivers/pci/pci.h | 19 +++++++++++++++++++
12
drivers/pci/pci.h | 19 +++++++++++++++++++
12
drivers/pci/setup-bus.c | 3 ++-
13
drivers/pci/setup-bus.c | 3 ++-
13
3 files changed, 33 insertions(+), 11 deletions(-)
14
3 files changed, 37 insertions(+), 11 deletions(-)
14
15
15
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
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/drivers/pci/iov.c
18
--- a/drivers/pci/iov.c
18
+++ b/drivers/pci/iov.c
19
+++ b/drivers/pci/iov.c
...
...
28
@@ -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)
29
    virtfn->multifunction = 0;
30
    virtfn->multifunction = 0;
30
31
31
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
32
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
32
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
33
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
33
+        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];
34
        if (!res->parent)
37
        if (!res->parent)
35
            continue;
38
            continue;
36
        virtfn->resource[i].name = pci_name(virtfn);
39
        virtfn->resource[i].name = pci_name(virtfn);
37
        virtfn->resource[i].flags = res->flags;
40
        virtfn->resource[i].flags = res->flags;
38
-        size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
41
-        size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
39
+        size = pci_iov_resource_size(dev,
42
+        size = pci_iov_resource_size(dev, idx);
40
+                     pci_resource_num_from_vf_bar(i));
41
        resource_set_range(&virtfn->resource[i],
43
        resource_set_range(&virtfn->resource[i],
42
                 res->start + size * id, size);
44
                 res->start + size * id, size);
43
        rc = request_resource(res, &virtfn->resource[i]);
45
        rc = request_resource(res, &virtfn->resource[i]);
44
@@ -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)
45
47
46
    nres = 0;
48
    nres = 0;
47
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
49
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
48
-        bars |= (1 << (i + PCI_IOV_RESOURCES));
50
-        bars |= (1 << (i + PCI_IOV_RESOURCES));
49
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
51
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
50
+        bars |= (1 << pci_resource_num_from_vf_bar(i));
52
+        int idx = pci_resource_num_from_vf_bar(i);
51
+        res = &dev->resource[pci_resource_num_from_vf_bar(i)];
53
+
54
+        bars |= (1 << idx);
55
+        res = &dev->resource[idx];
52
        if (res->parent)
56
        if (res->parent)
53
            nres++;
57
            nres++;
54
    }
58
    }
55
@@ -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)
56
60
57
    nres = 0;
61
    nres = 0;
58
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
62
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
59
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
63
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
60
-        res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES);
64
-        res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES);
61
+        res = &dev->resource[pci_resource_num_from_vf_bar(i)];
65
+        int idx = pci_resource_num_from_vf_bar(i);
62
+        res_name = pci_resource_name(dev,
66
+
63
+                     pci_resource_num_from_vf_bar(i));
67
+        res = &dev->resource[idx];
68
+        res_name = pci_resource_name(dev, idx);
64
69
65
        /*
70
        /*
66
         * If it is already FIXED, don't change it, something
71
         * If it is already FIXED, don't change it, something
67
@@ -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)
68
    dev->is_physfn = 0;
73
    dev->is_physfn = 0;
...
...
135
@@ -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)
136
    bool *unassigned = data;
141
    bool *unassigned = data;
137
142
138
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
143
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
139
-        struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES];
144
-        struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES];
140
+        struct resource *r =
145
+        int idx = pci_resource_num_from_vf_bar(i);
141
+            &dev->resource[pci_resource_num_from_vf_bar(i)];
146
+        struct resource *r = &dev->resource[idx];
142
        struct pci_bus_region region;
147
        struct pci_bus_region region;
143
148
144
        /* Not assigned or rejected by kernel? */
149
        /* Not assigned or rejected by kernel? */
145
--
150
--
146
2.48.1
151
2.49.0
147
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 | 10 +++++++++-
15
drivers/pci/pci.c | 10 +++++++++-
...
...
50
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
52
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
51
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
52
--- a/drivers/pci/pci.c
54
--- a/drivers/pci/pci.c
53
+++ b/drivers/pci/pci.c
55
+++ b/drivers/pci/pci.c
54
@@ -XXX,XX +XXX,XX @@ static int pci_rebar_find_pos(struct pci_dev *pdev, int bar)
56
@@ -XXX,XX +XXX,XX @@ static int pci_rebar_find_pos(struct pci_dev *pdev, int bar)
55
{
56
    unsigned int pos, nbars, i;
57
    unsigned int pos, nbars, i;
57
    u32 ctrl;
58
    u32 ctrl;
58
+    int cap;
59
59
60
-    pos = pdev->rebar_cap;
60
-    pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR);
61
+    if (pci_resource_is_iov(bar)) {
61
+    if (pci_resource_is_iov(bar)) {
62
+        cap = PCI_EXT_CAP_ID_VF_REBAR;
62
+        if (!pdev->physfn)
63
+            return -ENOTSUPP;
64
+        pos = pdev->sriov->vf_rebar_cap;
63
+        bar = pci_resource_num_to_vf_bar(bar);
65
+        bar = pci_resource_num_to_vf_bar(bar);
64
+    } else {
66
+    } else {
65
+        cap = PCI_EXT_CAP_ID_REBAR;
67
+        pos = pdev->rebar_cap;
66
+    }
68
+    }
67
+
69
+
68
+    pos = pci_find_ext_capability(pdev, cap);
69
    if (!pos)
70
    if (!pos)
70
        return -ENOTSUPP;
71
        return -ENOTSUPP;
71
72
72
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
73
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
73
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
...
...
119
+
120
+
120
+static void pci_resize_resource_set_size(struct pci_dev *dev, int resno,
121
+static void pci_resize_resource_set_size(struct pci_dev *dev, int resno,
121
+                     int size)
122
+                     int size)
122
+{
123
+{
123
+    resource_size_t res_size = pci_rebar_size_to_bytes(size);
124
+    resource_size_t res_size = pci_rebar_size_to_bytes(size);
124
+    struct resource *res = dev->resource + resno;
125
+    struct resource *res = pci_resource_n(dev, resno);
125
+
126
+
126
+    if (!pci_resource_is_iov(resno)) {
127
+    if (!pci_resource_is_iov(resno)) {
127
+        resource_set_size(res, res_size);
128
+        resource_set_size(res, res_size);
128
+    } else {
129
+    } else {
129
+        resource_set_size(res, res_size * pci_sriov_get_totalvfs(dev));
130
+        resource_set_size(res, res_size * pci_sriov_get_totalvfs(dev));
...
...
168
+    pci_resize_resource_set_size(dev, resno, old);
169
+    pci_resize_resource_set_size(dev, resno, old);
169
    return ret;
170
    return ret;
170
}
171
}
171
EXPORT_SYMBOL(pci_resize_resource);
172
EXPORT_SYMBOL(pci_resize_resource);
172
--
173
--
173
2.48.1
174
2.49.0
174
175
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).
3
Functions that can potentially be created (total VFs). If for whatever
4
4
reason it's not possible to accommodate all VFs - the resource is not
5
If it's not possible to accommodate all VFs - the resource is not
6
assigned and no VFs can be created.
5
assigned and no VFs can be created.
7
6
8
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
9
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
10
assignment is no longer sufficient.
9
assignment is no longer sufficient.
11
10
12
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
13
fits within the underlying reservation resource.
12
fits within the underlying reservation resource.
14
13
15
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
14
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
16
---
15
---
17
drivers/pci/iov.c | 5 +++++
16
drivers/pci/iov.c | 3 +++
18
1 file changed, 5 insertions(+)
17
1 file changed, 3 insertions(+)
19
18
20
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
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/drivers/pci/iov.c
21
--- a/drivers/pci/iov.c
23
+++ b/drivers/pci/iov.c
22
+++ b/drivers/pci/iov.c
24
@@ -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)
25
26
    nres = 0;
24
    nres = 0;
27
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
25
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
28
+        resource_size_t vf_bar_sz =
26
        int idx = pci_resource_num_from_vf_bar(i);
29
+            pci_iov_resource_size(dev,
27
+        resource_size_t vf_bar_sz = pci_iov_resource_size(dev, idx);
30
+                     pci_resource_num_from_vf_bar(i));
28
31
        bars |= (1 << pci_resource_num_from_vf_bar(i));
29
        bars |= (1 << idx);
32
        res = &dev->resource[pci_resource_num_from_vf_bar(i)];
30
        res = &dev->resource[idx];
33
+        if (vf_bar_sz * nr_virtfn > resource_size(res))
31
+        if (vf_bar_sz * nr_virtfn > resource_size(res))
34
+            continue;
32
+            continue;
35
        if (res->parent)
33
        if (res->parent)
36
            nres++;
34
            nres++;
37
    }
35
    }
38
--
36
--
39
2.48.1
37
2.49.0
40
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
...
...
122
+{ return 0; }
113
+{ return 0; }
123
static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { }
114
static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { }
124
#endif
115
#endif
125
116
126
--
117
--
127
2.48.1
118
2.49.0
128
119
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);
...
...
69
+
71
+
70
    err = pci_enable_sriov(pdev, num_vfs);
72
    err = pci_enable_sriov(pdev, num_vfs);
71
    if (err < 0)
73
    if (err < 0)
72
        goto failed;
74
        goto failed;
73
--
75
--
74
2.48.1
76
2.49.0
75
77
diff view generated by jsdifflib