Skip to content

Commit f2a3bc0

Browse files
mjruhldledford
authored andcommitted
IB/hfi1: Protect context array set/clear with spinlock
The rcd array can be accessed from user context or during interrupts. Protecting this with a mutex isn't a good idea because the mutex should not be used from an IRQ. Protect the allocation and freeing of rcd array elements with a spinlock. Reviewed-by: Mike Marciniszyn <[email protected]> Reviewed-by: Sebastian Sanchez <[email protected]> Signed-off-by: Michael J. Ruhl <[email protected]> Signed-off-by: Dennis Dalessandro <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 64a296f commit f2a3bc0

File tree

5 files changed

+229
-181
lines changed

5 files changed

+229
-181
lines changed

drivers/infiniband/hw/hfi1/chip.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15054,10 +15054,16 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
1505415054
if (ret)
1505515055
goto bail_cleanup;
1505615056

15057-
ret = hfi1_create_ctxts(dd);
15057+
ret = hfi1_create_kctxts(dd);
1505815058
if (ret)
1505915059
goto bail_cleanup;
1506015060

15061+
/*
15062+
* Initialize aspm, to be done after gen3 transition and setting up
15063+
* contexts and before enabling interrupts
15064+
*/
15065+
aspm_init(dd);
15066+
1506115067
dd->rcvhdrsize = DEFAULT_RCVHDRSIZE;
1506215068
/*
1506315069
* rcd[0] is guaranteed to be valid by this point. Also, all
@@ -15076,7 +15082,7 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
1507615082
goto bail_cleanup;
1507715083
}
1507815084

15079-
/* use contexts created by hfi1_create_ctxts */
15085+
/* use contexts created by hfi1_create_kctxts */
1508015086
ret = set_up_interrupts(dd);
1508115087
if (ret)
1508215088
goto bail_cleanup;

drivers/infiniband/hw/hfi1/file_ops.c

Lines changed: 74 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma);
7979

8080
static u64 kvirt_to_phys(void *addr);
8181
static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo);
82-
static int init_subctxts(struct hfi1_ctxtdata *uctxt,
83-
const struct hfi1_user_info *uinfo);
82+
static void init_subctxts(struct hfi1_ctxtdata *uctxt,
83+
const struct hfi1_user_info *uinfo);
8484
static int init_user_ctxt(struct hfi1_filedata *fd,
8585
struct hfi1_ctxtdata *uctxt);
8686
static void user_init(struct hfi1_ctxtdata *uctxt);
@@ -758,7 +758,6 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
758758
goto done;
759759

760760
hfi1_cdbg(PROC, "freeing ctxt %u:%u", uctxt->ctxt, fdata->subctxt);
761-
mutex_lock(&hfi1_mutex);
762761

763762
flush_wc();
764763
/* drain user sdma queue */
@@ -778,6 +777,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
778777
HFI1_MAX_SHARED_CTXTS) + fdata->subctxt;
779778
*ev = 0;
780779

780+
mutex_lock(&hfi1_mutex);
781781
__clear_bit(fdata->subctxt, uctxt->in_use_ctxts);
782782
fdata->uctxt = NULL;
783783
hfi1_rcd_put(uctxt); /* fdata reference */
@@ -844,6 +844,38 @@ static u64 kvirt_to_phys(void *addr)
844844
return paddr;
845845
}
846846

