Commit 568a8990 authored by Thomas Renninger's avatar Thomas Renninger Committed by Dominik Brodowski

cpupower: Better interface for accessing AMD pci registers

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: default avatarThomas Renninger <trenn@suse.de>
CC: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 6b21d18e
...@@ -112,14 +112,12 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family, ...@@ -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) int amd_pci_get_num_boost_states(int *active, int *states)
{ {
struct pci_access *pci_acc; struct pci_access *pci_acc;
int vendor_id = 0x1022;
int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0};
struct pci_dev *device; struct pci_dev *device;
uint8_t val = 0; uint8_t val = 0;
*active = *states = 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) if (device == NULL)
return -ENODEV; return -ENODEV;
......
...@@ -132,8 +132,11 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); ...@@ -132,8 +132,11 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
/* PCI stuff ****************************/ /* PCI stuff ****************************/
extern int amd_pci_get_num_boost_states(int *active, int *states); 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, extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain,
int *dev_ids); 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 ****************************/ /* PCI stuff ****************************/
......
...@@ -10,19 +10,24 @@ ...@@ -10,19 +10,24 @@
* **pacc : if a valid pci_dev is returned * **pacc : if a valid pci_dev is returned
* *pacc must be passed to pci_acc_cleanup to free it * *pacc must be passed to pci_acc_cleanup to free it
* *
* vendor_id : the pci vendor id matching the pci device to access * domain: domain
* dev_ids : device ids matching the pci device to access * bus: bus
* slot: slot
* func: func
* vendor: vendor
* device: device
* Pass -1 for one of the six above to match any
* *
* Returns : * Returns :
* struct pci_dev which can be used with pci_{read,write}_* functions * struct pci_dev which can be used with pci_{read,write}_* functions
* to access the PCI config space of matching pci devices * to access the PCI config space of matching pci devices
*/ */
struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
int *dev_ids) 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; struct pci_dev *device;
unsigned int i;
*pacc = pci_alloc(); *pacc = pci_alloc();
if (*pacc == NULL) if (*pacc == NULL)
...@@ -31,14 +36,20 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, ...@@ -31,14 +36,20 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
pci_init(*pacc); pci_init(*pacc);
pci_scan_bus(*pacc); pci_scan_bus(*pacc);
for (i = 0; dev_ids[i] != 0; i++) { for (device = (*pacc)->devices; device; device = device->next) {
filter_nb_link.device = dev_ids[i]; if (pci_filter_match(&filter_nb_link, device))
for (device = (*pacc)->devices; device; device = device->next) { return device;
if (pci_filter_match(&filter_nb_link, device))
return device;
}
} }
pci_cleanup(*pacc); pci_cleanup(*pacc);
return NULL; 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__) */ #endif /* defined(__i386__) || defined(__x86_64__) */
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include "idle_monitor/cpupower-monitor.h" #include "idle_monitor/cpupower-monitor.h"
#include "helpers/helpers.h" #include "helpers/helpers.h"
/******** PCI parts could go into own file and get shared ***************/
#define PCI_NON_PC0_OFFSET 0xb0 #define PCI_NON_PC0_OFFSET 0xb0
#define PCI_PC1_OFFSET 0xb4 #define PCI_PC1_OFFSET 0xb4
#define PCI_PC6_OFFSET 0xb8 #define PCI_PC6_OFFSET 0xb8
...@@ -82,10 +80,7 @@ static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = { ...@@ -82,10 +80,7 @@ static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
}; };
static struct pci_access *pci_acc; 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 struct pci_dev *amd_fam14h_pci_dev;
static int nbp1_entered; static int nbp1_entered;
struct timespec start_time; struct timespec start_time;
...@@ -303,7 +298,9 @@ struct cpuidle_monitor *amd_fam14h_register(void) ...@@ -303,7 +298,9 @@ struct cpuidle_monitor *amd_fam14h_register(void)
sizeof(unsigned long long)); 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) if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment