Skip to content

Commit 5a1d568

Browse files
committed
Merge branch 'pci/enumeration'
- Batch sizing of multiple BARs while memory decoding is disabled instead of disabling/enabling decoding for each BAR individually; this optimizes virtualized environments where toggling decoding enable is expensive (Alex Williamson) * pci/enumeration: PCI: Batch BAR sizing operations
2 parents 06fd49e + 4453f36 commit 5a1d568

File tree

3 files changed

+78
-27
lines changed

3 files changed

+78
-27
lines changed

drivers/pci/iov.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
747747
struct resource *res;
748748
const char *res_name;
749749
struct pci_dev *pdev;
750+
u32 sriovbars[PCI_SRIOV_NUM_BARS];
750751

751752
pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl);
752753
if (ctrl & PCI_SRIOV_CTRL_VFE) {
@@ -783,6 +784,10 @@ static int sriov_init(struct pci_dev *dev, int pos)
783784
if (!iov)
784785
return -ENOMEM;
785786

787+
/* Sizing SR-IOV BARs with VF Enable cleared - no decode */
788+
__pci_size_stdbars(dev, PCI_SRIOV_NUM_BARS,
789+
pos + PCI_SRIOV_BAR, sriovbars);
790+
786791
nres = 0;
787792
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
788793
res = &dev->resource[i + PCI_IOV_RESOURCES];
@@ -796,7 +801,8 @@ static int sriov_init(struct pci_dev *dev, int pos)
796801
bar64 = (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
797802
else
798803
bar64 = __pci_read_base(dev, pci_bar_unknown, res,
799-
pos + PCI_SRIOV_BAR + i * 4);
804+
pos + PCI_SRIOV_BAR + i * 4,
805+
&sriovbars[i]);
800806
if (!res->flags)
801807
continue;
802808
if (resource_size(res) & (PAGE_SIZE - 1)) {

drivers/pci/pci.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,10 @@ bool pci_bus_generic_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
315315
int pci_idt_bus_quirk(struct pci_bus *bus, int devfn, u32 *pl, int rrs_timeout);
316316

317317
int pci_setup_device(struct pci_dev *dev);
318+
void __pci_size_stdbars(struct pci_dev *dev, int count,
319+
unsigned int pos, u32 *sizes);
318320
int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
319-
struct resource *res, unsigned int reg);
321+
struct resource *res, unsigned int reg, u32 *sizes);
320322
void pci_configure_ari(struct pci_dev *dev);
321323
void __pci_bus_size_bridges(struct pci_bus *bus,
322324
struct list_head *realloc_head);

drivers/pci/probe.c

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -164,41 +164,67 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
164164

165165
#define PCI_COMMAND_DECODE_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)
166166

