1
Hi,
1
Hi,
2
2
3
In v4, the approach to extending the BAR was changed to follow the
3
Another revision after the feedback from Ilpo.
4
suggestion from Christian.
4
Few tweaks here and there, the biggest change is the removal of the
5
The control is now entirely on the driver side, with PCI subsystem
5
loop in pci_iov_vf_bar_get_sizes().
6
checking whether the resource fits during VF enabling.
7
I also added helpers to move between IOV / BAR # (suggested by Ilpo),
8
since the ifdefs started to look mighty ugly after addressing some of
9
the review feedback.
10
6
11
v3 can be found here:
7
v6 can be found here:
12
https://lore.kernel.org/dri-devel/20241010103203.382898-1-michal.winiarski@intel.com/
8
https://lore.kernel.org/linux-pci/20250320110854.3866284-1-michal.winiarski@intel.com/
13
9
14
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
15
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
16
driver can query using pci_rebar_get_possible_sizes.
12
driver can query using pci_rebar_get_possible_sizes.
17
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.
...
...
20
resource boundary).
16
resource boundary).
21
17
22
Thanks,
18
Thanks,
23
-Michał
19
-Michał
24
20
25
v1 -> v2:
21
v6 -> v7:
26
- Add pci_iov_resource_extend() and usage in Xe driver
22
- Eliminate the loop in pci_iov_vf_bar_get_sizes() (Ilpo)
27
- Reduce the number of ifdefs (Christian)
23
- Use helper variable for indexes (Ilpo)
28
- Drop patch 2/2 from v1 (Christian)
24
- Kerneldoc formatting (Ilpo)
29
- Add a helper to avoid upsetting static analysis tools (Krzysztof)
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)
33
34
v4 -> v5:
35
- Rename pci_resource_to/from_iov helpers and add WARN if called without
36
CONFIG_PCI_IOV (Ilpo)
37
- Reword kerneldoc for pci_iov_vf_bar_get_sizes (Bjorn)
38
- Reword commit message for VF BAR size check, extract the additional
39
size check to separate conditional (Bjorn)
40
41
v3 -> v4:
42
- Change the approach to extending the BAR (Christian)
43
- Tidy the commit messages, use 80 line limit where necessary (Bjorn)
44
- Add kerneldocs to exported functions (Bjorn)
45
- Add pci_resource_to_iov() / pci_resource_from_iov() helpers (Ilpo)
46
- Use FIELD_GET(), tidy whitespace (Ilpo)
30
47
31
v2 -> v3:
48
v2 -> v3:
32
- Extract introducing pci_resource_is_iov to separate commit and
49
- Extract introducing pci_resource_is_iov to separate commit and
33
use it elsewhere in PCI subsystem (Christian)
50
use it elsewhere in PCI subsystem (Christian)
34
- Extract restoring VF rebar state to separate commit (Christian)
51
- Extract restoring VF rebar state to separate commit (Christian)
35
- Reorganize memory decoding check (Christian)
52
- Reorganize memory decoding check (Christian)
36
- Don't use dev_WARN (Ilpo)
53
- Don't use dev_WARN (Ilpo)
37
- Fix build without CONFIG_PCI_IOV (CI)
54
- Fix build without CONFIG_PCI_IOV (CI)
38
55
39
v3 -> v4:
56
v1 -> v2:
40
- Change the approach to extending the BAR (Christian)
57
- Add pci_iov_resource_extend() and usage in Xe driver
41
- Tidy the commit messages, use 80 line limit where necessary (Bjorn)
58
- Reduce the number of ifdefs (Christian)
42
- Add kerneldocs to exported functions (Bjorn)
59
- Drop patch 2/2 from v1 (Christian)
43
- Add pci_resource_to_iov() / pci_resource_from_iov() helpers (Ilpo)
60
- Add a helper to avoid upsetting static analysis tools (Krzysztof)
44
- Use FIELD_GET(), tidy whitespace (Ilpo)
45
61
46
Michał Winiarski (7):
62
Michał Winiarski (6):
47
PCI/IOV: Restore VF resizable BAR state after reset
63
PCI/IOV: Restore VF resizable BAR state after reset
48
PCI: Add a helper to identify IOV resources
64
PCI: Add a helper to convert between VF BAR number and IOV resource
49
PCI: Add a helper to convert between standard and IOV resources
50
PCI: Allow IOV resources to be resized in pci_resize_resource()
65
PCI: Allow IOV resources to be resized in pci_resize_resource()
51
PCI/IOV: Check that VF BAR fits within the reservation
66
PCI/IOV: Check that VF BAR fits within the reservation
52
PCI: Allow drivers to control VF BAR size
67
PCI: Allow drivers to control VF BAR size
53
drm/xe/pf: Set VF LMEM BAR size
68
drm/xe/pf: Set VF LMEM BAR size
54
69
55
drivers/gpu/drm/xe/regs/xe_bars.h | 1 +
70
drivers/gpu/drm/xe/regs/xe_bars.h | 1 +
56
drivers/gpu/drm/xe/xe_pci_sriov.c | 22 +++++
71
drivers/gpu/drm/xe/xe_pci_sriov.c | 22 +++++
57
drivers/pci/iov.c | 158 +++++++++++++++++++++++++++---
72
drivers/pci/iov.c | 149 +++++++++++++++++++++++++++---
58
drivers/pci/pci.c | 10 +-
73
drivers/pci/pci.c | 10 +-
59
drivers/pci/pci.h | 45 ++++++++-
74
drivers/pci/pci.h | 29 ++++++
60
drivers/pci/setup-bus.c | 9 +-
75
drivers/pci/setup-bus.c | 3 +-
61
drivers/pci/setup-res.c | 40 ++++++--
76
drivers/pci/setup-res.c | 35 ++++++-
62
include/linux/pci.h | 6 ++
77
include/linux/pci.h | 6 ++
63
include/uapi/linux/pci_regs.h | 1 +
78
include/uapi/linux/pci_regs.h | 9 ++
64
9 files changed, 261 insertions(+), 31 deletions(-)
79
9 files changed, 246 insertions(+), 18 deletions(-)
65
80
66
--
81
--
67
2.47.0
82
2.49.0
68
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>
12
Reviewed-by: Christian König <christian.koenig@amd.com>
10
---
13
---
11
drivers/pci/iov.c | 29 ++++++++++++++++++++++++++++-
14
drivers/pci/iov.c | 30 +++++++++++++++++++++++++++++-
12
include/uapi/linux/pci_regs.h | 1 +
15
drivers/pci/pci.h | 1 +
13
2 files changed, 29 insertions(+), 1 deletion(-)
16
include/uapi/linux/pci_regs.h | 9 +++++++++
17
3 files changed, 39 insertions(+), 1 deletion(-)
14
18
15
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
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/drivers/pci/iov.c
21
--- a/drivers/pci/iov.c
18
+++ b/drivers/pci/iov.c
22
+++ b/drivers/pci/iov.c
...
...
22
26
23
+#include <linux/bitfield.h>
27
+#include <linux/bitfield.h>
24
#include <linux/pci.h>
28
#include <linux/pci.h>
25
#include <linux/slab.h>
29
#include <linux/slab.h>
26
#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);
27
@@ -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)
28
    dev->sriov = NULL;
