From 0861e41de53044694bfdf2e8f246a0d8fb077e5d Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Sat, 16 Feb 2019 00:39:14 +0200 Subject: habanalabs: add context and ASID modules This patch adds two modules - ASID and context. Each user process that opens a device's file must have at least one context before it is able to "work" with the device. Each context has its own device address-space and contains information about its runtime state (its active command submissions). To have address-space separation between contexts, each context is assigned a unique ASID, which stands for "address-space id". Goya supports up to 1024 ASIDs. Currently, the driver doesn't support multiple contexts. Therefore, the user doesn't need to actively create a context. A "primary context" is created automatically when the user opens the device's file. Reviewed-by: Mike Rapoport Signed-off-by: Oded Gabbay Signed-off-by: Greg Kroah-Hartman --- drivers/misc/habanalabs/device.c | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/misc/habanalabs/device.c') diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c index a4feaa784db3..2423588ecf22 100644 --- a/drivers/misc/habanalabs/device.c +++ b/drivers/misc/habanalabs/device.c @@ -22,6 +22,12 @@ static void hpriv_release(struct kref *ref) put_pid(hpriv->taskpid); kfree(hpriv); + + /* Now the FD is really closed */ + atomic_dec(&hdev->fd_open_cnt); + + /* This allows a new user context to open the device */ + hdev->user_ctx = NULL; } void hl_hpriv_get(struct hl_fpriv *hpriv) @@ -46,6 +52,8 @@ static int hl_device_release(struct inode *inode, struct file *filp) { struct hl_fpriv *hpriv = filp->private_data; + hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr); + filp->private_data = NULL; hl_hpriv_put(hpriv); @@ -137,7 +145,20 @@ static int device_early_init(struct hl_device *hdev) if (rc) return rc; + rc = hl_asid_init(hdev); + if (rc) + goto early_fini; + + mutex_init(&hdev->fd_open_cnt_lock); + atomic_set(&hdev->fd_open_cnt, 0); + return 0; + +early_fini: + if (hdev->asic_funcs->early_fini) + hdev->asic_funcs->early_fini(hdev); + + return rc; } /* @@ -149,9 +170,12 @@ static int device_early_init(struct hl_device *hdev) static void device_early_fini(struct hl_device *hdev) { + hl_asid_fini(hdev); + if (hdev->asic_funcs->early_fini) hdev->asic_funcs->early_fini(hdev); + mutex_destroy(&hdev->fd_open_cnt_lock); } /* @@ -245,11 +269,30 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) if (rc) goto early_fini; + /* Allocate the kernel context */ + hdev->kernel_ctx = kzalloc(sizeof(*hdev->kernel_ctx), GFP_KERNEL); + if (!hdev->kernel_ctx) { + rc = -ENOMEM; + goto sw_fini; + } + + hdev->user_ctx = NULL; + + rc = hl_ctx_init(hdev, hdev->kernel_ctx, true); + if (rc) { + dev_err(hdev->dev, "failed to initialize kernel context\n"); + goto free_ctx; + } + dev_notice(hdev->dev, "Successfully added device to habanalabs driver\n"); return 0; +free_ctx: + kfree(hdev->kernel_ctx); +sw_fini: + hdev->asic_funcs->sw_fini(hdev); early_fini: device_early_fini(hdev); release_device: @@ -282,6 +325,10 @@ void hl_device_fini(struct hl_device *hdev) /* Mark device as disabled */ hdev->disabled = true; + /* Release kernel context */ + if ((hdev->kernel_ctx) && (hl_ctx_put(hdev->kernel_ctx) != 1)) + dev_err(hdev->dev, "kernel ctx is still alive\n"); + /* Call ASIC S/W finalize function */ hdev->asic_funcs->sw_fini(hdev); -- cgit v1.2.3