Skip to content

Commit

Permalink
cpupower: Better interface for accessing AMD pci registers
Browse files Browse the repository at this point in the history
AMD's BKDG (Bios and Kernel Developers Guide) talks in the CPU spec of their
CPU families about PCI registers defined by "device" (slot) and func(tion).

Assuming that CPU specific configuration PCI devices are always on domain
and bus zero a pci_slot_func_init() func which gets the slot and func of
the desired PCI device passed looks like the most convenient way.

This also obsoletes the PCI device id maintenance.

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
  • Loading branch information
watologo1 authored and Dominik Brodowski committed Mar 3, 2012
1 parent 6b21d18 commit 568a899
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 23 deletions.
4 changes: 1 addition & 3 deletions tools/power/cpupower/utils/helpers/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,12 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family,
int amd_pci_get_num_boost_states(int *active, int *states)
{
struct pci_access *pci_acc;
int vendor_id = 0x1022;
int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0};
struct pci_dev *device;
uint8_t val = 0;

*active = *states = 0;

device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids);
device = pci_slot_func_init(&pci_acc, 0x18, 4);

if (device == NULL)
return -ENODEV;
Expand Down
7 changes: 5 additions & 2 deletions tools/power/cpupower/utils/helpers/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,11 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);

/* PCI stuff ****************************/
extern int amd_pci_get_num_boost_states(int *active, int *states);
extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
int *dev_ids);
extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain,
int bus, int slot, int func, int vendor,
int dev);
extern struct pci_dev *pci_slot_func_init(struct pci_access **pacc,
int slot, int func);

/* PCI stuff ****************************/

Expand Down
35 changes: 23 additions & 12 deletions tools/power/cpupower/utils/helpers/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,24 @@
* **pacc : if a valid pci_dev is returned
* *pacc must be passed to pci_acc_cleanup to free it
*
* vendor_id : the pci vendor id matching the pci device to access
* dev_ids : device ids matching the pci device to access
* domain: domain
* bus: bus
* slot: slot
* func: func
* vendor: vendor
* device: device
* Pass -1 for one of the six above to match any
*
* Returns :
* struct pci_dev which can be used with pci_{read,write}_* functions
* to access the PCI config space of matching pci devices
*/
struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
int *dev_ids)
struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
int slot, int func, int vendor, int dev)
{
struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0};
struct pci_filter filter_nb_link = { domain, bus, slot, func,
vendor, dev };
struct pci_dev *device;
unsigned int i;

*pacc = pci_alloc();
if (*pacc == NULL)
Expand All @@ -31,14 +36,20 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
pci_init(*pacc);
pci_scan_bus(*pacc);

for (i = 0; dev_ids[i] != 0; i++) {
filter_nb_link.device = dev_ids[i];
for (device = (*pacc)->devices; device; device = device->next) {
if (pci_filter_match(&filter_nb_link, device))
return device;
}
for (device = (*pacc)->devices; device; device = device->next) {
if (pci_filter_match(&filter_nb_link, device))
return device;
}
pci_cleanup(*pacc);
return NULL;
}

/* Typically one wants to get a specific slot(device)/func of the root domain
and bus */
struct pci_dev *pci_slot_func_init(struct pci_access **pacc, int slot,
int func)
{
return pci_acc_init(pacc, 0, 0, slot, func, -1, -1);
}

#endif /* defined(__i386__) || defined(__x86_64__) */
9 changes: 3 additions & 6 deletions tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
#include "idle_monitor/cpupower-monitor.h"
#include "helpers/helpers.h"

/******** PCI parts could go into own file and get shared ***************/

#define PCI_NON_PC0_OFFSET 0xb0
#define PCI_PC1_OFFSET 0xb4
#define PCI_PC6_OFFSET 0xb8
Expand Down Expand Up @@ -82,10 +80,7 @@ static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
};

static struct pci_access *pci_acc;
static int pci_vendor_id = 0x1022;
static int pci_dev_ids[2] = {0x1716, 0};
static struct pci_dev *amd_fam14h_pci_dev;

static int nbp1_entered;

struct timespec start_time;
Expand Down Expand Up @@ -303,7 +298,9 @@ struct cpuidle_monitor *amd_fam14h_register(void)
sizeof(unsigned long long));
}

amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids);
/* We need PCI device: Slot 18, Func 6, compare with BKDG
for fam 12h/14h */
amd_fam14h_pci_dev = pci_slot_func_init(&pci_acc, 0x18, 6);
if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
return NULL;

Expand Down

0 comments on commit 568a899

Please sign in to comment.