summaryrefslogtreecommitdiff
path: root/irq.c
blob: fc2427bd0fa061689205035ca27c28ba98f8d9b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * netsniff-ng - the packet sniffing beast
 * Copyright 2009 - 2013 Daniel Borkmann.
 * Copyright 2009, 2010 Emmanuel Roullit.
 * Subject to the GPL, version 2.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "irq.h"
#include "str.h"
#include "die.h"
#include "xutils.h"

int device_irq_number(const char *ifname)
{
	int irq = 0;
	char buff[128], sysname[128];
	FILE *fp;

	if (!strncmp("lo", ifname, strlen("lo")))
		return 0;

	slprintf(sysname, sizeof(sysname),
		 "/sys/class/net/%s/device/irq",
		 ifname);

	fp = fopen(sysname, "r");
	if (!fp)
		return -ENOENT;

	memset(buff, 0, sizeof(buff));

	if (fgets(buff, sizeof(buff), fp) != NULL) {
		buff[sizeof(buff) - 1] = 0;
		irq = atoi(buff);
	}

	fclose(fp);
	return irq;
}

static char nic_irq_affinity_list[128];
static bool nic_irq_stored = false;
static int  nic_irq = -1;

static void device_save_irq_affinity_list(void)
{
	int ret, fd;
	char file[128];

	bug_on(nic_irq_stored);

	slprintf(file, sizeof(file),
		 "/proc/irq/%d/smp_affinity_list", nic_irq);

	fd = open(file, O_RDONLY);
	if (fd < 0)
		return;

	memset(nic_irq_affinity_list, 0, sizeof(nic_irq_affinity_list));

	ret = read(fd, nic_irq_affinity_list,
		   sizeof(nic_irq_affinity_list));
	if (ret < 0)
		panic("Cannot store NIC IRQ affinity!\n");

	close(fd);

	nic_irq_stored = true;
}

void device_restore_irq_affinity_list(void)
{
	int ret, fd;
	char file[128];

	if (!nic_irq_stored)
		return;

	bug_on(nic_irq == -1);

	slprintf(file, sizeof(file),
		 "/proc/irq/%d/smp_affinity_list", nic_irq);

	fd = open(file, O_WRONLY);
	if (fd < 0)
		return;

	ret = write(fd, nic_irq_affinity_list,
		    sizeof(nic_irq_affinity_list));
	if (ret < 0)
		panic("Cannot restore NIC IRQ affinity!\n");

	close(fd);
}

int device_set_irq_affinity_list(int irq, unsigned long from, unsigned long to)
{
	int ret, fd;
	char file[128], list[64];

	if (!nic_irq_stored) {
		nic_irq = irq;
		device_save_irq_affinity_list();
	}

	slprintf(file, sizeof(file), "/proc/irq/%d/smp_affinity_list", irq);
	slprintf(list, sizeof(list), "%lu-%lu\n", from, to);

	fd = open(file, O_WRONLY);
	if (fd < 0)
		return -ENOENT;

	ret = write(fd, list, strlen(list));

	close(fd);
	return ret;
}

int device_bind_irq_to_cpu(int irq, int cpu)
{
	return device_set_irq_affinity_list(irq, cpu, cpu);
}