40
    dev->sriov = NULL;
29
}
41
}
30
42
31
+static void sriov_restore_vf_rebar_state(struct pci_dev *dev)
43
+static void sriov_restore_vf_rebar_state(struct pci_dev *dev)
32
+{
44
+{
33
+    unsigned int pos, nbars, i;
45
+    unsigned int pos, nbars, i;
34
+    u32 ctrl;
46
+    u32 ctrl;
35
+
47
+
36
+    pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VF_REBAR);
48
+    pos = dev->sriov->vf_rebar_cap;
37
+    if (!pos)
49
+    if (!pos)
38
+        return;
50
+        return;
39
+
51
+
40
+    pci_read_config_dword(dev, pos + PCI_REBAR_CTRL, &ctrl);
52
+    pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl);
41
+    nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl);
53
+    nbars = FIELD_GET(PCI_VF_REBAR_CTRL_NBAR_MASK, ctrl);
42
+
54
+
43
+    for (i = 0; i < nbars; i++, pos += 8) {
55
+    for (i = 0; i < nbars; i++, pos += 8) {
44
+        int bar_idx, size;
56
+        int bar_idx, size;
45
+
57
+
46
+        pci_read_config_dword(dev, pos + PCI_REBAR_CTRL, &ctrl);
58
+        pci_read_config_dword(dev, pos + PCI_VF_REBAR_CTRL, &ctrl);
47
+        bar_idx = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, ctrl);
59
+        bar_idx = FIELD_GET(PCI_VF_REBAR_CTRL_BAR_IDX, ctrl);
48
+        size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]);
60
+        size = pci_rebar_bytes_to_size(dev->sriov->barsz[bar_idx]);
49
+        ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
61
+        ctrl &= ~PCI_VF_REBAR_CTRL_BAR_SIZE;
50
+        ctrl |= FIELD_PREP(PCI_REBAR_CTRL_BAR_SIZE, size);
62
+        ctrl |= FIELD_PREP(PCI_VF_REBAR_CTRL_BAR_SIZE, size);
51
+        pci_write_config_dword(dev, pos + PCI_REBAR_CTRL, ctrl);
63
+        pci_write_config_dword(dev, pos + PCI_VF_REBAR_CTRL, ctrl);
52
+    }
64
+    }
53
+}
65
+}
54
+
66
+
55
static void sriov_restore_state(struct pci_dev *dev)
67
static void sriov_restore_state(struct pci_dev *dev)
56
{
68
{
...
...
65
        sriov_restore_state(dev);
77
        sriov_restore_state(dev);
66
+    }
78
+    }
67
}
79
}
68
80
69
/**
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
70
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
71
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
72
--- a/include/uapi/linux/pci_regs.h
96
--- a/include/uapi/linux/pci_regs.h
73
+++ b/include/uapi/linux/pci_regs.h
97
+++ b/include/uapi/linux/pci_regs.h
74
@@ -XXX,XX +XXX,XX @@
98
@@ -XXX,XX +XXX,XX @@
...
...
77
#define PCI_EXT_CAP_ID_DVSEC    0x23    /* Designated Vendor-Specific */
101
#define PCI_EXT_CAP_ID_DVSEC    0x23    /* Designated Vendor-Specific */
78
+#define PCI_EXT_CAP_ID_VF_REBAR 0x24    /* VF Resizable BAR */
102
+#define PCI_EXT_CAP_ID_VF_REBAR 0x24    /* VF Resizable BAR */
79
#define PCI_EXT_CAP_ID_DLF    0x25    /* Data Link Feature */
103
#define PCI_EXT_CAP_ID_DLF    0x25    /* Data Link Feature */
80
#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 */
81
#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 */
82
--
121
--
83
2.47.0
122
2.49.0
84
123
diff view generated by jsdifflib
Deleted patch
1
There are multiple places where special handling is required for IOV
2
resources.
3
1
4
Extract it to pci_resource_is_iov() helper and drop a few ifdefs.
5
6
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
7
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
8
---
9
drivers/pci/pci.h | 19 +++++++++++++++----
10
drivers/pci/setup-bus.c | 7 +++----
11
drivers/pci/setup-res.c | 4 +---
12
3 files changed, 19 insertions(+), 11 deletions(-)
13
14
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/drivers/pci/pci.h
17
+++ b/drivers/pci/pci.h
18
@@ -XXX,XX +XXX,XX @@ void pci_iov_update_resource(struct pci_dev *dev, int resno);
19
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
20
void pci_restore_iov_state(struct pci_dev *dev);
21
int pci_iov_bus_range(struct pci_bus *bus);
22
+static inline bool pci_resource_is_iov(int resno)
23
+{
24
+    return resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END;
25
+}
26
extern const struct attribute_group sriov_pf_dev_attr_group;
27
extern const struct attribute_group sriov_vf_dev_attr_group;
28
#else
29
@@ -XXX,XX +XXX,XX @@ static inline int pci_iov_init(struct pci_dev *dev)
30
}
31
static inline void pci_iov_release(struct pci_dev *dev) { }
32
static inline void pci_iov_remove(struct pci_dev *dev) { }
33
+static inline void pci_iov_update_resource(struct pci_dev *dev, int resno) { }
34
+static inline resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,
35
+                             int resno)
36
+{
37
+    return 0;
38
+}
39
static inline void pci_restore_iov_state(struct pci_dev *dev) { }
40
static inline int pci_iov_bus_range(struct pci_bus *bus)
41
{
42
    return 0;
43
}
44
-
45
+static inline bool pci_resource_is_iov(int resno)
46
+{
47
+    return false;
48
+}
49
#endif /* CONFIG_PCI_IOV */
50
51
#ifdef CONFIG_PCIE_PTM
52
@@ -XXX,XX +XXX,XX @@ unsigned long pci_cardbus_resource_alignment(struct resource *);
53
static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
54
                         struct resource *res)
