blob: 4b6c8de46dd8645158d808d88614de675bd55a15 [file] [log] [blame]
Oded Gabbayc4d66342019-02-16 00:39:11 +02001// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright 2016-2019 HabanaLabs, Ltd.
5 * All Rights Reserved.
6 */
7
Tomer Tayare00dac32019-04-10 15:18:46 +03008#define pr_fmt(fmt) "habanalabs: " fmt
9
Oded Gabbayc4d66342019-02-16 00:39:11 +020010#include "habanalabs.h"
11
12#include <linux/pci.h>
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +020013#include <linux/sched/signal.h>
Oded Gabbayd91389b2019-02-16 00:39:19 +020014#include <linux/hwmon.h>
Dalit Ben Zooraa957082019-03-24 10:15:44 +020015#include <uapi/misc/habanalabs.h>
Oded Gabbayc4d66342019-02-16 00:39:11 +020016
Omer Shpigelmanf650a952019-03-13 13:36:28 +020017#define HL_PLDM_PENDING_RESET_PER_SEC (HL_PENDING_RESET_PER_SEC * 10)
18
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +020019bool hl_device_disabled_or_in_reset(struct hl_device *hdev)
20{
21 if ((hdev->disabled) || (atomic_read(&hdev->in_reset)))
22 return true;
23 else
24 return false;
25}
26
Dalit Ben Zooraa957082019-03-24 10:15:44 +020027enum hl_device_status hl_device_status(struct hl_device *hdev)
28{
29 enum hl_device_status status;
30
31 if (hdev->disabled)
32 status = HL_DEVICE_STATUS_MALFUNCTION;
33 else if (atomic_read(&hdev->in_reset))
34 status = HL_DEVICE_STATUS_IN_RESET;
35 else
36 status = HL_DEVICE_STATUS_OPERATIONAL;
37
38 return status;
Oded Gabbay7491c032020-01-07 23:44:32 +020039}
Dalit Ben Zooraa957082019-03-24 10:15:44 +020040
Oded Gabbayc4d66342019-02-16 00:39:11 +020041static void hpriv_release(struct kref *ref)
42{
43 struct hl_fpriv *hpriv;
44 struct hl_device *hdev;
45
46 hpriv = container_of(ref, struct hl_fpriv, refcount);
47
48 hdev = hpriv->hdev;
49
50 put_pid(hpriv->taskpid);
51
Oded Gabbayc2164772019-02-16 00:39:24 +020052 hl_debugfs_remove_file(hpriv);
53
Oded Gabbayeff6f4a2019-02-16 00:39:21 +020054 mutex_destroy(&hpriv->restore_phase_mutex);
55
Oded Gabbayeb7caf82019-07-30 11:56:09 +030056 mutex_lock(&hdev->fpriv_list_lock);
57 list_del(&hpriv->dev_node);
Oded Gabbay86d53072019-07-30 11:49:36 +030058 hdev->compute_ctx = NULL;
Oded Gabbayeb7caf82019-07-30 11:56:09 +030059 mutex_unlock(&hdev->fpriv_list_lock);
60
61 kfree(hpriv);
Oded Gabbayc4d66342019-02-16 00:39:11 +020062}
63
64void hl_hpriv_get(struct hl_fpriv *hpriv)
65{
66 kref_get(&hpriv->refcount);
67}
68
69void hl_hpriv_put(struct hl_fpriv *hpriv)
70{
71 kref_put(&hpriv->refcount, hpriv_release);
72}
73
74/*
75 * hl_device_release - release function for habanalabs device
76 *
77 * @inode: pointer to inode structure
78 * @filp: pointer to file structure
79 *
80 * Called when process closes an habanalabs device
81 */
82static int hl_device_release(struct inode *inode, struct file *filp)
83{
84 struct hl_fpriv *hpriv = filp->private_data;
85
Oded Gabbaybe5d9262019-02-16 00:39:15 +020086 hl_cb_mgr_fini(hpriv->hdev, &hpriv->cb_mgr);
Oded Gabbay0861e412019-02-16 00:39:14 +020087 hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
88
Oded Gabbayc4d66342019-02-16 00:39:11 +020089 filp->private_data = NULL;
90
91 hl_hpriv_put(hpriv);
92
93 return 0;
94}
95
Oded Gabbay4d6a7752019-07-30 09:10:50 +030096static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
97{
98 struct hl_fpriv *hpriv = filp->private_data;
99 struct hl_device *hdev;
100
101 filp->private_data = NULL;
102
103 hdev = hpriv->hdev;
104
105 mutex_lock(&hdev->fpriv_list_lock);
106 list_del(&hpriv->dev_node);
107 mutex_unlock(&hdev->fpriv_list_lock);
108
109 kfree(hpriv);
110
111 return 0;
112}
113
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200114/*
115 * hl_mmap - mmap function for habanalabs device
116 *
117 * @*filp: pointer to file structure
118 * @*vma: pointer to vm_area_struct of the process
119 *
120 * Called when process does an mmap on habanalabs device. Call the device's mmap
121 * function at the end of the common code.
122 */
123static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
124{
125 struct hl_fpriv *hpriv = filp->private_data;
126
127 if ((vma->vm_pgoff & HL_MMAP_CB_MASK) == HL_MMAP_CB_MASK) {
128 vma->vm_pgoff ^= HL_MMAP_CB_MASK;
129 return hl_cb_mmap(hpriv, vma);
130 }
131
Oded Gabbay5e6e0232019-02-27 12:15:16 +0200132 return -EINVAL;
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200133}
134
Oded Gabbayc4d66342019-02-16 00:39:11 +0200135static const struct file_operations hl_ops = {
136 .owner = THIS_MODULE,
137 .open = hl_device_open,
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200138 .release = hl_device_release,
139 .mmap = hl_mmap,
140 .unlocked_ioctl = hl_ioctl,
141 .compat_ioctl = hl_ioctl
Oded Gabbayc4d66342019-02-16 00:39:11 +0200142};
143
Oded Gabbay4d6a7752019-07-30 09:10:50 +0300144static const struct file_operations hl_ctrl_ops = {
145 .owner = THIS_MODULE,
146 .open = hl_device_open_ctrl,
147 .release = hl_device_release_ctrl,
148 .unlocked_ioctl = hl_ioctl_control,
149 .compat_ioctl = hl_ioctl_control
150};
151
Tomer Tayarea451f82019-08-08 12:25:52 +0000152static void device_release_func(struct device *dev)
153{
154 kfree(dev);
155}
156
Oded Gabbayc4d66342019-02-16 00:39:11 +0200157/*
Tomer Tayarea451f82019-08-08 12:25:52 +0000158 * device_init_cdev - Initialize cdev and device for habanalabs device
Oded Gabbayc4d66342019-02-16 00:39:11 +0200159 *
160 * @hdev: pointer to habanalabs device structure
161 * @hclass: pointer to the class object of the device
162 * @minor: minor number of the specific device
Oded Gabbayb968eb12019-07-30 09:10:02 +0300163 * @fpos: file operations to install for this device
164 * @name: name of the device as it will appear in the filesystem
Tomer Tayarea451f82019-08-08 12:25:52 +0000165 * @cdev: pointer to the char device object that will be initialized
166 * @dev: pointer to the device object that will be initialized
Oded Gabbayc4d66342019-02-16 00:39:11 +0200167 *
Tomer Tayarea451f82019-08-08 12:25:52 +0000168 * Initialize a cdev and a Linux device for habanalabs's device.
Oded Gabbayc4d66342019-02-16 00:39:11 +0200169 */
Tomer Tayarea451f82019-08-08 12:25:52 +0000170static int device_init_cdev(struct hl_device *hdev, struct class *hclass,
Oded Gabbayb968eb12019-07-30 09:10:02 +0300171 int minor, const struct file_operations *fops,
172 char *name, struct cdev *cdev,
173 struct device **dev)
Oded Gabbayc4d66342019-02-16 00:39:11 +0200174{
Oded Gabbayb968eb12019-07-30 09:10:02 +0300175 cdev_init(cdev, fops);
176 cdev->owner = THIS_MODULE;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200177
Tomer Tayarea451f82019-08-08 12:25:52 +0000178 *dev = kzalloc(sizeof(**dev), GFP_KERNEL);
179 if (!*dev)
180 return -ENOMEM;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200181
Tomer Tayarea451f82019-08-08 12:25:52 +0000182 device_initialize(*dev);
183 (*dev)->devt = MKDEV(hdev->major, minor);
184 (*dev)->class = hclass;
185 (*dev)->release = device_release_func;
Oded Gabbayb968eb12019-07-30 09:10:02 +0300186 dev_set_drvdata(*dev, hdev);
Tomer Tayarea451f82019-08-08 12:25:52 +0000187 dev_set_name(*dev, "%s", name);
188
189 return 0;
190}
191
192static int device_cdev_sysfs_add(struct hl_device *hdev)
193{
194 int rc;
195
196 rc = cdev_device_add(&hdev->cdev, hdev->dev);
197 if (rc) {
198 dev_err(hdev->dev,
199 "failed to add a char device to the system\n");
200 return rc;
201 }
202
203 rc = cdev_device_add(&hdev->cdev_ctrl, hdev->dev_ctrl);
204 if (rc) {
205 dev_err(hdev->dev,
206 "failed to add a control char device to the system\n");
207 goto delete_cdev_device;
208 }
209
210 /* hl_sysfs_init() must be done after adding the device to the system */
211 rc = hl_sysfs_init(hdev);
212 if (rc) {
213 dev_err(hdev->dev, "failed to initialize sysfs\n");
214 goto delete_ctrl_cdev_device;
215 }
216
217 hdev->cdev_sysfs_created = true;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200218
219 return 0;
220
Tomer Tayarea451f82019-08-08 12:25:52 +0000221delete_ctrl_cdev_device:
222 cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
223delete_cdev_device:
224 cdev_device_del(&hdev->cdev, hdev->dev);
225 return rc;
226}
227
228static void device_cdev_sysfs_del(struct hl_device *hdev)
229{
230 /* device_release() won't be called so must free devices explicitly */
231 if (!hdev->cdev_sysfs_created) {
232 kfree(hdev->dev_ctrl);
233 kfree(hdev->dev);
234 return;
235 }
236
237 hl_sysfs_fini(hdev);
238 cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
239 cdev_device_del(&hdev->cdev, hdev->dev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200240}
241
242/*
243 * device_early_init - do some early initialization for the habanalabs device
244 *
245 * @hdev: pointer to habanalabs device structure
246 *
247 * Install the relevant function pointers and call the early_init function,
248 * if such a function exists
249 */
250static int device_early_init(struct hl_device *hdev)
251{
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200252 int rc;
253
Oded Gabbayc4d66342019-02-16 00:39:11 +0200254 switch (hdev->asic_type) {
255 case ASIC_GOYA:
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200256 goya_set_asic_funcs(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200257 strlcpy(hdev->asic_name, "GOYA", sizeof(hdev->asic_name));
258 break;
Oded Gabbayaf57cb82020-05-11 10:47:05 +0300259 case ASIC_GAUDI:
260 gaudi_set_asic_funcs(hdev);
261 sprintf(hdev->asic_name, "GAUDI");
262 break;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200263 default:
264 dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
265 hdev->asic_type);
266 return -EINVAL;
267 }
268
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200269 rc = hdev->asic_funcs->early_init(hdev);
270 if (rc)
271 return rc;
272
Oded Gabbay0861e412019-02-16 00:39:14 +0200273 rc = hl_asid_init(hdev);
274 if (rc)
275 goto early_fini;
276
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200277 hdev->cq_wq = alloc_workqueue("hl-free-jobs", WQ_UNBOUND, 0);
278 if (hdev->cq_wq == NULL) {
279 dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
280 rc = -ENOMEM;
281 goto asid_fini;
282 }
283
Oded Gabbay1251f232019-02-16 00:39:18 +0200284 hdev->eq_wq = alloc_workqueue("hl-events", WQ_UNBOUND, 0);
285 if (hdev->eq_wq == NULL) {
286 dev_err(hdev->dev, "Failed to allocate EQ workqueue\n");
287 rc = -ENOMEM;
288 goto free_cq_wq;
289 }
290
Oded Gabbayd91389b2019-02-16 00:39:19 +0200291 hdev->hl_chip_info = kzalloc(sizeof(struct hwmon_chip_info),
292 GFP_KERNEL);
293 if (!hdev->hl_chip_info) {
294 rc = -ENOMEM;
295 goto free_eq_wq;
296 }
297
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300298 hdev->idle_busy_ts_arr = kmalloc_array(HL_IDLE_BUSY_TS_ARR_SIZE,
299 sizeof(struct hl_device_idle_busy_ts),
300 (GFP_KERNEL | __GFP_ZERO));
301 if (!hdev->idle_busy_ts_arr) {
302 rc = -ENOMEM;
303 goto free_chip_info;
304 }
305
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200306 hl_cb_mgr_init(&hdev->kernel_cb_mgr);
307
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200308 mutex_init(&hdev->send_cpu_message_lock);
Oded Gabbay19734972019-05-04 17:36:06 +0300309 mutex_init(&hdev->debug_lock);
Tomer Tayar8d45f1de2019-05-13 12:13:39 +0300310 mutex_init(&hdev->mmu_cache_lock);
Oded Gabbayeff6f4a2019-02-16 00:39:21 +0200311 INIT_LIST_HEAD(&hdev->hw_queues_mirror_list);
312 spin_lock_init(&hdev->hw_queues_mirror_lock);
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300313 INIT_LIST_HEAD(&hdev->fpriv_list);
314 mutex_init(&hdev->fpriv_list_lock);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200315 atomic_set(&hdev->in_reset, 0);
Oded Gabbay0861e412019-02-16 00:39:14 +0200316
Oded Gabbayc4d66342019-02-16 00:39:11 +0200317 return 0;
Oded Gabbay0861e412019-02-16 00:39:14 +0200318
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300319free_chip_info:
320 kfree(hdev->hl_chip_info);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200321free_eq_wq:
322 destroy_workqueue(hdev->eq_wq);
Oded Gabbay1251f232019-02-16 00:39:18 +0200323free_cq_wq:
324 destroy_workqueue(hdev->cq_wq);
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200325asid_fini:
326 hl_asid_fini(hdev);
Oded Gabbay0861e412019-02-16 00:39:14 +0200327early_fini:
328 if (hdev->asic_funcs->early_fini)
329 hdev->asic_funcs->early_fini(hdev);
330
331 return rc;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200332}
333
334/*
335 * device_early_fini - finalize all that was done in device_early_init
336 *
337 * @hdev: pointer to habanalabs device structure
338 *
339 */
340static void device_early_fini(struct hl_device *hdev)
341{
Tomer Tayar8d45f1de2019-05-13 12:13:39 +0300342 mutex_destroy(&hdev->mmu_cache_lock);
Oded Gabbay19734972019-05-04 17:36:06 +0300343 mutex_destroy(&hdev->debug_lock);
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200344 mutex_destroy(&hdev->send_cpu_message_lock);
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200345
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300346 mutex_destroy(&hdev->fpriv_list_lock);
347
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200348 hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr);
349
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300350 kfree(hdev->idle_busy_ts_arr);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200351 kfree(hdev->hl_chip_info);
352
Oded Gabbay1251f232019-02-16 00:39:18 +0200353 destroy_workqueue(hdev->eq_wq);
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200354 destroy_workqueue(hdev->cq_wq);
355
Oded Gabbay0861e412019-02-16 00:39:14 +0200356 hl_asid_fini(hdev);
357
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200358 if (hdev->asic_funcs->early_fini)
359 hdev->asic_funcs->early_fini(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200360}
361
Oded Gabbayd91389b2019-02-16 00:39:19 +0200362static void set_freq_to_low_job(struct work_struct *work)
363{
364 struct hl_device *hdev = container_of(work, struct hl_device,
365 work_freq.work);
366
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300367 mutex_lock(&hdev->fpriv_list_lock);
368
369 if (!hdev->compute_ctx)
Oded Gabbayd91389b2019-02-16 00:39:19 +0200370 hl_device_set_frequency(hdev, PLL_LOW);
371
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300372 mutex_unlock(&hdev->fpriv_list_lock);
373
Oded Gabbayd91389b2019-02-16 00:39:19 +0200374 schedule_delayed_work(&hdev->work_freq,
375 usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
376}
377
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200378static void hl_device_heartbeat(struct work_struct *work)
379{
380 struct hl_device *hdev = container_of(work, struct hl_device,
381 work_heartbeat.work);
382
383 if (hl_device_disabled_or_in_reset(hdev))
384 goto reschedule;
385
386 if (!hdev->asic_funcs->send_heartbeat(hdev))
387 goto reschedule;
388
389 dev_err(hdev->dev, "Device heartbeat failed!\n");
390 hl_device_reset(hdev, true, false);
391
392 return;
393
394reschedule:
395 schedule_delayed_work(&hdev->work_heartbeat,
396 usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
397}
398
Oded Gabbayd91389b2019-02-16 00:39:19 +0200399/*
400 * device_late_init - do late stuff initialization for the habanalabs device
401 *
402 * @hdev: pointer to habanalabs device structure
403 *
404 * Do stuff that either needs the device H/W queues to be active or needs
405 * to happen after all the rest of the initialization is finished
406 */
407static int device_late_init(struct hl_device *hdev)
408{
409 int rc;
410
Oded Gabbay0b28d262019-05-29 14:24:51 +0300411 if (hdev->asic_funcs->late_init) {
412 rc = hdev->asic_funcs->late_init(hdev);
413 if (rc) {
414 dev_err(hdev->dev,
415 "failed late initialization for the H/W\n");
416 return rc;
417 }
418 }
419
Oded Gabbayd91389b2019-02-16 00:39:19 +0200420 hdev->high_pll = hdev->asic_prop.high_pll;
421
422 /* force setting to low frequency */
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300423 hdev->curr_pll_profile = PLL_LOW;
Oded Gabbayd91389b2019-02-16 00:39:19 +0200424
425 if (hdev->pm_mng_profile == PM_AUTO)
426 hdev->asic_funcs->set_pll_profile(hdev, PLL_LOW);
427 else
428 hdev->asic_funcs->set_pll_profile(hdev, PLL_LAST);
429
Oded Gabbay0b28d262019-05-29 14:24:51 +0300430 INIT_DELAYED_WORK(&hdev->work_freq, set_freq_to_low_job);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200431 schedule_delayed_work(&hdev->work_freq,
Oded Gabbay0b28d262019-05-29 14:24:51 +0300432 usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
Oded Gabbayd91389b2019-02-16 00:39:19 +0200433
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200434 if (hdev->heartbeat) {
435 INIT_DELAYED_WORK(&hdev->work_heartbeat, hl_device_heartbeat);
436 schedule_delayed_work(&hdev->work_heartbeat,
437 usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
438 }
439
Oded Gabbayd91389b2019-02-16 00:39:19 +0200440 hdev->late_init_done = true;
441
442 return 0;
443}
444
445/*
446 * device_late_fini - finalize all that was done in device_late_init
447 *
448 * @hdev: pointer to habanalabs device structure
449 *
450 */
451static void device_late_fini(struct hl_device *hdev)
452{
453 if (!hdev->late_init_done)
454 return;
455
456 cancel_delayed_work_sync(&hdev->work_freq);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200457 if (hdev->heartbeat)
458 cancel_delayed_work_sync(&hdev->work_heartbeat);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200459
460 if (hdev->asic_funcs->late_fini)
461 hdev->asic_funcs->late_fini(hdev);
462
463 hdev->late_init_done = false;
464}
465
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300466uint32_t hl_device_utilization(struct hl_device *hdev, uint32_t period_ms)
467{
468 struct hl_device_idle_busy_ts *ts;
469 ktime_t zero_ktime, curr = ktime_get();
470 u32 overlap_cnt = 0, last_index = hdev->idle_busy_ts_idx;
471 s64 period_us, last_start_us, last_end_us, last_busy_time_us,
472 total_busy_time_us = 0, total_busy_time_ms;
473
474 zero_ktime = ktime_set(0, 0);
475 period_us = period_ms * USEC_PER_MSEC;
476 ts = &hdev->idle_busy_ts_arr[last_index];
477
478 /* check case that device is currently in idle */
479 if (!ktime_compare(ts->busy_to_idle_ts, zero_ktime) &&
480 !ktime_compare(ts->idle_to_busy_ts, zero_ktime)) {
481
482 last_index--;
483 /* Handle case idle_busy_ts_idx was 0 */
484 if (last_index > HL_IDLE_BUSY_TS_ARR_SIZE)
485 last_index = HL_IDLE_BUSY_TS_ARR_SIZE - 1;
486
487 ts = &hdev->idle_busy_ts_arr[last_index];
488 }
489
490 while (overlap_cnt < HL_IDLE_BUSY_TS_ARR_SIZE) {
491 /* Check if we are in last sample case. i.e. if the sample
492 * begun before the sampling period. This could be a real
493 * sample or 0 so need to handle both cases
494 */
495 last_start_us = ktime_to_us(
496 ktime_sub(curr, ts->idle_to_busy_ts));
497
498 if (last_start_us > period_us) {
499
500 /* First check two cases:
501 * 1. If the device is currently busy
502 * 2. If the device was idle during the whole sampling
503 * period
504 */
505
506 if (!ktime_compare(ts->busy_to_idle_ts, zero_ktime)) {
507 /* Check if the device is currently busy */
508 if (ktime_compare(ts->idle_to_busy_ts,
509 zero_ktime))
510 return 100;
511
512 /* We either didn't have any activity or we
513 * reached an entry which is 0. Either way,
514 * exit and return what was accumulated so far
515 */
516 break;
517 }
518
519 /* If sample has finished, check it is relevant */
520 last_end_us = ktime_to_us(
521 ktime_sub(curr, ts->busy_to_idle_ts));
522
523 if (last_end_us > period_us)
524 break;
525
526 /* It is relevant so add it but with adjustment */
527 last_busy_time_us = ktime_to_us(
528 ktime_sub(ts->busy_to_idle_ts,
529 ts->idle_to_busy_ts));
530 total_busy_time_us += last_busy_time_us -
531 (last_start_us - period_us);
532 break;
533 }
534
535 /* Check if the sample is finished or still open */
536 if (ktime_compare(ts->busy_to_idle_ts, zero_ktime))
537 last_busy_time_us = ktime_to_us(
538 ktime_sub(ts->busy_to_idle_ts,
539 ts->idle_to_busy_ts));
540 else
541 last_busy_time_us = ktime_to_us(
542 ktime_sub(curr, ts->idle_to_busy_ts));
543
544 total_busy_time_us += last_busy_time_us;
545
546 last_index--;
547 /* Handle case idle_busy_ts_idx was 0 */
548 if (last_index > HL_IDLE_BUSY_TS_ARR_SIZE)
549 last_index = HL_IDLE_BUSY_TS_ARR_SIZE - 1;
550
551 ts = &hdev->idle_busy_ts_arr[last_index];
552
553 overlap_cnt++;
554 }
555
556 total_busy_time_ms = DIV_ROUND_UP_ULL(total_busy_time_us,
557 USEC_PER_MSEC);
558
559 return DIV_ROUND_UP_ULL(total_busy_time_ms * 100, period_ms);
560}
561
Oded Gabbayd91389b2019-02-16 00:39:19 +0200562/*
563 * hl_device_set_frequency - set the frequency of the device
564 *
565 * @hdev: pointer to habanalabs device structure
566 * @freq: the new frequency value
567 *
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300568 * Change the frequency if needed. This function has no protection against
569 * concurrency, therefore it is assumed that the calling function has protected
570 * itself against the case of calling this function from multiple threads with
571 * different values
572 *
573 * Returns 0 if no change was done, otherwise returns 1
Oded Gabbayd91389b2019-02-16 00:39:19 +0200574 */
575int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq)
576{
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300577 if ((hdev->pm_mng_profile == PM_MANUAL) ||
578 (hdev->curr_pll_profile == freq))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200579 return 0;
580
Oded Gabbayd91389b2019-02-16 00:39:19 +0200581 dev_dbg(hdev->dev, "Changing device frequency to %s\n",
582 freq == PLL_HIGH ? "high" : "low");
583
584 hdev->asic_funcs->set_pll_profile(hdev, freq);
585
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300586 hdev->curr_pll_profile = freq;
587
Oded Gabbayd91389b2019-02-16 00:39:19 +0200588 return 1;
589}
590
Oded Gabbay19734972019-05-04 17:36:06 +0300591int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
592{
593 int rc = 0;
594
595 mutex_lock(&hdev->debug_lock);
596
597 if (!enable) {
598 if (!hdev->in_debug) {
599 dev_err(hdev->dev,
600 "Failed to disable debug mode because device was not in debug mode\n");
601 rc = -EFAULT;
602 goto out;
603 }
604
Omer Shpigelmana37e4712020-01-05 09:05:45 +0000605 if (!hdev->hard_reset_pending)
606 hdev->asic_funcs->halt_coresight(hdev);
607
Oded Gabbay19734972019-05-04 17:36:06 +0300608 hdev->in_debug = 0;
609
Oded Gabbayca624332020-05-09 12:17:21 +0300610 if (!hdev->hard_reset_pending)
611 hdev->asic_funcs->enable_clock_gating(hdev);
612
Oded Gabbay19734972019-05-04 17:36:06 +0300613 goto out;
614 }
615
616 if (hdev->in_debug) {
617 dev_err(hdev->dev,
618 "Failed to enable debug mode because device is already in debug mode\n");
619 rc = -EFAULT;
620 goto out;
621 }
622
Oded Gabbayca624332020-05-09 12:17:21 +0300623 hdev->asic_funcs->disable_clock_gating(hdev);
Oded Gabbay19734972019-05-04 17:36:06 +0300624 hdev->in_debug = 1;
625
Oded Gabbay19734972019-05-04 17:36:06 +0300626out:
627 mutex_unlock(&hdev->debug_lock);
628
629 return rc;
630}
631
Oded Gabbayc4d66342019-02-16 00:39:11 +0200632/*
633 * hl_device_suspend - initiate device suspend
634 *
635 * @hdev: pointer to habanalabs device structure
636 *
637 * Puts the hw in the suspend state (all asics).
638 * Returns 0 for success or an error on failure.
639 * Called at driver suspend.
640 */
641int hl_device_suspend(struct hl_device *hdev)
642{
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200643 int rc;
644
Oded Gabbayc4d66342019-02-16 00:39:11 +0200645 pci_save_state(hdev->pdev);
646
Oded Gabbay7cb51012019-03-03 22:29:20 +0200647 /* Block future CS/VM/JOB completion operations */
648 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
649 if (rc) {
650 dev_err(hdev->dev, "Can't suspend while in reset\n");
651 return -EIO;
652 }
653
654 /* This blocks all other stuff that is not blocked by in_reset */
655 hdev->disabled = true;
656
657 /*
658 * Flush anyone that is inside the critical section of enqueue
659 * jobs to the H/W
660 */
661 hdev->asic_funcs->hw_queues_lock(hdev);
662 hdev->asic_funcs->hw_queues_unlock(hdev);
663
664 /* Flush processes that are sending message to CPU */
665 mutex_lock(&hdev->send_cpu_message_lock);
666 mutex_unlock(&hdev->send_cpu_message_lock);
667
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200668 rc = hdev->asic_funcs->suspend(hdev);
669 if (rc)
670 dev_err(hdev->dev,
671 "Failed to disable PCI access of device CPU\n");
672
Oded Gabbayc4d66342019-02-16 00:39:11 +0200673 /* Shut down the device */
674 pci_disable_device(hdev->pdev);
675 pci_set_power_state(hdev->pdev, PCI_D3hot);
676
677 return 0;
678}
679
680/*
681 * hl_device_resume - initiate device resume
682 *
683 * @hdev: pointer to habanalabs device structure
684 *
685 * Bring the hw back to operating state (all asics).
686 * Returns 0 for success or an error on failure.
687 * Called at driver resume.
688 */
689int hl_device_resume(struct hl_device *hdev)
690{
691 int rc;
692
693 pci_set_power_state(hdev->pdev, PCI_D0);
694 pci_restore_state(hdev->pdev);
Oded Gabbay7cb51012019-03-03 22:29:20 +0200695 rc = pci_enable_device_mem(hdev->pdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200696 if (rc) {
697 dev_err(hdev->dev,
698 "Failed to enable PCI device in resume\n");
699 return rc;
700 }
701
Oded Gabbay7cb51012019-03-03 22:29:20 +0200702 pci_set_master(hdev->pdev);
703
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200704 rc = hdev->asic_funcs->resume(hdev);
705 if (rc) {
Oded Gabbay7cb51012019-03-03 22:29:20 +0200706 dev_err(hdev->dev, "Failed to resume device after suspend\n");
707 goto disable_device;
708 }
709
710
711 hdev->disabled = false;
712 atomic_set(&hdev->in_reset, 0);
713
714 rc = hl_device_reset(hdev, true, false);
715 if (rc) {
716 dev_err(hdev->dev, "Failed to reset device during resume\n");
717 goto disable_device;
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200718 }
719
Oded Gabbayc4d66342019-02-16 00:39:11 +0200720 return 0;
Oded Gabbay7cb51012019-03-03 22:29:20 +0200721
722disable_device:
723 pci_clear_master(hdev->pdev);
724 pci_disable_device(hdev->pdev);
725
726 return rc;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200727}
728
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300729static void device_kill_open_processes(struct hl_device *hdev)
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200730{
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200731 u16 pending_total, pending_cnt;
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300732 struct hl_fpriv *hpriv;
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200733 struct task_struct *task = NULL;
734
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200735 if (hdev->pldm)
736 pending_total = HL_PLDM_PENDING_RESET_PER_SEC;
737 else
738 pending_total = HL_PENDING_RESET_PER_SEC;
739
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300740 /* Giving time for user to close FD, and for processes that are inside
741 * hl_device_open to finish
742 */
743 if (!list_empty(&hdev->fpriv_list))
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200744 ssleep(1);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200745
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300746 mutex_lock(&hdev->fpriv_list_lock);
747
748 /* This section must be protected because we are dereferencing
749 * pointers that are freed if the process exits
750 */
751 list_for_each_entry(hpriv, &hdev->fpriv_list, dev_node) {
752 task = get_pid_task(hpriv->taskpid, PIDTYPE_PID);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200753 if (task) {
Oded Gabbay4d6a7752019-07-30 09:10:50 +0300754 dev_info(hdev->dev, "Killing user process pid=%d\n",
755 task_pid_nr(task));
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200756 send_sig(SIGKILL, task, 1);
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300757 usleep_range(1000, 10000);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200758
759 put_task_struct(task);
760 }
761 }
762
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300763 mutex_unlock(&hdev->fpriv_list_lock);
764
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300765 /* We killed the open users, but because the driver cleans up after the
766 * user contexts are closed (e.g. mmu mappings), we need to wait again
767 * to make sure the cleaning phase is finished before continuing with
768 * the reset
769 */
770
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200771 pending_cnt = pending_total;
772
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300773 while ((!list_empty(&hdev->fpriv_list)) && (pending_cnt)) {
774 dev_info(hdev->dev,
775 "Waiting for all unmap operations to finish before hard reset\n");
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200776
777 pending_cnt--;
778
779 ssleep(1);
780 }
781
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300782 if (!list_empty(&hdev->fpriv_list))
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200783 dev_crit(hdev->dev,
784 "Going to hard reset with open user contexts\n");
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300785}
786
787static void device_hard_reset_pending(struct work_struct *work)
788{
789 struct hl_device_reset_work *device_reset_work =
790 container_of(work, struct hl_device_reset_work, reset_work);
791 struct hl_device *hdev = device_reset_work->hdev;
792
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200793 hl_device_reset(hdev, true, true);
794
795 kfree(device_reset_work);
796}
797
798/*
799 * hl_device_reset - reset the device
800 *
801 * @hdev: pointer to habanalabs device structure
802 * @hard_reset: should we do hard reset to all engines or just reset the
803 * compute/dma engines
804 *
805 * Block future CS and wait for pending CS to be enqueued
806 * Call ASIC H/W fini
807 * Flush all completions
808 * Re-initialize all internal data structures
809 * Call ASIC H/W init, late_init
810 * Test queues
811 * Enable device
812 *
813 * Returns 0 for success or an error on failure.
814 */
815int hl_device_reset(struct hl_device *hdev, bool hard_reset,
816 bool from_hard_reset_thread)
817{
818 int i, rc;
819
820 if (!hdev->init_done) {
821 dev_err(hdev->dev,
822 "Can't reset before initialization is done\n");
823 return 0;
824 }
825
826 /*
827 * Prevent concurrency in this function - only one reset should be
828 * done at any given time. Only need to perform this if we didn't
829 * get from the dedicated hard reset thread
830 */
831 if (!from_hard_reset_thread) {
832 /* Block future CS/VM/JOB completion operations */
833 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
834 if (rc)
835 return 0;
836
837 /* This also blocks future CS/VM/JOB completion operations */
838 hdev->disabled = true;
839
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300840 /* Flush anyone that is inside the critical section of enqueue
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200841 * jobs to the H/W
842 */
843 hdev->asic_funcs->hw_queues_lock(hdev);
844 hdev->asic_funcs->hw_queues_unlock(hdev);
845
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300846 /* Flush anyone that is inside device open */
847 mutex_lock(&hdev->fpriv_list_lock);
848 mutex_unlock(&hdev->fpriv_list_lock);
849
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200850 dev_err(hdev->dev, "Going to RESET device!\n");
851 }
852
853again:
854 if ((hard_reset) && (!from_hard_reset_thread)) {
855 struct hl_device_reset_work *device_reset_work;
856
Oded Gabbay3f5398c2019-04-06 15:41:35 +0300857 hdev->hard_reset_pending = true;
858
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200859 device_reset_work = kzalloc(sizeof(*device_reset_work),
860 GFP_ATOMIC);
861 if (!device_reset_work) {
862 rc = -ENOMEM;
863 goto out_err;
864 }
865
866 /*
867 * Because the reset function can't run from interrupt or
868 * from heartbeat work, we need to call the reset function
869 * from a dedicated work
870 */
871 INIT_WORK(&device_reset_work->reset_work,
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300872 device_hard_reset_pending);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200873 device_reset_work->hdev = hdev;
874 schedule_work(&device_reset_work->reset_work);
875
876 return 0;
877 }
878
879 if (hard_reset) {
880 device_late_fini(hdev);
881
882 /*
883 * Now that the heartbeat thread is closed, flush processes
884 * which are sending messages to CPU
885 */
886 mutex_lock(&hdev->send_cpu_message_lock);
887 mutex_unlock(&hdev->send_cpu_message_lock);
888 }
889
890 /*
891 * Halt the engines and disable interrupts so we won't get any more
892 * completions from H/W and we won't have any accesses from the
893 * H/W to the host machine
894 */
895 hdev->asic_funcs->halt_engines(hdev, hard_reset);
896
Oded Gabbayeff6f4a2019-02-16 00:39:21 +0200897 /* Go over all the queues, release all CS and their jobs */
898 hl_cs_rollback_all(hdev);
899
Oded Gabbay55f6d682019-11-17 17:41:57 +0200900 if (hard_reset) {
901 /* Kill processes here after CS rollback. This is because the
902 * process can't really exit until all its CSs are done, which
903 * is what we do in cs rollback
904 */
Oded Gabbay4aecb052019-07-22 17:37:22 +0300905 device_kill_open_processes(hdev);
906
Oded Gabbay55f6d682019-11-17 17:41:57 +0200907 /* Flush the Event queue workers to make sure no other thread is
908 * reading or writing to registers during the reset
909 */
910 flush_workqueue(hdev->eq_wq);
911 }
912
Oded Gabbay0878a422019-03-17 09:12:29 +0200913 /* Release kernel context */
914 if ((hard_reset) && (hl_ctx_put(hdev->kernel_ctx) == 1))
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200915 hdev->kernel_ctx = NULL;
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200916
917 /* Reset the H/W. It will be in idle state after this returns */
918 hdev->asic_funcs->hw_fini(hdev, hard_reset);
919
Omer Shpigelman0feaf862019-02-16 00:39:22 +0200920 if (hard_reset) {
921 hl_vm_fini(hdev);
Oded Gabbay37d68ce2019-05-29 14:43:04 +0300922 hl_mmu_fini(hdev);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200923 hl_eq_reset(hdev, &hdev->event_queue);
Omer Shpigelman0feaf862019-02-16 00:39:22 +0200924 }
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200925
926 /* Re-initialize PI,CI to 0 in all queues (hw queue, cq) */
927 hl_hw_queue_reset(hdev, hard_reset);
928 for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
929 hl_cq_reset(hdev, &hdev->completion_queue[i]);
930
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300931 hdev->idle_busy_ts_idx = 0;
932 hdev->idle_busy_ts_arr[0].busy_to_idle_ts = ktime_set(0, 0);
933 hdev->idle_busy_ts_arr[0].idle_to_busy_ts = ktime_set(0, 0);
934
935 if (hdev->cs_active_cnt)
936 dev_crit(hdev->dev, "CS active cnt %d is not 0 during reset\n",
937 hdev->cs_active_cnt);
938
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300939 mutex_lock(&hdev->fpriv_list_lock);
940
Oded Gabbay027d35d2019-04-25 20:15:42 +0300941 /* Make sure the context switch phase will run again */
Oded Gabbay86d53072019-07-30 11:49:36 +0300942 if (hdev->compute_ctx) {
943 atomic_set(&hdev->compute_ctx->thread_ctx_switch_token, 1);
944 hdev->compute_ctx->thread_ctx_switch_wait_token = 0;
Oded Gabbayeff6f4a2019-02-16 00:39:21 +0200945 }
946
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300947 mutex_unlock(&hdev->fpriv_list_lock);
948
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200949 /* Finished tear-down, starting to re-initialize */
950
951 if (hard_reset) {
Oded Gabbaya28ce422019-02-28 10:46:12 +0200952 hdev->device_cpu_disabled = false;
Oded Gabbay3f5398c2019-04-06 15:41:35 +0300953 hdev->hard_reset_pending = false;
Oded Gabbaya28ce422019-02-28 10:46:12 +0200954
Oded Gabbay0878a422019-03-17 09:12:29 +0200955 if (hdev->kernel_ctx) {
956 dev_crit(hdev->dev,
957 "kernel ctx was alive during hard reset, something is terribly wrong\n");
958 rc = -EBUSY;
959 goto out_err;
960 }
961
Oded Gabbay37d68ce2019-05-29 14:43:04 +0300962 rc = hl_mmu_init(hdev);
963 if (rc) {
964 dev_err(hdev->dev,
965 "Failed to initialize MMU S/W after hard reset\n");
966 goto out_err;
967 }
968
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200969 /* Allocate the kernel context */
970 hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx),
971 GFP_KERNEL);
972 if (!hdev->kernel_ctx) {
973 rc = -ENOMEM;
974 goto out_err;
975 }
976
Oded Gabbay86d53072019-07-30 11:49:36 +0300977 hdev->compute_ctx = NULL;
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200978
979 rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
980 if (rc) {
981 dev_err(hdev->dev,
982 "failed to init kernel ctx in hard reset\n");
983 kfree(hdev->kernel_ctx);
984 hdev->kernel_ctx = NULL;
985 goto out_err;
986 }
987 }
988
989 rc = hdev->asic_funcs->hw_init(hdev);
990 if (rc) {
991 dev_err(hdev->dev,
992 "failed to initialize the H/W after reset\n");
993 goto out_err;
994 }
995
996 hdev->disabled = false;
997
998 /* Check that the communication with the device is working */
999 rc = hdev->asic_funcs->test_queues(hdev);
1000 if (rc) {
1001 dev_err(hdev->dev,
1002 "Failed to detect if device is alive after reset\n");
1003 goto out_err;
1004 }
1005
1006 if (hard_reset) {
1007 rc = device_late_init(hdev);
1008 if (rc) {
1009 dev_err(hdev->dev,
1010 "Failed late init after hard reset\n");
1011 goto out_err;
1012 }
1013
Omer Shpigelman0feaf862019-02-16 00:39:22 +02001014 rc = hl_vm_init(hdev);
1015 if (rc) {
1016 dev_err(hdev->dev,
1017 "Failed to init memory module after hard reset\n");
1018 goto out_err;
1019 }
1020
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001021 hl_set_max_power(hdev, hdev->max_power);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001022 } else {
1023 rc = hdev->asic_funcs->soft_reset_late_init(hdev);
1024 if (rc) {
1025 dev_err(hdev->dev,
1026 "Failed late init after soft reset\n");
1027 goto out_err;
1028 }
1029 }
1030
1031 atomic_set(&hdev->in_reset, 0);
1032
1033 if (hard_reset)
1034 hdev->hard_reset_cnt++;
1035 else
1036 hdev->soft_reset_cnt++;
1037
Oded Gabbay867b58a2019-08-08 16:48:55 +03001038 dev_warn(hdev->dev, "Successfully finished resetting the device\n");
1039
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001040 return 0;
1041
1042out_err:
1043 hdev->disabled = true;
1044
1045 if (hard_reset) {
1046 dev_err(hdev->dev,
1047 "Failed to reset! Device is NOT usable\n");
1048 hdev->hard_reset_cnt++;
1049 } else {
1050 dev_err(hdev->dev,
1051 "Failed to do soft-reset, trying hard reset\n");
1052 hdev->soft_reset_cnt++;
1053 hard_reset = true;
1054 goto again;
1055 }
1056
1057 atomic_set(&hdev->in_reset, 0);
1058
1059 return rc;
1060}
1061
Oded Gabbayc4d66342019-02-16 00:39:11 +02001062/*
1063 * hl_device_init - main initialization function for habanalabs device
1064 *
1065 * @hdev: pointer to habanalabs device structure
1066 *
1067 * Allocate an id for the device, do early initialization and then call the
1068 * ASIC specific initialization functions. Finally, create the cdev and the
1069 * Linux device to expose it to the user
1070 */
1071int hl_device_init(struct hl_device *hdev, struct class *hclass)
1072{
Omer Shpigelman1fa185c2020-03-01 19:59:39 +02001073 int i, rc, cq_cnt, cq_ready_cnt;
Oded Gabbayb968eb12019-07-30 09:10:02 +03001074 char *name;
Tomer Tayarea451f82019-08-08 12:25:52 +00001075 bool add_cdev_sysfs_on_err = false;
Oded Gabbayb968eb12019-07-30 09:10:02 +03001076
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001077 name = kasprintf(GFP_KERNEL, "hl%d", hdev->id / 2);
Tomer Tayarea451f82019-08-08 12:25:52 +00001078 if (!name) {
1079 rc = -ENOMEM;
1080 goto out_disabled;
1081 }
Oded Gabbayc4d66342019-02-16 00:39:11 +02001082
Tomer Tayarea451f82019-08-08 12:25:52 +00001083 /* Initialize cdev and device structures */
1084 rc = device_init_cdev(hdev, hclass, hdev->id, &hl_ops, name,
Oded Gabbayb968eb12019-07-30 09:10:02 +03001085 &hdev->cdev, &hdev->dev);
1086
1087 kfree(name);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001088
1089 if (rc)
1090 goto out_disabled;
1091
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001092 name = kasprintf(GFP_KERNEL, "hl_controlD%d", hdev->id / 2);
1093 if (!name) {
1094 rc = -ENOMEM;
Tomer Tayarea451f82019-08-08 12:25:52 +00001095 goto free_dev;
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001096 }
1097
Tomer Tayarea451f82019-08-08 12:25:52 +00001098 /* Initialize cdev and device structures for control device */
1099 rc = device_init_cdev(hdev, hclass, hdev->id_control, &hl_ctrl_ops,
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001100 name, &hdev->cdev_ctrl, &hdev->dev_ctrl);
1101
1102 kfree(name);
1103
1104 if (rc)
Tomer Tayarea451f82019-08-08 12:25:52 +00001105 goto free_dev;
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001106
Oded Gabbayc4d66342019-02-16 00:39:11 +02001107 /* Initialize ASIC function pointers and perform early init */
1108 rc = device_early_init(hdev);
1109 if (rc)
Tomer Tayarea451f82019-08-08 12:25:52 +00001110 goto free_dev_ctrl;
Oded Gabbayc4d66342019-02-16 00:39:11 +02001111
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001112 /*
1113 * Start calling ASIC initialization. First S/W then H/W and finally
1114 * late init
1115 */
1116 rc = hdev->asic_funcs->sw_init(hdev);
1117 if (rc)
1118 goto early_fini;
1119
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001120 /*
1121 * Initialize the H/W queues. Must be done before hw_init, because
1122 * there the addresses of the kernel queue are being written to the
1123 * registers of the device
1124 */
1125 rc = hl_hw_queues_create(hdev);
1126 if (rc) {
1127 dev_err(hdev->dev, "failed to initialize kernel queues\n");
1128 goto sw_fini;
1129 }
1130
Omer Shpigelman1fa185c2020-03-01 19:59:39 +02001131 cq_cnt = hdev->asic_prop.completion_queues_count;
1132
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001133 /*
1134 * Initialize the completion queues. Must be done before hw_init,
1135 * because there the addresses of the completion queues are being
1136 * passed as arguments to request_irq
1137 */
Omer Shpigelman1fa185c2020-03-01 19:59:39 +02001138 hdev->completion_queue = kcalloc(cq_cnt,
1139 sizeof(*hdev->completion_queue),
1140 GFP_KERNEL);
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001141
1142 if (!hdev->completion_queue) {
1143 dev_err(hdev->dev, "failed to allocate completion queues\n");
1144 rc = -ENOMEM;
1145 goto hw_queues_destroy;
1146 }
1147
Omer Shpigelman1fa185c2020-03-01 19:59:39 +02001148 for (i = 0, cq_ready_cnt = 0 ; i < cq_cnt ; i++, cq_ready_cnt++) {
1149 rc = hl_cq_init(hdev, &hdev->completion_queue[i],
1150 hdev->asic_funcs->get_queue_id_for_cq(hdev, i));
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001151 if (rc) {
1152 dev_err(hdev->dev,
1153 "failed to initialize completion queue\n");
1154 goto cq_fini;
1155 }
1156 }
1157
Oded Gabbay1251f232019-02-16 00:39:18 +02001158 /*
1159 * Initialize the event queue. Must be done before hw_init,
1160 * because there the address of the event queue is being
1161 * passed as argument to request_irq
1162 */
1163 rc = hl_eq_init(hdev, &hdev->event_queue);
1164 if (rc) {
1165 dev_err(hdev->dev, "failed to initialize event queue\n");
1166 goto cq_fini;
1167 }
1168
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001169 /* MMU S/W must be initialized before kernel context is created */
1170 rc = hl_mmu_init(hdev);
1171 if (rc) {
1172 dev_err(hdev->dev, "Failed to initialize MMU S/W structures\n");
1173 goto eq_fini;
1174 }
1175
Oded Gabbay0861e412019-02-16 00:39:14 +02001176 /* Allocate the kernel context */
1177 hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx), GFP_KERNEL);
1178 if (!hdev->kernel_ctx) {
1179 rc = -ENOMEM;
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001180 goto mmu_fini;
Oded Gabbay0861e412019-02-16 00:39:14 +02001181 }
1182
Oded Gabbay86d53072019-07-30 11:49:36 +03001183 hdev->compute_ctx = NULL;
Oded Gabbay0861e412019-02-16 00:39:14 +02001184
1185 rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
1186 if (rc) {
1187 dev_err(hdev->dev, "failed to initialize kernel context\n");
Tomer Tayar508c5842019-08-01 13:57:36 +00001188 kfree(hdev->kernel_ctx);
1189 goto mmu_fini;
Oded Gabbay0861e412019-02-16 00:39:14 +02001190 }
1191
Oded Gabbaybe5d9262019-02-16 00:39:15 +02001192 rc = hl_cb_pool_init(hdev);
1193 if (rc) {
1194 dev_err(hdev->dev, "failed to initialize CB pool\n");
1195 goto release_ctx;
1196 }
1197
Oded Gabbayc2164772019-02-16 00:39:24 +02001198 hl_debugfs_add_device(hdev);
1199
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001200 if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) {
1201 dev_info(hdev->dev,
1202 "H/W state is dirty, must reset before initializing\n");
Oded Gabbay908087f2019-12-23 17:51:48 +02001203 hdev->asic_funcs->halt_engines(hdev, true);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001204 hdev->asic_funcs->hw_fini(hdev, true);
1205 }
1206
Tomer Tayarea451f82019-08-08 12:25:52 +00001207 /*
1208 * From this point, in case of an error, add char devices and create
1209 * sysfs nodes as part of the error flow, to allow debugging.
1210 */
1211 add_cdev_sysfs_on_err = true;
1212
Oded Gabbay839c4802019-02-16 00:39:16 +02001213 rc = hdev->asic_funcs->hw_init(hdev);
1214 if (rc) {
1215 dev_err(hdev->dev, "failed to initialize the H/W\n");
1216 rc = 0;
1217 goto out_disabled;
1218 }
1219
1220 hdev->disabled = false;
1221
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001222 /* Check that the communication with the device is working */
1223 rc = hdev->asic_funcs->test_queues(hdev);
1224 if (rc) {
1225 dev_err(hdev->dev, "Failed to detect if device is alive\n");
1226 rc = 0;
1227 goto out_disabled;
1228 }
1229
Oded Gabbayd91389b2019-02-16 00:39:19 +02001230 rc = device_late_init(hdev);
1231 if (rc) {
1232 dev_err(hdev->dev, "Failed late initialization\n");
1233 rc = 0;
1234 goto out_disabled;
1235 }
1236
1237 dev_info(hdev->dev, "Found %s device with %lluGB DRAM\n",
1238 hdev->asic_name,
1239 hdev->asic_prop.dram_size / 1024 / 1024 / 1024);
1240
Omer Shpigelman0feaf862019-02-16 00:39:22 +02001241 rc = hl_vm_init(hdev);
1242 if (rc) {
1243 dev_err(hdev->dev, "Failed to initialize memory module\n");
1244 rc = 0;
1245 goto out_disabled;
1246 }
1247
Oded Gabbayd91389b2019-02-16 00:39:19 +02001248 /*
Tomer Tayarea451f82019-08-08 12:25:52 +00001249 * Expose devices and sysfs nodes to user.
1250 * From here there is no need to add char devices and create sysfs nodes
1251 * in case of an error.
1252 */
1253 add_cdev_sysfs_on_err = false;
1254 rc = device_cdev_sysfs_add(hdev);
1255 if (rc) {
1256 dev_err(hdev->dev,
1257 "Failed to add char devices and sysfs nodes\n");
1258 rc = 0;
1259 goto out_disabled;
1260 }
1261
1262 /*
1263 * hl_hwmon_init() must be called after device_late_init(), because only
Oded Gabbayd91389b2019-02-16 00:39:19 +02001264 * there we get the information from the device about which
Tomer Tayarea451f82019-08-08 12:25:52 +00001265 * hwmon-related sensors the device supports.
1266 * Furthermore, it must be done after adding the device to the system.
Oded Gabbayd91389b2019-02-16 00:39:19 +02001267 */
1268 rc = hl_hwmon_init(hdev);
1269 if (rc) {
1270 dev_err(hdev->dev, "Failed to initialize hwmon\n");
1271 rc = 0;
1272 goto out_disabled;
1273 }
1274
Oded Gabbayc4d66342019-02-16 00:39:11 +02001275 dev_notice(hdev->dev,
1276 "Successfully added device to habanalabs driver\n");
1277
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001278 hdev->init_done = true;
1279
Oded Gabbayc4d66342019-02-16 00:39:11 +02001280 return 0;
1281
Oded Gabbaybe5d9262019-02-16 00:39:15 +02001282release_ctx:
1283 if (hl_ctx_put(hdev->kernel_ctx) != 1)
1284 dev_err(hdev->dev,
1285 "kernel ctx is still alive on initialization failure\n");
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001286mmu_fini:
1287 hl_mmu_fini(hdev);
Oded Gabbay1251f232019-02-16 00:39:18 +02001288eq_fini:
1289 hl_eq_fini(hdev, &hdev->event_queue);
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001290cq_fini:
1291 for (i = 0 ; i < cq_ready_cnt ; i++)
1292 hl_cq_fini(hdev, &hdev->completion_queue[i]);
1293 kfree(hdev->completion_queue);
1294hw_queues_destroy:
1295 hl_hw_queues_destroy(hdev);
Oded Gabbay0861e412019-02-16 00:39:14 +02001296sw_fini:
1297 hdev->asic_funcs->sw_fini(hdev);
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001298early_fini:
1299 device_early_fini(hdev);
Tomer Tayarea451f82019-08-08 12:25:52 +00001300free_dev_ctrl:
1301 kfree(hdev->dev_ctrl);
1302free_dev:
1303 kfree(hdev->dev);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001304out_disabled:
1305 hdev->disabled = true;
Tomer Tayarea451f82019-08-08 12:25:52 +00001306 if (add_cdev_sysfs_on_err)
1307 device_cdev_sysfs_add(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001308 if (hdev->pdev)
1309 dev_err(&hdev->pdev->dev,
1310 "Failed to initialize hl%d. Device is NOT usable !\n",
Oded Gabbay307eae92019-09-01 16:13:25 +03001311 hdev->id / 2);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001312 else
1313 pr_err("Failed to initialize hl%d. Device is NOT usable !\n",
Oded Gabbay307eae92019-09-01 16:13:25 +03001314 hdev->id / 2);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001315
1316 return rc;
1317}
1318
1319/*
1320 * hl_device_fini - main tear-down function for habanalabs device
1321 *
1322 * @hdev: pointer to habanalabs device structure
1323 *
1324 * Destroy the device, call ASIC fini functions and release the id
1325 */
1326void hl_device_fini(struct hl_device *hdev)
1327{
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001328 int i, rc;
1329 ktime_t timeout;
1330
Oded Gabbayc4d66342019-02-16 00:39:11 +02001331 dev_info(hdev->dev, "Removing device\n");
1332
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001333 /*
1334 * This function is competing with the reset function, so try to
1335 * take the reset atomic and if we are already in middle of reset,
1336 * wait until reset function is finished. Reset function is designed
Omer Shpigelmane09498b2020-05-09 12:18:01 +03001337 * to always finish. However, in Gaudi, because of all the network
1338 * ports, the hard reset could take between 10-30 seconds
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001339 */
1340
1341 timeout = ktime_add_us(ktime_get(),
Omer Shpigelmane09498b2020-05-09 12:18:01 +03001342 HL_HARD_RESET_MAX_TIMEOUT * 1000 * 1000);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001343 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
1344 while (rc) {
1345 usleep_range(50, 200);
1346 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
1347 if (ktime_compare(ktime_get(), timeout) > 0) {
1348 WARN(1, "Failed to remove device because reset function did not finish\n");
1349 return;
1350 }
Oded Gabbaya1c92d12019-04-02 15:46:02 +03001351 }
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001352
Oded Gabbayc4d66342019-02-16 00:39:11 +02001353 /* Mark device as disabled */
1354 hdev->disabled = true;
1355
Oded Gabbayeb7caf82019-07-30 11:56:09 +03001356 /* Flush anyone that is inside the critical section of enqueue
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +03001357 * jobs to the H/W
1358 */
1359 hdev->asic_funcs->hw_queues_lock(hdev);
1360 hdev->asic_funcs->hw_queues_unlock(hdev);
1361
Oded Gabbayeb7caf82019-07-30 11:56:09 +03001362 /* Flush anyone that is inside device open */
1363 mutex_lock(&hdev->fpriv_list_lock);
1364 mutex_unlock(&hdev->fpriv_list_lock);
1365
Oded Gabbay3f5398c2019-04-06 15:41:35 +03001366 hdev->hard_reset_pending = true;
1367
Oded Gabbayd91389b2019-02-16 00:39:19 +02001368 hl_hwmon_fini(hdev);
1369
1370 device_late_fini(hdev);
1371
Oded Gabbayc2164772019-02-16 00:39:24 +02001372 hl_debugfs_remove_device(hdev);
1373
Oded Gabbay1251f232019-02-16 00:39:18 +02001374 /*
1375 * Halt the engines and disable interrupts so we won't get any more
1376 * completions from H/W and we won't have any accesses from the
1377 * H/W to the host machine
1378 */
1379 hdev->asic_funcs->halt_engines(hdev, true);
1380
Oded Gabbayeff6f4a2019-02-16 00:39:21 +02001381 /* Go over all the queues, release all CS and their jobs */
1382 hl_cs_rollback_all(hdev);
1383
Oded Gabbay4aecb052019-07-22 17:37:22 +03001384 /* Kill processes here after CS rollback. This is because the process
1385 * can't really exit until all its CSs are done, which is what we
1386 * do in cs rollback
1387 */
1388 device_kill_open_processes(hdev);
1389
Oded Gabbaybe5d9262019-02-16 00:39:15 +02001390 hl_cb_pool_fini(hdev);
1391
Oded Gabbay0861e412019-02-16 00:39:14 +02001392 /* Release kernel context */
1393 if ((hdev->kernel_ctx) && (hl_ctx_put(hdev->kernel_ctx) != 1))
1394 dev_err(hdev->dev, "kernel ctx is still alive\n");
1395
Oded Gabbay839c4802019-02-16 00:39:16 +02001396 /* Reset the H/W. It will be in idle state after this returns */
1397 hdev->asic_funcs->hw_fini(hdev, true);
1398
Omer Shpigelman0feaf862019-02-16 00:39:22 +02001399 hl_vm_fini(hdev);
1400
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001401 hl_mmu_fini(hdev);
1402
Oded Gabbay1251f232019-02-16 00:39:18 +02001403 hl_eq_fini(hdev, &hdev->event_queue);
1404
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001405 for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
1406 hl_cq_fini(hdev, &hdev->completion_queue[i]);
1407 kfree(hdev->completion_queue);
1408
1409 hl_hw_queues_destroy(hdev);
1410
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001411 /* Call ASIC S/W finalize function */
1412 hdev->asic_funcs->sw_fini(hdev);
1413
Oded Gabbayc4d66342019-02-16 00:39:11 +02001414 device_early_fini(hdev);
1415
Tomer Tayarea451f82019-08-08 12:25:52 +00001416 /* Hide devices and sysfs nodes from user */
1417 device_cdev_sysfs_del(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001418
1419 pr_info("removed device successfully\n");
1420}
1421
1422/*
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001423 * MMIO register access helper functions.
1424 */
1425
1426/*
1427 * hl_rreg - Read an MMIO register
1428 *
1429 * @hdev: pointer to habanalabs device structure
1430 * @reg: MMIO register offset (in bytes)
1431 *
1432 * Returns the value of the MMIO register we are asked to read
1433 *
1434 */
1435inline u32 hl_rreg(struct hl_device *hdev, u32 reg)
1436{
1437 return readl(hdev->rmmio + reg);
1438}
1439
1440/*
1441 * hl_wreg - Write to an MMIO register
1442 *
1443 * @hdev: pointer to habanalabs device structure
1444 * @reg: MMIO register offset (in bytes)
1445 * @val: 32-bit value
1446 *
1447 * Writes the 32-bit value into the MMIO register
1448 *
1449 */
1450inline void hl_wreg(struct hl_device *hdev, u32 reg, u32 val)
1451{
1452 writel(val, hdev->rmmio + reg);
1453}