aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael J. Ruhl <michael.j.ruhl@intel.com>2017-05-04 08:15:15 -0400
committerDoug Ledford <dledford@redhat.com>2017-05-04 19:31:46 -0400
commit8737ce95c463c6d8c4307ab3d6858cbf71cd4fc8 (patch)
tree1afce2cd49297cb1211ebc09f4131806dc036eb3
parent9b60d2cbe07486658a32d4ed2fff7085c44bae7a (diff)
IB/hfi1: Fix an assign/ordering issue with shared context IDs
The current algorithm for generating sub-context IDs is FILO. If the contexts are not closed in that order, the uniqueness of the ID will be compromised. I.e. logging the creation/deletion of context IDs with an application that assigns and closes in a FIFO order reveals: cache_id: assign: uctxt: 3 sub_ctxt: 0 cache_id: assign: uctxt: 3 sub_ctxt: 1 cache_id: assign: uctxt: 3 sub_ctxt: 2 cache_id: close: uctxt: 3 sub_ctxt: 0 cache_id: assign: uctxt: 3 sub_ctxt: 2 <<< The sub_ctxt ID 2 is reused incorrectly. Update the sub-context ID assign algorithm to use a bitmask of in_use contexts. The new algorithm will allow the contexts to be closed in any order, and will only re-use unused contexts. Size subctxt and subctxt_cnt to match the user API size. 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>
-rw-r--r--drivers/infiniband/hw/hfi1/driver.c2
-rw-r--r--drivers/infiniband/hw/hfi1/file_ops.c51
-rw-r--r--drivers/infiniband/hw/hfi1/hfi.h8
-rw-r--r--drivers/infiniband/hw/hfi1/init.c3
-rw-r--r--drivers/infiniband/hw/hfi1/intr.c3
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.h2
6 files changed, 41 insertions, 28 deletions
diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c
index 566d152e36f2..a50870e455a3 100644
--- a/drivers/infiniband/hw/hfi1/driver.c
+++ b/drivers/infiniband/hw/hfi1/driver.c
@@ -1289,7 +1289,7 @@ int hfi1_reset_device(int unit)
1289 if (dd->rcd) 1289 if (dd->rcd)
1290 for (i = dd->first_dyn_alloc_ctxt; 1290 for (i = dd->first_dyn_alloc_ctxt;
1291 i < dd->num_rcv_contexts; i++) { 1291 i < dd->num_rcv_contexts; i++) {
1292 if (!dd->rcd[i] || !dd->rcd[i]->cnt) 1292 if (!dd->rcd[i])
1293 continue; 1293 continue;
1294 spin_unlock_irqrestore(&dd->uctxt_lock, flags); 1294 spin_unlock_irqrestore(&dd->uctxt_lock, flags);
1295 ret = -EBUSY; 1295 ret = -EBUSY;
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index 467f876551ba..9c177ef79db5 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -49,6 +49,7 @@
49#include <linux/vmalloc.h> 49#include <linux/vmalloc.h>
50#include <linux/io.h> 50#include <linux/io.h>
51#include <linux/sched/mm.h> 51#include <linux/sched/mm.h>
52#include <linux/bitmap.h>
52 53
53#include <rdma/ib.h> 54#include <rdma/ib.h>
54 55
@@ -95,11 +96,10 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
95 struct hfi1_user_info *uinfo); 96 struct hfi1_user_info *uinfo);
96static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt); 97static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt);
97static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt); 98static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt);
98static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt, 99static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
99 unsigned long events); 100 unsigned long events);
100static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned subctxt, 101static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, u16 subctxt, u16 pkey);
101 u16 pkey); 102static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
102static int manage_rcvq(struct hfi1_ctxtdata *uctxt, unsigned subctxt,
103 int start_stop); 103 int start_stop);
104static int vma_fault(struct vm_fault *vmf); 104static int vma_fault(struct vm_fault *vmf);
105static long hfi1_file_ioctl(struct file *fp, unsigned int cmd, 105static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
@@ -773,8 +773,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
773 HFI1_MAX_SHARED_CTXTS) + fdata->subctxt; 773 HFI1_MAX_SHARED_CTXTS) + fdata->subctxt;
774 *ev = 0; 774 *ev = 0;
775 775
776 if (--uctxt->cnt) { 776 __clear_bit(fdata->subctxt, uctxt->in_use_ctxts);
777 uctxt->active_slaves &= ~(1 << fdata->subctxt); 777 if (!bitmap_empty(uctxt->in_use_ctxts, HFI1_MAX_SHARED_CTXTS)) {
778 mutex_unlock(&hfi1_mutex); 778 mutex_unlock(&hfi1_mutex);
779 goto done; 779 goto done;
780 } 780 }
@@ -868,7 +868,7 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
868 } 868 }
869 869
870 /* 870 /*
871 * Allocate a base context f context sharing is not required or we 871 * Allocate a base context if context sharing is not required or we
872 * couldn't find a sub context. 872 * couldn't find a sub context.
873 */ 873 */
874 if (!ret) 874 if (!ret)
@@ -905,17 +905,24 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
905 return ret; 905 return ret;
906} 906}
907 907
908/*
909 * The hfi1_mutex must be held when this function is called. It is
910 * necessary to ensure serialized access to the bitmask in_use_ctxts.
911 */
908static int find_sub_ctxt(struct hfi1_filedata *fd, 912static int find_sub_ctxt(struct hfi1_filedata *fd,
909 const struct hfi1_user_info *uinfo) 913 const struct hfi1_user_info *uinfo)
910{ 914{
911 int i; 915 int i;
912 struct hfi1_devdata *dd = fd->dd; 916 struct hfi1_devdata *dd = fd->dd;
917 u16 subctxt;
913 918
914 for (i = dd->first_dyn_alloc_ctxt; i < dd->num_rcv_contexts; i++) { 919 for (i = dd->first_dyn_alloc_ctxt; i < dd->num_rcv_contexts; i++) {
915 struct hfi1_ctxtdata *uctxt = dd->rcd[i]; 920 struct hfi1_ctxtdata *uctxt = dd->rcd[i];
916 921
917 /* Skip ctxts which are not yet open */ 922 /* Skip ctxts which are not yet open */
918 if (!uctxt || !uctxt->cnt) 923 if (!uctxt ||
924 bitmap_empty(uctxt->in_use_ctxts,
925 HFI1_MAX_SHARED_CTXTS))
919 continue; 926 continue;
920 927
921 /* Skip dynamically allocted kernel contexts */ 928 /* Skip dynamically allocted kernel contexts */
@@ -931,13 +938,19 @@ static int find_sub_ctxt(struct hfi1_filedata *fd,
931 continue; 938 continue;
932 939
933 /* Verify the sharing process matches the master */ 940 /* Verify the sharing process matches the master */
934 if (uctxt->userversion != uinfo->userversion || 941 if (uctxt->userversion != uinfo->userversion)
935 uctxt->cnt >= uctxt->subctxt_cnt) {
936 return -EINVAL; 942 return -EINVAL;
937 } 943
944 /* Find an unused context */
945 subctxt = find_first_zero_bit(uctxt->in_use_ctxts,
946 HFI1_MAX_SHARED_CTXTS);
947 if (subctxt >= uctxt->subctxt_cnt)
948 return -EINVAL;
949
938 fd->uctxt = uctxt; 950 fd->uctxt = uctxt;
939 fd->subctxt = uctxt->cnt++; 951 fd->subctxt = subctxt;
940 uctxt->active_slaves |= 1 << fd->subctxt; 952 __set_bit(fd->subctxt, uctxt->in_use_ctxts);
953
941 return 1; 954 return 1;
942 } 955 }
943 956
@@ -1055,7 +1068,7 @@ ctxdata_free:
1055static int init_subctxts(struct hfi1_ctxtdata *uctxt, 1068static int init_subctxts(struct hfi1_ctxtdata *uctxt,
1056 const struct hfi1_user_info *uinfo) 1069 const struct hfi1_user_info *uinfo)
1057{ 1070{
1058 unsigned num_subctxts; 1071 u16 num_subctxts;
1059 1072
1060 num_subctxts = uinfo->subctxt_cnt; 1073 num_subctxts = uinfo->subctxt_cnt;
1061 if (num_subctxts > HFI1_MAX_SHARED_CTXTS) 1074 if (num_subctxts > HFI1_MAX_SHARED_CTXTS)
@@ -1063,7 +1076,6 @@ static int init_subctxts(struct hfi1_ctxtdata *uctxt,
1063 1076
1064 uctxt->subctxt_cnt = uinfo->subctxt_cnt; 1077 uctxt->subctxt_cnt = uinfo->subctxt_cnt;
1065 uctxt->subctxt_id = uinfo->subctxt_id; 1078 uctxt->subctxt_id = uinfo->subctxt_id;
1066 uctxt->active_slaves = 1;
1067 uctxt->redirect_seq_cnt = 1; 1079 uctxt->redirect_seq_cnt = 1;
1068 set_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags); 1080 set_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
1069 1081
@@ -1073,7 +1085,7 @@ static int init_subctxts(struct hfi1_ctxtdata *uctxt,
1073static int setup_subctxt(struct hfi1_ctxtdata *uctxt) 1085static int setup_subctxt(struct hfi1_ctxtdata *uctxt)
1074{ 1086{
1075 int ret = 0; 1087 int ret = 0;
1076 unsigned num_subctxts = uctxt->subctxt_cnt; 1088 u16 num_subctxts = uctxt->subctxt_cnt;
1077 1089
1078 uctxt->subctxt_uregbase = vmalloc_user(PAGE_SIZE); 1090 uctxt->subctxt_uregbase = vmalloc_user(PAGE_SIZE);
1079 if (!uctxt->subctxt_uregbase) 1091 if (!uctxt->subctxt_uregbase)
@@ -1425,7 +1437,7 @@ done:
1425 * overflow conditions. start_stop==1 re-enables, to be used to 1437 * overflow conditions. start_stop==1 re-enables, to be used to
1426 * re-init the software copy of the head register 1438 * re-init the software copy of the head register
1427 */ 1439 */
1428static int manage_rcvq(struct hfi1_ctxtdata *uctxt, unsigned subctxt, 1440static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
1429 int start_stop) 1441 int start_stop)
1430{ 1442{
1431 struct hfi1_devdata *dd = uctxt->dd; 1443 struct hfi1_devdata *dd = uctxt->dd;
@@ -1460,7 +1472,7 @@ bail:
1460 * User process then performs actions appropriate to bit having been 1472 * User process then performs actions appropriate to bit having been
1461 * set, if desired, and checks again in future. 1473 * set, if desired, and checks again in future.
1462 */ 1474 */
1463static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt, 1475static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
1464 unsigned long events) 1476 unsigned long events)
1465{ 1477{
1466 int i; 1478 int i;
@@ -1481,8 +1493,7 @@ static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt,
1481 return 0; 1493 return 0;
1482} 1494}
1483 1495
1484static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned subctxt, 1496static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, u16 subctxt, u16 pkey)
1485 u16 pkey)
1486{ 1497{
1487 int ret = -ENOENT, i, intable = 0; 1498 int ret = -ENOENT, i, intable = 0;
1488 struct hfi1_pportdata *ppd = uctxt->ppd; 1499 struct hfi1_pportdata *ppd = uctxt->ppd;
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h
index 1b7203a3f1ce..f3d75fcd5f07 100644
--- a/drivers/infiniband/hw/hfi1/hfi.h
+++ b/drivers/infiniband/hw/hfi1/hfi.h
@@ -228,7 +228,7 @@ struct hfi1_ctxtdata {
228 unsigned ctxt; 228 unsigned ctxt;
229 /* 229 /*
230 * non-zero if ctxt can be shared, and defines the maximum number of 230 * non-zero if ctxt can be shared, and defines the maximum number of
231 * sub contexts allowed. 231 * sub-contexts for this device context.
232 */ 232 */
233 u16 subctxt_cnt; 233 u16 subctxt_cnt;
234 /* non-zero if ctxt is being shared. */ 234 /* non-zero if ctxt is being shared. */
@@ -287,10 +287,10 @@ struct hfi1_ctxtdata {
287 void *subctxt_rcvegrbuf; 287 void *subctxt_rcvegrbuf;
288 /* An array of pages for the eager header queue entries * N */ 288 /* An array of pages for the eager header queue entries * N */
289 void *subctxt_rcvhdr_base; 289 void *subctxt_rcvhdr_base;
290 /* Bitmask of in use context(s) */
291 DECLARE_BITMAP(in_use_ctxts, HFI1_MAX_SHARED_CTXTS);
290 /* The version of the library which opened this ctxt */ 292 /* The version of the library which opened this ctxt */
291 u32 userversion; 293 u32 userversion;
292 /* Bitmask of active slaves */
293 u32 active_slaves;
294 /* Type of packets or conditions we want to poll for */ 294 /* Type of packets or conditions we want to poll for */
295 u16 poll_type; 295 u16 poll_type;
296 /* receive packet sequence counter */ 296 /* receive packet sequence counter */
@@ -1239,9 +1239,9 @@ struct mmu_rb_handler;
1239struct hfi1_filedata { 1239struct hfi1_filedata {
1240 struct hfi1_devdata *dd; 1240 struct hfi1_devdata *dd;
1241 struct hfi1_ctxtdata *uctxt; 1241 struct hfi1_ctxtdata *uctxt;
1242 unsigned subctxt;
1243 struct hfi1_user_sdma_comp_q *cq; 1242 struct hfi1_user_sdma_comp_q *cq;
1244 struct hfi1_user_sdma_pkt_q *pq; 1243 struct hfi1_user_sdma_pkt_q *pq;
1244 u16 subctxt;
1245 /* for cpu affinity; -1 if none */ 1245 /* for cpu affinity; -1 if none */
1246 int rec_cpu_num; 1246 int rec_cpu_num;
1247 u32 tid_n_pinned; 1247 u32 tid_n_pinned;
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
index 52a6364c30de..694a8ecf9f26 100644
--- a/drivers/infiniband/hw/hfi1/init.c
+++ b/drivers/infiniband/hw/hfi1/init.c
@@ -53,6 +53,7 @@
53#include <linux/module.h> 53#include <linux/module.h>
54#include <linux/printk.h> 54#include <linux/printk.h>
55#include <linux/hrtimer.h> 55#include <linux/hrtimer.h>
56#include <linux/bitmap.h>
56#include <rdma/rdma_vt.h> 57#include <rdma/rdma_vt.h>
57 58
58#include "hfi.h" 59#include "hfi.h"
@@ -222,7 +223,7 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt,
222 INIT_LIST_HEAD(&rcd->qp_wait_list); 223 INIT_LIST_HEAD(&rcd->qp_wait_list);
223 rcd->ppd = ppd; 224 rcd->ppd = ppd;
224 rcd->dd = dd; 225 rcd->dd = dd;
225 rcd->cnt = 1; 226 __set_bit(0, rcd->in_use_ctxts);
226 rcd->ctxt = ctxt; 227 rcd->ctxt = ctxt;
227 dd->rcd[ctxt] = rcd; 228 dd->rcd[ctxt] = rcd;
228 rcd->numa_id = numa; 229 rcd->numa_id = numa;
diff --git a/drivers/infiniband/hw/hfi1/intr.c b/drivers/infiniband/hw/hfi1/intr.c
index 232014d46f79..ba265d0ae93b 100644
--- a/drivers/infiniband/hw/hfi1/intr.c
+++ b/drivers/infiniband/hw/hfi1/intr.c
@@ -47,6 +47,7 @@
47 47
48#include <linux/pci.h> 48#include <linux/pci.h>
49#include <linux/delay.h> 49#include <linux/delay.h>
50#include <linux/bitmap.h>
50 51
51#include "hfi.h" 52#include "hfi.h"
52#include "common.h" 53#include "common.h"
@@ -189,7 +190,7 @@ void handle_user_interrupt(struct hfi1_ctxtdata *rcd)
189 unsigned long flags; 190 unsigned long flags;
190 191
191 spin_lock_irqsave(&dd->uctxt_lock, flags); 192 spin_lock_irqsave(&dd->uctxt_lock, flags);
192 if (!rcd->cnt) 193 if (bitmap_empty(rcd->in_use_ctxts, HFI1_MAX_SHARED_CTXTS))
193 goto done; 194 goto done;
194 195
195 if (test_and_clear_bit(HFI1_CTXT_WAITING_RCV, &rcd->event_flags)) { 196 if (test_and_clear_bit(HFI1_CTXT_WAITING_RCV, &rcd->event_flags)) {
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.h b/drivers/infiniband/hw/hfi1/user_sdma.h
index 9181d7cbe8f6..e5b10aefe212 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.h
+++ b/drivers/infiniband/hw/hfi1/user_sdma.h
@@ -58,7 +58,7 @@ extern uint extended_psn;
58struct hfi1_user_sdma_pkt_q { 58struct hfi1_user_sdma_pkt_q {
59 struct list_head list; 59 struct list_head list;
60 unsigned ctxt; 60 unsigned ctxt;
61 unsigned subctxt; 61 u16 subctxt;
62 u16 n_max_reqs; 62 u16 n_max_reqs;
63 atomic_t n_reqs; 63 atomic_t n_reqs;
64 u16 reqidx; 64 u16 reqidx;