Skip to content

Commit 1e42de8

Browse files
spandruvadajwrdegoede
authored andcommitted
platform/x86: ISST: Optimize CPU to PCI device mapping
It was observed that some of the high performance benchmarks are spending more time in kernel depending on which CPU package they are executing. The difference is significant and benchmark scores varies more than 10%. These benchmarks adjust class of service to improve thread performance which run in parallel. This class of service change causes access to MMIO region of Intel Speed Select PCI devices depending on the CPU package they are executing. This mapping from CPU to PCI device instance uses a standard Linux PCI interface "pci_get_domain_bus_and_slot()". This function does a linear search to get to a PCI device. Since these platforms have 100+ PCI devices, this search can be expensive in fast path for benchmarks. Since the device and function of PCI device is fixed for Intel Speed Select PCI devices, the CPU to PCI device information can be cached at the same time when bus number for the CPU is read. In this way during runtime the cached information can be used. This improves performance of these benchmarks significantly. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Link: https://lore.kernel.org/r/20210616221329.1909276-1-srinivas.pandruvada@linux.intel.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent 307722e commit 1e42de8

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

drivers/platform/x86/intel_speed_select_if/isst_if_common.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,27 @@ static int isst_if_get_platform_info(void __user *argp)
281281
struct isst_if_cpu_info {
282282
/* For BUS 0 and BUS 1 only, which we need for PUNIT interface */
283283
int bus_info[2];
284+
struct pci_dev *pci_dev[2];
284285
int punit_cpu_id;
285286
};
286287

287288
static struct isst_if_cpu_info *isst_cpu_info;
288289

290+
static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
291+
{
292+
int bus_number;
293+
294+
if (bus_no < 0 || bus_no > 1 || cpu < 0 || cpu >= nr_cpu_ids ||
295+
cpu >= num_possible_cpus())
296+
return NULL;
297+
298+
bus_number = isst_cpu_info[cpu].bus_info[bus_no];
299+
if (bus_number < 0)
300+
return NULL;
301+
302+
return pci_get_domain_bus_and_slot(0, bus_number, PCI_DEVFN(dev, fn));
303+
}
304+
289305
/**
290306
* isst_if_get_pci_dev() - Get the PCI device instance for a CPU
291307
* @cpu: Logical CPU number.
@@ -300,17 +316,18 @@ static struct isst_if_cpu_info *isst_cpu_info;
300316
*/
301317
struct pci_dev *isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
302318
{
303-
int bus_number;
319+
struct pci_dev *pci_dev;
304320

305321
if (bus_no < 0 || bus_no > 1 || cpu < 0 || cpu >= nr_cpu_ids ||
306322
cpu >= num_possible_cpus())
307323
return NULL;
308324

309-
bus_number = isst_cpu_info[cpu].bus_info[bus_no];
310-
if (bus_number < 0)
311-
return NULL;
325+
pci_dev = isst_cpu_info[cpu].pci_dev[bus_no];
312326

313-
return pci_get_domain_bus_and_slot(0, bus_number, PCI_DEVFN(dev, fn));
327+
if (pci_dev && pci_dev->devfn == PCI_DEVFN(dev, fn))
328+
return pci_dev;
329+
330+
return _isst_if_get_pci_dev(cpu, bus_no, dev, fn);
314331
}
315332
EXPORT_SYMBOL_GPL(isst_if_get_pci_dev);
316333

@@ -327,6 +344,8 @@ static int isst_if_cpu_online(unsigned int cpu)
327344
} else {
328345
isst_cpu_info[cpu].bus_info[0] = data & 0xff;
329346
isst_cpu_info[cpu].bus_info[1] = (data >> 8) & 0xff;
347+
isst_cpu_info[cpu].pci_dev[0] = _isst_if_get_pci_dev(cpu, 0, 0, 1);
348+
isst_cpu_info[cpu].pci_dev[1] = _isst_if_get_pci_dev(cpu, 1, 30, 1);
330349
}
331350

332351
ret = rdmsrl_safe(MSR_THREAD_ID_INFO, &data);

0 commit comments

Comments
 (0)