From: Yunsheng Lin <linyunsh...@huawei.com>

The misc interrupt is used to schedule the reset and mailbox
subtask, and a 1 sec timer is used to schedule the service
subtask, which does periodic work.

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 <linyunsh...@huawei.com>
Signed-off-by: Peng Li <lipeng...@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazh...@huawei.com>
---
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 59 ++++++++++++++++++++--
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h    |  4 ++
 2 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index f345095..fe45986 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -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;
 }
 
@@ -2502,14 +2508,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)
@@ -2517,7 +2525,8 @@ static void hclge_task_schedule(struct hclge_dev *hdev)
        if (!test_bit(HCLGE_STATE_DOWN, &hdev->state) &&
            !test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
            !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state))
-               (void)schedule_work(&hdev->service_task);
+               queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
+                             &hdev->service_task);
 }
 
 static int hclge_get_mac_link_status(struct hclge_dev *hdev)
@@ -2921,6 +2930,39 @@ 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);
+       del_timer_sync(&hdev->service_timer);
+       hdev->service_timer.expires = jiffies + HZ;
+       add_timer_on(&hdev->service_timer, cpumask_first(&hdev->affinity_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;
@@ -6151,7 +6193,10 @@ static void hclge_set_timer_task(struct hnae3_handle 
*handle, bool enable)
        struct hclge_dev *hdev = vport->back;
 
        if (enable) {
-               mod_timer(&hdev->service_timer, jiffies + HZ);
+               del_timer_sync(&hdev->service_timer);
+               hdev->service_timer.expires = jiffies + HZ;
+               add_timer_on(&hdev->service_timer,
+                            cpumask_first(&hdev->affinity_mask));
        } else {
                del_timer_sync(&hdev->service_timer);
                cancel_work_sync(&hdev->service_task);
@@ -8809,6 +8854,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);
 
@@ -8970,6 +9020,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)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 6a12285..14df23c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -864,6 +864,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 */
-- 
2.7.4

Reply via email to