167+
/**
168+
* __pci_size_bars - Read the raw BAR mask for a range of PCI BARs
169+
* @dev: the PCI device
170+
* @count: number of BARs to size
171+
* @pos: starting config space position
172+
* @sizes: array to store mask values
173+
* @rom: indicate whether to use ROM mask, which avoids enabling ROM BARs
174+
*
175+
* Provided @sizes array must be sufficiently sized to store results for
176+
* @count u32 BARs. Caller is responsible for disabling decode to specified
177+
* BAR range around calling this function. This function is intended to avoid
178+
* disabling decode around sizing each BAR individually, which can result in
179+
* non-trivial overhead in virtualized environments with very large PCI BARs.
180+
*/
181+
static void __pci_size_bars(struct pci_dev *dev, int count,
182+
unsigned int pos, u32 *sizes, bool rom)
183+
{
184+
u32 orig, mask = rom ? PCI_ROM_ADDRESS_MASK : ~0;
185+
int i;
186+
187+
for (i = 0; i < count; i++, pos += 4, sizes++) {
188+
pci_read_config_dword(dev, pos, &orig);
189+
pci_write_config_dword(dev, pos, mask);
190+
pci_read_config_dword(dev, pos, sizes);
191+
pci_write_config_dword(dev, pos, orig);
192+
}
193+
}
194+
195+
void __pci_size_stdbars(struct pci_dev *dev, int count,
196+
unsigned int pos, u32 *sizes)
197+
{
198+
__pci_size_bars(dev, count, pos, sizes, false);
199+
}
200+
201+
static void __pci_size_rom(struct pci_dev *dev, unsigned int pos, u32 *sizes)
202+
{
203+
__pci_size_bars(dev, 1, pos, sizes, true);
204+
}
205+
167206
/**
168207
* __pci_read_base - Read a PCI BAR
169208
* @dev: the PCI device
170209
* @type: type of the BAR
171210
* @res: resource buffer to be filled in
172211
* @pos: BAR position in the config space
212+
* @sizes: array of one or more pre-read BAR masks
173213
*
174214
* Returns 1 if the BAR is 64-bit, or 0 if 32-bit.
175215
*/
176216
int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
177-
struct resource *res, unsigned int pos)
217+
struct resource *res, unsigned int pos, u32 *sizes)
178218
{
179-
u32 l = 0, sz = 0, mask;
219+
u32 l = 0, sz;
180220
u64 l64, sz64, mask64;
181-
u16 orig_cmd;
182221
struct pci_bus_region region, inverted_region;
183222
const char *res_name = pci_resource_name(dev, res - dev->resource);
184223

185-
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
186-
187-
/* No printks while decoding is disabled! */
188-
if (!dev->mmio_always_on) {
189-
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
190-
if (orig_cmd & PCI_COMMAND_DECODE_ENABLE) {
191-
pci_write_config_word(dev, PCI_COMMAND,
192-
orig_cmd & ~PCI_COMMAND_DECODE_ENABLE);
193-
}
194-
}
195-
196224
res->name = pci_name(dev);
197225

198226
pci_read_config_dword(dev, pos, &l);
199-
pci_write_config_dword(dev, pos, l | mask);
200-
pci_read_config_dword(dev, pos, &sz);
201-
pci_write_config_dword(dev, pos, l);
227+
sz = sizes[0];
202228

203229
/*
204230
* All bits set in sz means the device isn't working properly.
@@ -238,18 +264,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
238264

239265
if (res->flags & IORESOURCE_MEM_64) {
240266
pci_read_config_dword(dev, pos + 4, &l);
241-
pci_write_config_dword(dev, pos + 4, ~0);
242-
pci_read_config_dword(dev, pos + 4, &sz);
243-
pci_write_config_dword(dev, pos + 4, l);
267+
sz = sizes[1];
244268

245269
l64 |= ((u64)l << 32);
246270
sz64 |= ((u64)sz << 32);
247271
mask64 |= ((u64)~0 << 32);
248272
}
249273

250-
if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
251-
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
252-
253274
if (!sz64)
254275
goto fail;
255276

@@ -320,7 +341,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
320341

321342
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
322343
{
344+
u32 rombar, stdbars[PCI_STD_NUM_BARS];
323345
unsigned int pos, reg;
346+
u16 orig_cmd;
347+
348+
BUILD_BUG_ON(howmany > PCI_STD_NUM_BARS);
324349

325350
if (dev->non_compliant_bars)
326351
return;
@@ -329,18 +354,36 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
329354
if (dev->is_virtfn)
330355
return;
331356

357+
/* No printks while decoding is disabled! */
358+
if (!dev->mmio_always_on) {
359+
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
360+
if (orig_cmd & PCI_COMMAND_DECODE_ENABLE) {
361+
pci_write_config_word(dev, PCI_COMMAND,
362+
orig_cmd & ~PCI_COMMAND_DECODE_ENABLE);
363+
}
364+
}
365+
366+
__pci_size_stdbars(dev, howmany, PCI_BASE_ADDRESS_0, stdbars);
367+
if (rom)
368+
__pci_size_rom(dev, rom, &rombar);
369+
370+
if (!dev->mmio_always_on &&
371+
(orig_cmd & PCI_COMMAND_DECODE_ENABLE))
372+
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
373+
332374
for (pos = 0; pos < howmany; pos++) {
333375
struct resource *res = &dev->resource[pos];
334376
reg = PCI_BASE_ADDRESS_0 + (pos << 2);
335-
pos += __pci_read_base(dev, pci_bar_unknown, res, reg);
377+
pos += __pci_read_base(dev, pci_bar_unknown,
378+
res, reg, &stdbars[pos]);
336379
}
337380

338381
if (rom) {
339382
struct resource *res = &dev->resource[PCI_ROM_RESOURCE];
340383
dev->rom_base_reg = rom;
341384
res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH |
342385
IORESOURCE_READONLY | IORESOURCE_SIZEALIGN;
343-
__pci_read_base(dev, pci_bar_mem32, res, rom);
386+
__pci_read_base(dev, pci_bar_mem32, res, rom, &rombar);
344387
}
345388
}
346389

0 commit comments

Comments
 (0)