From ea97c0ef77bd1c50f8220020daabacfb7cd463cc Mon Sep 17 00:00:00 2001 From: Chiqijun Date: Thu, 6 Aug 2020 10:33:59 +0000 Subject: [PATCH] net/hinic: Synchronize time to firmware every hour driver inclusion category: bugfix bugzilla: 4472 ----------------------------------------------------------------------- At present, the time will be synchronized with the firmware only when the driver is probed. After a long time, the firmware time may be inconsistent with the system time, which affects positioning, so the driver synchronizes the time with the firmware every hour. Signed-off-by: Chiqijun Reviewed-by: Zengweiliang Signed-off-by: Yang Yingliang --- drivers/net/ethernet/huawei/hinic/hinic_cfg.c | 10 ++++ .../net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_lld.c | 48 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c index 05f9a58d2ec9..07bc87d47f78 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c @@ -110,6 +110,16 @@ int hinic_sync_time(void *hwdev, u64 time) return err; } +void hinic_sync_time_async(void *hwdev, u64 time) +{ + struct hinic_sync_time_info time_info = { 0 }; + + time_info.mstime = time; + hinic_msg_to_mgmt_async(hwdev, HINIC_MOD_COMM, + HINIC_MGMT_CMD_SYNC_TIME, &time_info, + sizeof(time_info)); +} + static void parse_sf_en_cap(struct service_cap *cap, struct hinic_dev_cap *dev_cap, enum func_type type) { diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h index a2242cc852e9..43602591b6ae 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h @@ -526,6 +526,7 @@ int hinic_alloc_ceqs(void *hwdev, enum hinic_service_type type, int req_num, int *ceq_id_array, int *resp_num); void hinic_free_ceq(void *hwdev, enum hinic_service_type type, int ceq_id); int hinic_sync_time(void *hwdev, u64 time); +void hinic_sync_time_async(void *hwdev, u64 time); struct hinic_micro_log_info { int (*init)(void *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c index 412f4c8a93ea..81461da5e9aa 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c @@ -117,6 +117,8 @@ struct hinic_pcidev { enum hinic_chip_mode chip_mode; bool nic_cur_enable; bool nic_des_enable; + + struct timer_list syncfw_time_timer; }; #define HINIC_EVENT_PROCESS_TIMEOUT 10000 @@ -424,6 +426,49 @@ void hinic_unregister_uld(enum hinic_service_type type) } EXPORT_SYMBOL(hinic_unregister_uld); +#define HINIC_SYNFW_TIME_PERIOD (60 * 60 * 1000) + +static void hinic_syncfw_timer_handler(struct timer_list *t) +{ + struct hinic_pcidev *pci_adapter = from_timer(pci_adapter, t, + syncfw_time_timer); + struct timeval tv = {0}; + u64 tv_msec; + + do_gettimeofday(&tv); + + tv_msec = tv.tv_sec * MSEC_PER_SEC + + tv.tv_usec / USEC_PER_MSEC; + + hinic_sync_time_async(pci_adapter->hwdev, tv_msec); + mod_timer(&pci_adapter->syncfw_time_timer, + jiffies + msecs_to_jiffies(HINIC_SYNFW_TIME_PERIOD)); +} + +void hinic_init_syncfw_timer(struct hinic_pcidev *pci_adapter) +{ + if (hinic_get_func_mode(pci_adapter->hwdev) != FUNC_MOD_NORMAL_HOST || + hinic_func_type(pci_adapter->hwdev) != TYPE_PPF) + return; + + timer_setup(&pci_adapter->syncfw_time_timer, + hinic_syncfw_timer_handler, 0); + + pci_adapter->syncfw_time_timer.expires = + jiffies + msecs_to_jiffies(HINIC_SYNFW_TIME_PERIOD); + + add_timer(&pci_adapter->syncfw_time_timer); +} + +void hinic_destroy_syncfw_timer(struct hinic_pcidev *pci_adapter) +{ + if (hinic_get_func_mode(pci_adapter->hwdev) != FUNC_MOD_NORMAL_HOST || + hinic_func_type(pci_adapter->hwdev) != TYPE_PPF) + return; + + del_timer_sync(&pci_adapter->syncfw_time_timer); +} + static void hinic_sync_time_to_fmw(struct hinic_pcidev *pdev_pri) { struct timeval tv = {0}; @@ -2391,6 +2436,7 @@ static int hinic_func_init(struct pci_dev *pdev, if (!HINIC_FUNC_IS_VF(pci_adapter->hwdev)) hinic_sync_time_to_fmw(pci_adapter); + hinic_init_syncfw_timer(pci_adapter); /* dbgtool init */ lld_lock_chip_node(); @@ -2398,6 +2444,7 @@ static int hinic_func_init(struct pci_dev *pdev, if (err) { lld_unlock_chip_node(); sdk_err(&pdev->dev, "Failed to initialize dbgtool\n"); + hinic_destroy_syncfw_timer(pci_adapter); hinic_event_unregister(pci_adapter->hwdev); return err; } @@ -2454,6 +2501,7 @@ static void hinic_func_deinit(struct pci_dev *pdev) lld_lock_chip_node(); dbgtool_knl_deinit(pci_adapter->hwdev, pci_adapter->chip_node); lld_unlock_chip_node(); + hinic_destroy_syncfw_timer(pci_adapter); hinic_event_unregister(pci_adapter->hwdev); } -- GitLab