Skip to content

Commit 1357158

Browse files
committed
Merge branch 'pci/resource'
- Prevent resource tree corruption when BAR resize fails (Ilpo Järvinen) - Restore BARs to the original size if a BAR resize fails (Ilpo Järvinen) - Remove BAR release from BAR resize attempts by the xe, i915, and amdgpu drivers so the PCI core can restore BARs if the resize fails (Ilpo Järvinen) - Move Resizable BAR code to rebar.c (Ilpo Järvinen) - Add pci_rebar_size_supported() and use it in i915 and xe (Ilpo Järvinen) - Add pci_rebar_get_max_size() and use it in xe and amdgpu (Ilpo Järvinen) * pci/resource: PCI: Validate pci_rebar_size_supported() input PCI: Convert BAR sizes bitmasks to u64 drm/amdgpu: Use pci_rebar_get_max_size() drm/xe/vram: Use pci_rebar_get_max_size() PCI: Add pci_rebar_get_max_size() drm/xe/vram: Use PCI rebar helpers in resize_vram_bar() drm/i915/gt: Use pci_rebar_size_supported() PCI: Add pci_rebar_size_supported() helper PCI: Improve Resizable BAR functions kernel doc PCI: Move pci_rebar_size_to_bytes() and export it PCI: Move pci_rebar_bytes_to_size() and clean it up PCI: Move Resizable BAR code to rebar.c PCI: Prevent restoring assigned resources drm/amdgpu: Remove driver side BAR release before resize drm/i915: Remove driver side BAR release before resize drm/xe: Remove driver side BAR release before resize PCI: Add kerneldoc for pci_resize_resource() PCI: Fix restoring BARs on BAR resize rollback path PCI: Free saved list without holding pci_bus_sem PCI: Try BAR resize even when no window was released PCI: Change pci_dev variable from 'bridge' to 'dev' PCI/IOV: Adjust ->barsz[] when changing BAR size PCI: Prevent resource tree corruption when BAR resize fails
2 parents c1e900d + 48f0143 commit 1357158

14 files changed

Lines changed: 475 additions & 363 deletions

File tree

Documentation/driver-api/pci/pci.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ PCI Support Library
3737
.. kernel-doc:: drivers/pci/slot.c
3838
:export:
3939

40+
.. kernel-doc:: drivers/pci/rebar.c
41+
:export:
42+
4043
.. kernel-doc:: drivers/pci/rom.c
4144
:export:
4245

drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,9 +1673,9 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
16731673
int rbar_size = pci_rebar_bytes_to_size(adev->gmc.real_vram_size);
16741674
struct pci_bus *root;
16751675
struct resource *res;
1676+
int max_size, r;
16761677
unsigned int i;
16771678
u16 cmd;
1678-
int r;
16791679