55
{
56
-#ifdef CONFIG_PCI_IOV
57
    int resno = res - dev->resource;
58
59
-    if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
60
+    if (pci_resource_is_iov(resno))
61
        return pci_sriov_resource_alignment(dev, resno);
62
-#endif
63
    if (dev->class >> 8 == PCI_CLASS_BRIDGE_CARDBUS)
64
        return pci_cardbus_resource_alignment(res);
65
    return resource_alignment(res);
66
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/drivers/pci/setup-bus.c
69
+++ b/drivers/pci/setup-bus.c
70
@@ -XXX,XX +XXX,XX @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
71
             (r->flags & mask) != type3))
72
                continue;
73
            r_size = resource_size(r);
74
-#ifdef CONFIG_PCI_IOV
75
+
76
            /* Put SRIOV requested res to the optional list */
77
-            if (realloc_head && i >= PCI_IOV_RESOURCES &&
78
-                    i <= PCI_IOV_RESOURCE_END) {
79
+            if (realloc_head && pci_resource_is_iov(i)) {
80
                add_align = max(pci_resource_alignment(dev, r), add_align);
81
                r->end = r->start - 1;
82
                add_to_list(realloc_head, dev, r, r_size, 0 /* Don't care */);
83
                children_add_size += r_size;
84
                continue;
85
            }
86
-#endif
87
+
88
            /*
89
             * aligns[0] is for 1MB (since bridge memory
90
             * windows are always at least 1MB aligned), so
91
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/drivers/pci/setup-res.c
94
+++ b/drivers/pci/setup-res.c
95
@@ -XXX,XX +XXX,XX @@ void pci_update_resource(struct pci_dev *dev, int resno)
96
{
97
    if (resno <= PCI_ROM_RESOURCE)
98
        pci_std_update_resource(dev, resno);
99
-#ifdef CONFIG_PCI_IOV
100
-    else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
101
+    else if (pci_resource_is_iov(resno))
102
        pci_iov_update_resource(dev, resno);
103
-#endif
104
}
105
106
int pci_claim_resource(struct pci_dev *dev, int resource)
107
--
108
2.47.0
109
diff view generated by jsdifflib
1
There are multiple places where conversions between IOV resources and
1
There are multiple places where conversions between IOV resources and
2
standard resources are done.
2
corresponding VF BAR numbers are done.
3
3
4
Extract the logic to pci_resource_to_iov() and pci_resource_from_iov()
4
Extract the logic to pci_resource_num_from_vf_bar() and
5
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 | 20 ++++++++++----------
11
drivers/pci/iov.c | 26 ++++++++++++++++----------
11
drivers/pci/pci.h | 18 ++++++++++++++++++
12
drivers/pci/pci.h | 19 +++++++++++++++++++
12
drivers/pci/setup-bus.c | 2 +-
13
drivers/pci/setup-bus.c | 3 ++-
13
3 files changed, 29 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
19
@@ -XXX,XX +XXX,XX @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
20
@@ -XXX,XX +XXX,XX @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
20
    if (!dev->is_physfn)
21
    if (!dev->is_physfn)
21
        return 0;
22
        return 0;
22
23
23
-    return dev->sriov->barsz[resno - PCI_IOV_RESOURCES];
24
-    return dev->sriov->barsz[resno - PCI_IOV_RESOURCES];
24
+    return dev->sriov->barsz[pci_resource_from_iov(resno)];
25
+    return dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)];
25
}
26
}
26
27
27
static void pci_read_vf_config_common(struct pci_dev *virtfn)
28
static void pci_read_vf_config_common(struct pci_dev *virtfn)
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_to_iov(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, pci_resource_to_iov(i));
42
+        size = pci_iov_resource_size(dev, idx);
40
        virtfn->resource[i].start = res->start + size * id;
43
        resource_set_range(&virtfn->resource[i],
41
        virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
44
                 res->start + size * id, size);
42
        rc = request_resource(res, &virtfn->resource[i]);
45
        rc = request_resource(res, &virtfn->resource[i]);
43
@@ -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)
44
47
45
    nres = 0;
48
    nres = 0;
46
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
49
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
47
-        bars |= (1 << (i + PCI_IOV_RESOURCES));
50
-        bars |= (1 << (i + PCI_IOV_RESOURCES));
48
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
51
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
49
+        bars |= (1 << pci_resource_to_iov(i));
52
+        int idx = pci_resource_num_from_vf_bar(i);
50
+        res = &dev->resource[pci_resource_to_iov(i)];
53
+
54
+        bars |= (1 << idx);
55
+        res = &dev->resource[idx];
51
        if (res->parent)
56
        if (res->parent)
52
            nres++;
57
            nres++;
53
    }
58
    }
54
@@ -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)
55
60
56
    nres = 0;
61
    nres = 0;
57
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
62
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
58
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
63
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
59
-        res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES);
64
-        res_name = pci_resource_name(dev, i + PCI_IOV_RESOURCES);
60
+        res = &dev->resource[pci_resource_to_iov(i)];
65
+        int idx = pci_resource_num_from_vf_bar(i);
61
+        res_name = pci_resource_name(dev, pci_resource_to_iov(i));
66
+
67
+        res = &dev->resource[idx];
68
+        res_name = pci_resource_name(dev, idx);
62
69
63
        /*
70
        /*
64
         * If it is already FIXED, don't change it, something
71
         * If it is already FIXED, don't change it, something
65
@@ -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)
66
    dev->is_physfn = 0;
73
    dev->is_physfn = 0;
67
failed:
74
failed:
68
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
75
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
69
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
76
-        res = &dev->resource[i + PCI_IOV_RESOURCES];
70
+        res = &dev->resource[pci_resource_to_iov(i)];
77
+        res = &dev->resource[pci_resource_num_from_vf_bar(i)];
71
        res->flags = 0;
78
        res->flags = 0;
72
    }
79
    }
73
80
74
@@ -XXX,XX +XXX,XX @@ static void sriov_restore_state(struct pci_dev *dev)
81
@@ -XXX,XX +XXX,XX @@ static void sriov_restore_state(struct pci_dev *dev)
75
    pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl);
82
    pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl);
76
83
77
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
84
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
78
-        pci_update_resource(dev, i + PCI_IOV_RESOURCES);
85
-        pci_update_resource(dev, i + PCI_IOV_RESOURCES);
79
+        pci_update_resource(dev, pci_resource_to_iov(i));
86
+        pci_update_resource(dev, pci_resource_num_from_vf_bar(i));
80
87
81
    pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
88
    pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
82
    pci_iov_set_numvfs(dev, iov->num_VFs);
89
    pci_iov_set_numvfs(dev, iov->num_VFs);
83
@@ -XXX,XX +XXX,XX @@ void pci_iov_update_resource(struct pci_dev *dev, int resno)
90
@@ -XXX,XX +XXX,XX @@ void pci_iov_update_resource(struct pci_dev *dev, int resno)
84
{
91
{
85
    struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL;
92
    struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL;
86
    struct resource *res = dev->resource + resno;
93
    struct resource *res = pci_resource_n(dev, resno);
87
-    int vf_bar = resno - PCI_IOV_RESOURCES;
94
-    int vf_bar = resno - PCI_IOV_RESOURCES;
88
+    int vf_bar = pci_resource_from_iov(resno);
95
+    int vf_bar = pci_resource_num_to_vf_bar(resno);
89
    struct pci_bus_region region;
96
    struct pci_bus_region region;
90
    u16 cmd;
97
    u16 cmd;
91
    u32 new;
98
    u32 new;
92
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
99
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
93
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
94
--- a/drivers/pci/pci.h
101
--- a/drivers/pci/pci.h
95
+++ b/drivers/pci/pci.h
102
+++ b/drivers/pci/pci.h
96
@@ -XXX,XX +XXX,XX @@ static inline bool pci_resource_is_iov(int resno)
103
@@ -XXX,XX +XXX,XX @@ static inline bool pci_resource_is_iov(int resno)
97
{
104
{
98
    return resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END;
105
    return resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END;
99
}
106
}
100
+static inline int pci_resource_to_iov(int resno)
107
+static inline int pci_resource_num_from_vf_bar(int resno)
101
+{
108
+{
102
+    return resno + PCI_IOV_RESOURCES;
109
+    return resno + PCI_IOV_RESOURCES;
103
+}
110
+}
104
+
111
+
105
+static inline int pci_resource_from_iov(int resno)
112
+static inline int pci_resource_num_to_vf_bar(int resno)
106
+{
113
+{
107
+    return resno - PCI_IOV_RESOURCES;
114
+    return resno - PCI_IOV_RESOURCES;
108
+}
115
+}
109
extern const struct attribute_group sriov_pf_dev_attr_group;
116
extern const struct attribute_group sriov_pf_dev_attr_group;
110
extern const struct attribute_group sriov_vf_dev_attr_group;
117
extern const struct attribute_group sriov_vf_dev_attr_group;
111
#else
118
#else
112
@@ -XXX,XX +XXX,XX @@ static inline bool pci_resource_is_iov(int resno)
119
@@ -XXX,XX +XXX,XX @@ static inline bool pci_resource_is_iov(int resno)
113
{
120
{
114
    return false;
121
    return false;
115
}
122
}
116
+static inline int pci_resource_to_iov(int resno)
123
+static inline int pci_resource_num_from_vf_bar(int resno)
117
+{
124
+{
125
+    WARN_ON_ONCE(1);
118
+    return -ENODEV;
126
+    return -ENODEV;
119
+}
127
+}
120
+
128
+static inline int pci_resource_num_to_vf_bar(int resno)
121
+static inline int pci_resource_from_iov(int resno)
122
+{
129
+{
130
+    WARN_ON_ONCE(1);
123
+    return -ENODEV;
131
+    return -ENODEV;
124
+}
132
+}
125
#endif /* CONFIG_PCI_IOV */
133
#endif /* CONFIG_PCI_IOV */
126
134
127
#ifdef CONFIG_PCIE_PTM
135
#ifdef CONFIG_PCIE_TPH
128
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
136
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
129
index XXXXXXX..XXXXXXX 100644
137
index XXXXXXX..XXXXXXX 100644
130
--- a/drivers/pci/setup-bus.c
138
--- a/drivers/pci/setup-bus.c
131
+++ b/drivers/pci/setup-bus.c
139
+++ b/drivers/pci/setup-bus.c
132
@@ -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)
133
    bool *unassigned = data;
