net: hns3: add interrupt affinity support for misc interrupt
authorYunsheng Lin <linyunsheng@huawei.com>
Mon, 29 Jul 2019 02:53:29 +0000 (10:53 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 29 Jul 2019 15:23:41 +0000 (08:23 -0700)
The misc interrupt is used to schedule the reset and mailbox
subtask, and service_task delayed_work is used to do periodic
management work each second.

This patch sets the above three subtask's affinity using the
misc interrupt' affinity.

Also this patch setups a affinity notify for misc interrupt to
allow user to change the above three subtask's affinity.

Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h

index 13c9697f3a0207f44f0dd2ddfc7d258c4043dc6e..30a70743de89fc3a8383fbafcb163df18d72c68b 100644 (file)
@@ -1270,6 +1270,12 @@ static int hclge_configure(struct hclge_dev *hdev)
 
        hclge_init_kdump_kernel_config(hdev);
 
+       /* Set the init affinity based on pci func number */
+       i = cpumask_weight(cpumask_of_node(dev_to_node(&hdev->pdev->dev)));
+       i = i ? PCI_FUNC(hdev->pdev->devfn) % i : 0;
+       cpumask_set_cpu(cpumask_local_spread(i, dev_to_node(&hdev->pdev->dev)),
+                       &hdev->affinity_mask);
+
        return ret;
 }
 
@@ -2499,14 +2505,16 @@ static void hclge_mbx_task_schedule(struct hclge_dev *hdev)
 {
        if (!test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) &&
            !test_and_set_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state))
-               schedule_work(&hdev->mbx_service_task);
+               queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
+                             &hdev->mbx_service_task);
 }
 
 static void hclge_reset_task_schedule(struct hclge_dev *hdev)
 {
        if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
            !test_and_set_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
-               schedule_work(&hdev->rst_service_task);
+               queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
+                             &hdev->rst_service_task);
 }
 
 static void hclge_task_schedule(struct hclge_dev *hdev)
@@ -2516,8 +2524,9 @@ static void hclge_task_schedule(struct hclge_dev *hdev)
            !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) {
                hdev->hw_stats.stats_timer++;
                hdev->fd_arfs_expire_timer++;
-               mod_delayed_work(system_wq, &hdev->service_task,
-                                round_jiffies_relative(HZ));
+               mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
+                                   system_wq, &hdev->service_task,
+                                   round_jiffies_relative(HZ));
        }
 }
 
@@ -2903,6 +2912,36 @@ static void hclge_get_misc_vector(struct hclge_dev *hdev)
        hdev->num_msi_used += 1;
 }
 
+static void hclge_irq_affinity_notify(struct irq_affinity_notify *notify,
+                                     const cpumask_t *mask)
+{
+       struct hclge_dev *hdev = container_of(notify, struct hclge_dev,
+                                             affinity_notify);
+
+       cpumask_copy(&hdev->affinity_mask, mask);
+}
+
+static void hclge_irq_affinity_release(struct kref *ref)
+{
+}
+
+static void hclge_misc_affinity_setup(struct hclge_dev *hdev)
+{
+       irq_set_affinity_hint(hdev->misc_vector.vector_irq,
+                             &hdev->affinity_mask);
+
+       hdev->affinity_notify.notify = hclge_irq_affinity_notify;
+       hdev->affinity_notify.release = hclge_irq_affinity_release;
+       irq_set_affinity_notifier(hdev->misc_vector.vector_irq,
+                                 &hdev->affinity_notify);
+}
+
+static void hclge_misc_affinity_teardown(struct hclge_dev *hdev)
+{
+       irq_set_affinity_notifier(hdev->misc_vector.vector_irq, NULL);
+       irq_set_affinity_hint(hdev->misc_vector.vector_irq, NULL);
+}
+
 static int hclge_misc_irq_init(struct hclge_dev *hdev)
 {
        int ret;
@@ -8794,6 +8833,11 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
        INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task);
        INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task);
 
+       /* Setup affinity after service timer setup because add_timer_on
+        * is called in affinity notify.
+        */
+       hclge_misc_affinity_setup(hdev);
+
        hclge_clear_all_event_cause(hdev);
        hclge_clear_resetting_state(hdev);
 
@@ -8955,6 +8999,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
        struct hclge_dev *hdev = ae_dev->priv;
        struct hclge_mac *mac = &hdev->hw.mac;
 
+       hclge_misc_affinity_teardown(hdev);
        hclge_state_uninit(hdev);
 
        if (mac->phydev)
index dde8f22b08104c06625612b108db7e053fa4257b..688e4250491dd6f40518a34ef89ea305fd77a5bf 100644 (file)
@@ -863,6 +863,10 @@ struct hclge_dev {
 
        DECLARE_KFIFO(mac_tnl_log, struct hclge_mac_tnl_stats,
                      HCLGE_MAC_TNL_LOG_SIZE);
+
+       /* affinity mask and notify for misc interrupt */
+       cpumask_t affinity_mask;
+       struct irq_affinity_notify affinity_notify;
 };
 
 /* VPort level vlan tag configuration for TX direction */