aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/misc/habanalabs
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/habanalabs')
-rw-r--r--drivers/misc/habanalabs/common/debugfs.c5
-rw-r--r--drivers/misc/habanalabs/common/device.c40
-rw-r--r--drivers/misc/habanalabs/common/habanalabs.h2
-rw-r--r--drivers/misc/habanalabs/common/habanalabs_ioctl.c12
-rw-r--r--drivers/misc/habanalabs/common/irq.c2
-rw-r--r--drivers/misc/habanalabs/common/mmu/mmu.c38
6 files changed, 75 insertions, 24 deletions
diff --git a/drivers/misc/habanalabs/common/debugfs.c b/drivers/misc/habanalabs/common/debugfs.c
index df847a6d19f4..9f19bee7b592 100644
--- a/drivers/misc/habanalabs/common/debugfs.c
+++ b/drivers/misc/habanalabs/common/debugfs.c
@@ -992,7 +992,6 @@ void hl_debugfs_add_device(struct hl_device *hdev)
struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
int count = ARRAY_SIZE(hl_debugfs_list);
struct hl_debugfs_entry *entry;
- struct dentry *ent;
int i;
dev_entry->hdev = hdev;
@@ -1105,13 +1104,11 @@ void hl_debugfs_add_device(struct hl_device *hdev)
&hl_security_violations_fops);
for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
-
- ent = debugfs_create_file(hl_debugfs_list[i].name,
+ debugfs_create_file(hl_debugfs_list[i].name,
0444,
dev_entry->root,
entry,
&hl_debugfs_fops);
- entry->dent = ent;
entry->info_ent = &hl_debugfs_list[i];
entry->dev_entry = dev_entry;
}
diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c
index 15fcb5c31c4b..334009e83823 100644
--- a/drivers/misc/habanalabs/common/device.c
+++ b/drivers/misc/habanalabs/common/device.c
@@ -93,12 +93,19 @@ void hl_hpriv_put(struct hl_fpriv *hpriv)
static int hl_device_release(struct inode *inode, struct file *filp)
{
struct hl_fpriv *hpriv = filp->private_data;
+ struct hl_device *hdev = hpriv->hdev;
+
+ filp->private_data = NULL;
+
+ if (!hdev) {
+ pr_crit("Closing FD after device was removed. Memory leak will occur and it is advised to reboot.\n");
+ put_pid(hpriv->taskpid);
+ return 0;
+ }
hl_cb_mgr_fini(hpriv->hdev, &hpriv->cb_mgr);
hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
- filp->private_data = NULL;
-
hl_hpriv_put(hpriv);
return 0;
@@ -107,15 +114,20 @@ static int hl_device_release(struct inode *inode, struct file *filp)
static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
{
struct hl_fpriv *hpriv = filp->private_data;
- struct hl_device *hdev;
+ struct hl_device *hdev = hpriv->hdev;
filp->private_data = NULL;
- hdev = hpriv->hdev;
+ if (!hdev) {
+ pr_err("Closing FD after device was removed\n");
+ goto out;
+ }
mutex_lock(&hdev->fpriv_list_lock);
list_del(&hpriv->dev_node);
mutex_unlock(&hdev->fpriv_list_lock);
+out:
+ put_pid(hpriv->taskpid);
kfree(hpriv);
@@ -134,8 +146,14 @@ static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct hl_fpriv *hpriv = filp->private_data;
+ struct hl_device *hdev = hpriv->hdev;
unsigned long vm_pgoff;
+ if (!hdev) {
+ pr_err_ratelimited("Trying to mmap after device was removed! Please close FD\n");
+ return -ENODEV;
+ }
+
vm_pgoff = vma->vm_pgoff;
vma->vm_pgoff = HL_MMAP_OFFSET_VALUE_GET(vm_pgoff);
@@ -883,6 +901,16 @@ wait_for_processes:
return -EBUSY;
}
+static void device_disable_open_processes(struct hl_device *hdev)
+{
+ struct hl_fpriv *hpriv;
+
+ mutex_lock(&hdev->fpriv_list_lock);
+ list_for_each_entry(hpriv, &hdev->fpriv_list, dev_node)
+ hpriv->hdev = NULL;
+ mutex_unlock(&hdev->fpriv_list_lock);
+}
+
/*
* hl_device_reset - reset the device
*
@@ -1556,8 +1584,10 @@ void hl_device_fini(struct hl_device *hdev)
HL_PENDING_RESET_LONG_SEC);
rc = device_kill_open_processes(hdev, HL_PENDING_RESET_LONG_SEC);
- if (rc)
+ if (rc) {
dev_crit(hdev->dev, "Failed to kill all open processes\n");
+ device_disable_open_processes(hdev);
+ }
hl_cb_pool_fini(hdev);
diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h
index d933878b24d1..4b321e4f8059 100644
--- a/drivers/misc/habanalabs/common/habanalabs.h
+++ b/drivers/misc/habanalabs/common/habanalabs.h
@@ -1465,12 +1465,10 @@ struct hl_info_list {
/**
* struct hl_debugfs_entry - debugfs dentry wrapper.
- * @dent: base debugfs entry structure.
* @info_ent: dentry realted ops.
* @dev_entry: ASIC specific debugfs manager.
*/
struct hl_debugfs_entry {
- struct dentry *dent;
const struct hl_info_list *info_ent;
struct hl_dbg_device_entry *dev_entry;
};
diff --git a/drivers/misc/habanalabs/common/habanalabs_ioctl.c b/drivers/misc/habanalabs/common/habanalabs_ioctl.c
index 03af61cecd37..083a30969c5f 100644
--- a/drivers/misc/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/misc/habanalabs/common/habanalabs_ioctl.c
@@ -5,6 +5,8 @@
* All Rights Reserved.
*/
+#define pr_fmt(fmt) "habanalabs: " fmt
+
#include <uapi/misc/habanalabs.h>
#include "habanalabs.h"
@@ -682,6 +684,11 @@ long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
const struct hl_ioctl_desc *ioctl = NULL;
unsigned int nr = _IOC_NR(cmd);
+ if (!hdev) {
+ pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n");
+ return -ENODEV;
+ }
+
if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) {
ioctl = &hl_ioctls[nr];
} else {
@@ -700,6 +707,11 @@ long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg)
const struct hl_ioctl_desc *ioctl = NULL;
unsigned int nr = _IOC_NR(cmd);
+ if (!hdev) {
+ pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n");
+ return -ENODEV;
+ }
+
if (nr == _IOC_NR(HL_IOCTL_INFO)) {
ioctl = &hl_ioctls_control[nr];
} else {
diff --git a/drivers/misc/habanalabs/common/irq.c b/drivers/misc/habanalabs/common/irq.c
index de53fb5f978a..44a0522b59b9 100644
--- a/drivers/misc/habanalabs/common/irq.c
+++ b/drivers/misc/habanalabs/common/irq.c
@@ -47,7 +47,7 @@ inline u32 hl_cq_inc_ptr(u32 ptr)
* Increment ptr by 1. If it reaches the number of event queue
* entries, set it to 0
*/
-inline u32 hl_eq_inc_ptr(u32 ptr)
+static inline u32 hl_eq_inc_ptr(u32 ptr)
{
ptr++;
if (unlikely(ptr == HL_EQ_LENGTH))
diff --git a/drivers/misc/habanalabs/common/mmu/mmu.c b/drivers/misc/habanalabs/common/mmu/mmu.c
index 71703a32350f..93c9e5f587e1 100644
--- a/drivers/misc/habanalabs/common/mmu/mmu.c
+++ b/drivers/misc/habanalabs/common/mmu/mmu.c
@@ -499,18 +499,32 @@ static void hl_mmu_pa_page_with_offset(struct hl_ctx *ctx, u64 virt_addr,
else /* HL_VA_RANGE_TYPE_DRAM */
p = &prop->dmmu;
- /*
- * find the correct hop shift field in hl_mmu_properties structure
- * in order to determine the right maks for the page offset.
- */
- hop0_shift_off = offsetof(struct hl_mmu_properties, hop0_shift);
- p = (char *)p + hop0_shift_off;
- p = (char *)p + ((hops->used_hops - 1) * sizeof(u64));
- hop_shift = *(u64 *)p;
- offset_mask = (1ull << hop_shift) - 1;
- addr_mask = ~(offset_mask);
- *phys_addr = (tmp_phys_addr & addr_mask) |
- (virt_addr & offset_mask);
+ if ((hops->range_type == HL_VA_RANGE_TYPE_DRAM) &&
+ !is_power_of_2(prop->dram_page_size)) {
+ u32 bit;
+ u64 page_offset_mask;
+ u64 phys_addr_mask;
+
+ bit = __ffs64((u64)prop->dram_page_size);
+ page_offset_mask = ((1ull << bit) - 1);
+ phys_addr_mask = ~page_offset_mask;
+ *phys_addr = (tmp_phys_addr & phys_addr_mask) |
+ (virt_addr & page_offset_mask);
+ } else {
+ /*
+ * find the correct hop shift field in hl_mmu_properties
+ * structure in order to determine the right masks
+ * for the page offset.
+ */
+ hop0_shift_off = offsetof(struct hl_mmu_properties, hop0_shift);
+ p = (char *)p + hop0_shift_off;
+ p = (char *)p + ((hops->used_hops - 1) * sizeof(u64));
+ hop_shift = *(u64 *)p;
+ offset_mask = (1ull << hop_shift) - 1;
+ addr_mask = ~(offset_mask);
+ *phys_addr = (tmp_phys_addr & addr_mask) |
+ (virt_addr & offset_mask);
+ }
}
int hl_mmu_va_to_pa(struct hl_ctx *ctx, u64 virt_addr, u64 *phys_addr)