141
    bool *unassigned = data;
134
142
135
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
143
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
136
-        struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES];
144
-        struct resource *r = &dev->resource[i + PCI_IOV_RESOURCES];
137
+        struct resource *r = &dev->resource[pci_resource_to_iov(i)];
145
+        int idx = pci_resource_num_from_vf_bar(i);
146
+        struct resource *r = &dev->resource[idx];
138
        struct pci_bus_region region;
147
        struct pci_bus_region region;
139
148
140
        /* Not assigned or rejected by kernel? */
149
        /* Not assigned or rejected by kernel? */
141
--
150
--
142
2.47.0
151
2.49.0
143
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 +++++++++-
14
drivers/pci/pci.h | 10 +++++++++-
16
drivers/pci/pci.h | 9 +++++++++
15
drivers/pci/setup-res.c | 36 +++++++++++++++++++++++++++++++-----
17
drivers/pci/setup-res.c | 35 ++++++++++++++++++++++++++++++-----
16
4 files changed, 70 insertions(+), 7 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
22
@@ -XXX,XX +XXX,XX @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
24
@@ -XXX,XX +XXX,XX @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
23
    return dev->sriov->barsz[pci_resource_from_iov(resno)];
25
    return dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)];
24
}
26
}
25
27
26
+void pci_iov_resource_set_size(struct pci_dev *dev, int resno,
28
+void pci_iov_resource_set_size(struct pci_dev *dev, int resno,
27
+             resource_size_t size)
29
+             resource_size_t size)
28
+{
30
+{
29
+    if (!pci_resource_is_iov(resno)) {
31
+    if (!pci_resource_is_iov(resno)) {
30
+        pci_warn(dev, "%s is not an IOV resource\n",
32
+        pci_warn(dev, "%s is not an IOV resource\n",
31
+             pci_resource_name(dev, resno));
33
+             pci_resource_name(dev, resno));
32
+        return;
34
+        return;
33
+    }
35
+    }
34
+
36
+
35
+    dev->sriov->barsz[pci_resource_from_iov(resno)] = size;
37
+    dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)] = size;
36
+}
38
+}
37
+
39
+
38
+bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev)
40
+bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev)
39
+{
41
+{
40
+    u16 cmd;
42
+    u16 cmd;
...
...
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
+        bar = pci_resource_from_iov(bar);
63
+            return -ENOTSUPP;
64
+        pos = pdev->sriov->vf_rebar_cap;
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
...
...
94
+    return false;
95
+    return false;
95
+}
96
+}
96
static inline bool pci_resource_is_iov(int resno)
97
static inline bool pci_resource_is_iov(int resno)
97
{
98
{
98
    return false;
99
    return false;
99
@@ -XXX,XX +XXX,XX @@ static inline int pci_resource_to_iov(int resno)
100
{
101
    return -ENODEV;
102
}
103
-
104
static inline int pci_resource_from_iov(int resno)
105
{
106
    return -ENODEV;
107
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
100
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
108
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
109
--- a/drivers/pci/setup-res.c
102
--- a/drivers/pci/setup-res.c
110
+++ b/drivers/pci/setup-res.c
103
+++ b/drivers/pci/setup-res.c
111
@@ -XXX,XX +XXX,XX @@ void pci_release_resource(struct pci_dev *dev, int resno)
104
@@ -XXX,XX +XXX,XX @@ void pci_release_resource(struct pci_dev *dev, int resno)
...
...
127
+
120
+
128
+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,
129
+                     int size)
122
+                     int size)
130
+{
123
+{
131
+    resource_size_t res_size = pci_rebar_size_to_bytes(size);
124
+    resource_size_t res_size = pci_rebar_size_to_bytes(size);
132
+    struct resource *res = dev->resource + resno;
125
+    struct resource *res = pci_resource_n(dev, resno);
133
+
126
+
134
+    if (!pci_resource_is_iov(resno)) {
127
+    if (!pci_resource_is_iov(resno)) {
135
+        res->end = res->start + res_size - 1;
128
+        resource_set_size(res, res_size);
136
+    } else {
129
+    } else {
137
+        res->end = res->start +
130
+        resource_set_size(res, res_size * pci_sriov_get_totalvfs(dev));
138
+            res_size * pci_sriov_get_totalvfs(dev) - 1;
139
+        pci_iov_resource_set_size(dev, resno, res_size);
131
+        pci_iov_resource_set_size(dev, resno, res_size);
140
+    }
132
+    }
141
+}
133
+}
142
+
134
+
143
int pci_resize_resource(struct pci_dev *dev, int resno, int size)
135
int pci_resize_resource(struct pci_dev *dev, int resno, int size)
144
{
136
{
145
    struct resource *res = dev->resource + resno;
137
    struct resource *res = pci_resource_n(dev, resno);
146
    struct pci_host_bridge *host;
138
    struct pci_host_bridge *host;
147
    int old, ret;
139
    int old, ret;
148
    u32 sizes;
140
    u32 sizes;
149
-    u16 cmd;
141
-    u16 cmd;
150
142
...
...
162
    sizes = pci_rebar_get_possible_sizes(dev, resno);
154
    sizes = pci_rebar_get_possible_sizes(dev, resno);
163
@@ -XXX,XX +XXX,XX @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
155
@@ -XXX,XX +XXX,XX @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
164
    if (ret)
156
    if (ret)
165
        return ret;
157
        return ret;
166
158
167
-    res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
159
-    resource_set_size(res, pci_rebar_size_to_bytes(size));
168
+    pci_resize_resource_set_size(dev, resno, size);
160
+    pci_resize_resource_set_size(dev, resno, size);
169
161
170
    /* Check if the new config works by trying to assign everything. */
162
    /* Check if the new config works by trying to assign everything. */
171
    if (dev->bus->self) {
163
    if (dev->bus->self) {
172
@@ -XXX,XX +XXX,XX @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
164
@@ -XXX,XX +XXX,XX @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
173
165
174
error_resize:
166
error_resize:
175
    pci_rebar_set_size(dev, resno, old);
167
    pci_rebar_set_size(dev, resno, old);
176
-    res->end = res->start + pci_rebar_size_to_bytes(old) - 1;
168
-    resource_set_size(res, pci_rebar_size_to_bytes(old));
177
+    pci_resize_resource_set_size(dev, resno, old);
169
+    pci_resize_resource_set_size(dev, resno, old);
178
    return ret;
170
    return ret;
179
}
171
}
180
EXPORT_SYMBOL(pci_resize_resource);
172
EXPORT_SYMBOL(pci_resize_resource);
181
--
173
--
182
2.47.0
174
2.49.0
183
175
diff view generated by jsdifflib
1
VF MMIO resource reservation, either created by system firmware and
1
When the resource representing VF MMIO BAR reservation is created, its
2
inherited by Linux PCI subsystem or created by the subsystem itself,
2
size is always large enough to accommodate the BAR of all SR-IOV Virtual
3
should contain enough space to fit the BAR of all SR-IOV Virtual
3
Functions that can potentially be created (total VFs). If for whatever
4
Functions that can potentially be created (total VFs supported by the
4
reason it's not possible to accommodate all VFs - the resource is not
5
device).
5
assigned and no VFs can be created.
6
6
7
However, that assumption only holds in an environment where VF BAR size
7
An upcoming change will allow VF BAR size to be modified by drivers at
8
can't be modified.
8
a later point in time, which means that the check for resource
9
assignment is no longer sufficient.
9
10
10
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
11
fits within the underlying reservation resource.
12
fits within the underlying reservation resource.
12
13
13
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
14
Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
14
---
15
---
15
drivers/pci/iov.c | 8 ++++++--
16
drivers/pci/iov.c | 3 +++
16
1 file changed, 6 insertions(+), 2 deletions(-)
17
1 file changed, 3 insertions(+)
17
18
18
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
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/drivers/pci/iov.c
21
--- a/drivers/pci/iov.c
21
+++ b/drivers/pci/iov.c
22
+++ b/drivers/pci/iov.c
22
@@ -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)
23
24
    nres = 0;
24
    nres = 0;
25
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
25
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
26
+        int vf_bar_sz = pci_iov_resource_size(dev,
26
        int idx = pci_resource_num_from_vf_bar(i);
27
+                         pci_resource_to_iov(i));
27
+        resource_size_t vf_bar_sz = pci_iov_resource_size(dev, idx);
28
        bars |= (1 << pci_resource_to_iov(i));
28
29
        res = &dev->resource[pci_resource_to_iov(i)];
29
        bars |= (1 << idx);
30
-        if (res->parent)
30
        res = &dev->resource[idx];
31
-            nres++;
31
+        if (vf_bar_sz * nr_virtfn > resource_size(res))
32
+        if (!res->parent || vf_bar_sz * nr_virtfn > resource_size(res))
33
+            continue;
32
+            continue;
34
+
33
        if (res->parent)
35
+        nres++;
34
            nres++;
36
    }
35
    }
