From: Neil Horman <nhorman@tuxdriver.com>
Date: Fri, 24 May 2013 07:32:31 -0400
Subject: Make irqbalance work with Xen PV guest
Git-commit: 736a91b739018530c44e59d9b17252f88227fe51
Patch-mainline: v1.0.6
References: bsc#949276

This patch does two things:

1. extract IRQ name in parse_proc_interrupts() then pass it to add_new_irq()
2. do classification in add_new_irq()

Signed-off-by: Wei Liu <liuw@liuw.name>
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>

---
 classify.c       |   20 +++++++++++++++-----
 irqbalance.h     |    2 +-
 procinterrupts.c |   27 ++++++++++++++++++++++++++-
 types.h          |   10 +++++++---
 4 files changed, 49 insertions(+), 10 deletions(-)

--- a/classify.c
+++ b/classify.c
@@ -18,11 +18,12 @@ char *classes[] = {
 	"ethernet",
 	"gbit-ethernet",
 	"10gbit-ethernet",
+	"virt-event",
 	0
 };
 
-int map_class_to_level[7] = 
-{ BALANCE_PACKAGE, BALANCE_CACHE, BALANCE_CACHE, BALANCE_NONE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE };
+int map_class_to_level[8] =
+{ BALANCE_PACKAGE, BALANCE_CACHE, BALANCE_CACHE, BALANCE_NONE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE };
 
 
 #define MAX_CLASS 0x12
@@ -368,7 +369,7 @@ void rebuild_irq_db(void)
 		
 }
 
-struct irq_info *add_new_irq(int irq)
+struct irq_info *add_new_irq(int irq, const char *irq_name)
 {
 	struct irq_info *new, *nnew;
 
@@ -378,8 +379,17 @@ struct irq_info *add_new_irq(int irq)
 		return NULL;
 
 	new->irq = irq;
-	new->type = IRQ_TYPE_LEGACY;
-	new->class = IRQ_OTHER;
+	/* Do classification here. As Xen PV is the first resident
+	 * here, this is done rather simple.
+	 */
+	if (strstr(irq_name, "xen-dyn-event") != NULL) {
+		new->type = IRQ_TYPE_VIRT_EVENT;
+		new->class = IRQ_VIRT_EVENT;
+	} else {
+		new->type = IRQ_TYPE_LEGACY;
+		new->class = IRQ_OTHER;
+	}
+	new->level = map_class_to_level[new->class];
 	new->numa_node = get_numa_node(-1);
 	memcpy(nnew, new, sizeof(struct irq_info));
 	interrupts_db = g_list_append(interrupts_db, new);
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -108,7 +108,7 @@ extern void add_banned_irq(int irq);
 extern void for_each_irq(GList *list, void (*cb)(struct irq_info *info,  void *data), void *data);
 extern struct irq_info *get_irq_info(int irq);
 extern void migrate_irq(GList **from, GList **to, struct irq_info *info);
-extern struct irq_info *add_new_irq(int irq);
+extern struct irq_info *add_new_irq(int irq, const char *irq_name);
 #define irq_numa_node(irq) ((irq)->numa_node)
 
 
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -61,6 +61,8 @@ void parse_proc_interrupts(void)
 		uint64_t count;
 		char *c, *c2;
 		struct irq_info *info;
+		char *irq_name, *last_token, *p, *savedptr;
+		char savedline[1024];
 
 		if (getline(&line, &size, file)==0)
 			break;
@@ -79,15 +81,38 @@ void parse_proc_interrupts(void)
 		c = strchr(line, ':');
 		if (!c)
 			continue;
+
+		strncpy(savedline, line, sizeof(savedline));
+
 		*c = 0;
 		c++;
 		number = strtoul(line, NULL, 10);
+
+		/* Extract interrupt name such as "IO-APIC-fasteoi". At
+		 * this point "savedline" is string like (note that
+		 * special interrupts are all ignored above):
+		 *
+		 *  4:      150    IO-APIC-fasteoi  serial
+		 *
+		 * The string contains at least four fields
+		 * delineated by white spaces. The first field is
+		 * interrupt number, followed by nr_cpus (>=1)
+		 * interrupt counts, followed by interrupt name, then
+		 * followed by device name.
+		 */
+		irq_name = strtok_r(savedline, " ", &savedptr);
+		last_token = strtok_r(NULL, " ", &savedptr);
+		while ((p = strtok_r(NULL, " ", &savedptr))) {
+			irq_name = last_token;
+			last_token = p;
+		}
+
 		info = get_irq_info(number);
 		if (!info) {
 			if (!cycle_count)
 				continue;
 			need_rescan = 1;
-			info = add_new_irq(number);
+			info = add_new_irq(number, irq_name);
 		}
 
 		count = 0;
--- a/types.h
+++ b/types.h
@@ -18,13 +18,17 @@
 #define IRQ_SCSI        2
 #define IRQ_TIMER       3
 #define IRQ_ETH         4
+#define IRQ_GBETH       5
+#define IRQ_10GBETH     6
+#define IRQ_VIRT_EVENT  7
 
 /*
  * IRQ Types
  */
-#define IRQ_TYPE_LEGACY 0
-#define IRQ_TYPE_MSI	1
-#define IRQ_TYPE_MSIX	2
+#define IRQ_TYPE_LEGACY     0
+#define IRQ_TYPE_MSI        1
+#define IRQ_TYPE_MSIX       2
+#define IRQ_TYPE_VIRT_EVENT 3
 
 enum obj_type_e {
 	OBJ_TYPE_CPU,
