diff options
author | Oded Gabbay <oded.gabbay@gmail.com> | 2019-07-30 09:10:50 +0300 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2019-09-05 14:55:26 +0300 |
commit | 4d6a7751f6c376f8d20f46685fe87bc47557e233 (patch) | |
tree | a24ace3555d51bb073f493611669035035760888 /drivers/misc/habanalabs/device.c | |
parent | b968eb1a84e09f30eab9b88d30758187087b3492 (diff) |
habanalabs: create two char devices per ASIC
This patch changes the driver to create two char devices for each ASIC
it discovers. This is done to allow system/monitoring applications to
query the device for stats, information, idle state and more, while also
allowing the deep-learning application to send work to the ASIC.
One char device is the original device, hlX. IOCTL calls through this
device file can perform any task on the device (compute, memory, queries).
The open function for this device will fail if it was called before but
the file-descriptor it created was not completely released yet (the
release callback function is not called from the kernel until all
instances of that FD are closed). The driver needs to keep this behavior
to support backward compatibility with existing userspace, which count
that the open will fail if the device is "occupied".
The second char device is called "hl_controlDx", where x is the same index
of the main device with a minor number of the original char device + 1.
Applications that open this device can only call the INFO IOCTL. There is
no limitation on the number of applications opening this device.
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/habanalabs/device.c')
-rw-r--r-- | drivers/misc/habanalabs/device.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c index 204930607720..b90ba3b789eb 100644 --- a/drivers/misc/habanalabs/device.c +++ b/drivers/misc/habanalabs/device.c @@ -95,6 +95,24 @@ static int hl_device_release(struct inode *inode, struct file *filp) return 0; } +static int hl_device_release_ctrl(struct inode *inode, struct file *filp) +{ + struct hl_fpriv *hpriv = filp->private_data; + struct hl_device *hdev; + + filp->private_data = NULL; + + hdev = hpriv->hdev; + + mutex_lock(&hdev->fpriv_list_lock); + list_del(&hpriv->dev_node); + mutex_unlock(&hdev->fpriv_list_lock); + + kfree(hpriv); + + return 0; +} + /* * hl_mmap - mmap function for habanalabs device * @@ -125,6 +143,14 @@ static const struct file_operations hl_ops = { .compat_ioctl = hl_ioctl }; +static const struct file_operations hl_ctrl_ops = { + .owner = THIS_MODULE, + .open = hl_device_open_ctrl, + .release = hl_device_release_ctrl, + .unlocked_ioctl = hl_ioctl_control, + .compat_ioctl = hl_ioctl_control +}; + /* * device_setup_cdev - setup cdev and device for habanalabs device * @@ -567,7 +593,8 @@ static void device_kill_open_processes(struct hl_device *hdev) list_for_each_entry(hpriv, &hdev->fpriv_list, dev_node) { task = get_pid_task(hpriv->taskpid, PIDTYPE_PID); if (task) { - dev_info(hdev->dev, "Killing user process\n"); + dev_info(hdev->dev, "Killing user process pid=%d\n", + task_pid_nr(task)); send_sig(SIGKILL, task, 1); usleep_range(1000, 10000); @@ -872,7 +899,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) int i, rc, cq_ready_cnt; char *name; - name = kasprintf(GFP_KERNEL, "hl%d", hdev->id); + name = kasprintf(GFP_KERNEL, "hl%d", hdev->id / 2); if (!name) return -ENOMEM; @@ -885,10 +912,25 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) if (rc) goto out_disabled; + name = kasprintf(GFP_KERNEL, "hl_controlD%d", hdev->id / 2); + if (!name) { + rc = -ENOMEM; + goto release_device; + } + + /* Create control device */ + rc = device_setup_cdev(hdev, hclass, hdev->id_control, &hl_ctrl_ops, + name, &hdev->cdev_ctrl, &hdev->dev_ctrl); + + kfree(name); + + if (rc) + goto release_device; + /* Initialize ASIC function pointers and perform early init */ rc = device_early_init(hdev); if (rc) - goto release_device; + goto release_control_device; /* * Start calling ASIC initialization. First S/W then H/W and finally @@ -1063,6 +1105,9 @@ sw_fini: hdev->asic_funcs->sw_fini(hdev); early_fini: device_early_fini(hdev); +release_control_device: + device_destroy(hclass, hdev->dev_ctrl->devt); + cdev_del(&hdev->cdev_ctrl); release_device: device_destroy(hclass, hdev->dev->devt); cdev_del(&hdev->cdev); @@ -1178,6 +1223,8 @@ void hl_device_fini(struct hl_device *hdev) device_early_fini(hdev); /* Hide device from user */ + device_destroy(hdev->dev_ctrl->class, hdev->dev_ctrl->devt); + cdev_del(&hdev->cdev_ctrl); device_destroy(hdev->dev->class, hdev->dev->devt); cdev_del(&hdev->cdev); |