add irq hotplug feature for irqbalance
This commit is contained in:
parent
004c7abcdb
commit
0ba4a60a2a
80
classify.c
80
classify.c
|
@ -619,7 +619,7 @@ static void add_new_irq(char *path, struct irq_info *hint, GList *proc_interrupt
|
|||
/*
|
||||
* Figures out which interrupt(s) relate to the device we"re looking at in dirname
|
||||
*/
|
||||
static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
|
||||
static void build_one_dev_entry(const char *dirname, GList *tmp_irqs, int build_irq)
|
||||
{
|
||||
struct dirent *entry;
|
||||
DIR *msidir;
|
||||
|
@ -642,10 +642,14 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
|
|||
if (!entry)
|
||||
break;
|
||||
irqnum = strtol(entry->d_name, NULL, 10);
|
||||
if (irqnum) {
|
||||
/* If build_irq is valid, only add irq when it's number equals to build_irq */
|
||||
if (irqnum && ((build_irq < 0) || (irqnum == build_irq))) {
|
||||
printf("add irq:%d %d for %s\n", irqnum, build_irq, path);
|
||||
hint.irq = irqnum;
|
||||
hint.type = IRQ_TYPE_MSIX;
|
||||
add_new_irq(devpath, &hint, tmp_irqs);
|
||||
if (build_irq >= 0)
|
||||
break;
|
||||
}
|
||||
} while (entry != NULL);
|
||||
closedir(msidir);
|
||||
|
@ -665,9 +669,12 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
|
|||
#else
|
||||
if (irqnum) {
|
||||
#endif
|
||||
hint.irq = irqnum;
|
||||
hint.type = IRQ_TYPE_LEGACY;
|
||||
add_new_irq(devpath, &hint, tmp_irqs);
|
||||
/* If build_irq is valid, only add irq when it's number equals to build_irq */
|
||||
if ((build_irq < 0) || (irqnum == build_irq)) {
|
||||
hint.irq = irqnum;
|
||||
hint.type = IRQ_TYPE_LEGACY;
|
||||
add_new_irq(devpath, &hint, tmp_irqs);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -712,31 +719,60 @@ static void free_tmp_irqs(gpointer data)
|
|||
free(info);
|
||||
}
|
||||
|
||||
void rebuild_irq_db(void)
|
||||
static struct irq_info * build_dev_irqs(GList *tmp_irqs, int build_irq)
|
||||
{
|
||||
DIR *devdir;
|
||||
struct dirent *entry;
|
||||
struct irq_info *new_irq = NULL;
|
||||
|
||||
devdir = opendir(SYSPCI_DIR);
|
||||
if (devdir) {
|
||||
do {
|
||||
entry = readdir(devdir);
|
||||
if (!entry)
|
||||
break;
|
||||
/* when hotplug irqs, we add one irq at one time */
|
||||
build_one_dev_entry(entry->d_name, tmp_irqs, build_irq);
|
||||
if (build_irq >= 0) {
|
||||
new_irq = get_irq_info(build_irq);
|
||||
if (new_irq)
|
||||
break;
|
||||
}
|
||||
} while (entry != NULL);
|
||||
closedir(devdir);
|
||||
}
|
||||
return new_irq;
|
||||
}
|
||||
|
||||
int proc_irq_hotplug(char *savedline, int irq, struct irq_info **pinfo)
|
||||
{
|
||||
struct irq_info tmp_info = {0};
|
||||
|
||||
/* firstly, init irq info by read device info */
|
||||
*pinfo = build_dev_irqs(interrupts_db, irq);
|
||||
if (*pinfo == NULL) {
|
||||
/* secondly, init irq info by parse savedline */
|
||||
init_irq_class_and_type(savedline, &tmp_info, irq);
|
||||
add_new_irq(NULL, &tmp_info, interrupts_db);
|
||||
*pinfo = get_irq_info(irq);
|
||||
}
|
||||
if (*pinfo == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
force_rebalance_irq(*pinfo, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rebuild_irq_db(void)
|
||||
{
|
||||
GList *tmp_irqs = NULL;
|
||||
|
||||
free_irq_db();
|
||||
|
||||
tmp_irqs = collect_full_irq_list();
|
||||
|
||||
devdir = opendir(SYSPCI_DIR);
|
||||
|
||||
if (devdir) {
|
||||
do {
|
||||
entry = readdir(devdir);
|
||||
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
build_one_dev_entry(entry->d_name, tmp_irqs);
|
||||
|
||||
} while (entry != NULL);
|
||||
|
||||
closedir(devdir);
|
||||
}
|
||||
|
||||
build_dev_irqs(tmp_irqs, -1);
|
||||
|
||||
for_each_irq(tmp_irqs, add_missing_irq, interrupts_db);
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ static void dump_object_tree(void)
|
|||
for_each_object(numa_nodes, dump_numa_node_info, NULL);
|
||||
}
|
||||
|
||||
static void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
|
||||
void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
|
||||
{
|
||||
if (info->level == BALANCE_NONE)
|
||||
return;
|
||||
|
|
|
@ -40,8 +40,11 @@ extern GList* collect_full_irq_list();
|
|||
extern void parse_proc_stat(void);
|
||||
extern void set_interrupt_count(int number, uint64_t count);
|
||||
extern void set_msi_interrupt_numa(int number);
|
||||
extern void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq);
|
||||
extern int proc_irq_hotplug(char *line, int irq, struct irq_info **pinfo);
|
||||
|
||||
extern GList *rebalance_irq_list;
|
||||
extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
|
||||
|
||||
void update_migration_status(void);
|
||||
void dump_workloads(void);
|
||||
|
@ -52,7 +55,6 @@ void dump_tree(void);
|
|||
void activate_mappings(void);
|
||||
void clear_cpu_tree(void);
|
||||
void free_cpu_topo(gpointer data);
|
||||
|
||||
/*===================NEW BALANCER FUNCTIONS============================*/
|
||||
|
||||
/*
|
||||
|
|
104
procinterrupts.c
104
procinterrupts.c
|
@ -145,16 +145,59 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
|
|||
}
|
||||
#endif
|
||||
|
||||
void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
|
||||
{
|
||||
char *irq_name = NULL;
|
||||
char *irq_mod = NULL;
|
||||
char *savedptr = NULL;
|
||||
char *last_token = NULL;
|
||||
char *p = NULL;
|
||||
int is_xen_dyn = 0;
|
||||
#ifdef AARCH64
|
||||
char *tmp = NULL;
|
||||
#endif
|
||||
|
||||
irq_name = strtok_r(savedline, " ", &savedptr);
|
||||
if (strstr(irq_name, "xen-dyn") != NULL)
|
||||
is_xen_dyn = 1;
|
||||
last_token = strtok_r(NULL, " ", &savedptr);
|
||||
while ((p = strtok_r(NULL, " ", &savedptr))) {
|
||||
irq_name = last_token;
|
||||
if (strstr(irq_name, "xen-dyn") != NULL)
|
||||
is_xen_dyn = 1;
|
||||
last_token = p;
|
||||
}
|
||||
|
||||
#ifdef AARCH64
|
||||
irq_name = last_token;
|
||||
tmp = strchr(irq_name, '\n');
|
||||
if (tmp)
|
||||
*tmp = 0;
|
||||
#endif
|
||||
irq_mod = last_token;
|
||||
info->irq = irq;
|
||||
|
||||
if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
|
||||
info->type = IRQ_TYPE_VIRT_EVENT;
|
||||
info->class = IRQ_VIRT_EVENT;
|
||||
} else {
|
||||
#ifdef AARCH64
|
||||
guess_arm_irq_hints(irq_name, info);
|
||||
#else
|
||||
info->type = IRQ_TYPE_LEGACY;
|
||||
info->class = IRQ_OTHER;
|
||||
#endif
|
||||
}
|
||||
info->numa_node = get_numa_node(0);
|
||||
info->name = strdup(irq_mod);
|
||||
}
|
||||
|
||||
GList* collect_full_irq_list()
|
||||
{
|
||||
GList *tmp_list = NULL;
|
||||
FILE *file;
|
||||
char *line = NULL;
|
||||
size_t size = 0;
|
||||
char *irq_name, *irq_mod, *savedptr, *last_token, *p;
|
||||
#ifdef AARCH64
|
||||
char *tmp;
|
||||
#endif
|
||||
|
||||
file = fopen("/proc/interrupts", "r");
|
||||
if (!file)
|
||||
|
@ -169,7 +212,6 @@ GList* collect_full_irq_list()
|
|||
|
||||
while (!feof(file)) {
|
||||
int number;
|
||||
int is_xen_dyn = 0;
|
||||
struct irq_info *info;
|
||||
char *c;
|
||||
char *savedline = NULL;
|
||||
|
@ -191,44 +233,12 @@ GList* collect_full_irq_list()
|
|||
savedline = strdup(line);
|
||||
if (!savedline)
|
||||
break;
|
||||
irq_name = strtok_r(savedline, " ", &savedptr);
|
||||
if (strstr(irq_name, "xen-dyn") != NULL)
|
||||
is_xen_dyn = 1;
|
||||
last_token = strtok_r(NULL, " ", &savedptr);
|
||||
while ((p = strtok_r(NULL, " ", &savedptr))) {
|
||||
irq_name = last_token;
|
||||
if (strstr(irq_name, "xen-dyn") != NULL)
|
||||
is_xen_dyn = 1;
|
||||
last_token = p;
|
||||
}
|
||||
|
||||
#ifdef AARCH64
|
||||
/* Of course the formatting for /proc/interrupts is different on different arches */
|
||||
irq_name = last_token;
|
||||
tmp = strchr(irq_name, '\n');
|
||||
if (tmp)
|
||||
*tmp = 0;
|
||||
#endif
|
||||
irq_mod = last_token;
|
||||
|
||||
*c = 0;
|
||||
number = strtoul(line, NULL, 10);
|
||||
|
||||
info = calloc(1, sizeof(struct irq_info));
|
||||
if (info) {
|
||||
info->irq = number;
|
||||
if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
|
||||
info->type = IRQ_TYPE_VIRT_EVENT;
|
||||
info->class = IRQ_VIRT_EVENT;
|
||||
} else {
|
||||
#ifdef AARCH64
|
||||
guess_arm_irq_hints(irq_name, info);
|
||||
#else
|
||||
info->type = IRQ_TYPE_LEGACY;
|
||||
info->class = IRQ_OTHER;
|
||||
#endif
|
||||
}
|
||||
info->name = strdup(irq_mod);
|
||||
init_irq_class_and_type(savedline, info, number);
|
||||
tmp_list = g_list_append(tmp_list, info);
|
||||
}
|
||||
free(savedline);
|
||||
|
@ -238,11 +248,13 @@ GList* collect_full_irq_list()
|
|||
return tmp_list;
|
||||
}
|
||||
|
||||
|
||||
void parse_proc_interrupts(void)
|
||||
{
|
||||
FILE *file;
|
||||
char *line = NULL;
|
||||
size_t size = 0;
|
||||
int ret;
|
||||
|
||||
file = fopen("/proc/interrupts", "r");
|
||||
if (!file)
|
||||
|
@ -261,6 +273,7 @@ void parse_proc_interrupts(void)
|
|||
uint64_t count;
|
||||
char *c, *c2;
|
||||
struct irq_info *info;
|
||||
char *savedline = NULL;
|
||||
|
||||
if (getline(&line, &size, file)<=0)
|
||||
break;
|
||||
|
@ -280,15 +293,24 @@ void parse_proc_interrupts(void)
|
|||
if (!c)
|
||||
continue;
|
||||
|
||||
savedline = strdup(line);
|
||||
if (!savedline)
|
||||
break;
|
||||
*c = 0;
|
||||
c++;
|
||||
number = strtoul(line, NULL, 10);
|
||||
|
||||
info = get_irq_info(number);
|
||||
if (!info) {
|
||||
need_rescan = 1;
|
||||
break;
|
||||
ret = proc_irq_hotplug(savedline, number, &info);
|
||||
if (ret < 0) {
|
||||
/* hotplug fail, need to rescan */
|
||||
need_rescan = 1;
|
||||
free(savedline);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(savedline);
|
||||
|
||||
count = 0;
|
||||
cpunr = 0;
|
||||
|
@ -316,7 +338,7 @@ void parse_proc_interrupts(void)
|
|||
break;
|
||||
}
|
||||
|
||||
info->last_irq_count = info->irq_count;
|
||||
info->last_irq_count = info->irq_count;
|
||||
info->irq_count = count;
|
||||
|
||||
/* is interrupt MSI based? */
|
||||
|
|
Loading…
Reference in a new issue