37
    if (nres != iov->nres) {
38
        pci_err(dev, "not enough MMIO resources for SR-IOV\n");
39
--
36
--
40
2.47.0
37
2.49.0
41
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 | 80 +++++++++++++++++++++++++++++++++++++++++++++
12
drivers/pci/iov.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
13
include/linux/pci.h | 6 ++++
13
include/linux/pci.h | 6 ++++
14
2 files changed, 86 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
...
...
24
+
24
+
25
+/**
25
+/**
26
+ * pci_iov_vf_bar_set_size - set a new size for a VF BAR
26
+ * pci_iov_vf_bar_set_size - set a new size for a VF BAR
27
+ * @dev: the PCI device
27
+ * @dev: the PCI device
28
+ * @resno: the resource number
28
+ * @resno: the resource number
29
+ * @size: new size as defined in the spec (0=1MB, 19=512GB)
29
+ * @size: new size as defined in the spec (0=1MB, 31=128TB)
30
+ *
30
+ *
31
+ * Set the new size of a VF BAR that supports VF resizable BAR capability.
31
+ * Set the new size of a VF BAR that supports VF resizable BAR capability.
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
+ *
39
+ */
38
+ */
40
+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)
41
+{
40
+{
42
+    int ret;
41
+    int ret;
43
+    u32 sizes;
42
+    u32 sizes;
...
...
64
+    return 0;
63
+    return 0;
65
+}
64
+}
66
+EXPORT_SYMBOL_GPL(pci_iov_vf_bar_set_size);
65
+EXPORT_SYMBOL_GPL(pci_iov_vf_bar_set_size);
67
+
66
+
68
+/**
67
+/**
69
+ * pci_iov_vf_bar_get_sizes - get VF BAR sizes that allow to create up to num_vfs
68
+ * pci_iov_vf_bar_get_sizes - get VF BAR sizes allowing to create up to num_vfs
70
+ * @dev: the PCI device
69
+ * @dev: the PCI device
71
+ * @resno: the resource number
70
+ * @resno: the resource number
72
+ * @num_vfs: number of VFs
71
+ * @num_vfs: number of VFs
73
+ *
72
+ *
74
+ * Get the sizes of a VF resizable BAR that can fit up to num_vfs within the
73
+ * Get the sizes of a VF resizable BAR that can accommodate @num_vfs within
75
+ * resource that reserves the MMIO space (originally up to total_VFs) the as
74
+ * the currently assigned size of the resource @resno.
76
+ * bitmask defined in the spec (bit 0=1MB, bit 19=512GB).
77
+ *
75
+ *
78
+ * Returns 0 if BAR isn't resizable.
76
+ * Return: A bitmask of sizes in format defined in the spec (bit 0=1MB,
79
+ *
77
+ * bit 31=128TB).
80
+ */
78
+ */
81
+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)
82
+{
80
+{
83
+    resource_size_t size;
81
+    resource_size_t vf_len = pci_resource_len(dev, resno);
84
+    u32 sizes;
82
+    u32 sizes;
85
+    int i;
86
+
83
+
87
+    sizes = pci_rebar_get_possible_sizes(dev, resno);
84
+    if (!num_vfs)
88
+    if (!sizes)
89
+        return 0;
85
+        return 0;
90
+
86
+
91
+    while (sizes > 0) {
87
+    do_div(vf_len, num_vfs);
92
+        i = __fls(sizes);
88
+    sizes = (roundup_pow_of_two(vf_len + 1) - 1) >> ilog2(SZ_1M);
93
+        size = pci_rebar_size_to_bytes(i);
94
+
89
+
95
+        if (size * num_vfs <= pci_resource_len(dev, resno))
90
+    return sizes & pci_rebar_get_possible_sizes(dev, resno);
96
+            break;
97
+
98
+        sizes &= ~BIT(i);
99
+    }
100
+
101
+    return sizes;
102
+}
91
+}
103
+EXPORT_SYMBOL_GPL(pci_iov_vf_bar_get_sizes);
92
+EXPORT_SYMBOL_GPL(pci_iov_vf_bar_get_sizes);
104
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
105
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
106
--- a/include/linux/pci.h
95
--- a/include/linux/pci.h
...
...
124
+{ return 0; }
113
+{ return 0; }
125
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) { }
126
#endif
115
#endif
127
116
128
--
117
--
129
2.47.0
118
2.49.0
130
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.47.0
76
2.49.0
75
77
diff view generated by jsdifflib