|
|
@@ -39,6 +39,7 @@
|
|
|
#include <linux/prefetch.h>
|
|
|
#include <net/ip6_checksum.h>
|
|
|
#include <linux/ktime.h>
|
|
|
+#include <linux/numa.h>
|
|
|
#ifdef CONFIG_RFS_ACCEL
|
|
|
#include <linux/cpu_rmap.h>
|
|
|
#endif
|
|
|
@@ -112,6 +113,71 @@ static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
|
|
|
{3, 6}, /* 10 - 40 Gbps */
|
|
|
};
|
|
|
|
|
|
+static void enic_init_affinity_hint(struct enic *enic)
|
|
|
+{
|
|
|
+ int numa_node = dev_to_node(&enic->pdev->dev);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < enic->intr_count; i++) {
|
|
|
+ if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i) ||
|
|
|
+ (enic->msix[i].affinity_mask &&
|
|
|
+ !cpumask_empty(enic->msix[i].affinity_mask)))
|
|
|
+ continue;
|
|
|
+ if (zalloc_cpumask_var(&enic->msix[i].affinity_mask,
|
|
|
+ GFP_KERNEL))
|
|
|
+ cpumask_set_cpu(cpumask_local_spread(i, numa_node),
|
|
|
+ enic->msix[i].affinity_mask);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void enic_free_affinity_hint(struct enic *enic)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < enic->intr_count; i++) {
|
|
|
+ if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i))
|
|
|
+ continue;
|
|
|
+ free_cpumask_var(enic->msix[i].affinity_mask);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void enic_set_affinity_hint(struct enic *enic)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ for (i = 0; i < enic->intr_count; i++) {
|
|
|
+ if (enic_is_err_intr(enic, i) ||
|
|
|
+ enic_is_notify_intr(enic, i) ||
|
|
|
+ !enic->msix[i].affinity_mask ||
|
|
|
+ cpumask_empty(enic->msix[i].affinity_mask))
|
|
|
+ continue;
|
|
|
+ err = irq_set_affinity_hint(enic->msix_entry[i].vector,
|
|
|
+ enic->msix[i].affinity_mask);
|
|
|
+ if (err)
|
|
|
+ netdev_warn(enic->netdev, "irq_set_affinity_hint failed, err %d\n",
|
|
|
+ err);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < enic->wq_count; i++) {
|
|
|
+ int wq_intr = enic_msix_wq_intr(enic, i);
|
|
|
+
|
|
|
+ if (enic->msix[wq_intr].affinity_mask &&
|
|
|
+ !cpumask_empty(enic->msix[wq_intr].affinity_mask))
|
|
|
+ netif_set_xps_queue(enic->netdev,
|
|
|
+ enic->msix[wq_intr].affinity_mask,
|
|
|
+ i);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void enic_unset_affinity_hint(struct enic *enic)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < enic->intr_count; i++)
|
|
|
+ irq_set_affinity_hint(enic->msix_entry[i].vector, NULL);
|
|
|
+}
|
|
|
+
|
|
|
int enic_is_dynamic(struct enic *enic)
|
|
|
{
|
|
|
return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
|
|
|
@@ -1649,6 +1715,8 @@ static int enic_open(struct net_device *netdev)
|
|
|
netdev_err(netdev, "Unable to request irq.\n");
|
|
|
return err;
|
|
|
}
|
|
|
+ enic_init_affinity_hint(enic);
|
|
|
+ enic_set_affinity_hint(enic);
|
|
|
|
|
|
err = enic_dev_notify_set(enic);
|
|
|
if (err) {
|
|
|
@@ -1701,6 +1769,7 @@ err_out_free_rq:
|
|
|
vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
|
|
|
enic_dev_notify_unset(enic);
|
|
|
err_out_free_intr:
|
|
|
+ enic_unset_affinity_hint(enic);
|
|
|
enic_free_intr(enic);
|
|
|
|
|
|
return err;
|
|
|
@@ -1754,6 +1823,7 @@ static int enic_stop(struct net_device *netdev)
|
|
|
}
|
|
|
|
|
|
enic_dev_notify_unset(enic);
|
|
|
+ enic_unset_affinity_hint(enic);
|
|
|
enic_free_intr(enic);
|
|
|
|
|
|
for (i = 0; i < enic->wq_count; i++)
|
|
|
@@ -2309,6 +2379,7 @@ static void enic_dev_deinit(struct enic *enic)
|
|
|
|
|
|
enic_free_vnic_resources(enic);
|
|
|
enic_clear_intr_mode(enic);
|
|
|
+ enic_free_affinity_hint(enic);
|
|
|
}
|
|
|
|
|
|
static void enic_kdump_kernel_config(struct enic *enic)
|
|
|
@@ -2404,6 +2475,7 @@ static int enic_dev_init(struct enic *enic)
|
|
|
return 0;
|
|
|
|
|
|
err_out_free_vnic_resources:
|
|
|
+ enic_free_affinity_hint(enic);
|
|
|
enic_clear_intr_mode(enic);
|
|
|
enic_free_vnic_resources(enic);
|
|
|
|