847+
static int complete_subctxt(struct hfi1_filedata *fd)
848+
{
849+
int ret;
850+
851+
/*
852+
* sub-context info can only be set up after the base context
853+
* has been completed.
854+
*/
855+
ret = wait_event_interruptible(
856+
fd->uctxt->wait,
857+
!test_bit(HFI1_CTXT_BASE_UNINIT, &fd->uctxt->event_flags));
858+
859+
if (test_bit(HFI1_CTXT_BASE_FAILED, &fd->uctxt->event_flags))
860+
ret = -ENOMEM;
861+
862+
/* The only thing a sub context needs is the user_xxx stuff */
863+
if (!ret) {
864+
fd->rec_cpu_num = hfi1_get_proc_affinity(fd->uctxt->numa_id);
865+
ret = init_user_ctxt(fd, fd->uctxt);
866+
}
867+
868+
if (ret) {
869+
hfi1_rcd_put(fd->uctxt);
870+
fd->uctxt = NULL;
871+
mutex_lock(&hfi1_mutex);
872+
__clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts);
873+
mutex_unlock(&hfi1_mutex);
874+
}
875+
876+
return ret;
877+
}
878+
847879
static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
848880
{
849881
int ret;
@@ -854,79 +886,57 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
854886
if (swmajor != HFI1_USER_SWMAJOR)
855887
return -ENODEV;
856888

889+
if (uinfo->subctxt_cnt > HFI1_MAX_SHARED_CTXTS)
890+
return -EINVAL;
891+
857892
swminor = uinfo->userversion & 0xffff;
858893

894+
/*
895+
* Acquire the mutex to protect against multiple creations of what
896+
* could be a shared base context.
897+
*/
859898
mutex_lock(&hfi1_mutex);
860899
/*
861-
* Get a sub context if necessary.
900+
* Get a sub context if available (fd->uctxt will be set).
862901
* ret < 0 error, 0 no context, 1 sub-context found
863902
*/
864-
ret = 0;
865-
if (uinfo->subctxt_cnt) {
866-
ret = find_sub_ctxt(fd, uinfo);
867-
if (ret > 0)
868-
fd->rec_cpu_num =
869-
hfi1_get_proc_affinity(fd->uctxt->numa_id);
870-
}
903+
ret = find_sub_ctxt(fd, uinfo);
871904

872905
/*
873-
* Allocate a base context if context sharing is not required or we
874-
* couldn't find a sub context.
906+
* Allocate a base context if context sharing is not required or a
907+
* sub context wasn't found.
875908
*/
876909
if (!ret)
877910
ret = allocate_ctxt(fd, fd->dd, uinfo, &uctxt);
878911

879912
mutex_unlock(&hfi1_mutex);
880913

881914
/* Depending on the context type, do the appropriate init */
882-
if (ret > 0) {
883-
/*
884-
* sub-context info can only be set up after the base
885-
* context has been completed.
886-
*/
887-
ret = wait_event_interruptible(fd->uctxt->wait, !test_bit(
888-
HFI1_CTXT_BASE_UNINIT,
889-
&fd->uctxt->event_flags));
890-
if (test_bit(HFI1_CTXT_BASE_FAILED, &fd->uctxt->event_flags))
891-
ret = -ENOMEM;
892-
893-
/* The only thing a sub context needs is the user_xxx stuff */
894-
if (!ret)
895-
ret = init_user_ctxt(fd, fd->uctxt);
896-
897-
if (ret)
898-
clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts);
899-
900-
} else if (!ret) {
915+
switch (ret) {
916+
case 0:
901917
ret = setup_base_ctxt(fd, uctxt);
902918
if (uctxt->subctxt_cnt) {
903-
/* If there is an error, set the failed bit. */
904-
if (ret)
905-
set_bit(HFI1_CTXT_BASE_FAILED,
906-
&uctxt->event_flags);
907919
/*
908920
* Base context is done, notify anybody using a
909921
* sub-context that is waiting for this completion
910922
*/
911923
clear_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
912924
wake_up(&uctxt->wait);
913925
}
914-
if (ret)
915-
deallocate_ctxt(uctxt);
916-
}
917-
918-
/* If an error occurred, clear the reference */
919-
if (ret && fd->uctxt) {
920-
hfi1_rcd_put(fd->uctxt);
921-
fd->uctxt = NULL;
926+
break;
927+
case 1:
928+
ret = complete_subctxt(fd);
929+
break;
930+
default:
931+
break;
922932
}
923933

924934
return ret;
925935
}
926936

