aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/qib/qib.h3
-rw-r--r--drivers/infiniband/hw/qib/qib_driver.c9
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c77
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.c36
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h3
5 files changed, 87 insertions, 41 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 97e623383e1a..b881bdc401f5 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -223,6 +223,9 @@ struct qib_ctxtdata {
223 /* ctxt rcvhdrq head offset */ 223 /* ctxt rcvhdrq head offset */
224 u32 head; 224 u32 head;
225 u32 pkt_count; 225 u32 pkt_count;
226 /* lookaside fields */
227 struct qib_qp *lookaside_qp;
228 u32 lookaside_qpn;
226 /* QPs waiting for context processing */ 229 /* QPs waiting for context processing */
227 struct list_head qp_wait_list; 230 struct list_head qp_wait_list;
228}; 231};
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c
index 89264ffc7ee9..d35c9d38ceee 100644
--- a/drivers/infiniband/hw/qib/qib_driver.c
+++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -547,6 +547,15 @@ move_along:
547 updegr = 0; 547 updegr = 0;
548 } 548 }
549 } 549 }
550 /*
551 * Notify qib_destroy_qp() if it is waiting
552 * for lookaside_qp to finish.
553 */
554 if (rcd->lookaside_qp) {
555 if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
556 wake_up(&rcd->lookaside_qp->wait);
557 rcd->lookaside_qp = NULL;
558 }
550 559
551 rcd->head = l; 560 rcd->head = l;
552 rcd->pkt_count += i; 561 rcd->pkt_count += i;
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 9d094f910360..500981bce9c0 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -34,6 +34,7 @@
34 34
35#include <linux/err.h> 35#include <linux/err.h>
36#include <linux/vmalloc.h> 36#include <linux/vmalloc.h>
37#include <linux/jhash.h>
37 38
38#include "qib.h" 39#include "qib.h"
39 40
@@ -204,6 +205,13 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
204 clear_bit(qpn & BITS_PER_PAGE_MASK, map->page); 205 clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
205} 206}
206 207
208static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
209{
210 return jhash_1word(qpn, dev->qp_rnd) &
211 (dev->qp_table_size - 1);
212}
213
214
207/* 215/*
208 * Put the QP into the hash table. 216 * Put the QP into the hash table.
209 * The hash table holds a reference to the QP. 217 * The hash table holds a reference to the QP.
@@ -211,22 +219,23 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
211static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp) 219static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
212{ 220{
213 struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 221 struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
214 unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
215 unsigned long flags; 222 unsigned long flags;
223 unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
216 224
217 spin_lock_irqsave(&dev->qpt_lock, flags); 225 spin_lock_irqsave(&dev->qpt_lock, flags);
226 atomic_inc(&qp->refcount);
218 227
219 if (qp->ibqp.qp_num == 0) 228 if (qp->ibqp.qp_num == 0)
220 ibp->qp0 = qp; 229 rcu_assign_pointer(ibp->qp0, qp);
221 else if (qp->ibqp.qp_num == 1) 230 else if (qp->ibqp.qp_num == 1)
222 ibp->qp1 = qp; 231 rcu_assign_pointer(ibp->qp1, qp);
223 else { 232 else {
224 qp->next = dev->qp_table[n]; 233 qp->next = dev->qp_table[n];
225 dev->qp_table[n] = qp; 234 rcu_assign_pointer(dev->qp_table[n], qp);
226 } 235 }
227 atomic_inc(&qp->refcount);
228 236
229 spin_unlock_irqrestore(&dev->qpt_lock, flags); 237 spin_unlock_irqrestore(&dev->qpt_lock, flags);
238 synchronize_rcu();
230} 239}
231 240
232/* 241/*
@@ -236,29 +245,32 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
236static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp) 245static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
237{ 246{
238 struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 247 struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
239 struct qib_qp *q, **qpp; 248 unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
240 unsigned long flags; 249 unsigned long flags;
241 250
242 qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
243
244 spin_lock_irqsave(&dev->qpt_lock, flags); 251 spin_lock_irqsave(&dev->qpt_lock, flags);
245 252
246 if (ibp->qp0 == qp) { 253 if (ibp->qp0 == qp) {
247 ibp->qp0 = NULL;
248 atomic_dec(&qp->refcount); 254 atomic_dec(&qp->refcount);
255 rcu_assign_pointer(ibp->qp0, NULL);
249 } else if (ibp->qp1 == qp) { 256 } else if (ibp->qp1 == qp) {
250 ibp->qp1 = NULL;
251 atomic_dec(&qp->refcount); 257 atomic_dec(&qp->refcount);
252 } else 258 rcu_assign_pointer(ibp->qp1, NULL);
259 } else {
260 struct qib_qp *q, **qpp;
261
262 qpp = &dev->qp_table[n];
253 for (; (q = *qpp) != NULL; qpp = &q->next) 263 for (; (q = *qpp) != NULL; qpp = &q->next)
254 if (q == qp) { 264 if (q == qp) {
255 *qpp = qp->next;
256 qp->next = NULL;
257 atomic_dec(&qp->refcount); 265 atomic_dec(&qp->refcount);
266 rcu_assign_pointer(*qpp, qp->next);
267 qp->next = NULL;
258 break; 268 break;
259 } 269 }
270 }
260 271
261 spin_unlock_irqrestore(&dev->qpt_lock, flags); 272 spin_unlock_irqrestore(&dev->qpt_lock, flags);
273 synchronize_rcu();
262} 274}
263 275
264/** 276/**
@@ -280,21 +292,24 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
280 292
281 if (!qib_mcast_tree_empty(ibp)) 293 if (!qib_mcast_tree_empty(ibp))
282 qp_inuse++; 294 qp_inuse++;
283 if (ibp->qp0) 295 rcu_read_lock();
296 if (rcu_dereference(ibp->qp0))
284 qp_inuse++; 297 qp_inuse++;
285 if (ibp->qp1) 298 if (rcu_dereference(ibp->qp1))
286 qp_inuse++; 299 qp_inuse++;
300 rcu_read_unlock();
287 } 301 }
288 302
289 spin_lock_irqsave(&dev->qpt_lock, flags); 303 spin_lock_irqsave(&dev->qpt_lock, flags);
290 for (n = 0; n < dev->qp_table_size; n++) { 304 for (n = 0; n < dev->qp_table_size; n++) {
291 qp = dev->qp_table[n]; 305 qp = dev->qp_table[n];
292 dev->qp_table[n] = NULL; 306 rcu_assign_pointer(dev->qp_table[n], NULL);
293 307
294 for (; qp; qp = qp->next) 308 for (; qp; qp = qp->next)
295 qp_inuse++; 309 qp_inuse++;
296 } 310 }
297 spin_unlock_irqrestore(&dev->qpt_lock, flags); 311 spin_unlock_irqrestore(&dev->qpt_lock, flags);
312 synchronize_rcu();
298 313
299 return qp_inuse; 314 return qp_inuse;
300} 315}
@@ -309,25 +324,28 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
309 */ 324 */
310struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn) 325struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
311{ 326{
312 struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev; 327 struct qib_qp *qp = NULL;
313 unsigned long flags;
314 struct qib_qp *qp;
315 328
316 spin_lock_irqsave(&dev->qpt_lock, flags); 329 if (unlikely(qpn <= 1)) {
330 rcu_read_lock();
331 if (qpn == 0)
332 qp = rcu_dereference(ibp->qp0);
333 else
334 qp = rcu_dereference(ibp->qp1);
335 } else {
336 struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
337 unsigned n = qpn_hash(dev, qpn);
317 338
318 if (qpn == 0) 339 rcu_read_lock();
319 qp = ibp->qp0; 340 for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
320 else if (qpn == 1)
321 qp = ibp->qp1;
322 else
323 for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
324 qp = qp->next)
325 if (qp->ibqp.qp_num == qpn) 341 if (qp->ibqp.qp_num == qpn)
326 break; 342 break;
343 }
327 if (qp) 344 if (qp)
328 atomic_inc(&qp->refcount); 345 if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
346 qp = NULL;
329 347
330 spin_unlock_irqrestore(&dev->qpt_lock, flags); 348 rcu_read_unlock();
331 return qp; 349 return qp;
332} 350}
333 351
@@ -1015,6 +1033,7 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd,
1015 ret = ERR_PTR(-ENOMEM); 1033 ret = ERR_PTR(-ENOMEM);
1016 goto bail_swq; 1034 goto bail_swq;
1017 } 1035 }
1036 RCU_INIT_POINTER(qp->next, NULL);
1018 if (init_attr->srq) 1037 if (init_attr->srq)
1019 sz = 0; 1038 sz = 0;
1020 else { 1039 else {
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index 9fab40488850..9627cb737125 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -38,11 +38,12 @@
38#include <linux/utsname.h> 38#include <linux/utsname.h>
39#include <linux/rculist.h> 39#include <linux/rculist.h>
40#include <linux/mm.h> 40#include <linux/mm.h>
41#include <linux/random.h>
41 42
42#include "qib.h" 43#include "qib.h"
43#include "qib_common.h" 44#include "qib_common.h"
44 45
45static unsigned int ib_qib_qp_table_size = 251; 46static unsigned int ib_qib_qp_table_size = 256;
46module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO); 47module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO);
47MODULE_PARM_DESC(qp_table_size, "QP table size"); 48MODULE_PARM_DESC(qp_table_size, "QP table size");
48 49
@@ -659,17 +660,25 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
659 if (atomic_dec_return(&mcast->refcount) <= 1) 660 if (atomic_dec_return(&mcast->refcount) <= 1)
660 wake_up(&mcast->wait); 661 wake_up(&mcast->wait);
661 } else { 662 } else {
662 qp = qib_lookup_qpn(ibp, qp_num); 663 if (rcd->lookaside_qp) {
663 if (!qp) 664 if (rcd->lookaside_qpn != qp_num) {
664 goto drop; 665 if (atomic_dec_and_test(
666 &rcd->lookaside_qp->refcount))
667 wake_up(
668 &rcd->lookaside_qp->wait);
669 rcd->lookaside_qp = NULL;
670 }
671 }
672 if (!rcd->lookaside_qp) {
673 qp = qib_lookup_qpn(ibp, qp_num);
674 if (!qp)
675 goto drop;
676 rcd->lookaside_qp = qp;
677 rcd->lookaside_qpn = qp_num;
678 } else
679 qp = rcd->lookaside_qp;
665 ibp->n_unicast_rcv++; 680 ibp->n_unicast_rcv++;
666 qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp); 681 qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);
667 /*
668 * Notify qib_destroy_qp() if it is waiting
669 * for us to finish.
670 */
671 if (atomic_dec_and_test(&qp->refcount))
672 wake_up(&qp->wait);
673 } 682 }
674 return; 683 return;
675 684
@@ -1974,6 +1983,8 @@ static void init_ibport(struct qib_pportdata *ppd)
1974 ibp->z_excessive_buffer_overrun_errors = 1983 ibp->z_excessive_buffer_overrun_errors =
1975 cntrs.excessive_buffer_overrun_errors; 1984 cntrs.excessive_buffer_overrun_errors;
1976 ibp->z_vl15_dropped = cntrs.vl15_dropped; 1985 ibp->z_vl15_dropped = cntrs.vl15_dropped;
1986 RCU_INIT_POINTER(ibp->qp0, NULL);
1987 RCU_INIT_POINTER(ibp->qp1, NULL);
1977} 1988}
1978 1989
1979/** 1990/**
@@ -1990,12 +2001,15 @@ int qib_register_ib_device(struct qib_devdata *dd)
1990 int ret; 2001 int ret;
1991 2002
1992 dev->qp_table_size = ib_qib_qp_table_size; 2003 dev->qp_table_size = ib_qib_qp_table_size;
1993 dev->qp_table = kzalloc(dev->qp_table_size * sizeof *dev->qp_table, 2004 get_random_bytes(&dev->qp_rnd, sizeof(dev->qp_rnd));
2005 dev->qp_table = kmalloc(dev->qp_table_size * sizeof *dev->qp_table,
1994 GFP_KERNEL); 2006 GFP_KERNEL);
1995 if (!dev->qp_table) { 2007 if (!dev->qp_table) {
1996 ret = -ENOMEM; 2008 ret = -ENOMEM;
1997 goto err_qpt; 2009 goto err_qpt;
1998 } 2010 }
2011 for (i = 0; i < dev->qp_table_size; i++)
2012 RCU_INIT_POINTER(dev->qp_table[i], NULL);
1999 2013
2000 for (i = 0; i < dd->num_pports; i++) 2014 for (i = 0; i < dd->num_pports; i++)
2001 init_ibport(ppd + i); 2015 init_ibport(ppd + i);
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index ec3711f743c5..d7b6109528a4 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -724,7 +724,8 @@ struct qib_ibdev {
724 dma_addr_t pio_hdrs_phys; 724 dma_addr_t pio_hdrs_phys;
725 /* list of QPs waiting for RNR timer */ 725 /* list of QPs waiting for RNR timer */
726 spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */ 726 spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
727 unsigned qp_table_size; /* size of the hash table */ 727 u32 qp_table_size; /* size of the hash table */
728 u32 qp_rnd; /* random bytes for hash */
728 spinlock_t qpt_lock; 729 spinlock_t qpt_lock;
729 730
730 u32 n_piowait; 731 u32 n_piowait;