blob: 459fee70a597a8fa0fc82e8225448fd3afacc508 [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;
39};
40
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;
Oded Gabbayeb7caf82019-07-30 11:56:09 +030045 struct hl_ctx *ctx;
Oded Gabbayc4d66342019-02-16 00:39:11 +020046
47 hpriv = container_of(ref, struct hl_fpriv, refcount);
48
49 hdev = hpriv->hdev;
Oded Gabbayeb7caf82019-07-30 11:56:09 +030050 ctx = hpriv->ctx;
Oded Gabbayc4d66342019-02-16 00:39:11 +020051
52 put_pid(hpriv->taskpid);
53
Oded Gabbayc2164772019-02-16 00:39:24 +020054 hl_debugfs_remove_file(hpriv);
55
Oded Gabbayeff6f4a2019-02-16 00:39:21 +020056 mutex_destroy(&hpriv->restore_phase_mutex);
57
Oded Gabbayeb7caf82019-07-30 11:56:09 +030058 mutex_lock(&hdev->fpriv_list_lock);
59 list_del(&hpriv->dev_node);
Oded Gabbay86d53072019-07-30 11:49:36 +030060 hdev->compute_ctx = NULL;
Oded Gabbayeb7caf82019-07-30 11:56:09 +030061 mutex_unlock(&hdev->fpriv_list_lock);
62
63 kfree(hpriv);
Oded Gabbayc4d66342019-02-16 00:39:11 +020064}
65
66void hl_hpriv_get(struct hl_fpriv *hpriv)
67{
68 kref_get(&hpriv->refcount);
69}
70
71void hl_hpriv_put(struct hl_fpriv *hpriv)
72{
73 kref_put(&hpriv->refcount, hpriv_release);
74}
75
76/*
77 * hl_device_release - release function for habanalabs device
78 *
79 * @inode: pointer to inode structure
80 * @filp: pointer to file structure
81 *
82 * Called when process closes an habanalabs device
83 */
84static int hl_device_release(struct inode *inode, struct file *filp)
85{
86 struct hl_fpriv *hpriv = filp->private_data;
87
Oded Gabbaybe5d9262019-02-16 00:39:15 +020088 hl_cb_mgr_fini(hpriv->hdev, &hpriv->cb_mgr);
Oded Gabbay0861e412019-02-16 00:39:14 +020089 hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
90
Oded Gabbayc4d66342019-02-16 00:39:11 +020091 filp->private_data = NULL;
92
93 hl_hpriv_put(hpriv);
94
95 return 0;
96}
97
Oded Gabbay4d6a7752019-07-30 09:10:50 +030098static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
99{
100 struct hl_fpriv *hpriv = filp->private_data;
101 struct hl_device *hdev;
102
103 filp->private_data = NULL;
104
105 hdev = hpriv->hdev;
106
107 mutex_lock(&hdev->fpriv_list_lock);
108 list_del(&hpriv->dev_node);
109 mutex_unlock(&hdev->fpriv_list_lock);
110
111 kfree(hpriv);
112
113 return 0;
114}
115
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200116/*
117 * hl_mmap - mmap function for habanalabs device
118 *
119 * @*filp: pointer to file structure
120 * @*vma: pointer to vm_area_struct of the process
121 *
122 * Called when process does an mmap on habanalabs device. Call the device's mmap
123 * function at the end of the common code.
124 */
125static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
126{
127 struct hl_fpriv *hpriv = filp->private_data;
128
129 if ((vma->vm_pgoff & HL_MMAP_CB_MASK) == HL_MMAP_CB_MASK) {
130 vma->vm_pgoff ^= HL_MMAP_CB_MASK;
131 return hl_cb_mmap(hpriv, vma);
132 }
133
Oded Gabbay5e6e0232019-02-27 12:15:16 +0200134 return -EINVAL;
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200135}
136
Oded Gabbayc4d66342019-02-16 00:39:11 +0200137static const struct file_operations hl_ops = {
138 .owner = THIS_MODULE,
139 .open = hl_device_open,
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200140 .release = hl_device_release,
141 .mmap = hl_mmap,
142 .unlocked_ioctl = hl_ioctl,
143 .compat_ioctl = hl_ioctl
Oded Gabbayc4d66342019-02-16 00:39:11 +0200144};
145
Oded Gabbay4d6a7752019-07-30 09:10:50 +0300146static const struct file_operations hl_ctrl_ops = {
147 .owner = THIS_MODULE,
148 .open = hl_device_open_ctrl,
149 .release = hl_device_release_ctrl,
150 .unlocked_ioctl = hl_ioctl_control,
151 .compat_ioctl = hl_ioctl_control
152};
153
Tomer Tayarea451f82019-08-08 12:25:52 +0000154static void device_release_func(struct device *dev)
155{
156 kfree(dev);
157}
158
Oded Gabbayc4d66342019-02-16 00:39:11 +0200159/*
Tomer Tayarea451f82019-08-08 12:25:52 +0000160 * device_init_cdev - Initialize cdev and device for habanalabs device
Oded Gabbayc4d66342019-02-16 00:39:11 +0200161 *
162 * @hdev: pointer to habanalabs device structure
163 * @hclass: pointer to the class object of the device
164 * @minor: minor number of the specific device
Oded Gabbayb968eb12019-07-30 09:10:02 +0300165 * @fpos: file operations to install for this device
166 * @name: name of the device as it will appear in the filesystem
Tomer Tayarea451f82019-08-08 12:25:52 +0000167 * @cdev: pointer to the char device object that will be initialized
168 * @dev: pointer to the device object that will be initialized
Oded Gabbayc4d66342019-02-16 00:39:11 +0200169 *
Tomer Tayarea451f82019-08-08 12:25:52 +0000170 * Initialize a cdev and a Linux device for habanalabs's device.
Oded Gabbayc4d66342019-02-16 00:39:11 +0200171 */
Tomer Tayarea451f82019-08-08 12:25:52 +0000172static int device_init_cdev(struct hl_device *hdev, struct class *hclass,
Oded Gabbayb968eb12019-07-30 09:10:02 +0300173 int minor, const struct file_operations *fops,
174 char *name, struct cdev *cdev,
175 struct device **dev)
Oded Gabbayc4d66342019-02-16 00:39:11 +0200176{
Oded Gabbayb968eb12019-07-30 09:10:02 +0300177 cdev_init(cdev, fops);
178 cdev->owner = THIS_MODULE;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200179
Tomer Tayarea451f82019-08-08 12:25:52 +0000180 *dev = kzalloc(sizeof(**dev), GFP_KERNEL);
181 if (!*dev)
182 return -ENOMEM;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200183
Tomer Tayarea451f82019-08-08 12:25:52 +0000184 device_initialize(*dev);
185 (*dev)->devt = MKDEV(hdev->major, minor);
186 (*dev)->class = hclass;
187 (*dev)->release = device_release_func;
Oded Gabbayb968eb12019-07-30 09:10:02 +0300188 dev_set_drvdata(*dev, hdev);
Tomer Tayarea451f82019-08-08 12:25:52 +0000189 dev_set_name(*dev, "%s", name);
190
191 return 0;
192}
193
194static int device_cdev_sysfs_add(struct hl_device *hdev)
195{
196 int rc;
197
198 rc = cdev_device_add(&hdev->cdev, hdev->dev);
199 if (rc) {
200 dev_err(hdev->dev,
201 "failed to add a char device to the system\n");
202 return rc;
203 }
204
205 rc = cdev_device_add(&hdev->cdev_ctrl, hdev->dev_ctrl);
206 if (rc) {
207 dev_err(hdev->dev,
208 "failed to add a control char device to the system\n");
209 goto delete_cdev_device;
210 }
211
212 /* hl_sysfs_init() must be done after adding the device to the system */
213 rc = hl_sysfs_init(hdev);
214 if (rc) {
215 dev_err(hdev->dev, "failed to initialize sysfs\n");
216 goto delete_ctrl_cdev_device;
217 }
218
219 hdev->cdev_sysfs_created = true;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200220
221 return 0;
222
Tomer Tayarea451f82019-08-08 12:25:52 +0000223delete_ctrl_cdev_device:
224 cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
225delete_cdev_device:
226 cdev_device_del(&hdev->cdev, hdev->dev);
227 return rc;
228}
229
230static void device_cdev_sysfs_del(struct hl_device *hdev)
231{
232 /* device_release() won't be called so must free devices explicitly */
233 if (!hdev->cdev_sysfs_created) {
234 kfree(hdev->dev_ctrl);
235 kfree(hdev->dev);
236 return;
237 }
238
239 hl_sysfs_fini(hdev);
240 cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
241 cdev_device_del(&hdev->cdev, hdev->dev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200242}
243
244/*
245 * device_early_init - do some early initialization for the habanalabs device
246 *
247 * @hdev: pointer to habanalabs device structure
248 *
249 * Install the relevant function pointers and call the early_init function,
250 * if such a function exists
251 */
252static int device_early_init(struct hl_device *hdev)
253{
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200254 int rc;
255
Oded Gabbayc4d66342019-02-16 00:39:11 +0200256 switch (hdev->asic_type) {
257 case ASIC_GOYA:
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200258 goya_set_asic_funcs(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200259 strlcpy(hdev->asic_name, "GOYA", sizeof(hdev->asic_name));
260 break;
261 default:
262 dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
263 hdev->asic_type);
264 return -EINVAL;
265 }
266
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200267 rc = hdev->asic_funcs->early_init(hdev);
268 if (rc)
269 return rc;
270
Oded Gabbay0861e412019-02-16 00:39:14 +0200271 rc = hl_asid_init(hdev);
272 if (rc)
273 goto early_fini;
274
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200275 hdev->cq_wq = alloc_workqueue("hl-free-jobs", WQ_UNBOUND, 0);
276 if (hdev->cq_wq == NULL) {
277 dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
278 rc = -ENOMEM;
279 goto asid_fini;
280 }
281
Oded Gabbay1251f232019-02-16 00:39:18 +0200282 hdev->eq_wq = alloc_workqueue("hl-events", WQ_UNBOUND, 0);
283 if (hdev->eq_wq == NULL) {
284 dev_err(hdev->dev, "Failed to allocate EQ workqueue\n");
285 rc = -ENOMEM;
286 goto free_cq_wq;
287 }
288
Oded Gabbayd91389b2019-02-16 00:39:19 +0200289 hdev->hl_chip_info = kzalloc(sizeof(struct hwmon_chip_info),
290 GFP_KERNEL);
291 if (!hdev->hl_chip_info) {
292 rc = -ENOMEM;
293 goto free_eq_wq;
294 }
295
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300296 hdev->idle_busy_ts_arr = kmalloc_array(HL_IDLE_BUSY_TS_ARR_SIZE,
297 sizeof(struct hl_device_idle_busy_ts),
298 (GFP_KERNEL | __GFP_ZERO));
299 if (!hdev->idle_busy_ts_arr) {
300 rc = -ENOMEM;
301 goto free_chip_info;
302 }
303
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200304 hl_cb_mgr_init(&hdev->kernel_cb_mgr);
305
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200306 mutex_init(&hdev->send_cpu_message_lock);
Oded Gabbay19734972019-05-04 17:36:06 +0300307 mutex_init(&hdev->debug_lock);
Tomer Tayar8d45f1de2019-05-13 12:13:39 +0300308 mutex_init(&hdev->mmu_cache_lock);
Oded Gabbayeff6f4a2019-02-16 00:39:21 +0200309 INIT_LIST_HEAD(&hdev->hw_queues_mirror_list);
310 spin_lock_init(&hdev->hw_queues_mirror_lock);
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300311 INIT_LIST_HEAD(&hdev->fpriv_list);
312 mutex_init(&hdev->fpriv_list_lock);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200313 atomic_set(&hdev->in_reset, 0);
Oded Gabbay0861e412019-02-16 00:39:14 +0200314
Oded Gabbayc4d66342019-02-16 00:39:11 +0200315 return 0;
Oded Gabbay0861e412019-02-16 00:39:14 +0200316
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300317free_chip_info:
318 kfree(hdev->hl_chip_info);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200319free_eq_wq:
320 destroy_workqueue(hdev->eq_wq);
Oded Gabbay1251f232019-02-16 00:39:18 +0200321free_cq_wq:
322 destroy_workqueue(hdev->cq_wq);
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200323asid_fini:
324 hl_asid_fini(hdev);
Oded Gabbay0861e412019-02-16 00:39:14 +0200325early_fini:
326 if (hdev->asic_funcs->early_fini)
327 hdev->asic_funcs->early_fini(hdev);
328
329 return rc;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200330}
331
332/*
333 * device_early_fini - finalize all that was done in device_early_init
334 *
335 * @hdev: pointer to habanalabs device structure
336 *
337 */
338static void device_early_fini(struct hl_device *hdev)
339{
Tomer Tayar8d45f1de2019-05-13 12:13:39 +0300340 mutex_destroy(&hdev->mmu_cache_lock);
Oded Gabbay19734972019-05-04 17:36:06 +0300341 mutex_destroy(&hdev->debug_lock);
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200342 mutex_destroy(&hdev->send_cpu_message_lock);
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200343
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300344 mutex_destroy(&hdev->fpriv_list_lock);
345
Oded Gabbaybe5d9262019-02-16 00:39:15 +0200346 hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr);
347
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300348 kfree(hdev->idle_busy_ts_arr);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200349 kfree(hdev->hl_chip_info);
350
Oded Gabbay1251f232019-02-16 00:39:18 +0200351 destroy_workqueue(hdev->eq_wq);
Oded Gabbay9494a8d2019-02-16 00:39:17 +0200352 destroy_workqueue(hdev->cq_wq);
353
Oded Gabbay0861e412019-02-16 00:39:14 +0200354 hl_asid_fini(hdev);
355
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200356 if (hdev->asic_funcs->early_fini)
357 hdev->asic_funcs->early_fini(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200358}
359
Oded Gabbayd91389b2019-02-16 00:39:19 +0200360static void set_freq_to_low_job(struct work_struct *work)
361{
362 struct hl_device *hdev = container_of(work, struct hl_device,
363 work_freq.work);
364
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300365 mutex_lock(&hdev->fpriv_list_lock);
366
367 if (!hdev->compute_ctx)
Oded Gabbayd91389b2019-02-16 00:39:19 +0200368 hl_device_set_frequency(hdev, PLL_LOW);
369
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300370 mutex_unlock(&hdev->fpriv_list_lock);
371
Oded Gabbayd91389b2019-02-16 00:39:19 +0200372 schedule_delayed_work(&hdev->work_freq,
373 usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
374}
375
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200376static void hl_device_heartbeat(struct work_struct *work)
377{
378 struct hl_device *hdev = container_of(work, struct hl_device,
379 work_heartbeat.work);
380
381 if (hl_device_disabled_or_in_reset(hdev))
382 goto reschedule;
383
384 if (!hdev->asic_funcs->send_heartbeat(hdev))
385 goto reschedule;
386
387 dev_err(hdev->dev, "Device heartbeat failed!\n");
388 hl_device_reset(hdev, true, false);
389
390 return;
391
392reschedule:
393 schedule_delayed_work(&hdev->work_heartbeat,
394 usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
395}
396
Oded Gabbayd91389b2019-02-16 00:39:19 +0200397/*
398 * device_late_init - do late stuff initialization for the habanalabs device
399 *
400 * @hdev: pointer to habanalabs device structure
401 *
402 * Do stuff that either needs the device H/W queues to be active or needs
403 * to happen after all the rest of the initialization is finished
404 */
405static int device_late_init(struct hl_device *hdev)
406{
407 int rc;
408
Oded Gabbay0b28d262019-05-29 14:24:51 +0300409 if (hdev->asic_funcs->late_init) {
410 rc = hdev->asic_funcs->late_init(hdev);
411 if (rc) {
412 dev_err(hdev->dev,
413 "failed late initialization for the H/W\n");
414 return rc;
415 }
416 }
417
Oded Gabbayd91389b2019-02-16 00:39:19 +0200418 hdev->high_pll = hdev->asic_prop.high_pll;
419
420 /* force setting to low frequency */
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300421 hdev->curr_pll_profile = PLL_LOW;
Oded Gabbayd91389b2019-02-16 00:39:19 +0200422
423 if (hdev->pm_mng_profile == PM_AUTO)
424 hdev->asic_funcs->set_pll_profile(hdev, PLL_LOW);
425 else
426 hdev->asic_funcs->set_pll_profile(hdev, PLL_LAST);
427
Oded Gabbay0b28d262019-05-29 14:24:51 +0300428 INIT_DELAYED_WORK(&hdev->work_freq, set_freq_to_low_job);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200429 schedule_delayed_work(&hdev->work_freq,
Oded Gabbay0b28d262019-05-29 14:24:51 +0300430 usecs_to_jiffies(HL_PLL_LOW_JOB_FREQ_USEC));
Oded Gabbayd91389b2019-02-16 00:39:19 +0200431
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200432 if (hdev->heartbeat) {
433 INIT_DELAYED_WORK(&hdev->work_heartbeat, hl_device_heartbeat);
434 schedule_delayed_work(&hdev->work_heartbeat,
435 usecs_to_jiffies(HL_HEARTBEAT_PER_USEC));
436 }
437
Oded Gabbayd91389b2019-02-16 00:39:19 +0200438 hdev->late_init_done = true;
439
440 return 0;
441}
442
443/*
444 * device_late_fini - finalize all that was done in device_late_init
445 *
446 * @hdev: pointer to habanalabs device structure
447 *
448 */
449static void device_late_fini(struct hl_device *hdev)
450{
451 if (!hdev->late_init_done)
452 return;
453
454 cancel_delayed_work_sync(&hdev->work_freq);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200455 if (hdev->heartbeat)
456 cancel_delayed_work_sync(&hdev->work_heartbeat);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200457
458 if (hdev->asic_funcs->late_fini)
459 hdev->asic_funcs->late_fini(hdev);
460
461 hdev->late_init_done = false;
462}
463
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300464uint32_t hl_device_utilization(struct hl_device *hdev, uint32_t period_ms)
465{
466 struct hl_device_idle_busy_ts *ts;
467 ktime_t zero_ktime, curr = ktime_get();
468 u32 overlap_cnt = 0, last_index = hdev->idle_busy_ts_idx;
469 s64 period_us, last_start_us, last_end_us, last_busy_time_us,
470 total_busy_time_us = 0, total_busy_time_ms;
471
472 zero_ktime = ktime_set(0, 0);
473 period_us = period_ms * USEC_PER_MSEC;
474 ts = &hdev->idle_busy_ts_arr[last_index];
475
476 /* check case that device is currently in idle */
477 if (!ktime_compare(ts->busy_to_idle_ts, zero_ktime) &&
478 !ktime_compare(ts->idle_to_busy_ts, zero_ktime)) {
479
480 last_index--;
481 /* Handle case idle_busy_ts_idx was 0 */
482 if (last_index > HL_IDLE_BUSY_TS_ARR_SIZE)
483 last_index = HL_IDLE_BUSY_TS_ARR_SIZE - 1;
484
485 ts = &hdev->idle_busy_ts_arr[last_index];
486 }
487
488 while (overlap_cnt < HL_IDLE_BUSY_TS_ARR_SIZE) {
489 /* Check if we are in last sample case. i.e. if the sample
490 * begun before the sampling period. This could be a real
491 * sample or 0 so need to handle both cases
492 */
493 last_start_us = ktime_to_us(
494 ktime_sub(curr, ts->idle_to_busy_ts));
495
496 if (last_start_us > period_us) {
497
498 /* First check two cases:
499 * 1. If the device is currently busy
500 * 2. If the device was idle during the whole sampling
501 * period
502 */
503
504 if (!ktime_compare(ts->busy_to_idle_ts, zero_ktime)) {
505 /* Check if the device is currently busy */
506 if (ktime_compare(ts->idle_to_busy_ts,
507 zero_ktime))
508 return 100;
509
510 /* We either didn't have any activity or we
511 * reached an entry which is 0. Either way,
512 * exit and return what was accumulated so far
513 */
514 break;
515 }
516
517 /* If sample has finished, check it is relevant */
518 last_end_us = ktime_to_us(
519 ktime_sub(curr, ts->busy_to_idle_ts));
520
521 if (last_end_us > period_us)
522 break;
523
524 /* It is relevant so add it but with adjustment */
525 last_busy_time_us = ktime_to_us(
526 ktime_sub(ts->busy_to_idle_ts,
527 ts->idle_to_busy_ts));
528 total_busy_time_us += last_busy_time_us -
529 (last_start_us - period_us);
530 break;
531 }
532
533 /* Check if the sample is finished or still open */
534 if (ktime_compare(ts->busy_to_idle_ts, zero_ktime))
535 last_busy_time_us = ktime_to_us(
536 ktime_sub(ts->busy_to_idle_ts,
537 ts->idle_to_busy_ts));
538 else
539 last_busy_time_us = ktime_to_us(
540 ktime_sub(curr, ts->idle_to_busy_ts));
541
542 total_busy_time_us += last_busy_time_us;
543
544 last_index--;
545 /* Handle case idle_busy_ts_idx was 0 */
546 if (last_index > HL_IDLE_BUSY_TS_ARR_SIZE)
547 last_index = HL_IDLE_BUSY_TS_ARR_SIZE - 1;
548
549 ts = &hdev->idle_busy_ts_arr[last_index];
550
551 overlap_cnt++;
552 }
553
554 total_busy_time_ms = DIV_ROUND_UP_ULL(total_busy_time_us,
555 USEC_PER_MSEC);
556
557 return DIV_ROUND_UP_ULL(total_busy_time_ms * 100, period_ms);
558}
559
Oded Gabbayd91389b2019-02-16 00:39:19 +0200560/*
561 * hl_device_set_frequency - set the frequency of the device
562 *
563 * @hdev: pointer to habanalabs device structure
564 * @freq: the new frequency value
565 *
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300566 * Change the frequency if needed. This function has no protection against
567 * concurrency, therefore it is assumed that the calling function has protected
568 * itself against the case of calling this function from multiple threads with
569 * different values
570 *
571 * Returns 0 if no change was done, otherwise returns 1
Oded Gabbayd91389b2019-02-16 00:39:19 +0200572 */
573int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq)
574{
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300575 if ((hdev->pm_mng_profile == PM_MANUAL) ||
576 (hdev->curr_pll_profile == freq))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200577 return 0;
578
Oded Gabbayd91389b2019-02-16 00:39:19 +0200579 dev_dbg(hdev->dev, "Changing device frequency to %s\n",
580 freq == PLL_HIGH ? "high" : "low");
581
582 hdev->asic_funcs->set_pll_profile(hdev, freq);
583
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300584 hdev->curr_pll_profile = freq;
585
Oded Gabbayd91389b2019-02-16 00:39:19 +0200586 return 1;
587}
588
Oded Gabbay19734972019-05-04 17:36:06 +0300589int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
590{
591 int rc = 0;
592
593 mutex_lock(&hdev->debug_lock);
594
595 if (!enable) {
596 if (!hdev->in_debug) {
597 dev_err(hdev->dev,
598 "Failed to disable debug mode because device was not in debug mode\n");
599 rc = -EFAULT;
600 goto out;
601 }
602
603 hdev->asic_funcs->halt_coresight(hdev);
604 hdev->in_debug = 0;
605
606 goto out;
607 }
608
609 if (hdev->in_debug) {
610 dev_err(hdev->dev,
611 "Failed to enable debug mode because device is already in debug mode\n");
612 rc = -EFAULT;
613 goto out;
614 }
615
Oded Gabbay19734972019-05-04 17:36:06 +0300616 hdev->in_debug = 1;
617
Oded Gabbay19734972019-05-04 17:36:06 +0300618out:
619 mutex_unlock(&hdev->debug_lock);
620
621 return rc;
622}
623
Oded Gabbayc4d66342019-02-16 00:39:11 +0200624/*
625 * hl_device_suspend - initiate device suspend
626 *
627 * @hdev: pointer to habanalabs device structure
628 *
629 * Puts the hw in the suspend state (all asics).
630 * Returns 0 for success or an error on failure.
631 * Called at driver suspend.
632 */
633int hl_device_suspend(struct hl_device *hdev)
634{
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200635 int rc;
636
Oded Gabbayc4d66342019-02-16 00:39:11 +0200637 pci_save_state(hdev->pdev);
638
Oded Gabbay7cb51012019-03-03 22:29:20 +0200639 /* Block future CS/VM/JOB completion operations */
640 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
641 if (rc) {
642 dev_err(hdev->dev, "Can't suspend while in reset\n");
643 return -EIO;
644 }
645
646 /* This blocks all other stuff that is not blocked by in_reset */
647 hdev->disabled = true;
648
649 /*
650 * Flush anyone that is inside the critical section of enqueue
651 * jobs to the H/W
652 */
653 hdev->asic_funcs->hw_queues_lock(hdev);
654 hdev->asic_funcs->hw_queues_unlock(hdev);
655
656 /* Flush processes that are sending message to CPU */
657 mutex_lock(&hdev->send_cpu_message_lock);
658 mutex_unlock(&hdev->send_cpu_message_lock);
659
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200660 rc = hdev->asic_funcs->suspend(hdev);
661 if (rc)
662 dev_err(hdev->dev,
663 "Failed to disable PCI access of device CPU\n");
664
Oded Gabbayc4d66342019-02-16 00:39:11 +0200665 /* Shut down the device */
666 pci_disable_device(hdev->pdev);
667 pci_set_power_state(hdev->pdev, PCI_D3hot);
668
669 return 0;
670}
671
672/*
673 * hl_device_resume - initiate device resume
674 *
675 * @hdev: pointer to habanalabs device structure
676 *
677 * Bring the hw back to operating state (all asics).
678 * Returns 0 for success or an error on failure.
679 * Called at driver resume.
680 */
681int hl_device_resume(struct hl_device *hdev)
682{
683 int rc;
684
685 pci_set_power_state(hdev->pdev, PCI_D0);
686 pci_restore_state(hdev->pdev);
Oded Gabbay7cb51012019-03-03 22:29:20 +0200687 rc = pci_enable_device_mem(hdev->pdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +0200688 if (rc) {
689 dev_err(hdev->dev,
690 "Failed to enable PCI device in resume\n");
691 return rc;
692 }
693
Oded Gabbay7cb51012019-03-03 22:29:20 +0200694 pci_set_master(hdev->pdev);
695
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200696 rc = hdev->asic_funcs->resume(hdev);
697 if (rc) {
Oded Gabbay7cb51012019-03-03 22:29:20 +0200698 dev_err(hdev->dev, "Failed to resume device after suspend\n");
699 goto disable_device;
700 }
701
702
703 hdev->disabled = false;
704 atomic_set(&hdev->in_reset, 0);
705
706 rc = hl_device_reset(hdev, true, false);
707 if (rc) {
708 dev_err(hdev->dev, "Failed to reset device during resume\n");
709 goto disable_device;
Oded Gabbay99b9d7b2019-02-16 00:39:13 +0200710 }
711
Oded Gabbayc4d66342019-02-16 00:39:11 +0200712 return 0;
Oded Gabbay7cb51012019-03-03 22:29:20 +0200713
714disable_device:
715 pci_clear_master(hdev->pdev);
716 pci_disable_device(hdev->pdev);
717
718 return rc;
Oded Gabbayc4d66342019-02-16 00:39:11 +0200719}
720
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300721static void device_kill_open_processes(struct hl_device *hdev)
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200722{
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200723 u16 pending_total, pending_cnt;
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300724 struct hl_fpriv *hpriv;
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200725 struct task_struct *task = NULL;
726
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200727 if (hdev->pldm)
728 pending_total = HL_PLDM_PENDING_RESET_PER_SEC;
729 else
730 pending_total = HL_PENDING_RESET_PER_SEC;
731
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300732 /* Giving time for user to close FD, and for processes that are inside
733 * hl_device_open to finish
734 */
735 if (!list_empty(&hdev->fpriv_list))
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200736 ssleep(1);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200737
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300738 mutex_lock(&hdev->fpriv_list_lock);
739
740 /* This section must be protected because we are dereferencing
741 * pointers that are freed if the process exits
742 */
743 list_for_each_entry(hpriv, &hdev->fpriv_list, dev_node) {
744 task = get_pid_task(hpriv->taskpid, PIDTYPE_PID);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200745 if (task) {
Oded Gabbay4d6a7752019-07-30 09:10:50 +0300746 dev_info(hdev->dev, "Killing user process pid=%d\n",
747 task_pid_nr(task));
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200748 send_sig(SIGKILL, task, 1);
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300749 usleep_range(1000, 10000);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200750
751 put_task_struct(task);
752 }
753 }
754
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300755 mutex_unlock(&hdev->fpriv_list_lock);
756
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300757 /* We killed the open users, but because the driver cleans up after the
758 * user contexts are closed (e.g. mmu mappings), we need to wait again
759 * to make sure the cleaning phase is finished before continuing with
760 * the reset
761 */
762
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200763 pending_cnt = pending_total;
764
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300765 while ((!list_empty(&hdev->fpriv_list)) && (pending_cnt)) {
766 dev_info(hdev->dev,
767 "Waiting for all unmap operations to finish before hard reset\n");
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200768
769 pending_cnt--;
770
771 ssleep(1);
772 }
773
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300774 if (!list_empty(&hdev->fpriv_list))
Omer Shpigelmanf650a952019-03-13 13:36:28 +0200775 dev_crit(hdev->dev,
776 "Going to hard reset with open user contexts\n");
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300777}
778
779static void device_hard_reset_pending(struct work_struct *work)
780{
781 struct hl_device_reset_work *device_reset_work =
782 container_of(work, struct hl_device_reset_work, reset_work);
783 struct hl_device *hdev = device_reset_work->hdev;
784
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200785 hl_device_reset(hdev, true, true);
786
787 kfree(device_reset_work);
788}
789
790/*
791 * hl_device_reset - reset the device
792 *
793 * @hdev: pointer to habanalabs device structure
794 * @hard_reset: should we do hard reset to all engines or just reset the
795 * compute/dma engines
796 *
797 * Block future CS and wait for pending CS to be enqueued
798 * Call ASIC H/W fini
799 * Flush all completions
800 * Re-initialize all internal data structures
801 * Call ASIC H/W init, late_init
802 * Test queues
803 * Enable device
804 *
805 * Returns 0 for success or an error on failure.
806 */
807int hl_device_reset(struct hl_device *hdev, bool hard_reset,
808 bool from_hard_reset_thread)
809{
810 int i, rc;
811
812 if (!hdev->init_done) {
813 dev_err(hdev->dev,
814 "Can't reset before initialization is done\n");
815 return 0;
816 }
817
818 /*
819 * Prevent concurrency in this function - only one reset should be
820 * done at any given time. Only need to perform this if we didn't
821 * get from the dedicated hard reset thread
822 */
823 if (!from_hard_reset_thread) {
824 /* Block future CS/VM/JOB completion operations */
825 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
826 if (rc)
827 return 0;
828
829 /* This also blocks future CS/VM/JOB completion operations */
830 hdev->disabled = true;
831
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300832 /* Flush anyone that is inside the critical section of enqueue
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200833 * jobs to the H/W
834 */
835 hdev->asic_funcs->hw_queues_lock(hdev);
836 hdev->asic_funcs->hw_queues_unlock(hdev);
837
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300838 /* Flush anyone that is inside device open */
839 mutex_lock(&hdev->fpriv_list_lock);
840 mutex_unlock(&hdev->fpriv_list_lock);
841
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200842 dev_err(hdev->dev, "Going to RESET device!\n");
843 }
844
845again:
846 if ((hard_reset) && (!from_hard_reset_thread)) {
847 struct hl_device_reset_work *device_reset_work;
848
Oded Gabbay3f5398c2019-04-06 15:41:35 +0300849 hdev->hard_reset_pending = true;
850
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200851 device_reset_work = kzalloc(sizeof(*device_reset_work),
852 GFP_ATOMIC);
853 if (!device_reset_work) {
854 rc = -ENOMEM;
855 goto out_err;
856 }
857
858 /*
859 * Because the reset function can't run from interrupt or
860 * from heartbeat work, we need to call the reset function
861 * from a dedicated work
862 */
863 INIT_WORK(&device_reset_work->reset_work,
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +0300864 device_hard_reset_pending);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200865 device_reset_work->hdev = hdev;
866 schedule_work(&device_reset_work->reset_work);
867
868 return 0;
869 }
870
871 if (hard_reset) {
872 device_late_fini(hdev);
873
874 /*
875 * Now that the heartbeat thread is closed, flush processes
876 * which are sending messages to CPU
877 */
878 mutex_lock(&hdev->send_cpu_message_lock);
879 mutex_unlock(&hdev->send_cpu_message_lock);
880 }
881
882 /*
883 * Halt the engines and disable interrupts so we won't get any more
884 * completions from H/W and we won't have any accesses from the
885 * H/W to the host machine
886 */
887 hdev->asic_funcs->halt_engines(hdev, hard_reset);
888
Oded Gabbayeff6f4a2019-02-16 00:39:21 +0200889 /* Go over all the queues, release all CS and their jobs */
890 hl_cs_rollback_all(hdev);
891
Oded Gabbay4aecb052019-07-22 17:37:22 +0300892 /* Kill processes here after CS rollback. This is because the process
893 * can't really exit until all its CSs are done, which is what we
894 * do in cs rollback
895 */
896 if (from_hard_reset_thread)
897 device_kill_open_processes(hdev);
898
Oded Gabbay0878a422019-03-17 09:12:29 +0200899 /* Release kernel context */
900 if ((hard_reset) && (hl_ctx_put(hdev->kernel_ctx) == 1))
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200901 hdev->kernel_ctx = NULL;
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200902
903 /* Reset the H/W. It will be in idle state after this returns */
904 hdev->asic_funcs->hw_fini(hdev, hard_reset);
905
Omer Shpigelman0feaf862019-02-16 00:39:22 +0200906 if (hard_reset) {
907 hl_vm_fini(hdev);
Oded Gabbay37d68ce2019-05-29 14:43:04 +0300908 hl_mmu_fini(hdev);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200909 hl_eq_reset(hdev, &hdev->event_queue);
Omer Shpigelman0feaf862019-02-16 00:39:22 +0200910 }
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200911
912 /* Re-initialize PI,CI to 0 in all queues (hw queue, cq) */
913 hl_hw_queue_reset(hdev, hard_reset);
914 for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
915 hl_cq_reset(hdev, &hdev->completion_queue[i]);
916
Oded Gabbay75b3cb22019-08-28 17:32:04 +0300917 hdev->idle_busy_ts_idx = 0;
918 hdev->idle_busy_ts_arr[0].busy_to_idle_ts = ktime_set(0, 0);
919 hdev->idle_busy_ts_arr[0].idle_to_busy_ts = ktime_set(0, 0);
920
921 if (hdev->cs_active_cnt)
922 dev_crit(hdev->dev, "CS active cnt %d is not 0 during reset\n",
923 hdev->cs_active_cnt);
924
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300925 mutex_lock(&hdev->fpriv_list_lock);
926
Oded Gabbay027d35d2019-04-25 20:15:42 +0300927 /* Make sure the context switch phase will run again */
Oded Gabbay86d53072019-07-30 11:49:36 +0300928 if (hdev->compute_ctx) {
929 atomic_set(&hdev->compute_ctx->thread_ctx_switch_token, 1);
930 hdev->compute_ctx->thread_ctx_switch_wait_token = 0;
Oded Gabbayeff6f4a2019-02-16 00:39:21 +0200931 }
932
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300933 mutex_unlock(&hdev->fpriv_list_lock);
934
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200935 /* Finished tear-down, starting to re-initialize */
936
937 if (hard_reset) {
Oded Gabbaya28ce422019-02-28 10:46:12 +0200938 hdev->device_cpu_disabled = false;
Oded Gabbay3f5398c2019-04-06 15:41:35 +0300939 hdev->hard_reset_pending = false;
Oded Gabbaya28ce422019-02-28 10:46:12 +0200940
Oded Gabbay0878a422019-03-17 09:12:29 +0200941 if (hdev->kernel_ctx) {
942 dev_crit(hdev->dev,
943 "kernel ctx was alive during hard reset, something is terribly wrong\n");
944 rc = -EBUSY;
945 goto out_err;
946 }
947
Oded Gabbay37d68ce2019-05-29 14:43:04 +0300948 rc = hl_mmu_init(hdev);
949 if (rc) {
950 dev_err(hdev->dev,
951 "Failed to initialize MMU S/W after hard reset\n");
952 goto out_err;
953 }
954
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200955 /* Allocate the kernel context */
956 hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx),
957 GFP_KERNEL);
958 if (!hdev->kernel_ctx) {
959 rc = -ENOMEM;
960 goto out_err;
961 }
962
Oded Gabbay86d53072019-07-30 11:49:36 +0300963 hdev->compute_ctx = NULL;
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200964
965 rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
966 if (rc) {
967 dev_err(hdev->dev,
968 "failed to init kernel ctx in hard reset\n");
969 kfree(hdev->kernel_ctx);
970 hdev->kernel_ctx = NULL;
971 goto out_err;
972 }
973 }
974
975 rc = hdev->asic_funcs->hw_init(hdev);
976 if (rc) {
977 dev_err(hdev->dev,
978 "failed to initialize the H/W after reset\n");
979 goto out_err;
980 }
981
982 hdev->disabled = false;
983
984 /* Check that the communication with the device is working */
985 rc = hdev->asic_funcs->test_queues(hdev);
986 if (rc) {
987 dev_err(hdev->dev,
988 "Failed to detect if device is alive after reset\n");
989 goto out_err;
990 }
991
992 if (hard_reset) {
993 rc = device_late_init(hdev);
994 if (rc) {
995 dev_err(hdev->dev,
996 "Failed late init after hard reset\n");
997 goto out_err;
998 }
999
Omer Shpigelman0feaf862019-02-16 00:39:22 +02001000 rc = hl_vm_init(hdev);
1001 if (rc) {
1002 dev_err(hdev->dev,
1003 "Failed to init memory module after hard reset\n");
1004 goto out_err;
1005 }
1006
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001007 hl_set_max_power(hdev, hdev->max_power);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001008 } else {
1009 rc = hdev->asic_funcs->soft_reset_late_init(hdev);
1010 if (rc) {
1011 dev_err(hdev->dev,
1012 "Failed late init after soft reset\n");
1013 goto out_err;
1014 }
1015 }
1016
1017 atomic_set(&hdev->in_reset, 0);
1018
1019 if (hard_reset)
1020 hdev->hard_reset_cnt++;
1021 else
1022 hdev->soft_reset_cnt++;
1023
Oded Gabbay867b58a2019-08-08 16:48:55 +03001024 dev_warn(hdev->dev, "Successfully finished resetting the device\n");
1025
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001026 return 0;
1027
1028out_err:
1029 hdev->disabled = true;
1030
1031 if (hard_reset) {
1032 dev_err(hdev->dev,
1033 "Failed to reset! Device is NOT usable\n");
1034 hdev->hard_reset_cnt++;
1035 } else {
1036 dev_err(hdev->dev,
1037 "Failed to do soft-reset, trying hard reset\n");
1038 hdev->soft_reset_cnt++;
1039 hard_reset = true;
1040 goto again;
1041 }
1042
1043 atomic_set(&hdev->in_reset, 0);
1044
1045 return rc;
1046}
1047
Oded Gabbayc4d66342019-02-16 00:39:11 +02001048/*
1049 * hl_device_init - main initialization function for habanalabs device
1050 *
1051 * @hdev: pointer to habanalabs device structure
1052 *
1053 * Allocate an id for the device, do early initialization and then call the
1054 * ASIC specific initialization functions. Finally, create the cdev and the
1055 * Linux device to expose it to the user
1056 */
1057int hl_device_init(struct hl_device *hdev, struct class *hclass)
1058{
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001059 int i, rc, cq_ready_cnt;
Oded Gabbayb968eb12019-07-30 09:10:02 +03001060 char *name;
Tomer Tayarea451f82019-08-08 12:25:52 +00001061 bool add_cdev_sysfs_on_err = false;
Oded Gabbayb968eb12019-07-30 09:10:02 +03001062
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001063 name = kasprintf(GFP_KERNEL, "hl%d", hdev->id / 2);
Tomer Tayarea451f82019-08-08 12:25:52 +00001064 if (!name) {
1065 rc = -ENOMEM;
1066 goto out_disabled;
1067 }
Oded Gabbayc4d66342019-02-16 00:39:11 +02001068
Tomer Tayarea451f82019-08-08 12:25:52 +00001069 /* Initialize cdev and device structures */
1070 rc = device_init_cdev(hdev, hclass, hdev->id, &hl_ops, name,
Oded Gabbayb968eb12019-07-30 09:10:02 +03001071 &hdev->cdev, &hdev->dev);
1072
1073 kfree(name);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001074
1075 if (rc)
1076 goto out_disabled;
1077
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001078 name = kasprintf(GFP_KERNEL, "hl_controlD%d", hdev->id / 2);
1079 if (!name) {
1080 rc = -ENOMEM;
Tomer Tayarea451f82019-08-08 12:25:52 +00001081 goto free_dev;
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001082 }
1083
Tomer Tayarea451f82019-08-08 12:25:52 +00001084 /* Initialize cdev and device structures for control device */
1085 rc = device_init_cdev(hdev, hclass, hdev->id_control, &hl_ctrl_ops,
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001086 name, &hdev->cdev_ctrl, &hdev->dev_ctrl);
1087
1088 kfree(name);
1089
1090 if (rc)
Tomer Tayarea451f82019-08-08 12:25:52 +00001091 goto free_dev;
Oded Gabbay4d6a7752019-07-30 09:10:50 +03001092
Oded Gabbayc4d66342019-02-16 00:39:11 +02001093 /* Initialize ASIC function pointers and perform early init */
1094 rc = device_early_init(hdev);
1095 if (rc)
Tomer Tayarea451f82019-08-08 12:25:52 +00001096 goto free_dev_ctrl;
Oded Gabbayc4d66342019-02-16 00:39:11 +02001097
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001098 /*
1099 * Start calling ASIC initialization. First S/W then H/W and finally
1100 * late init
1101 */
1102 rc = hdev->asic_funcs->sw_init(hdev);
1103 if (rc)
1104 goto early_fini;
1105
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001106 /*
1107 * Initialize the H/W queues. Must be done before hw_init, because
1108 * there the addresses of the kernel queue are being written to the
1109 * registers of the device
1110 */
1111 rc = hl_hw_queues_create(hdev);
1112 if (rc) {
1113 dev_err(hdev->dev, "failed to initialize kernel queues\n");
1114 goto sw_fini;
1115 }
1116
1117 /*
1118 * Initialize the completion queues. Must be done before hw_init,
1119 * because there the addresses of the completion queues are being
1120 * passed as arguments to request_irq
1121 */
1122 hdev->completion_queue =
1123 kcalloc(hdev->asic_prop.completion_queues_count,
1124 sizeof(*hdev->completion_queue), GFP_KERNEL);
1125
1126 if (!hdev->completion_queue) {
1127 dev_err(hdev->dev, "failed to allocate completion queues\n");
1128 rc = -ENOMEM;
1129 goto hw_queues_destroy;
1130 }
1131
1132 for (i = 0, cq_ready_cnt = 0;
1133 i < hdev->asic_prop.completion_queues_count;
1134 i++, cq_ready_cnt++) {
1135 rc = hl_cq_init(hdev, &hdev->completion_queue[i], i);
1136 if (rc) {
1137 dev_err(hdev->dev,
1138 "failed to initialize completion queue\n");
1139 goto cq_fini;
1140 }
1141 }
1142
Oded Gabbay1251f232019-02-16 00:39:18 +02001143 /*
1144 * Initialize the event queue. Must be done before hw_init,
1145 * because there the address of the event queue is being
1146 * passed as argument to request_irq
1147 */
1148 rc = hl_eq_init(hdev, &hdev->event_queue);
1149 if (rc) {
1150 dev_err(hdev->dev, "failed to initialize event queue\n");
1151 goto cq_fini;
1152 }
1153
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001154 /* MMU S/W must be initialized before kernel context is created */
1155 rc = hl_mmu_init(hdev);
1156 if (rc) {
1157 dev_err(hdev->dev, "Failed to initialize MMU S/W structures\n");
1158 goto eq_fini;
1159 }
1160
Oded Gabbay0861e412019-02-16 00:39:14 +02001161 /* Allocate the kernel context */
1162 hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx), GFP_KERNEL);
1163 if (!hdev->kernel_ctx) {
1164 rc = -ENOMEM;
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001165 goto mmu_fini;
Oded Gabbay0861e412019-02-16 00:39:14 +02001166 }
1167
Oded Gabbay86d53072019-07-30 11:49:36 +03001168 hdev->compute_ctx = NULL;
Oded Gabbay0861e412019-02-16 00:39:14 +02001169
1170 rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
1171 if (rc) {
1172 dev_err(hdev->dev, "failed to initialize kernel context\n");
Tomer Tayar508c5842019-08-01 13:57:36 +00001173 kfree(hdev->kernel_ctx);
1174 goto mmu_fini;
Oded Gabbay0861e412019-02-16 00:39:14 +02001175 }
1176
Oded Gabbaybe5d9262019-02-16 00:39:15 +02001177 rc = hl_cb_pool_init(hdev);
1178 if (rc) {
1179 dev_err(hdev->dev, "failed to initialize CB pool\n");
1180 goto release_ctx;
1181 }
1182
Oded Gabbayc2164772019-02-16 00:39:24 +02001183 hl_debugfs_add_device(hdev);
1184
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001185 if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) {
1186 dev_info(hdev->dev,
1187 "H/W state is dirty, must reset before initializing\n");
1188 hdev->asic_funcs->hw_fini(hdev, true);
1189 }
1190
Tomer Tayarea451f82019-08-08 12:25:52 +00001191 /*
1192 * From this point, in case of an error, add char devices and create
1193 * sysfs nodes as part of the error flow, to allow debugging.
1194 */
1195 add_cdev_sysfs_on_err = true;
1196
Oded Gabbay839c4802019-02-16 00:39:16 +02001197 rc = hdev->asic_funcs->hw_init(hdev);
1198 if (rc) {
1199 dev_err(hdev->dev, "failed to initialize the H/W\n");
1200 rc = 0;
1201 goto out_disabled;
1202 }
1203
1204 hdev->disabled = false;
1205
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001206 /* Check that the communication with the device is working */
1207 rc = hdev->asic_funcs->test_queues(hdev);
1208 if (rc) {
1209 dev_err(hdev->dev, "Failed to detect if device is alive\n");
1210 rc = 0;
1211 goto out_disabled;
1212 }
1213
Oded Gabbayd91389b2019-02-16 00:39:19 +02001214 rc = device_late_init(hdev);
1215 if (rc) {
1216 dev_err(hdev->dev, "Failed late initialization\n");
1217 rc = 0;
1218 goto out_disabled;
1219 }
1220
1221 dev_info(hdev->dev, "Found %s device with %lluGB DRAM\n",
1222 hdev->asic_name,
1223 hdev->asic_prop.dram_size / 1024 / 1024 / 1024);
1224
Omer Shpigelman0feaf862019-02-16 00:39:22 +02001225 rc = hl_vm_init(hdev);
1226 if (rc) {
1227 dev_err(hdev->dev, "Failed to initialize memory module\n");
1228 rc = 0;
1229 goto out_disabled;
1230 }
1231
Oded Gabbayd91389b2019-02-16 00:39:19 +02001232 /*
Tomer Tayarea451f82019-08-08 12:25:52 +00001233 * Expose devices and sysfs nodes to user.
1234 * From here there is no need to add char devices and create sysfs nodes
1235 * in case of an error.
1236 */
1237 add_cdev_sysfs_on_err = false;
1238 rc = device_cdev_sysfs_add(hdev);
1239 if (rc) {
1240 dev_err(hdev->dev,
1241 "Failed to add char devices and sysfs nodes\n");
1242 rc = 0;
1243 goto out_disabled;
1244 }
1245
1246 /*
1247 * hl_hwmon_init() must be called after device_late_init(), because only
Oded Gabbayd91389b2019-02-16 00:39:19 +02001248 * there we get the information from the device about which
Tomer Tayarea451f82019-08-08 12:25:52 +00001249 * hwmon-related sensors the device supports.
1250 * Furthermore, it must be done after adding the device to the system.
Oded Gabbayd91389b2019-02-16 00:39:19 +02001251 */
1252 rc = hl_hwmon_init(hdev);
1253 if (rc) {
1254 dev_err(hdev->dev, "Failed to initialize hwmon\n");
1255 rc = 0;
1256 goto out_disabled;
1257 }
1258
Oded Gabbayc4d66342019-02-16 00:39:11 +02001259 dev_notice(hdev->dev,
1260 "Successfully added device to habanalabs driver\n");
1261
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001262 hdev->init_done = true;
1263
Oded Gabbayc4d66342019-02-16 00:39:11 +02001264 return 0;
1265
Oded Gabbaybe5d9262019-02-16 00:39:15 +02001266release_ctx:
1267 if (hl_ctx_put(hdev->kernel_ctx) != 1)
1268 dev_err(hdev->dev,
1269 "kernel ctx is still alive on initialization failure\n");
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001270mmu_fini:
1271 hl_mmu_fini(hdev);
Oded Gabbay1251f232019-02-16 00:39:18 +02001272eq_fini:
1273 hl_eq_fini(hdev, &hdev->event_queue);
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001274cq_fini:
1275 for (i = 0 ; i < cq_ready_cnt ; i++)
1276 hl_cq_fini(hdev, &hdev->completion_queue[i]);
1277 kfree(hdev->completion_queue);
1278hw_queues_destroy:
1279 hl_hw_queues_destroy(hdev);
Oded Gabbay0861e412019-02-16 00:39:14 +02001280sw_fini:
1281 hdev->asic_funcs->sw_fini(hdev);
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001282early_fini:
1283 device_early_fini(hdev);
Tomer Tayarea451f82019-08-08 12:25:52 +00001284free_dev_ctrl:
1285 kfree(hdev->dev_ctrl);
1286free_dev:
1287 kfree(hdev->dev);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001288out_disabled:
1289 hdev->disabled = true;
Tomer Tayarea451f82019-08-08 12:25:52 +00001290 if (add_cdev_sysfs_on_err)
1291 device_cdev_sysfs_add(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001292 if (hdev->pdev)
1293 dev_err(&hdev->pdev->dev,
1294 "Failed to initialize hl%d. Device is NOT usable !\n",
Oded Gabbay307eae92019-09-01 16:13:25 +03001295 hdev->id / 2);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001296 else
1297 pr_err("Failed to initialize hl%d. Device is NOT usable !\n",
Oded Gabbay307eae92019-09-01 16:13:25 +03001298 hdev->id / 2);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001299
1300 return rc;
1301}
1302
1303/*
1304 * hl_device_fini - main tear-down function for habanalabs device
1305 *
1306 * @hdev: pointer to habanalabs device structure
1307 *
1308 * Destroy the device, call ASIC fini functions and release the id
1309 */
1310void hl_device_fini(struct hl_device *hdev)
1311{
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001312 int i, rc;
1313 ktime_t timeout;
1314
Oded Gabbayc4d66342019-02-16 00:39:11 +02001315 dev_info(hdev->dev, "Removing device\n");
1316
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001317 /*
1318 * This function is competing with the reset function, so try to
1319 * take the reset atomic and if we are already in middle of reset,
1320 * wait until reset function is finished. Reset function is designed
1321 * to always finish (could take up to a few seconds in worst case).
1322 */
1323
1324 timeout = ktime_add_us(ktime_get(),
1325 HL_PENDING_RESET_PER_SEC * 1000 * 1000 * 4);
1326 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
1327 while (rc) {
1328 usleep_range(50, 200);
1329 rc = atomic_cmpxchg(&hdev->in_reset, 0, 1);
1330 if (ktime_compare(ktime_get(), timeout) > 0) {
1331 WARN(1, "Failed to remove device because reset function did not finish\n");
1332 return;
1333 }
Oded Gabbaya1c92d12019-04-02 15:46:02 +03001334 }
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +02001335
Oded Gabbayc4d66342019-02-16 00:39:11 +02001336 /* Mark device as disabled */
1337 hdev->disabled = true;
1338
Oded Gabbayeb7caf82019-07-30 11:56:09 +03001339 /* Flush anyone that is inside the critical section of enqueue
Oded Gabbaycaa3c8e2019-04-06 13:23:54 +03001340 * jobs to the H/W
1341 */
1342 hdev->asic_funcs->hw_queues_lock(hdev);
1343 hdev->asic_funcs->hw_queues_unlock(hdev);
1344
Oded Gabbayeb7caf82019-07-30 11:56:09 +03001345 /* Flush anyone that is inside device open */
1346 mutex_lock(&hdev->fpriv_list_lock);
1347 mutex_unlock(&hdev->fpriv_list_lock);
1348
Oded Gabbay3f5398c2019-04-06 15:41:35 +03001349 hdev->hard_reset_pending = true;
1350
Oded Gabbayd91389b2019-02-16 00:39:19 +02001351 hl_hwmon_fini(hdev);
1352
1353 device_late_fini(hdev);
1354
Oded Gabbayc2164772019-02-16 00:39:24 +02001355 hl_debugfs_remove_device(hdev);
1356
Oded Gabbay1251f232019-02-16 00:39:18 +02001357 /*
1358 * Halt the engines and disable interrupts so we won't get any more
1359 * completions from H/W and we won't have any accesses from the
1360 * H/W to the host machine
1361 */
1362 hdev->asic_funcs->halt_engines(hdev, true);
1363
Oded Gabbayeff6f4a2019-02-16 00:39:21 +02001364 /* Go over all the queues, release all CS and their jobs */
1365 hl_cs_rollback_all(hdev);
1366
Oded Gabbay4aecb052019-07-22 17:37:22 +03001367 /* Kill processes here after CS rollback. This is because the process
1368 * can't really exit until all its CSs are done, which is what we
1369 * do in cs rollback
1370 */
1371 device_kill_open_processes(hdev);
1372
Oded Gabbaybe5d9262019-02-16 00:39:15 +02001373 hl_cb_pool_fini(hdev);
1374
Oded Gabbay0861e412019-02-16 00:39:14 +02001375 /* Release kernel context */
1376 if ((hdev->kernel_ctx) && (hl_ctx_put(hdev->kernel_ctx) != 1))
1377 dev_err(hdev->dev, "kernel ctx is still alive\n");
1378
Oded Gabbay839c4802019-02-16 00:39:16 +02001379 /* Reset the H/W. It will be in idle state after this returns */
1380 hdev->asic_funcs->hw_fini(hdev, true);
1381
Omer Shpigelman0feaf862019-02-16 00:39:22 +02001382 hl_vm_fini(hdev);
1383
Oded Gabbay37d68ce2019-05-29 14:43:04 +03001384 hl_mmu_fini(hdev);
1385
Oded Gabbay1251f232019-02-16 00:39:18 +02001386 hl_eq_fini(hdev, &hdev->event_queue);
1387
Oded Gabbay9494a8d2019-02-16 00:39:17 +02001388 for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
1389 hl_cq_fini(hdev, &hdev->completion_queue[i]);
1390 kfree(hdev->completion_queue);
1391
1392 hl_hw_queues_destroy(hdev);
1393
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001394 /* Call ASIC S/W finalize function */
1395 hdev->asic_funcs->sw_fini(hdev);
1396
Oded Gabbayc4d66342019-02-16 00:39:11 +02001397 device_early_fini(hdev);
1398
Tomer Tayarea451f82019-08-08 12:25:52 +00001399 /* Hide devices and sysfs nodes from user */
1400 device_cdev_sysfs_del(hdev);
Oded Gabbayc4d66342019-02-16 00:39:11 +02001401
1402 pr_info("removed device successfully\n");
1403}
1404
1405/*
Oded Gabbay99b9d7b2019-02-16 00:39:13 +02001406 * MMIO register access helper functions.
1407 */
1408
1409/*
1410 * hl_rreg - Read an MMIO register
1411 *
1412 * @hdev: pointer to habanalabs device structure
1413 * @reg: MMIO register offset (in bytes)
1414 *
1415 * Returns the value of the MMIO register we are asked to read
1416 *
1417 */
1418inline u32 hl_rreg(struct hl_device *hdev, u32 reg)
1419{
1420 return readl(hdev->rmmio + reg);
1421}
1422
1423/*
1424 * hl_wreg - Write to an MMIO register
1425 *
1426 * @hdev: pointer to habanalabs device structure
1427 * @reg: MMIO register offset (in bytes)
1428 * @val: 32-bit value
1429 *
1430 * Writes the 32-bit value into the MMIO register
1431 *
1432 */
1433inline void hl_wreg(struct hl_device *hdev, u32 reg, u32 val)
1434{
1435 writel(val, hdev->rmmio + reg);
1436}