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