diff options
author | Michael J. Ruhl <michael.j.ruhl@intel.com> | 2017-05-04 05:15:21 -0700 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2017-05-04 19:31:46 -0400 |
commit | 62239fc6e5545b2e59f83dfbc5db231a81f37a45 (patch) | |
tree | e09329080790c0f624f0b3f7f95facabf7acf369 /drivers/infiniband/hw/hfi1/file_ops.c | |
parent | 8737ce95c463c6d8c4307ab3d6858cbf71cd4fc8 (diff) |
IB/hfi1: Clean up on context initialization failure
The error path for context initialization is not consistent. Cleanup all
resources on failure.
Removed unused variable user_event_mask.
Add the _BASE_FAILED bit to the event flags so that a base context can
notify waiting sub contexts that they cannot continue.
Running out of sub contexts is an EBUSY result, not EINVAL.
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/hw/hfi1/file_ops.c')
-rw-r--r-- | drivers/infiniband/hw/hfi1/file_ops.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index 9c177ef79db5..3158128d57e8 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -82,7 +82,7 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo); static int init_subctxts(struct hfi1_ctxtdata *uctxt, const struct hfi1_user_info *uinfo); static int init_user_ctxt(struct hfi1_filedata *fd); -static int user_init(struct hfi1_ctxtdata *uctxt); +static void user_init(struct hfi1_ctxtdata *uctxt); static int get_ctxt_info(struct hfi1_filedata *fd, void __user *ubase, __u32 len); static int get_base_info(struct hfi1_filedata *fd, void __user *ubase, @@ -847,7 +847,7 @@ static u64 kvirt_to_phys(void *addr) static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo) { - int ret = 0; + int ret; unsigned int swmajor, swminor; swmajor = uinfo->userversion >> 16; @@ -857,14 +857,16 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo) swminor = uinfo->userversion & 0xffff; mutex_lock(&hfi1_mutex); - /* First, lets check if we need to get a sub context? */ + /* + * Get a sub context if necessary. + * ret < 0 error, 0 no context, 1 sub-context found + */ + ret = 0; if (uinfo->subctxt_cnt) { - /* < 0 error, 0 no context, 1 sub-context found */ ret = find_sub_ctxt(fd, uinfo); - if (ret > 0) { + if (ret > 0) fd->rec_cpu_num = hfi1_get_proc_affinity(fd->uctxt->numa_id); - } } /* @@ -885,17 +887,27 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo) ret = wait_event_interruptible(fd->uctxt->wait, !test_bit( HFI1_CTXT_BASE_UNINIT, &fd->uctxt->event_flags)); + if (test_bit(HFI1_CTXT_BASE_FAILED, &fd->uctxt->event_flags)) { + clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts); + return -ENOMEM; + } /* The only thing a sub context needs is the user_xxx stuff */ if (!ret) - init_user_ctxt(fd); + ret = init_user_ctxt(fd); + + if (ret) + clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts); } else if (!ret) { ret = setup_base_ctxt(fd); - - /* - * Base context is done, notify anybody using a sub-context - * that is waiting for this completion - */ - if (!ret && fd->uctxt->subctxt_cnt) { + if (fd->uctxt->subctxt_cnt) { + /* If there is an error, set the failed bit. */ + if (ret) + set_bit(HFI1_CTXT_BASE_FAILED, + &fd->uctxt->event_flags); + /* + * Base context is done, notify anybody using a + * sub-context that is waiting for this completion + */ clear_bit(HFI1_CTXT_BASE_UNINIT, &fd->uctxt->event_flags); wake_up(&fd->uctxt->wait); @@ -945,7 +957,7 @@ static int find_sub_ctxt(struct hfi1_filedata *fd, subctxt = find_first_zero_bit(uctxt->in_use_ctxts, HFI1_MAX_SHARED_CTXTS); if (subctxt >= uctxt->subctxt_cnt) - return -EINVAL; + return -EBUSY; fd->uctxt = uctxt; fd->subctxt = subctxt; @@ -1118,7 +1130,7 @@ bail_ureg: return ret; } -static int user_init(struct hfi1_ctxtdata *uctxt) +static void user_init(struct hfi1_ctxtdata *uctxt) { unsigned int rcvctrl_ops = 0; @@ -1168,8 +1180,6 @@ static int user_init(struct hfi1_ctxtdata *uctxt) else rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_DIS; hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt->ctxt); - - return 0; } static int get_ctxt_info(struct hfi1_filedata *fd, void __user *ubase, @@ -1238,28 +1248,32 @@ static int setup_base_ctxt(struct hfi1_filedata *fd) /* Now allocate the RcvHdr queue and eager buffers. */ ret = hfi1_create_rcvhdrq(dd, uctxt); if (ret) - goto done; + return ret; ret = hfi1_setup_eagerbufs(uctxt); if (ret) - goto done; + goto setup_failed; /* If sub-contexts are enabled, do the appropriate setup */ if (uctxt->subctxt_cnt) ret = setup_subctxt(uctxt); if (ret) - goto done; + goto setup_failed; ret = hfi1_user_exp_rcv_grp_init(fd); if (ret) - goto done; + goto setup_failed; ret = init_user_ctxt(fd); if (ret) - goto done; + goto setup_failed; - ret = user_init(uctxt); -done: + user_init(uctxt); + + return 0; + +setup_failed: + hfi1_free_ctxtdata(dd, uctxt); return ret; } |