summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c247
1 files changed, 190 insertions, 57 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
index 56d676396342..5d269ea94957 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
@@ -36,42 +36,50 @@
static DEFINE_MUTEX(kfd_dbgmgr_mutex);
-struct mutex *kfd_get_dbgmgr_mutex(void)
+struct mutex *
+get_dbgmgr_mutex(void)
{
return &kfd_dbgmgr_mutex;
}
+/*===========================================================================*/
-static void kfd_dbgmgr_uninitialize(struct kfd_dbgmgr *pmgr)
+static void
+kfd_dbgmgr_uninitialize(struct kfd_dbgmgr *pmgr)
{
- BUG_ON(!pmgr);
-
kfree(pmgr->dbgdev);
-
pmgr->dbgdev = NULL;
pmgr->pasid = 0;
pmgr->dev = NULL;
}
-void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr)
+/*===========================================================================*/
+
+void
+kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr)
{
if (pmgr != NULL) {
kfd_dbgmgr_uninitialize(pmgr);
kfree(pmgr);
+ pmgr = NULL;
}
}
-bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev)
+/*===========================================================================*/
+
+bool
+kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev)
{
- enum DBGDEV_TYPE type = DBGDEV_TYPE_DIQ;
+ DBGDEV_TYPE type = DBGDEV_TYPE_DIQ;
struct kfd_dbgmgr *new_buff;
BUG_ON(pdev == NULL);
BUG_ON(!pdev->init_complete);
new_buff = kfd_alloc_struct(new_buff);
- if (!new_buff) {
- pr_err("amdkfd: Failed to allocate dbgmgr instance\n");
+ if (!new_buff)
+ {
+ dev_err(NULL, "Error! kfd: In func %s >> failed to allocate dbgmgr instance\n", __func__);
return false;
}
@@ -79,7 +87,7 @@ bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev)
new_buff->dev = pdev;
new_buff->dbgdev = kfd_alloc_struct(new_buff->dbgdev);
if (!new_buff->dbgdev) {
- pr_err("amdkfd: Failed to allocate dbgdev instance\n");
+ dev_err(NULL, "Error! kfd: In func %s >> failed to allocate dbgdev\n", __func__);
kfree(new_buff);
return false;
}
@@ -94,75 +102,200 @@ bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev)
return true;
}
-long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
+/*===========================================================================*/
+
+long
+kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
{
- BUG_ON(!p || !pmgr || !pmgr->dbgdev);
+ long status = 0;
- if (pmgr->pasid != 0) {
- pr_debug("H/W debugger is already active using pasid %d\n",
- pmgr->pasid);
- return -EBUSY;
- }
+ do {
+
+ if ((pmgr == NULL) || (pmgr->dev == NULL) || (pmgr->dbgdev == NULL)) {
+ dev_info(NULL, "Error! kfd: In func %s >> Illegal pointers\n", __func__);
+ /* Invalid Pointer. */
+ status = -EINVAL;
+ break;
+ }
+ if (pmgr->pasid != 0) {
+ /* HW debugger is already active. */
+ status = -EBUSY;
+ break;
+ }
+
+ /* remember pasid */
+
+ pmgr->pasid = p->pasid;
+
+ /* provide the pqm for diq generation */
- /* remember pasid */
- pmgr->pasid = p->pasid;
+ pmgr->dbgdev->pqm = &p->pqm;
- /* provide the pqm for diq generation */
- pmgr->dbgdev->pqm = &p->pqm;
+ /* activate the actual registering */
+ /* todo: you should lock with the process mutex here */
+ pmgr->dbgdev->dbgdev_register(pmgr->dbgdev);
+ /* todo: you should unlock with the process mutex here */
- /* activate the actual registering */
- pmgr->dbgdev->dbgdev_register(pmgr->dbgdev);
+ } while (false);
- return 0;
+ return status;
}
-long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
+/* ========================================================================== */
+
+long
+kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
{
- BUG_ON(!p || !pmgr || !pmgr->dbgdev);
- /* Is the requests coming from the already registered process? */
- if (pmgr->pasid != p->pasid) {
- pr_debug("H/W debugger is not registered by calling pasid %d\n",
- p->pasid);
- return -EINVAL;
- }
+ long status = 0;
- pmgr->dbgdev->dbgdev_unregister(pmgr->dbgdev);
+ do {
- pmgr->pasid = 0;
+ if ((pmgr == NULL) || (pmgr->dev == NULL)
+ || (pmgr->dbgdev == NULL) || (p == NULL)) {
+ dev_info(NULL, "Error! kfd: In func %s >> Illegal pointers\n", __func__);
+ /* Invalid Pointer */
+ status = -EINVAL;
+ break;
+ }
+ if (pmgr->pasid != p->pasid) {
+ /* Is the requests coming from the already registered process? */
+ status = -EINVAL;
+ break;
+ }
+
+ /* todo: you should lock with the process mutex here */
+
+ pmgr->dbgdev->dbgdev_unregister(pmgr->dbgdev);
- return 0;
+ /* todo: you should unlock with the process mutex here */
+
+ pmgr->pasid = 0;
+
+ } while (false);
+
+ return status;
}
-long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr,
- struct dbg_wave_control_info *wac_info)
+/* =========================================================================== */
+
+long
+kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr, struct dbg_wave_control_info *wac_info)
{
- BUG_ON(!pmgr || !pmgr->dbgdev || !wac_info);
+ long status = 0;
- /* Is the requests coming from the already registered process? */
- if (pmgr->pasid != wac_info->process->pasid) {
- pr_debug("H/W debugger support was not registered for requester pasid %d\n",
- wac_info->process->pasid);
- return -EINVAL;
- }
+ dev_info(NULL, "kfd: In func %s\n", __func__);
+
+ do {
+
+ if ((pmgr == NULL) || (pmgr->dev == NULL) || (pmgr->dbgdev == NULL) || (wac_info == NULL)
+ || (wac_info->process == NULL)) {
+ /* Invalid Pointer */
+ dev_info(NULL, "Error! kfd: In func %s >> Illegal pointers\n", __func__);
+ status = -EINVAL;
+ break;
+ }
+ /* Is the requests coming from the already registered process? */
+ if (pmgr->pasid != wac_info->process->pasid) {
+ /* HW debugger support was not registered for requester process */
+ status = -EINVAL;
+ break;
+ }
+
+ status = (long) pmgr->dbgdev->dbgdev_wave_control(pmgr->dbgdev, wac_info);
+
+ } while (false);
+
+ return status;
- return (long) pmgr->dbgdev->dbgdev_wave_control(pmgr->dbgdev, wac_info);
}
-long kfd_dbgmgr_address_watch(struct kfd_dbgmgr *pmgr,
- struct dbg_address_watch_info *adw_info)
+/* =========================================================================== */
+
+long
+kfd_dbgmgr_address_watch(struct kfd_dbgmgr *pmgr, struct dbg_address_watch_info *adw_info)
{
- BUG_ON(!pmgr || !pmgr->dbgdev || !adw_info);
+ long status = 0;
+ dev_info(NULL, "kfd: In func %s\n", __func__);
- /* Is the requests coming from the already registered process? */
- if (pmgr->pasid != adw_info->process->pasid) {
- pr_debug("H/W debugger support was not registered for requester pasid %d\n",
- adw_info->process->pasid);
- return -EINVAL;
- }
+ do {
+
+ if ((pmgr == NULL) || (pmgr->dev == NULL) || (pmgr->dbgdev == NULL) || (adw_info == NULL)
+ || (adw_info->process == NULL)) {
+ /* Invalid Pointer */
+ dev_info(NULL, "Error! kfd: In func %s >> Illegal pointers\n", __func__);
+ status = -EINVAL;
+ break;
+ }
+ /* Is the requests coming from the already registered process? */
+ if (pmgr->pasid != adw_info->process->pasid) {
+ /* HW debugger support was not registered for requester process */
+ status = -EINVAL;
+ break;
+ }
+
+ status = (long) pmgr->dbgdev->dbgdev_address_watch(pmgr->dbgdev, adw_info);
+
+ } while (false);
+
+ return status;
- return (long) pmgr->dbgdev->dbgdev_address_watch(pmgr->dbgdev,
- adw_info);
}
+
+/* =========================================================================== */
+/*
+ * Handle abnormal process termination
+ * if we are in the midst of a debug session, we should kill all pending waves
+ * of the debugged process and unregister the process from the Debugger.
+ */
+long
+kfd_dbgmgr_abnormal_termination(struct kfd_dbgmgr *pmgr, struct kfd_process *process)
+{
+ long status = 0;
+ struct dbg_wave_control_info wac_info;
+
+ dev_info(NULL, "kfd: In func %s\n", __func__);
+
+ do {
+
+ if ((pmgr == NULL) || (pmgr->dev == NULL) || (pmgr->dbgdev == NULL)) {
+ /* Invalid Pointer */
+ dev_info(NULL, "Error! kfd: In func %s >> Illegal pointers\n", __func__);
+ status = -EINVAL;
+ break;
+ }
+ /* first, we kill all the wavefronts of this process */
+
+ wac_info.process = process;
+ wac_info.mode = HSA_DBG_WAVEMODE_BROADCAST_PROCESS;
+ wac_info.operand = HSA_DBG_WAVEOP_KILL;
+ wac_info.trapId = 0x0; /* not used for the KILL */
+ wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value = 0; /* not used for kill */
+ wac_info.dbgWave_msg.MemoryVA = NULL; /* not used for kill */
+
+ status = (long) pmgr->dbgdev->dbgdev_wave_control(pmgr->dbgdev, &wac_info);
+
+ if (status != 0) {
+ dev_info(NULL, "Error! kfd: In func %s: wave control failed, status is: %ld\n", __func__, status);
+ break;
+ }
+ if (pmgr->pasid == wac_info.process->pasid) {
+ /* if terminated process was registered for debug, then unregister it */
+ status = kfd_dbgmgr_unregister(pmgr, process);
+ pmgr->pasid = 0;
+ }
+ if (status != 0)
+ dev_info(NULL,
+ "Error! kfd: In func %s: unregister failed, status is: %ld debugger can not be reused\n",
+ __func__, status);
+
+ } while (false);
+
+ return status;
+
+}
+
+
+/*///////////////////////////////////////////////////////////////////////////////////////// */