summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-08-09 21:38:35 +0200
committerMichael Brown2009-08-10 23:19:39 +0200
commit0b1222f2332e89bcece1912ec6058479b45f62f1 (patch)
treecc096a5cfeff20073da09c710121a90bc5decf2e
parent[scsi] Make LUN a property of the SCSI backend only (diff)
downloadipxe-0b1222f2332e89bcece1912ec6058479b45f62f1.tar.gz
ipxe-0b1222f2332e89bcece1912ec6058479b45f62f1.tar.xz
ipxe-0b1222f2332e89bcece1912ec6058479b45f62f1.zip
[hermon] Randomise the high-order bits of queue pair numbers
The Infiniband Communication Manager will refuse to establish a connection if it believes the connection is already established. There is no immediately obvious way to ask it to tear down the existing connection and replace it; to issue a DREP we would need to know the local and remote communication IDs used for the previous connection setup. We can work around this by randomising the high-order bits of the queue pair number; these have no significance to the hardware, but are sufficient to convince the IB CM that this is a different connection.
-rw-r--r--src/drivers/infiniband/hermon.c9
-rw-r--r--src/drivers/infiniband/hermon.h4
2 files changed, 7 insertions, 6 deletions
diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c
index 6e2f3230..0012904f 100644
--- a/src/drivers/infiniband/hermon.c
+++ b/src/drivers/infiniband/hermon.c
@@ -857,7 +857,8 @@ static int hermon_alloc_qpn ( struct ib_device *ibdev,
hermon );
return qpn_offset;
}
- qp->qpn = ( hermon->qpn_base + qpn_offset );
+ qp->qpn = ( ( random() & HERMON_QPN_RANDOM_MASK ) |
+ ( hermon->qpn_base + qpn_offset ) );
return 0;
default:
DBGC ( hermon, "Hermon %p unsupported QP type %d\n",
@@ -877,7 +878,8 @@ static void hermon_free_qpn ( struct ib_device *ibdev,
struct hermon *hermon = ib_get_drvdata ( ibdev );
int qpn_offset;
- qpn_offset = ( qp->qpn - hermon->qpn_base );
+ qpn_offset = ( ( qp->qpn & ~HERMON_QPN_RANDOM_MASK )
+ - hermon->qpn_base );
if ( qpn_offset >= 0 )
hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 );
}
@@ -2529,8 +2531,7 @@ static int hermon_configure_special_qps ( struct hermon *hermon ) {
int rc;
/* Special QP block must be aligned on its own size */
- hermon->special_qpn_base = ( ( HERMON_QPN_BASE +
- hermon->cap.reserved_qps +
+ hermon->special_qpn_base = ( ( hermon->cap.reserved_qps +
HERMON_NUM_SPECIAL_QPS - 1 )
& ~( HERMON_NUM_SPECIAL_QPS - 1 ) );
hermon->qpn_base = ( hermon->special_qpn_base +
diff --git a/src/drivers/infiniband/hermon.h b/src/drivers/infiniband/hermon.h
index c3d895c6..f19fd359 100644
--- a/src/drivers/infiniband/hermon.h
+++ b/src/drivers/infiniband/hermon.h
@@ -422,8 +422,8 @@ struct hermon_recv_work_queue {
*/
#define HERMON_MAX_QPS 8
-/** Base queue pair number */
-#define HERMON_QPN_BASE 0x550000
+/** Queue pair number randomisation mask */
+#define HERMON_QPN_RANDOM_MASK 0xfff000
/** Hermon queue pair state */
enum hermon_queue_pair_state {