aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2006-08-28 18:15:18 -0400
committerRoland Dreier <rolandd@cisco.com>2006-09-22 18:22:45 -0400
commitf06d26537559113207e4b73af6a22eaa5c5e9dc3 (patch)
treed5d33db61adc4070a4b4b0d4f903d3223299db7b /drivers/infiniband
parent2b3e258e5dd1938e2708eb5354ad8ba056fe8154 (diff)
IB/cm: Randomize starting comm ID
Randomize the starting local comm ID to avoid getting a rejected connection due to a stale connection after a system reboot or reloading of the ib_cm. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/cm.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 1aad33e03528..c8982b02d9b6 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. 2 * Copyright (c) 2004-2006 Intel Corporation. All rights reserved.
3 * Copyright (c) 2004 Topspin Corporation. All rights reserved. 3 * Copyright (c) 2004 Topspin Corporation. All rights reserved.
4 * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. 4 * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
5 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
@@ -41,6 +41,7 @@
41#include <linux/idr.h> 41#include <linux/idr.h>
42#include <linux/interrupt.h> 42#include <linux/interrupt.h>
43#include <linux/pci.h> 43#include <linux/pci.h>
44#include <linux/random.h>
44#include <linux/rbtree.h> 45#include <linux/rbtree.h>
45#include <linux/spinlock.h> 46#include <linux/spinlock.h>
46#include <linux/workqueue.h> 47#include <linux/workqueue.h>
@@ -73,6 +74,7 @@ static struct ib_cm {
73 struct rb_root remote_id_table; 74 struct rb_root remote_id_table;
74 struct rb_root remote_sidr_table; 75 struct rb_root remote_sidr_table;
75 struct idr local_id_table; 76 struct idr local_id_table;
77 __be32 random_id_operand;
76 struct workqueue_struct *wq; 78 struct workqueue_struct *wq;
77} cm; 79} cm;
78 80
@@ -299,15 +301,17 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
299static int cm_alloc_id(struct cm_id_private *cm_id_priv) 301static int cm_alloc_id(struct cm_id_private *cm_id_priv)
300{ 302{
301 unsigned long flags; 303 unsigned long flags;
302 int ret; 304 int ret, id;
303 static int next_id; 305 static int next_id;
304 306
305 do { 307 do {
306 spin_lock_irqsave(&cm.lock, flags); 308 spin_lock_irqsave(&cm.lock, flags);
307 ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_id++, 309 ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
308 (__force int *) &cm_id_priv->id.local_id); 310 next_id++, &id);
309 spin_unlock_irqrestore(&cm.lock, flags); 311 spin_unlock_irqrestore(&cm.lock, flags);
310 } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); 312 } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
313
314 cm_id_priv->id.local_id = (__force __be32) (id ^ cm.random_id_operand);
311 return ret; 315 return ret;
312} 316}
313 317
@@ -316,7 +320,8 @@ static void cm_free_id(__be32 local_id)
316 unsigned long flags; 320 unsigned long flags;
317 321
318 spin_lock_irqsave(&cm.lock, flags); 322 spin_lock_irqsave(&cm.lock, flags);
319 idr_remove(&cm.local_id_table, (__force int) local_id); 323 idr_remove(&cm.local_id_table,
324 (__force int) (local_id ^ cm.random_id_operand));
320 spin_unlock_irqrestore(&cm.lock, flags); 325 spin_unlock_irqrestore(&cm.lock, flags);
321} 326}
322 327
@@ -324,7 +329,8 @@ static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
324{ 329{
325 struct cm_id_private *cm_id_priv; 330 struct cm_id_private *cm_id_priv;
326 331
327 cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id); 332 cm_id_priv = idr_find(&cm.local_id_table,
333 (__force int) (local_id ^ cm.random_id_operand));
328 if (cm_id_priv) { 334 if (cm_id_priv) {
329 if (cm_id_priv->id.remote_id == remote_id) 335 if (cm_id_priv->id.remote_id == remote_id)
330 atomic_inc(&cm_id_priv->refcount); 336 atomic_inc(&cm_id_priv->refcount);
@@ -2082,8 +2088,9 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
2082 spin_unlock_irqrestore(&cm.lock, flags); 2088 spin_unlock_irqrestore(&cm.lock, flags);
2083 return NULL; 2089 return NULL;
2084 } 2090 }
2085 cm_id_priv = idr_find(&cm.local_id_table, 2091 cm_id_priv = idr_find(&cm.local_id_table, (__force int)
2086 (__force int) timewait_info->work.local_id); 2092 (timewait_info->work.local_id ^
2093 cm.random_id_operand));
2087 if (cm_id_priv) { 2094 if (cm_id_priv) {
2088 if (cm_id_priv->id.remote_id == remote_id) 2095 if (cm_id_priv->id.remote_id == remote_id)
2089 atomic_inc(&cm_id_priv->refcount); 2096 atomic_inc(&cm_id_priv->refcount);
@@ -3360,6 +3367,7 @@ static int __init ib_cm_init(void)
3360 cm.remote_qp_table = RB_ROOT; 3367 cm.remote_qp_table = RB_ROOT;
3361 cm.remote_sidr_table = RB_ROOT; 3368 cm.remote_sidr_table = RB_ROOT;
3362 idr_init(&cm.local_id_table); 3369 idr_init(&cm.local_id_table);
3370 get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
3363 idr_pre_get(&cm.local_id_table, GFP_KERNEL); 3371 idr_pre_get(&cm.local_id_table, GFP_KERNEL);
3364 3372
3365 cm.wq = create_workqueue("ib_cm"); 3373 cm.wq = create_workqueue("ib_cm");