927937
/*
928938
* The hfi1_mutex must be held when this function is called. It is
929-
* necessary to ensure serialized access to the bitmask in_use_ctxts.
939+
* necessary to ensure serialized creation of shared contexts.
930940
*/
931941
static int find_sub_ctxt(struct hfi1_filedata *fd,
932942
const struct hfi1_user_info *uinfo)
@@ -935,6 +945,9 @@ static int find_sub_ctxt(struct hfi1_filedata *fd,
935945
struct hfi1_devdata *dd = fd->dd;
936946
u16 subctxt;
937947

948+
if (!uinfo->subctxt_cnt)
949+
return 0;
950+
938951
for (i = dd->first_dyn_alloc_ctxt; i < dd->num_rcv_contexts; i++) {
939952
struct hfi1_ctxtdata *uctxt = dd->rcd[i];
940953

@@ -983,7 +996,6 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
983996
struct hfi1_ctxtdata **cd)
984997
{
985998
struct hfi1_ctxtdata *uctxt;
986-
u16 ctxt;
987999
int ret, numa;
9881000

9891001
if (dd->flags & HFI1_FROZEN) {
@@ -997,22 +1009,9 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
9971009
return -EIO;
9981010
}
9991011

1000-
/*
1001-
* This check is sort of redundant to the next EBUSY error. It would
1002-
* also indicate an inconsistancy in the driver if this value was
1003-
* zero, but there were still contexts available.
1004-
*/
10051012
if (!dd->freectxts)
10061013
return -EBUSY;
10071014

1008-
for (ctxt = dd->first_dyn_alloc_ctxt;
1009-
ctxt < dd->num_rcv_contexts; ctxt++)
1010-
if (!dd->rcd[ctxt])
1011-
break;
1012-
1013-
if (ctxt == dd->num_rcv_contexts)
1014-
return -EBUSY;
1015-
10161015
/*
10171016
* If we don't have a NUMA node requested, preference is towards
10181017
* device NUMA node.
@@ -1022,11 +1021,10 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
10221021
numa = cpu_to_node(fd->rec_cpu_num);
10231022
else
10241023
numa = numa_node_id();
1025-
uctxt = hfi1_create_ctxtdata(dd->pport, ctxt, numa);
1026-
if (!uctxt) {
1027-
dd_dev_err(dd,
1028-
"Unable to allocate ctxtdata memory, failing open\n");
1029-
return -ENOMEM;
1024+
ret = hfi1_create_ctxtdata(dd->pport, numa, &uctxt);
1025+
if (ret < 0) {
1026+
dd_dev_err(dd, "user ctxtdata allocation failed\n");
1027+
return ret;
10301028
}
10311029
hfi1_cdbg(PROC, "[%u:%u] pid %u assigned to CPU %d (NUMA %u)",
10321030
uctxt->ctxt, fd->subctxt, current->pid, fd->rec_cpu_num,
@@ -1035,8 +1033,7 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
10351033
/*
10361034
* Allocate and enable a PIO send context.
10371035
*/
1038-
uctxt->sc = sc_alloc(dd, SC_USER, uctxt->rcvhdrqentsize,
1039-
uctxt->dd->node);
1036+
uctxt->sc = sc_alloc(dd, SC_USER, uctxt->rcvhdrqentsize, dd->node);
10401037
if (!uctxt->sc) {
10411038
ret = -ENOMEM;
10421039
goto ctxdata_free;
@@ -1048,20 +1045,13 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
10481045
goto ctxdata_free;
10491046

10501047
/*
1051-
* Setup sub context resources if the user-level has requested
1048+
* Setup sub context information if the user-level has requested
10521049
* sub contexts.
10531050
* This has to be done here so the rest of the sub-contexts find the
1054-
* proper master.
1051+
* proper base context.
10551052
*/
1056-
if (uinfo->subctxt_cnt) {
1057-
ret = init_subctxts(uctxt, uinfo);
1058-
/*
1059-
* On error, we don't need to disable and de-allocate the
1060-
* send context because it will be done during file close
1061-
*/
1062-
if (ret)
1063-
goto ctxdata_free;
1064-
}
1053+
if (uinfo->subctxt_cnt)
1054+
init_subctxts(uctxt, uinfo);
10651055
uctxt->userversion = uinfo->userversion;
10661056
uctxt->flags = hfi1_cap_mask; /* save current flag state */
10671057
init_waitqueue_head(&uctxt->wait);
@@ -1081,9 +1071,7 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
10811071
return 0;
10821072

10831073
ctxdata_free:
1084-
*cd = NULL;
1085-
dd->rcd[ctxt] = NULL;
1086-
hfi1_rcd_put(uctxt);
1074+
hfi1_free_ctxt(dd, uctxt);
10871075
return ret;
10881076
}
10891077

@@ -1093,28 +1081,17 @@ static void deallocate_ctxt(struct hfi1_ctxtdata *uctxt)
10931081
hfi1_stats.sps_ctxts--;
10941082
if (++uctxt->dd->freectxts == uctxt->dd->num_user_contexts)
10951083
aspm_enable_all(uctxt->dd);
1096-
1097-
/* _rcd_put() should be done after releasing mutex */
1098-
uctxt->dd->rcd[uctxt->ctxt] = NULL;
10991084
mutex_unlock(&hfi1_mutex);
1100-
hfi1_rcd_put(uctxt); /* dd reference */
1085+
1086+
hfi1_free_ctxt(uctxt->dd, uctxt);
11011087
}
11021088

1103-
static int init_subctxts(struct hfi1_ctxtdata *uctxt,
1104-
const struct hfi1_user_info *uinfo)
1089+
static void init_subctxts(struct hfi1_ctxtdata *uctxt,
1090+
const struct hfi1_user_info *uinfo)
11051091
{
1106-
u16 num_subctxts;
1107-
1108-
num_subctxts = uinfo->subctxt_cnt;
1109-
if (num_subctxts > HFI1_MAX_SHARED_CTXTS)
1110-
return -EINVAL;
1111-
11121092
uctxt->subctxt_cnt = uinfo->subctxt_cnt;
11131093
uctxt->subctxt_id = uinfo->subctxt_id;
1114-
uctxt->redirect_seq_cnt = 1;
11151094
set_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
1116-
1117-
return 0;
11181095
}
11191096

11201097
static int setup_subctxt(struct hfi1_ctxtdata *uctxt)
@@ -1302,8 +1279,8 @@ static int setup_base_ctxt(struct hfi1_filedata *fd,
13021279
return 0;
13031280

13041281
setup_failed:
1305-
/* Call _free_ctxtdata, not _rcd_put(). We still need the context. */
1306-
hfi1_free_ctxtdata(dd, uctxt);
1282+
set_bit(HFI1_CTXT_BASE_FAILED, &uctxt->event_flags);
1283+
deallocate_ctxt(uctxt);
13071284
return ret;
13081285
}
13091286

drivers/infiniband/hw/hfi1/hfi.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ struct hfi1_ctxtdata {
273273
u16 poll_type;
274274
/* receive packet sequence counter */
275275
u8 seq_cnt;
276-
u8 redirect_seq_cnt;
277276
/* ctxt rcvhdrq head offset */
278277
u32 head;
279278
/* QPs waiting for context processing */
@@ -1263,9 +1262,10 @@ void handle_user_interrupt(struct hfi1_ctxtdata *rcd);
12631262

12641263
int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd);
12651264
int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd);
1266-
int hfi1_create_ctxts(struct hfi1_devdata *dd);
1267-
struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u16 ctxt,
1268-
int numa);
1265+
int hfi1_create_kctxts(struct hfi1_devdata *dd);
1266+
int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa,
1267+
struct hfi1_ctxtdata **rcd);
1268+
void hfi1_free_ctxt(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd);
12691269
void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
12701270
struct hfi1_devdata *dd, u8 hw_pidx, u8 port);
12711271
void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd);

0 commit comments

Comments
 (0)