Browse Source

Blacklist IRQs like timer

Serj Kalichev 10 years ago
parent
commit
bd2707d0aa
3 changed files with 59 additions and 29 deletions
  1. 49 6
      balance.c
  2. 2 1
      irq.h
  3. 8 22
      irq_parse.c

+ 49 - 6
balance.c

@@ -32,6 +32,24 @@ static int drop_dont_move_flag(cpu_t *cpu)
 	return 0;
 }
 
+/* Remove IRQ from specified CPU */
+static int remove_irq_from_cpu(irq_t *irq, cpu_t *cpu)
+{
+	lub_list_node_t *node;
+
+	if (!irq || !cpu)
+		return -1;
+
+	irq->cpu = NULL;
+	node = lub_list_search(cpu->irqs, irq);
+	if (!node)
+		return 0;
+	lub_list_del(cpu->irqs, node);
+	lub_list_node_free(node);
+
+	return 0;
+}
+
 /* Move IRQ to specified CPU. Remove IRQ from the IRQ list
    of old CPU. */
 static int move_irq_to_cpu(irq_t *irq, cpu_t *cpu)
@@ -41,12 +59,7 @@ static int move_irq_to_cpu(irq_t *irq, cpu_t *cpu)
 
 	if (irq->cpu) {
 		cpu_t *old_cpu = irq->cpu;
-		lub_list_node_t *node;
-		node = lub_list_search(old_cpu->irqs, irq);
-		if (node) {
-			lub_list_del(old_cpu->irqs, node);
-			lub_list_node_free(node);
-		}
+		remove_irq_from_cpu(irq, old_cpu);
 		drop_dont_move_flag(old_cpu);
 	}
 	drop_dont_move_flag(cpu);
@@ -100,6 +113,36 @@ static cpu_t *choose_cpu(lub_list_t *cpus, cpumask_t cpumask, float threshold)
 	return cpu;
 }
 
+static int irq_set_affinity(irq_t *irq, cpumask_t cpumask)
+{
+	char path[PATH_MAX];
+	char buf[NR_CPUS + 1];
+	FILE *fd;
+
+	if (!irq)
+		return -1;
+
+	sprintf(path, "%s/%u/smp_affinity", PROC_IRQ, irq->irq);
+	if (!(fd = fopen(path, "w")))
+		return -1;
+	cpumask_scnprintf(buf, sizeof(buf), cpumask);
+	fprintf(fd, "%s", buf);
+	fclose(fd);
+
+	/* Check for newly apllied affinity. The affinities for some
+	   IRQ can't be changed. So don't consider such IRQs. The
+	   example is IRQ 0 - timer. */
+	irq_get_affinity(irq);
+	if (!cpus_equal(irq->affinity, cpumask)) {
+		/* Blacklist this IRQ */
+		irq->blacklisted = 1;
+		remove_irq_from_cpu(irq, irq->cpu);
+		printf("Blacklist IRQ %u\n", irq->irq);
+	}
+
+	return 0;
+}
+
 /* Find best CPUs for IRQs need to be balanced. */
 int balance(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold)
 {

+ 2 - 1
irq.h

@@ -15,6 +15,7 @@ struct irq_s {
 	unsigned long long old_intr; /* Previous total number of interrupts. */
 	cpu_t *cpu; /* Current IRQ affinity. Reference to correspondent CPU */
 	int dont_move; /* Flag to don't move current IRQ anyway */
+	int blacklisted; /* IRQ can be blacklisted when can't change affinity */
 };
 typedef struct irq_s irq_t;
 
@@ -30,6 +31,6 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs);
 int irq_list_free(lub_list_t *irqs);
 int irq_list_show(lub_list_t *irqs);
 irq_t * irq_list_search(lub_list_t *irqs, unsigned int num);
-int irq_set_affinity(irq_t *irq, cpumask_t cpumask);
+int irq_get_affinity(irq_t *irq);
 
 #endif

+ 8 - 22
irq_parse.c

@@ -38,6 +38,7 @@ static irq_t * irq_new(int num)
 	new->dont_move = 0;
 	cpus_setall(new->local_cpus);
 	cpus_clear(new->affinity);
+	new->blacklisted = 0;
 
 	return new;
 }
@@ -199,26 +200,7 @@ static int parse_sysfs(lub_list_t *irqs)
 	return 0;
 }
 
-int irq_set_affinity(irq_t *irq, cpumask_t cpumask)
-{
-	char path[PATH_MAX];
-	char buf[NR_CPUS + 1];
-	FILE *fd;
-
-	if (!irq)
-		return -1;
-
-	sprintf(path, "%s/%u/smp_affinity", PROC_IRQ, irq->irq);
-	if (!(fd = fopen(path, "w")))
-		return -1;
-	cpumask_scnprintf(buf, sizeof(buf), cpumask);
-	fprintf(fd, "%s", buf);
-	fclose(fd);
-
-	return 0;
-}
-
-static int irq_get_affinity(irq_t *irq)
+int irq_get_affinity(irq_t *irq)
 {
 	char path[PATH_MAX];
 	FILE *fd;
@@ -270,6 +252,10 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs)
 		/* Set refresh flag because IRQ was found */
 		irq->refresh = 1;
 
+		/* Doesn't refresh info for blacklisted IRQs */
+		if (irq->blacklisted)
+			continue;
+
 		/* Find IRQ type - first non-digital and non-space */
 		while (*endptr && !isalpha(*endptr))
 			endptr++;
@@ -288,13 +274,13 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs)
 		free(irq->desc);
 		irq->desc = strndup(tok, endptr - tok);
 
-		irq_get_affinity(irq);
-
 		if (new) {
 			/* By default all CPUs are local for IRQ. Real local
 			   CPUs will be find while sysfs scan. */
 			cpus_setall(irq->local_cpus);
 
+			irq_get_affinity(irq);
+
 			lub_list_add(balance_irqs, irq);
 			printf("Add IRQ %3d %s\n", irq->irq, STR(irq->desc));
 		}