aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/habanalabs/device.c
diff options
context:
space:
mode:
authorOded Gabbay <oded.gabbay@gmail.com>2019-07-30 09:10:50 +0300
committerOded Gabbay <oded.gabbay@gmail.com>2019-09-05 14:55:26 +0300
commit4d6a7751f6c376f8d20f46685fe87bc47557e233 (patch)
treea24ace3555d51bb073f493611669035035760888 /drivers/misc/habanalabs/device.c
parentb968eb1a84e09f30eab9b88d30758187087b3492 (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.c53
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);