1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright(c) 2007-2022 Intel Corporation */ 3 #include "adf_accel_devices.h" 4 #include "adf_heartbeat.h" 5 #include "adf_common_drv.h" 6 #include "icp_qat_fw_init_admin.h" 7 #include "adf_gen4_timer.h" 8 9 #include "adf_dev_err.h" 10 11 #define ADF_GEN4_INT_TIMER_VALUE_IN_MS 200 12 /* Interval within timer interrupt. Value in miliseconds. */ 13 14 #define ADF_GEN4_MAX_INT_TIMER_VALUE_IN_MS 0xFFFFFFFF 15 /* MAX Interval within timer interrupt. Value in miliseconds. */ 16 17 static u64 18 adf_get_next_timeout(u32 timeout_val) 19 { 20 u64 timeout = msecs_to_jiffies(timeout_val); 21 22 return rounddown(jiffies + timeout, timeout); 23 } 24 25 static void 26 adf_hb_irq_bh_handler(struct work_struct *work) 27 { 28 struct icp_qat_fw_init_admin_req req = { 0 }; 29 struct icp_qat_fw_init_admin_resp resp = { 0 }; 30 struct adf_hb_timer_data *hb_timer_data = 31 container_of(work, struct adf_hb_timer_data, hb_int_timer_work); 32 struct adf_accel_dev *accel_dev = hb_timer_data->accel_dev; 33 struct adf_hw_device_data *hw_data = accel_dev->hw_device; 34 u32 ae_mask = hw_data->ae_mask; 35 36 if (!accel_dev->int_timer || !accel_dev->int_timer->enabled) 37 goto end; 38 39 /* Update heartbeat count via init/admin cmd */ 40 if (!accel_dev->admin) { 41 device_printf(GET_DEV(accel_dev), 42 "adf_admin is not available\n"); 43 goto end; 44 } 45 46 req.cmd_id = ICP_QAT_FW_HEARTBEAT_SYNC; 47 req.heartbeat_ticks = accel_dev->int_timer->int_cnt; 48 49 if (adf_send_admin(accel_dev, &req, &resp, ae_mask)) 50 device_printf(GET_DEV(accel_dev), 51 "Failed to update qat's HB count\n"); 52 53 end: 54 kfree(hb_timer_data); 55 } 56 57 static void 58 timer_handler(struct timer_list *tl) 59 { 60 struct adf_int_timer *int_timer = from_timer(int_timer, tl, timer); 61 struct adf_accel_dev *accel_dev = int_timer->accel_dev; 62 struct adf_hb_timer_data *hb_timer_data = NULL; 63 u64 timeout_val = adf_get_next_timeout(int_timer->timeout_val); 64 /* Update TL TBD */ 65 66 /* Schedule a heartbeat work queue to update HB */ 67 hb_timer_data = kzalloc(sizeof(*hb_timer_data), GFP_ATOMIC); 68 if (hb_timer_data) { 69 hb_timer_data->accel_dev = accel_dev; 70 71 INIT_WORK(&hb_timer_data->hb_int_timer_work, 72 adf_hb_irq_bh_handler); 73 queue_work(int_timer->timer_irq_wq, 74 &hb_timer_data->hb_int_timer_work); 75 } else { 76 device_printf(GET_DEV(accel_dev), 77 "Failed to alloc heartbeat timer data\n"); 78 } 79 int_timer->int_cnt++; 80 mod_timer(tl, timeout_val); 81 } 82 83 int 84 adf_int_timer_init(struct adf_accel_dev *accel_dev) 85 { 86 u64 timeout_val = adf_get_next_timeout(ADF_GEN4_INT_TIMER_VALUE_IN_MS); 87 struct adf_int_timer *int_timer = NULL; 88 char wqname[32] = { 0 }; 89 90 if (!accel_dev) 91 return 0; 92 93 int_timer = kzalloc(sizeof(*int_timer), GFP_KERNEL); 94 if (!int_timer) 95 return -ENOMEM; 96 97 sprintf(wqname, "qat_timer_wq_%d", accel_dev->accel_id); 98 99 int_timer->timer_irq_wq = alloc_workqueue(wqname, WQ_MEM_RECLAIM, 1); 100 101 if (!int_timer->timer_irq_wq) { 102 kfree(int_timer); 103 return -ENOMEM; 104 } 105 106 int_timer->accel_dev = accel_dev; 107 int_timer->timeout_val = ADF_GEN4_INT_TIMER_VALUE_IN_MS; 108 int_timer->int_cnt = 0; 109 int_timer->enabled = true; 110 accel_dev->int_timer = int_timer; 111 112 timer_setup(&int_timer->timer, timer_handler, 0); 113 mod_timer(&int_timer->timer, timeout_val); 114 115 return 0; 116 } 117 118 void 119 adf_int_timer_exit(struct adf_accel_dev *accel_dev) 120 { 121 if (accel_dev && accel_dev->int_timer) { 122 del_timer_sync(&accel_dev->int_timer->timer); 123 accel_dev->int_timer->enabled = false; 124 125 if (accel_dev->int_timer->timer_irq_wq) { 126 flush_workqueue(accel_dev->int_timer->timer_irq_wq); 127 destroy_workqueue(accel_dev->int_timer->timer_irq_wq); 128 } 129 130 kfree(accel_dev->int_timer); 131 accel_dev->int_timer = NULL; 132 } 133 } 134