Skip to content

Commit 322cf7e

Browse files
Govindarajulu Varadarajandavem330
authored andcommitted
enic: assign affinity hint to interrupts
The affinity hint is used by the user space daemon, irqbalancer, to indicate a preferred CPU mask for irqs. This patch sets the irq affinity hint to local numa core first, when exausted we try non-local numa cores. Also set tx xps cpus mask bassed on affinity hint. v2: remove the global affinity policy. Signed-off-by: Govindarajulu Varadarajan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9920e48 commit 322cf7e

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

drivers/net/ethernet/cisco/enic/enic.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct enic_msix_entry {
5050
char devname[IFNAMSIZ];
5151
irqreturn_t (*isr)(int, void *);
5252
void *devid;
53+
cpumask_var_t affinity_mask;
5354
};
5455

5556
/* Store only the lower range. Higher range is given by fw. */
@@ -263,6 +264,32 @@ static inline unsigned int enic_msix_notify_intr(struct enic *enic)
263264
return enic->rq_count + enic->wq_count + 1;
264265
}
265266

267+
static inline bool enic_is_err_intr(struct enic *enic, int intr)
268+
{
269+
switch (vnic_dev_get_intr_mode(enic->vdev)) {
270+
case VNIC_DEV_INTR_MODE_INTX:
271+
return intr == enic_legacy_err_intr();
272+
case VNIC_DEV_INTR_MODE_MSIX:
273+
return intr == enic_msix_err_intr(enic);
274+
case VNIC_DEV_INTR_MODE_MSI:
275+
default:
276+
return false;
277+
}
278+
}
279+
280+
static inline bool enic_is_notify_intr(struct enic *enic, int intr)
281+
{
282+
switch (vnic_dev_get_intr_mode(enic->vdev)) {
283+
case VNIC_DEV_INTR_MODE_INTX:
284+
return intr == enic_legacy_notify_intr();
285+
case VNIC_DEV_INTR_MODE_MSIX:
286+
return intr == enic_msix_notify_intr(enic);
287+
case VNIC_DEV_INTR_MODE_MSI:
288+
default:
289+
return false;
290+
}
291+
}
292+
266293
static inline int enic_dma_map_check(struct enic *enic, dma_addr_t dma_addr)
267294
{
268295
if (unlikely(pci_dma_mapping_error(enic->pdev, dma_addr))) {

drivers/net/ethernet/cisco/enic/enic_main.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <linux/prefetch.h>
4040
#include <net/ip6_checksum.h>
4141
#include <linux/ktime.h>
42+
#include <linux/numa.h>
4243
#ifdef CONFIG_RFS_ACCEL
4344
#include <linux/cpu_rmap.h>
4445
#endif
@@ -112,6 +113,71 @@ static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
112113
{3, 6}, /* 10 - 40 Gbps */
113114
};
114115

116+
static void enic_init_affinity_hint(struct enic *enic)
117+
{
118+
int numa_node = dev_to_node(&enic->pdev->dev);
119+
int i;
120+
121+
for (i = 0; i < enic->intr_count; i++) {
122+
if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i) ||
123+
(enic->msix[i].affinity_mask &&
124+
!cpumask_empty(enic->msix[i].affinity_mask)))
125+
continue;
126+
if (zalloc_cpumask_var(&enic->msix[i].affinity_mask,
127+
GFP_KERNEL))
128+
cpumask_set_cpu(cpumask_local_spread(i, numa_node),
129+
enic->msix[i].affinity_mask);
130+
}
131+
}
132+
133+
static void enic_free_affinity_hint(struct enic *enic)
134+
{
135+
int i;
136+
137+
for (i = 0; i < enic->intr_count; i++) {
138+
if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i))
139+
continue;
140+
free_cpumask_var(enic->msix[i].affinity_mask);
141+
}
142+
}
143+
144+
static void enic_set_affinity_hint(struct enic *enic)
145+
{
146+
int i;
147+
int err;
148+
149+
for (i = 0; i < enic->intr_count; i++) {
150+
if (enic_is_err_intr(enic, i) ||
151+
enic_is_notify_intr(enic, i) ||
152+
!enic->msix[i].affinity_mask ||
153+
cpumask_empty(enic->msix[i].affinity_mask))
154+
continue;
155+
err = irq_set_affinity_hint(enic->msix_entry[i].vector,
156+
enic->msix[i].affinity_mask);
157+
if (err)
158+
netdev_warn(enic->netdev, "irq_set_affinity_hint failed, err %d\n",
159+
err);
160+
}
161+
162+
for (i = 0; i < enic->wq_count; i++) {
163+
int wq_intr = enic_msix_wq_intr(enic, i);
164+
165+
if (enic->msix[wq_intr].affinity_mask &&
166+
!cpumask_empty(enic->msix[wq_intr].affinity_mask))
167+
netif_set_xps_queue(enic->netdev,
168+
enic->msix[wq_intr].affinity_mask,
169+
i);
170+
}
171+
}
172+
173+
static void enic_unset_affinity_hint(struct enic *enic)
174+
{
175+
int i;
176+
177+
for (i = 0; i < enic->intr_count; i++)
178+
irq_set_affinity_hint(enic->msix_entry[i].vector, NULL);
179+
}
180+
115181
int enic_is_dynamic(struct enic *enic)
116182
{
117183
return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
@@ -1649,6 +1715,8 @@ static int enic_open(struct net_device *netdev)
16491715
netdev_err(netdev, "Unable to request irq.\n");
16501716
return err;
16511717
}
1718+
enic_init_affinity_hint(enic);
1719+
enic_set_affinity_hint(enic);
16521720

16531721
err = enic_dev_notify_set(enic);
16541722
if (err) {
@@ -1701,6 +1769,7 @@ static int enic_open(struct net_device *netdev)
17011769
vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
17021770
enic_dev_notify_unset(enic);
17031771
err_out_free_intr:
1772+
enic_unset_affinity_hint(enic);
17041773
enic_free_intr(enic);
17051774

17061775
return err;
@@ -1754,6 +1823,7 @@ static int enic_stop(struct net_device *netdev)
17541823
}
17551824

17561825
enic_dev_notify_unset(enic);
1826+
enic_unset_affinity_hint(enic);
17571827
enic_free_intr(enic);
17581828

17591829
for (i = 0; i < enic->wq_count; i++)
@@ -2309,6 +2379,7 @@ static void enic_dev_deinit(struct enic *enic)
23092379

23102380
enic_free_vnic_resources(enic);
23112381
enic_clear_intr_mode(enic);
2382+
enic_free_affinity_hint(enic);
23122383
}
23132384

23142385
static void enic_kdump_kernel_config(struct enic *enic)
@@ -2404,6 +2475,7 @@ static int enic_dev_init(struct enic *enic)
24042475
return 0;
24052476

24062477
err_out_free_vnic_resources:
2478+
enic_free_affinity_hint(enic);
24072479
enic_clear_intr_mode(enic);
24082480
enic_free_vnic_resources(enic);
24092481

0 commit comments

Comments
 (0)