16801680
if (!IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
16811681
return 0;
@@ -1721,30 +1721,28 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
17211721
return 0;
17221722

17231723
/* Limit the BAR size to what is available */
1724-
rbar_size = min(fls(pci_rebar_get_possible_sizes(adev->pdev, 0)) - 1,
1725-
rbar_size);
1724+
max_size = pci_rebar_get_max_size(adev->pdev, 0);
1725+
if (max_size < 0)
1726+
return 0;
1727+
rbar_size = min(max_size, rbar_size);
17261728

17271729
/* Disable memory decoding while we change the BAR addresses and size */
17281730
pci_read_config_word(adev->pdev, PCI_COMMAND, &cmd);
17291731
pci_write_config_word(adev->pdev, PCI_COMMAND,
17301732
cmd & ~PCI_COMMAND_MEMORY);
17311733

1732-
/* Free the VRAM and doorbell BAR, we most likely need to move both. */
1734+
/* Tear down doorbell as resizing will release BARs */
17331735
amdgpu_doorbell_fini(adev);
1734-
if (adev->asic_type >= CHIP_BONAIRE)
1735-
pci_release_resource(adev->pdev, 2);
17361736

1737-
pci_release_resource(adev->pdev, 0);
1738-
1739-
r = pci_resize_resource(adev->pdev, 0, rbar_size);
1737+
r = pci_resize_resource(adev->pdev, 0, rbar_size,
1738+
(adev->asic_type >= CHIP_BONAIRE) ? 1 << 5
1739+
: 1 << 2);
17401740
if (r == -ENOSPC)
17411741
dev_info(adev->dev,
17421742
"Not enough PCI address space for a large BAR.");
17431743
else if (r && r != -ENOTSUPP)
17441744
dev_err(adev->dev, "Problem resizing BAR0 (%d).", r);
17451745

1746-
pci_assign_unassigned_bus_resources(adev->pdev->bus);
1747-
17481746
/* When the doorbell or fb BAR isn't available we have no chance of
17491747
* using the device.
17501748
*/

drivers/gpu/drm/i915/gt/intel_region_lmem.c

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,14 @@
1818
#include "gt/intel_gt_regs.h"
1919

2020
#ifdef CONFIG_64BIT
21-
static void _release_bars(struct pci_dev *pdev)
22-
{
23-
int resno;
24-
25-
for (resno = PCI_STD_RESOURCES; resno < PCI_STD_RESOURCE_END; resno++) {
26-
if (pci_resource_len(pdev, resno))
27-
pci_release_resource(pdev, resno);
28-
}
29-
}
30-
3121
static void
3222
_resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size)
3323
{
3424
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
3525
int bar_size = pci_rebar_bytes_to_size(size);
3626
int ret;
3727

38-
_release_bars(pdev);
39-
40-
ret = pci_resize_resource(pdev, resno, bar_size);
28+
ret = pci_resize_resource(pdev, resno, bar_size, 0);
4129
if (ret) {
4230
drm_info(&i915->drm, "Failed to resize BAR%d to %dM (%pe)\n",
4331
resno, 1 << bar_size, ERR_PTR(ret));
@@ -61,16 +49,12 @@ static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t
6149
current_size = roundup_pow_of_two(pci_resource_len(pdev, GEN12_LMEM_BAR));
6250

6351
if (i915->params.lmem_bar_size) {
64-
u32 bar_sizes;
65-
66-
rebar_size = i915->params.lmem_bar_size *
67-
(resource_size_t)SZ_1M;
68-
bar_sizes = pci_rebar_get_possible_sizes(pdev, GEN12_LMEM_BAR);
69-
52+
rebar_size = i915->params.lmem_bar_size * (resource_size_t)SZ_1M;
7053
if (rebar_size == current_size)
7154
return;
7255

73-
if (!(bar_sizes & BIT(pci_rebar_bytes_to_size(rebar_size))) ||
56+
if (!pci_rebar_size_supported(pdev, GEN12_LMEM_BAR,
57+
pci_rebar_bytes_to_size(rebar_size)) ||
7458
rebar_size >= roundup_pow_of_two(lmem_size)) {
7559
rebar_size = lmem_size;
7660

drivers/gpu/drm/xe/xe_vram.c

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,14 @@
2424
#include "xe_vram.h"
2525
#include "xe_vram_types.h"
2626

27-
#define BAR_SIZE_SHIFT 20
28-
2927
static void
3028
_resize_bar(struct xe_device *xe, int resno, resource_size_t size)
3129
{
3230
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
3331
int bar_size = pci_rebar_bytes_to_size(size);
3432
int ret;
3533

36-
if (pci_resource_len(pdev, resno))
37-
pci_release_resource(pdev, resno);
38-
39-
ret = pci_resize_resource(pdev, resno, bar_size);
34+
ret = pci_resize_resource(pdev, resno, bar_size, 0);
4035
if (ret) {
4136
drm_info(&xe->drm, "Failed to resize BAR%d to %dM (%pe). Consider enabling 'Resizable BAR' support in your BIOS\n",
4237
resno, 1 << bar_size, ERR_PTR(ret));
@@ -58,41 +53,37 @@ static void resize_vram_bar(struct xe_device *xe)
5853
resource_size_t current_size;
5954
resource_size_t rebar_size;
6055
struct resource *root_res;
61-
u32 bar_size_mask;
56+
int max_size, i;
6257
u32 pci_cmd;
63-
int i;
6458

6559
/* gather some relevant info */
6660
current_size = pci_resource_len(pdev, LMEM_BAR);
67-
bar_size_mask = pci_rebar_get_possible_sizes(pdev, LMEM_BAR);
68-
69-
if (!bar_size_mask)
70-
return;
7161

7262
if (force_vram_bar_size < 0)
7363
return;
7464

7565
/* set to a specific size? */
7666
if (force_vram_bar_size) {
77-
u32 bar_size_bit;
67+
rebar_size = pci_rebar_bytes_to_size(force_vram_bar_size *
68+
(resource_size_t)SZ_1M);
7869

79-
rebar_size = force_vram_bar_size * (resource_size_t)SZ_1M;
80-
81-
bar_size_bit = bar_size_mask & BIT(pci_rebar_bytes_to_size(rebar_size));
82-
83-
if (!bar_size_bit) {
70+
if (!pci_rebar_size_supported(pdev, LMEM_BAR, rebar_size)) {
8471
drm_info(&xe->drm,
85-
"Requested size: %lluMiB is not supported by rebar sizes: 0x%x. Leaving default: %lluMiB\n",
86-
(u64)rebar_size >> 20, bar_size_mask, (u64)current_size >> 20);
72+
"Requested size: %lluMiB is not supported by rebar sizes: 0x%llx. Leaving default: %lluMiB\n",
73+
(u64)pci_rebar_size_to_bytes(rebar_size) >> 20,
74+
pci_rebar_get_possible_sizes(pdev, LMEM_BAR),
75+
(u64)current_size >> 20);
8776
return;
8877
}
8978

90-
rebar_size = 1ULL << (__fls(bar_size_bit) + BAR_SIZE_SHIFT);
91-
79+
rebar_size = pci_rebar_size_to_bytes(rebar_size);
9280
if (rebar_size == current_size)
9381
return;
9482
} else {
95-
rebar_size = 1ULL << (__fls(bar_size_mask) + BAR_SIZE_SHIFT);
83+
max_size = pci_rebar_get_max_size(pdev, LMEM_BAR);
84+
if (max_size < 0)
85+
return;
86+
rebar_size = pci_rebar_size_to_bytes(max_size);
9687

9788
/* only resize if larger than current */
9889
if (rebar_size <= current_size)

drivers/pci/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
obj-$(CONFIG_PCI) += access.o bus.o probe.o host-bridge.o \
66
remove.o pci.o pci-driver.o search.o \
7-
rom.o setup-res.o irq.o vpd.o \
7+
rebar.o rom.o setup-res.o irq.o vpd.o \
88
setup-bus.o vc.o mmap.o devres.o
99

1010
obj-$(CONFIG_PCI) += msi/

drivers/pci/iov.c

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -158,16 +158,16 @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
158158
return dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)];
159159
}
160160

161-
void pci_iov_resource_set_size(struct pci_dev *dev, int resno,
162-
resource_size_t size)
161+
void pci_iov_resource_set_size(struct pci_dev *dev, int resno, int size)
163162
{
164163
if (!pci_resource_is_iov(resno)) {
165164
pci_warn(dev, "%s is not an IOV resource\n",
166165
pci_resource_name(dev, resno));
167166
return;
168167
}
169168

170-
dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)] = size;
169+
resno = pci_resource_num_to_vf_bar(resno);
170+
dev->sriov->barsz[resno] = pci_rebar_size_to_bytes(size);
171171
}
172172

173173
bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev)
@@ -1339,29 +1339,16 @@ EXPORT_SYMBOL_GPL(pci_sriov_configure_simple);
13391339
*/
13401340
int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size)
13411341
{
1342-
u32 sizes;
1343-
int ret;
1344-
13451342
if (!pci_resource_is_iov(resno))
13461343
return -EINVAL;
13471344

13481345
if (pci_iov_is_memory_decoding_enabled(dev))
13491346
return -EBUSY;
13501347

1351-
sizes = pci_rebar_get_possible_sizes(dev, resno);
1352-
if (!sizes)
1353-
return -ENOTSUPP;
1354-
1355-
if (!(sizes & BIT(size)))
1348+
if (!pci_rebar_size_supported(dev, resno, size))
13561349
return -EINVAL;
13571350

1358-
ret = pci_rebar_set_size(dev, resno, size);
1359-
if (ret)
1360-
return ret;
1361-
1362-
pci_iov_resource_set_size(dev, resno, pci_rebar_size_to_bytes(size));
1363-
1364-
return 0;
1351+
return pci_rebar_set_size(dev, resno, size);
13651352
}
13661353
EXPORT_SYMBOL_GPL(pci_iov_vf_bar_set_size);
13671354

@@ -1380,7 +1367,7 @@ EXPORT_SYMBOL_GPL(pci_iov_vf_bar_set_size);
13801367
u32 pci_iov_vf_bar_get_sizes(struct pci_dev *dev, int resno, int num_vfs)
13811368
{
13821369
u64 vf_len = pci_resource_len(dev, resno);
1383-
u32 sizes;
1370+
u64 sizes;
13841371

13851372
if (!num_vfs)
13861373
return 0;

drivers/pci/pci-sysfs.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,7 +1587,7 @@ static ssize_t __resource_resize_show(struct device *dev, int n, char *buf)
15871587
pci_config_pm_runtime_get(pdev);
15881588

15891589
ret = sysfs_emit(buf, "%016llx\n",
1590-
(u64)pci_rebar_get_possible_sizes(pdev, n));
1590+
pci_rebar_get_possible_sizes(pdev, n));
15911591

15921592
pci_config_pm_runtime_put(pdev);
15931593

@@ -1599,18 +1599,13 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
15991599
{
16001600
struct pci_dev *pdev = to_pci_dev(dev);
16011601
struct pci_bus *bus = pdev->bus;
1602-
struct resource *b_win, *res;
16031602
unsigned long size;
1604-
int ret, i;
1603+
int ret;
16051604
u16 cmd;
16061605

16071606
if (kstrtoul(buf, 0, &size) < 0)
16081607
return -EINVAL;
16091608

1610-
b_win = pbus_select_window(bus, pci_resource_n(pdev, n));
1611-
if (!b_win)
1612-
return -EINVAL;
1613-
16141609
device_lock(dev);
16151610
if (dev->driver || pci_num_vf(pdev)) {
16161611
ret = -EBUSY;
@@ -1632,15 +1627,7 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
16321627

16331628
pci_remove_resource_files(pdev);
16341629

1635-
pci_dev_for_each_resource(pdev, res, i) {
1636-
if (i >= PCI_BRIDGE_RESOURCES)
1637-
break;
1638-
1639-
if (b_win == pbus_select_window(bus, res))
1640-
pci_release_resource(pdev, i);
1641-
}
1642-
1643-
ret = pci_resize_resource(pdev, n, size);
1630+
ret = pci_resize_resource(pdev, n, size, 0);
16441631

16451632
pci_assign_unassigned_bus_resources(bus);
16461633

0 commit comments

Comments
 (0)