Selaa lähdekoodia

[infiniband] Update all other MAD users to use a management interface

tags/v0.9.8
Michael Brown 15 vuotta sitten
vanhempi
commit
34bfc04e4c

+ 28
- 4
src/drivers/net/ipoib.c Näytä tiedosto

@@ -58,12 +58,14 @@ struct ipoib_device {
58 58
 	struct ib_queue_pair *qp;
59 59
 	/** Broadcast MAC */
60 60
 	struct ipoib_mac broadcast;
61
-	/** Joined to multicast group
61
+	/** Joined to IPv4 broadcast multicast group
62 62
 	 *
63 63
 	 * This flag indicates whether or not we have initiated the
64
-	 * join to the IPv4 multicast group.
64
+	 * join to the IPv4 broadcast multicast group.
65 65
 	 */
66 66
 	int broadcast_joined;
67
+	/** IPv4 broadcast multicast group membership */
68
+	struct ib_mc_membership broadcast_membership;
67 69
 };
68 70
 
69 71
 /** Broadcast IPoIB address */
@@ -456,6 +458,26 @@ static void ipoib_irq ( struct net_device *netdev __unused,
456 458
 	/* No implementation */
457 459
 }
458 460
 
461
+/**
462
+ * Handle IPv4 broadcast multicast group join completion
463
+ *
464
+ * @v ibdev		Infiniband device
465
+ * @v qp		Queue pair
466
+ * @v membership	Multicast group membership
467
+ * @v rc		Status code
468
+ * @v mad		Response MAD (or NULL on error)
469
+ */
470
+void ipoib_join_complete ( struct ib_device *ibdev __unused,
471
+			   struct ib_queue_pair *qp __unused,
472
+			   struct ib_mc_membership *membership, int rc,
473
+			   union ib_mad *mad __unused ) {
474
+	struct ipoib_device *ipoib = container_of ( membership,
475
+				   struct ipoib_device, broadcast_membership );
476
+
477
+	/* Record join status as link status */
478
+	netdev_link_err ( ipoib->netdev, rc );
479
+}
480
+
459 481
 /**
460 482
  * Join IPv4 broadcast multicast group
461 483
  *
@@ -466,7 +488,9 @@ static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
466 488
 	int rc;
467 489
 
468 490
 	if ( ( rc = ib_mcast_join ( ipoib->ibdev, ipoib->qp,
469
-				    &ipoib->broadcast.gid ) ) != 0 ) {
491
+				    &ipoib->broadcast_membership,
492
+				    &ipoib->broadcast.gid,
493
+				    ipoib_join_complete ) ) != 0 ) {
470 494
 		DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
471 495
 		       ipoib, strerror ( rc ) );
472 496
 		return rc;
@@ -485,7 +509,7 @@ static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
485 509
 
486 510
 	if ( ipoib->broadcast_joined ) {
487 511
 		ib_mcast_leave ( ipoib->ibdev, ipoib->qp,
488
-				 &ipoib->broadcast.gid );
512
+				 &ipoib->broadcast_membership );
489 513
 		ipoib->broadcast_joined = 0;
490 514
 	}
491 515
 }

+ 54
- 6
src/include/gpxe/ib_cm.h Näytä tiedosto

@@ -10,12 +10,60 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <gpxe/infiniband.h>
13
+#include <gpxe/retry.h>
13 14
 
14
-extern int ib_cm_connect ( struct ib_queue_pair *qp, struct ib_gid *dgid,
15
-			   struct ib_gid_half *service_id,
16
-			   void *private_data, size_t private_data_len,
17
-			   void ( * notify ) ( struct ib_queue_pair *qp,
18
-					       int rc, void *private_data,
19
-					       size_t private_data_len ) );
15
+struct ib_mad_transaction;
16
+struct ib_connection;
17
+
18
+/** Infiniband connection operations */
19
+struct ib_connection_operations {
20
+	/** Handle change of connection status
21
+	 *
22
+	 * @v ibdev		Infiniband device
23
+	 * @v qp		Queue pair
24
+	 * @v conn		Connection
25
+	 * @v rc		Connection status code
26
+	 * @v private_data	Private data, if available
27
+	 * @v private_data_len	Length of private data
28
+	 */
29
+	void ( * changed ) ( struct ib_device *ibdev, struct ib_queue_pair *qp,
30
+			     struct ib_connection *conn, int rc,
31
+			     void *private_data, size_t private_data_len );
32
+};
33
+
34
+/** An Infiniband connection */
35
+struct ib_connection {
36
+	/** Infiniband device */
37
+	struct ib_device *ibdev;
38
+	/** Queue pair */
39
+	struct ib_queue_pair *qp;
40
+	/** Local communication ID */
41
+	uint32_t local_id;
42
+	/** Remote communication ID */
43
+	uint32_t remote_id;
44
+	/** Target service ID */
45
+	struct ib_gid_half service_id;
46
+	/** Connection operations */
47
+	struct ib_connection_operations *op;
48
+
49
+	/** Path to target */
50
+	struct ib_path *path;
51
+	/** Connection request management transaction */
52
+	struct ib_mad_transaction *madx;
53
+
54
+	/** Length of connection request private data */
55
+	size_t private_data_len;
56
+	/** Connection request private data */
57
+	uint8_t private_data[0];
58
+};
59
+
60
+extern struct ib_connection *
61
+ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp,
62
+		 struct ib_gid *dgid, struct ib_gid_half *service_id,
63
+		 void *req_private_data, size_t req_private_data_len,
64
+		 struct ib_connection_operations *op );
65
+extern void ib_destroy_conn ( struct ib_device *ibdev,
66
+			      struct ib_queue_pair *qp,
67
+			      struct ib_connection *conn );
20 68
 
21 69
 #endif /* _GPXE_IB_CM_H */

+ 0
- 65
src/include/gpxe/ib_gma.h Näytä tiedosto

@@ -1,65 +0,0 @@
1
-#ifndef _GPXE_IB_GMA_H
2
-#define _GPXE_IB_GMA_H
3
-
4
-/** @file
5
- *
6
- * Infiniband General Management Agent
7
- *
8
- */
9
-
10
-FILE_LICENCE ( GPL2_OR_LATER );
11
-
12
-#include <gpxe/list.h>
13
-#include <gpxe/retry.h>
14
-#include <gpxe/tables.h>
15
-#include <gpxe/infiniband.h>
16
-
17
-struct ib_gma;
18
-
19
-/** A GMA attribute handler */
20
-struct ib_gma_handler {
21
-	/** Management class */
22
-	uint8_t mgmt_class;
23
-	/** Management class don't-care bits */
24
-	uint8_t mgmt_class_ignore;
25
-	/** Class version */
26
-	uint8_t class_version;
27
-	/** Method */
28
-	uint8_t method;
29
-	/** Attribute (in network byte order) */
30
-	uint16_t attr_id;
31
-	/** Handle attribute
32
-	 *
33
-	 * @v gma		General management agent
34
-	 * @v mad		MAD
35
-	 * @ret response	MAD response, or NULL to send no response
36
-	 */
37
-	union ib_mad * ( * handle ) ( struct ib_gma *gma, union ib_mad *mad );
38
-};
39
-
40
-/** GMA attribute handlers */
41
-#define IB_GMA_HANDLERS __table ( struct ib_gma_handler, "ib_gma_handlers" )
42
-
43
-/** Declare a GMA attribute handler */
44
-#define __ib_gma_handler __table_entry ( IB_GMA_HANDLERS, 01 )
45
-
46
-/** An Infiniband General Management Agent */
47
-struct ib_gma {
48
-	/** Infiniband device */
49
-	struct ib_device *ibdev;
50
-	/** Completion queue */
51
-	struct ib_completion_queue *cq;
52
-	/** Queue pair */
53
-	struct ib_queue_pair *qp;
54
-
55
-	/** List of outstanding MAD requests */
56
-	struct list_head requests;
57
-};
58
-
59
-extern int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad,
60
-			    struct ib_address_vector *av, int retry );
61
-extern struct ib_gma * ib_create_gma ( struct ib_device *ibdev,
62
-				       enum ib_queue_pair_type type );
63
-extern void ib_destroy_gma ( struct ib_gma *gma );
64
-
65
-#endif /* _GPXE_IB_GMA_H */

+ 11
- 0
src/include/gpxe/ib_mad.h Näytä tiedosto

@@ -303,6 +303,16 @@ union ib_sa_data {
303 303
 #define IB_CM_ATTR_LOAD_ALTERNATE_PATH		0x0019
304 304
 #define IB_CM_ATTR_ALTERNATE_PATH_RESPONSE	0x001a
305 305
 
306
+/** Communication management common fields */
307
+struct ib_cm_common {
308
+	/** Local communication ID */
309
+	uint32_t local_id;
310
+	/** Remote communication ID */
311
+	uint32_t remote_id;
312
+	/** Reserved */
313
+	uint8_t reserved[224];
314
+} __attribute__ (( packed ));
315
+
306 316
 /** A communication management path */
307 317
 struct ib_cm_path {
308 318
 	/** Local port LID */
@@ -438,6 +448,7 @@ struct ib_cm_ready_to_use {
438 448
 
439 449
 /** A communication management attribute */
440 450
 union ib_cm_data {
451
+	struct ib_cm_common common;
441 452
 	struct ib_cm_connect_request connect_request;
442 453
 	struct ib_cm_connect_reject connect_reject;
443 454
 	struct ib_cm_connect_reply connect_reply;

+ 31
- 2
src/include/gpxe/ib_mcast.h Näytä tiedosto

@@ -11,9 +11,38 @@ FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <gpxe/infiniband.h>
13 13
 
14
+struct ib_mad_transaction;
15
+
16
+/** An Infiniband multicast group membership */
17
+struct ib_mc_membership {
18
+	/** Queue pair */
19
+	struct ib_queue_pair *qp;
20
+	/** Multicast GID */
21
+	struct ib_gid gid;
22
+	/** Multicast group join transaction */
23
+	struct ib_mad_transaction *madx;
24
+	/** Handle join success/failure
25
+	 *
26
+	 * @v ibdev		Infiniband device
27
+	 * @v qp		Queue pair
28
+	 * @v membership	Multicast group membership
29
+	 * @v rc		Status code
30
+	 * @v mad		Response MAD (or NULL on error)
31
+	 */
32
+	void ( * complete ) ( struct ib_device *ibdev, struct ib_queue_pair *qp,
33
+			      struct ib_mc_membership *membership, int rc,
34
+			      union ib_mad *mad );
35
+};
36
+
14 37
 extern int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
15
-			   struct ib_gid *gid );
38
+			   struct ib_mc_membership *membership,
39
+			   struct ib_gid *gid,
40
+			   void ( * joined ) ( struct ib_device *ibdev,
41
+					       struct ib_queue_pair *qp,
42
+					       struct ib_mc_membership *memb,
43
+					       int rc, union ib_mad *mad ) );
44
+
16 45
 extern void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
17
-			     struct ib_gid *gid );
46
+			     struct ib_mc_membership *membership );
18 47
 
19 48
 #endif /* _GPXE_IB_MCAST_H */

+ 59
- 0
src/include/gpxe/ib_pathrec.h Näytä tiedosto

@@ -11,6 +11,65 @@ FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <gpxe/infiniband.h>
13 13
 
14
+struct ib_mad_transaction;
15
+struct ib_path;
16
+
17
+/** Infiniband path operations */
18
+struct ib_path_operations {
19
+	/** Handle path transaction completion
20
+	 *
21
+	 * @v ibdev		Infiniband device
22
+	 * @v path		Path
23
+	 * @v rc		Status code
24
+	 * @v av		Address vector, or NULL on error
25
+	 */
26
+	void ( * complete ) ( struct ib_device *ibdev,
27
+			      struct ib_path *path, int rc,
28
+			      struct ib_address_vector *av );
29
+};
30
+
31
+/** An Infiniband path */
32
+struct ib_path {
33
+	/** Infiniband device */
34
+	struct ib_device *ibdev;
35
+	/** Address vector */
36
+	struct ib_address_vector av;
37
+	/** Management transaction */
38
+	struct ib_mad_transaction *madx;
39
+	/** Path operations */
40
+	struct ib_path_operations *op;
41
+	/** Owner private data */
42
+	void *owner_priv;
43
+};
44
+
45
+/**
46
+ * Set Infiniband path owner-private data
47
+ *
48
+ * @v path		Path
49
+ * @v priv		Private data
50
+ */
51
+static inline __always_inline void
52
+ib_path_set_ownerdata ( struct ib_path *path, void *priv ) {
53
+	path->owner_priv = priv;
54
+}
55
+
56
+/**
57
+ * Get Infiniband path owner-private data
58
+ *
59
+ * @v path		Path
60
+ * @ret priv		Private data
61
+ */
62
+static inline __always_inline void *
63
+ib_path_get_ownerdata ( struct ib_path *path ) {
64
+	return path->owner_priv;
65
+}
66
+
67
+extern struct ib_path *
68
+ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
69
+		 struct ib_path_operations *op );
70
+extern void ib_destroy_path ( struct ib_device *ibdev,
71
+			      struct ib_path *path );
72
+
14 73
 extern int ib_resolve_path ( struct ib_device *ibdev,
15 74
 			     struct ib_address_vector *av );
16 75
 

+ 2
- 3
src/include/gpxe/infiniband.h Näytä tiedosto

@@ -46,7 +46,6 @@ struct ib_queue_pair;
46 46
 struct ib_address_vector;
47 47
 struct ib_completion_queue;
48 48
 struct ib_mad_interface;
49
-struct ib_gma;
50 49
 
51 50
 /** Infiniband transmission rates */
52 51
 enum ib_rate {
@@ -416,8 +415,8 @@ struct ib_device {
416 415
 
417 416
 	/** Subnet management interface */
418 417
 	struct ib_mad_interface *smi;
419
-	/** General management agent */
420
-	struct ib_gma *gma;
418
+	/** General services interface */
419
+	struct ib_mad_interface *gsi;
421 420
 
422 421
 	/** Driver private data */
423 422
 	void *drv_priv;

+ 8
- 9
src/net/infiniband.c Näytä tiedosto

@@ -35,7 +35,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
35 35
 #include <gpxe/infiniband.h>
36 36
 #include <gpxe/ib_mi.h>
37 37
 #include <gpxe/ib_sma.h>
38
-#include <gpxe/ib_gma.h>
39 38
 
40 39
 /** @file
41 40
  *
@@ -551,12 +550,12 @@ int ib_open ( struct ib_device *ibdev ) {
551 550
 		goto err_create_sma;
552 551
 	}
553 552
 
554
-	/* Create general management agent */
555
-	ibdev->gma = ib_create_gma ( ibdev, IB_QPT_GSI );
556
-	if ( ! ibdev->gma ) {
557
-		DBGC ( ibdev, "IBDEV %p could not create GMA\n", ibdev );
553
+	/* Create general services interface */
554
+	ibdev->gsi = ib_create_mi ( ibdev, IB_QPT_GSI );
555
+	if ( ! ibdev->gsi ) {
556
+		DBGC ( ibdev, "IBDEV %p could not create GSI\n", ibdev );
558 557
 		rc = -ENOMEM;
559
-		goto err_create_gma;
558
+		goto err_create_gsi;
560 559
 	}
561 560
 
562 561
 	/* Open device */
@@ -571,8 +570,8 @@ int ib_open ( struct ib_device *ibdev ) {
571 570
 
572 571
 	ibdev->op->close ( ibdev );
573 572
  err_open:
574
-	ib_destroy_gma ( ibdev->gma );
575
- err_create_gma:
573
+	ib_destroy_mi ( ibdev, ibdev->gsi );
574
+ err_create_gsi:
576 575
 	ib_destroy_sma ( ibdev, ibdev->smi );
577 576
  err_create_sma:
578 577
 	ib_destroy_mi ( ibdev, ibdev->smi );
@@ -594,7 +593,7 @@ void ib_close ( struct ib_device *ibdev ) {
594 593
 
595 594
 	/* Close device if this was the last remaining requested opening */
596 595
 	if ( ibdev->open_count == 0 ) {
597
-		ib_destroy_gma ( ibdev->gma );
596
+		ib_destroy_mi ( ibdev, ibdev->gsi );
598 597
 		ib_destroy_sma ( ibdev, ibdev->smi );
599 598
 		ib_destroy_mi ( ibdev, ibdev->smi );
600 599
 		ibdev->op->close ( ibdev );

+ 238
- 235
src/net/infiniband/ib_cm.c Näytä tiedosto

@@ -24,10 +24,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
24 24
 #include <byteswap.h>
25 25
 #include <errno.h>
26 26
 #include <assert.h>
27
-#include <gpxe/list.h>
28
-#include <gpxe/process.h>
29 27
 #include <gpxe/infiniband.h>
30
-#include <gpxe/ib_gma.h>
28
+#include <gpxe/ib_mi.h>
31 29
 #include <gpxe/ib_pathrec.h>
32 30
 #include <gpxe/ib_cm.h>
33 31
 
@@ -38,64 +36,170 @@ FILE_LICENCE ( GPL2_OR_LATER );
38 36
  *
39 37
  */
40 38
 
41
-/** An outstanding connection request */
42
-struct ib_cm_request {
43
-	/** List of all outstanding requests */
44
-	struct list_head list;
45
-	/** Local communication ID */
46
-	uint32_t local_id;
47
-	/** Remote communication ID */
48
-	uint32_t remote_id;
49
-	/** Queue pair */
50
-	struct ib_queue_pair *qp;
51
-	/** Target service ID */
52
-	struct ib_gid_half service_id;
53
-	/** Connection process */
54
-	struct process process;
55
-	/** Notification handler
56
-	 *
57
-	 * @v qp		Queue pair
58
-	 * @v rc		Connection status code
59
-	 * @v private_data	Private data
60
-	 * @v private_data_len	Length of private data
61
-	 */
62
-	void ( * notify ) ( struct ib_queue_pair *qp, int rc,
63
-			    void *private_data, size_t private_data_len );
64
-	/** Private data length */
65
-	size_t private_data_len;
66
-	/** Private data */
67
-	uint8_t private_data[0];
68
-};
39
+/**
40
+ * Send "ready to use" response
41
+ *
42
+ * @v ibdev		Infiniband device
43
+ * @v mi		Management interface
44
+ * @v conn		Connection
45
+ * @v av		Address vector
46
+ * @ret rc		Return status code
47
+ */
48
+static int ib_cm_send_rtu ( struct ib_device *ibdev,
49
+			    struct ib_mad_interface *mi,
50
+			    struct ib_connection *conn,
51
+			    struct ib_address_vector *av ) {
52
+	union ib_mad mad;
53
+	struct ib_cm_ready_to_use *ready =
54
+		&mad.cm.cm_data.ready_to_use;
55
+	int rc;
56
+
57
+	/* Construct "ready to use" response */
58
+	memset ( &mad, 0, sizeof ( mad ) );
59
+	mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
60
+	mad.hdr.class_version = IB_CM_CLASS_VERSION;
61
+	mad.hdr.method = IB_MGMT_METHOD_SEND;
62
+	mad.hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
63
+	ready->local_id = htonl ( conn->local_id );
64
+	ready->remote_id = htonl ( conn->remote_id );
65
+	if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
66
+		DBGC ( conn, "CM %p could not send RTU: %s\n",
67
+		       conn, strerror ( rc ) );
68
+		return rc;
69
+	}
69 70
 
70
-/** List of all outstanding connection requests */
71
-static LIST_HEAD ( ib_cm_requests );
71
+	return 0;
72
+}
72 73
 
73 74
 /**
74
- * Send connection request
75
+ * Handle connection request transaction completion
75 76
  *
76
- * @v request		Connection request
77
- * @ret rc		Return status code
77
+ * @v ibdev		Infiniband device
78
+ * @v mi		Management interface
79
+ * @v madx		Management transaction
80
+ * @v rc		Status code
81
+ * @v mad		Received MAD (or NULL on error)
82
+ * @v av		Source address vector (or NULL on error)
78 83
  */
79
-static int ib_cm_send_request ( struct ib_cm_request *request ) {
80
-	struct ib_queue_pair *qp = request->qp;
81
-	struct ib_device *ibdev = qp->ibdev;
82
-	struct ib_gma *gma = ibdev->gma;
84
+static void ib_cm_req_complete ( struct ib_device *ibdev,
85
+				 struct ib_mad_interface *mi,
86
+				 struct ib_mad_transaction *madx,
87
+				 int rc, union ib_mad *mad,
88
+				 struct ib_address_vector *av ) {
89
+	struct ib_connection *conn = ib_madx_get_ownerdata ( madx );
90
+	struct ib_queue_pair *qp = conn->qp;
91
+	struct ib_cm_common *common = &mad->cm.cm_data.common;
92
+	struct ib_cm_connect_reply *connect_rep =
93
+		&mad->cm.cm_data.connect_reply;
94
+	struct ib_cm_connect_reject *connect_rej =
95
+		&mad->cm.cm_data.connect_reject;
96
+	void *private_data = NULL;
97
+	size_t private_data_len = 0;
98
+
99
+	/* Report failures */
100
+	if ( rc != 0 ) {
101
+		DBGC ( conn, "CM %p connection request failed: %s\n",
102
+		       conn, strerror ( rc ) );
103
+		goto out;
104
+	}
105
+
106
+	/* Record remote communication ID */
107
+	conn->remote_id = ntohl ( common->local_id );
108
+
109
+	/* Handle response */
110
+	switch ( mad->hdr.attr_id ) {
111
+
112
+	case htons ( IB_CM_ATTR_CONNECT_REPLY ) :
113
+		/* Extract fields */
114
+		qp->av.qpn = ( ntohl ( connect_rep->local_qpn ) >> 8 );
115
+		qp->send.psn = ( ntohl ( connect_rep->starting_psn ) >> 8 );
116
+		private_data = &connect_rep->private_data;
117
+		private_data_len = sizeof ( connect_rep->private_data );
118
+		DBGC ( conn, "CM %p connected to QPN %lx PSN %x\n",
119
+		       conn, qp->av.qpn, qp->send.psn );
120
+
121
+		/* Modify queue pair */
122
+		if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
123
+			DBGC ( conn, "CM %p could not modify queue pair: %s\n",
124
+			       conn, strerror ( rc ) );
125
+			goto out;
126
+		}
127
+
128
+		/* Send "ready to use" reply */
129
+		if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
130
+			/* Treat as non-fatal */
131
+			rc = 0;
132
+		}
133
+		break;
134
+
135
+	case htons ( IB_CM_ATTR_CONNECT_REJECT ) :
136
+		/* Extract fields */
137
+		DBGC ( conn, "CM %p connection rejected (reason %d)\n",
138
+		       conn, ntohs ( connect_rej->reason ) );
139
+		private_data = &connect_rej->private_data;
140
+		private_data_len = sizeof ( connect_rej->private_data );
141
+		rc = -ENOTCONN;
142
+		break;
143
+
144
+	default:
145
+		DBGC ( conn, "CM %p unexpected response (attribute %04x)\n",
146
+		       conn, ntohs ( mad->hdr.attr_id ) );
147
+		rc = -EIO;
148
+		break;
149
+	}
150
+
151
+ out:
152
+	/* Destroy the completed transaction */
153
+	ib_destroy_madx ( ibdev, ibdev->gsi, madx );
154
+	conn->madx = NULL;
155
+
156
+	/* Hand off to the upper completion handler */
157
+	conn->op->changed ( ibdev, qp, conn, rc, private_data,
158
+			    private_data_len );
159
+}
160
+
161
+/** Connection request operations */
162
+static struct ib_mad_transaction_operations ib_cm_req_op = {
163
+	.complete = ib_cm_req_complete,
164
+};
165
+
166
+/**
167
+ * Handle connection path transaction completion
168
+ *
169
+ * @v ibdev		Infiniband device
170
+ * @v path		Path
171
+ * @v rc		Status code
172
+ * @v av		Address vector, or NULL on error
173
+ */
174
+static void ib_cm_path_complete ( struct ib_device *ibdev,
175
+				  struct ib_path *path, int rc,
176
+				  struct ib_address_vector *av ) {
177
+	struct ib_connection *conn = ib_path_get_ownerdata ( path );
178
+	struct ib_queue_pair *qp = conn->qp;
83 179
 	union ib_mad mad;
84
-	struct ib_mad_cm *cm = &mad.cm;
85 180
 	struct ib_cm_connect_request *connect_req =
86
-		&cm->cm_data.connect_request;
181
+		&mad.cm.cm_data.connect_request;
87 182
 	size_t private_data_len;
88
-	int rc;
183
+
184
+	/* Report failures */
185
+	if ( rc != 0 ) {
186
+		DBGC ( conn, "CM %p path lookup failed: %s\n",
187
+		       conn, strerror ( rc ) );
188
+		conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
189
+		goto out;
190
+	}
191
+
192
+	/* Update queue pair peer path */
193
+	memcpy ( &qp->av, av, sizeof ( qp->av ) );
89 194
 
90 195
 	/* Construct connection request */
91
-	memset ( cm, 0, sizeof ( *cm ) );
92
-	cm->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
93
-	cm->mad_hdr.mgmt_class = IB_MGMT_CLASS_CM;
94
-	cm->mad_hdr.class_version = IB_CM_CLASS_VERSION;
95
-	cm->mad_hdr.method = IB_MGMT_METHOD_SEND;
96
-	cm->mad_hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
97
-	connect_req->local_id = htonl ( request->local_id );
98
-	memcpy ( &connect_req->service_id, &request->service_id,
196
+	memset ( &mad, 0, sizeof ( mad ) );
197
+	mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
198
+	mad.hdr.class_version = IB_CM_CLASS_VERSION;
199
+	mad.hdr.method = IB_MGMT_METHOD_SEND;
200
+	mad.hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
201
+	connect_req->local_id = htonl ( conn->local_id );
202
+	memcpy ( &connect_req->service_id, &conn->service_id,
99 203
 		 sizeof ( connect_req->service_id ) );
100 204
 	ib_get_hca_info ( ibdev, &connect_req->local_ca );
101 205
 	connect_req->local_qpn__responder_resources =
@@ -113,217 +217,116 @@ static int ib_cm_send_request ( struct ib_cm_request *request ) {
113 217
 	connect_req->max_cm_retries__srq =
114 218
 		( ( 0x0f << 4 ) | ( 0 << 3 ) );
115 219
 	connect_req->primary.local_lid = htons ( ibdev->lid );
116
-	connect_req->primary.remote_lid = htons ( request->qp->av.lid );
220
+	connect_req->primary.remote_lid = htons ( conn->qp->av.lid );
117 221
 	memcpy ( &connect_req->primary.local_gid, &ibdev->gid,
118 222
 		 sizeof ( connect_req->primary.local_gid ) );
119
-	memcpy ( &connect_req->primary.remote_gid, &request->qp->av.gid,
223
+	memcpy ( &connect_req->primary.remote_gid, &conn->qp->av.gid,
120 224
 		 sizeof ( connect_req->primary.remote_gid ) );
121 225
 	connect_req->primary.flow_label__rate =
122
-		htonl ( ( 0 << 12 ) | ( request->qp->av.rate << 0 ) );
226
+		htonl ( ( 0 << 12 ) | ( conn->qp->av.rate << 0 ) );
123 227
 	connect_req->primary.hop_limit = 0;
124 228
 	connect_req->primary.sl__subnet_local =
125
-		( ( request->qp->av.sl << 4 ) | ( 1 << 3 ) );
229
+		( ( conn->qp->av.sl << 4 ) | ( 1 << 3 ) );
126 230
 	connect_req->primary.local_ack_timeout = ( 0x13 << 3 );
127
-	private_data_len = request->private_data_len;
231
+	private_data_len = conn->private_data_len;
128 232
 	if ( private_data_len > sizeof ( connect_req->private_data ) )
129 233
 		private_data_len = sizeof ( connect_req->private_data );
130
-	memcpy ( &connect_req->private_data, &request->private_data,
234
+	memcpy ( &connect_req->private_data, &conn->private_data,
131 235
 		 private_data_len );
132 236
 
133
-	/* Send request */
134
-	if ( ( rc = ib_gma_request ( gma, &mad, NULL, 1 ) ) != 0 ) {
135
-		DBGC ( gma, "GMA %p could not send connection request: %s\n",
136
-		       gma, strerror ( rc ) );
137
-		return rc;
138
-	}
139
-
140
-	return 0;
141
-
142
-}
143
-
144
-/**
145
- * Connection request process step
146
- *
147
- * @v process		Connection request process
148
- */
149
-static void ib_cm_step ( struct process *process ) {
150
-	struct ib_cm_request *request =
151
-		container_of ( process, struct ib_cm_request, process );
152
-	struct ib_queue_pair *qp = request->qp;
153
-	struct ib_device *ibdev = qp->ibdev;
154
-	int rc;
155
-
156
-	/* Wait until path can be resolved */
157
-	if ( ( rc = ib_resolve_path ( ibdev, &request->qp->av ) ) != 0 )
158
-		return;
159
-
160
-	/* Wait until request can be sent */
161
-	if ( ( rc = ib_cm_send_request ( request ) ) != 0 )
162
-		return;
163
-
164
-	/* Stop process */
165
-	process_del ( process );
166
-}
167
-
168
-/**
169
- * Identify connection request by communication ID
170
- *
171
- * @v local_id		Local communication ID
172
- * @v remote_id		Remote communication ID
173
- * @ret request		Connection request, or NULL
174
- */
175
-static struct ib_cm_request * ib_cm_find_request ( uint32_t local_id,
176
-						   uint32_t remote_id ) {
177
-	struct ib_cm_request *request;
178
-
179
-	list_for_each_entry ( request, &ib_cm_requests, list ) {
180
-		if ( request->local_id == local_id ) {
181
-			request->remote_id = remote_id;
182
-			return request;
183
-		}
184
-	}
185
-	return NULL;
186
-}
187
-
188
-/**
189
- * Handle connection reply
190
- *
191
- * @v gma		General management agent
192
- * @v mad		MAD
193
- * @ret response	MAD response
194
- */
195
-static union ib_mad * ib_cm_connect_reply ( struct ib_gma *gma,
196
-					    union ib_mad *mad ) {
197
-	struct ib_cm_connect_reply *connect_rep =
198
-		&mad->cm.cm_data.connect_reply;
199
-	struct ib_cm_ready_to_use *ready =
200
-		&mad->cm.cm_data.ready_to_use;
201
-	struct ib_cm_request *request;
202
-	int rc;
203
-
204
-	/* Identify request */
205
-	request = ib_cm_find_request ( ntohl ( connect_rep->remote_id ),
206
-				       ntohl ( connect_rep->local_id ) );
207
-	if ( ! request ) {
208
-		DBGC ( gma, "GMA %p received connection reply with unknown "
209
-		       "ID %08x\n", gma, ntohl ( connect_rep->remote_id ) );
210
-		return NULL;
237
+	/* Create connection request */
238
+	conn->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
239
+				      &ib_cm_req_op );
240
+	if ( ! conn->madx ) {
241
+		DBGC ( conn, "CM %p could not create connection request\n",
242
+		       conn );
243
+		conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
244
+		goto out;
211 245
 	}
246
+	ib_madx_set_ownerdata ( conn->madx, conn );
212 247
 
213
-	/* Extract fields */
214
-	request->qp->av.qpn = ( ntohl ( connect_rep->local_qpn ) >> 8 );
215
-	request->qp->send.psn = ( ntohl ( connect_rep->starting_psn ) >> 8 );
216
-	DBGC ( gma, "GMA %p QPN %lx connected to QPN %lx PSN %x\n", gma,
217
-	       request->qp->qpn, request->qp->av.qpn, request->qp->send.psn );
218
-
219
-	/* Modify queue pair */
220
-	if ( ( rc = ib_modify_qp ( request->qp->ibdev, request->qp ) ) != 0 ) {
221
-		DBGC ( gma, "GMA %p QPN %lx could not modify queue pair: %s\n",
222
-		       gma, request->qp->qpn, strerror ( rc ) );
223
-		return NULL;
224
-	}
225
-
226
-	/* Inform recipient that we are now connected */
227
-	request->notify ( request->qp, 0, &connect_rep->private_data,
228
-			  sizeof ( connect_rep->private_data ) );
229
-
230
-	/* Construct ready to use reply */
231
-	mad->hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
232
-	memset ( ready, 0, sizeof ( *ready ) );
233
-	ready->local_id = htonl ( request->local_id );
234
-	ready->remote_id = htonl ( request->remote_id );
235
-
236
-	return mad;
248
+ out:
249
+	/* Destroy the completed transaction */
250
+	ib_destroy_path ( ibdev, path );
251
+	conn->path = NULL;
237 252
 }
238 253
 
239
-/**
240
- * Handle connection rejection
241
- *
242
- * @v gma		General management agent
243
- * @v mad		MAD
244
- * @ret response	MAD response
245
- */
246
-static union ib_mad * ib_cm_connect_reject ( struct ib_gma *gma,
247
-					     union ib_mad *mad ) {
248
-	struct ib_cm_connect_reject *connect_rej =
249
-		&mad->cm.cm_data.connect_reject;
250
-	struct ib_cm_request *request;
251
-	uint16_t reason;
252
-
253
-	/* Identify request */
254
-	request = ib_cm_find_request ( ntohl ( connect_rej->remote_id ),
255
-				       ntohl ( connect_rej->local_id ) );
256
-	if ( ! request ) {
257
-		DBGC ( gma, "GMA %p received connection rejection with "
258
-		       "unknown ID %08x\n", gma,
259
-		       ntohl ( connect_rej->remote_id ) );
260
-		return NULL;
261
-	}
262
-
263
-	/* Extract fields */
264
-	reason = ntohs ( connect_rej->reason );
265
-	DBGC ( gma, "GMA %p QPN %lx connection rejected (reason %d)\n",
266
-	       gma, request->qp->qpn, reason );
267
-
268
-	/* Inform recipient that we are now disconnected */
269
-	request->notify ( request->qp, -ENOTCONN, &connect_rej->private_data,
270
-			  sizeof ( connect_rej->private_data ) );
271
-
272
-	return NULL;
273
-}
274
-
275
-/** Communication management MAD handlers */
276
-struct ib_gma_handler ib_cm_handlers[] __ib_gma_handler = {
277
-	{
278
-		.mgmt_class = IB_MGMT_CLASS_CM,
279
-		.class_version = IB_CM_CLASS_VERSION,
280
-		.method = IB_MGMT_METHOD_SEND,
281
-		.attr_id = htons ( IB_CM_ATTR_CONNECT_REPLY ),
282
-		.handle = ib_cm_connect_reply,
283
-	},
284
-	{
285
-		.mgmt_class = IB_MGMT_CLASS_CM,
286
-		.class_version = IB_CM_CLASS_VERSION,
287
-		.method = IB_MGMT_METHOD_SEND,
288
-		.attr_id = htons ( IB_CM_ATTR_CONNECT_REJECT ),
289
-		.handle = ib_cm_connect_reject,
290
-	},
254
+/** Connection path operations */
255
+static struct ib_path_operations ib_cm_path_op = {
256
+	.complete = ib_cm_path_complete,
291 257
 };
292 258
 
293 259
 /**
294
- * Connect to remote QP
260
+ * Create connection to remote QP
295 261
  *
262
+ * @v ibdev		Infiniband device
296 263
  * @v qp		Queue pair
297 264
  * @v dgid		Target GID
298 265
  * @v service_id	Target service ID
299
- * @v private_data	Private data
300
- * @v private_data_len	Length of private data
301
- * @ret rc		Return status code
266
+ * @v private_data	Connection request private data
267
+ * @v private_data_len	Length of connection request private data
268
+ * @v op		Connection operations
269
+ * @ret conn		Connection
302 270
  */
303
-int ib_cm_connect ( struct ib_queue_pair *qp, struct ib_gid *dgid,
304
-		    struct ib_gid_half *service_id,
305
-		    void *private_data, size_t private_data_len,
306
-		    void ( * notify ) ( struct ib_queue_pair *qp, int rc,
307
-					void *private_data,
308
-					size_t private_data_len ) ) {
309
-	struct ib_cm_request *request;
271
+struct ib_connection *
272
+ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp,
273
+		 struct ib_gid *dgid, struct ib_gid_half *service_id,
274
+		 void *private_data, size_t private_data_len,
275
+		 struct ib_connection_operations *op ) {
276
+	struct ib_connection *conn;
310 277
 
311 278
 	/* Allocate and initialise request */
312
-	request = zalloc ( sizeof ( *request ) + private_data_len );
313
-	if ( ! request )
314
-		return -ENOMEM;
315
-	list_add ( &request->list, &ib_cm_requests );
316
-	request->local_id = random();
317
-	request->qp = qp;
279
+	conn = zalloc ( sizeof ( *conn ) + private_data_len );
280
+	if ( ! conn )
281
+		goto err_alloc_conn;
282
+	conn->ibdev = ibdev;
283
+	conn->qp = qp;
318 284
 	memset ( &qp->av, 0, sizeof ( qp->av ) );
319 285
 	qp->av.gid_present = 1;
320 286
 	memcpy ( &qp->av.gid, dgid, sizeof ( qp->av.gid ) );
321
-	memcpy ( &request->service_id, service_id,
322
-		 sizeof ( request->service_id ) );
323
-	request->notify = notify;
324
-	request->private_data_len = private_data_len;
325
-	memcpy ( &request->private_data, private_data, private_data_len );
326
-	process_init ( &request->process, ib_cm_step, NULL );
287
+	conn->local_id = random();
288
+	memcpy ( &conn->service_id, service_id, sizeof ( conn->service_id ) );
289
+	conn->op = op;
290
+	conn->private_data_len = private_data_len;
291
+	memcpy ( &conn->private_data, private_data, private_data_len );
292
+
293
+	/* Create path */
294
+	conn->path = ib_create_path ( ibdev, &qp->av, &ib_cm_path_op );
295
+	if ( ! conn->path )
296
+		goto err_create_path;
297
+	ib_path_set_ownerdata ( conn->path, conn );
298
+
299
+	DBGC ( conn, "CM %p created for IBDEV %p QPN %lx\n",
300
+	       conn, ibdev, qp->qpn );
301
+	DBGC ( conn, "CM %p connecting to %08x:%08x:%08x:%08x %08x:%08x\n",
302
+	       conn, ntohl ( dgid->u.dwords[0] ), ntohl ( dgid->u.dwords[1] ),
303
+	       ntohl ( dgid->u.dwords[2] ), ntohl ( dgid->u.dwords[3] ),
304
+	       ntohl ( service_id->u.dwords[0] ),
305
+	       ntohl ( service_id->u.dwords[1] ) );
306
+
307
+	return conn;
308
+
309
+	ib_destroy_path ( ibdev, conn->path );
310
+ err_create_path:
311
+	free ( conn );
312
+ err_alloc_conn:
313
+	return NULL;
314
+}
327 315
 
328
-	return 0;
316
+/**
317
+ * Destroy connection to remote QP
318
+ *
319
+ * @v ibdev		Infiniband device
320
+ * @v qp		Queue pair
321
+ * @v conn		Connection
322
+ */
323
+void ib_destroy_conn ( struct ib_device *ibdev,
324
+		       struct ib_queue_pair *qp __unused,
325
+		       struct ib_connection *conn ) {
326
+
327
+	if ( conn->madx )
328
+		ib_destroy_madx ( ibdev, ibdev->gsi, conn->madx );
329
+	if ( conn->path )
330
+		ib_destroy_path ( ibdev, conn->path );
331
+	free ( conn );
329 332
 }

+ 0
- 403
src/net/infiniband/ib_gma.c Näytä tiedosto

@@ -1,403 +0,0 @@
1
-/*
2
- * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License as
6
- * published by the Free Software Foundation; either version 2 of the
7
- * License, or any later version.
8
- *
9
- * This program is distributed in the hope that it will be useful, but
10
- * WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
- * General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program; if not, write to the Free Software
16
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
- */
18
-
19
-FILE_LICENCE ( GPL2_OR_LATER );
20
-
21
-#include <stdint.h>
22
-#include <stdlib.h>
23
-#include <string.h>
24
-#include <errno.h>
25
-#include <stdio.h>
26
-#include <unistd.h>
27
-#include <byteswap.h>
28
-#include <gpxe/infiniband.h>
29
-#include <gpxe/iobuf.h>
30
-#include <gpxe/ib_gma.h>
31
-
32
-/**
33
- * @file
34
- *
35
- * Infiniband General Management Agent
36
- *
37
- */
38
-
39
-/** A MAD request */
40
-struct ib_mad_request {
41
-	/** Associated GMA */
42
-	struct ib_gma *gma;
43
-	/** List of outstanding MAD requests */
44
-	struct list_head list;
45
-	/** Retry timer */
46
-	struct retry_timer timer;
47
-	/** Destination address */
48
-	struct ib_address_vector av;
49
-	/** MAD request */
50
-	union ib_mad mad;
51
-};
52
-
53
-/** GMA number of send WQEs
54
- *
55
- * This is a policy decision.
56
- */
57
-#define IB_GMA_NUM_SEND_WQES 4
58
-
59
-/** GMA number of receive WQEs
60
- *
61
- * This is a policy decision.
62
- */
63
-#define IB_GMA_NUM_RECV_WQES 2
64
-
65
-/** GMA number of completion queue entries
66
- *
67
- * This is a policy decision
68
- */
69
-#define IB_GMA_NUM_CQES 8
70
-
71
-/** TID magic signature */
72
-#define IB_GMA_TID_MAGIC ( ( 'g' << 24 ) | ( 'P' << 16 ) | ( 'X' << 8 ) | 'E' )
73
-
74
-/** TID to use for next MAD request */
75
-static unsigned int next_request_tid;
76
-
77
-/*****************************************************************************
78
- *
79
- * General management agent
80
- *
81
- *****************************************************************************
82
- */
83
-
84
-/**
85
- * Call attribute handler
86
- *
87
- * @v gma		General management agent
88
- * @v mad		MAD
89
- * @ret mad		MAD response
90
- */
91
-static union ib_mad * ib_handle_mad ( struct ib_gma *gma, union ib_mad *mad ) {
92
-	struct ib_mad_hdr *hdr = &mad->hdr;
93
-	struct ib_gma_handler *handler;
94
-
95
-	for_each_table_entry ( handler, IB_GMA_HANDLERS ) {
96
-		if ( ( ( handler->mgmt_class & ~handler->mgmt_class_ignore ) ==
97
-		       ( hdr->mgmt_class & ~handler->mgmt_class_ignore ) ) &&
98
-		     ( handler->class_version == hdr->class_version ) &&
99
-		     ( handler->method == hdr->method ) &&
100
-		     ( handler->attr_id == hdr->attr_id ) ) {
101
-			return handler->handle ( gma, mad );
102
-		}
103
-	}
104
-
105
-	hdr->method = IB_MGMT_METHOD_TRAP;
106
-	hdr->status = htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
107
-	return mad;
108
-}
109
-
110
-/**
111
- * Complete GMA receive
112
- *
113
- *
114
- * @v ibdev		Infiniband device
115
- * @v qp		Queue pair
116
- * @v av		Address vector
117
- * @v iobuf		I/O buffer
118
- * @v rc		Completion status code
119
- */
120
-static void ib_gma_complete_recv ( struct ib_device *ibdev,
121
-				   struct ib_queue_pair *qp,
122
-				   struct ib_address_vector *av,
123
-				   struct io_buffer *iobuf, int rc ) {
124
-	struct ib_gma *gma = ib_qp_get_ownerdata ( qp );
125
-	struct ib_mad_request *request;
126
-	union ib_mad *mad;
127
-	struct ib_mad_hdr *hdr;
128
-	union ib_mad *response;
129
-
130
-	/* Ignore errors */
131
-	if ( rc != 0 ) {
132
-		DBGC ( gma, "GMA %p RX error: %s\n", gma, strerror ( rc ) );
133
-		goto out;
134
-	}
135
-
136
-	/* Sanity checks */
137
-	if ( iob_len ( iobuf ) != sizeof ( *mad ) ) {
138
-		DBGC ( gma, "GMA %p RX bad size (%zd bytes)\n",
139
-		       gma, iob_len ( iobuf ) );
140
-		DBGC_HDA ( gma, 0, iobuf->data, iob_len ( iobuf ) );
141
-		goto out;
142
-	}
143
-	mad = iobuf->data;
144
-	hdr = &mad->hdr;
145
-	if ( hdr->base_version != IB_MGMT_BASE_VERSION ) {
146
-		DBGC ( gma, "GMA %p unsupported base version %x\n",
147
-		       gma, hdr->base_version );
148
-		DBGC_HDA ( gma, 0, mad, sizeof ( *mad ) );
149
-		goto out;
150
-	}
151
-	DBGC ( gma, "GMA %p RX TID %08x%08x (%02x,%02x,%02x,%04x) status "
152
-	       "%04x\n", gma, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
153
-	       hdr->mgmt_class, hdr->class_version, hdr->method,
154
-	       ntohs ( hdr->attr_id ), ntohs ( hdr->status ) );
155
-	DBGC2_HDA ( gma, 0, mad, sizeof ( *mad ) );
156
-
157
-	/* Dequeue request if applicable */
158
-	list_for_each_entry ( request, &gma->requests, list ) {
159
-		if ( memcmp ( &request->mad.hdr.tid, &hdr->tid,
160
-			      sizeof ( request->mad.hdr.tid ) ) == 0 ) {
161
-			stop_timer ( &request->timer );
162
-			list_del ( &request->list );
163
-			free ( request );
164
-			break;
165
-		}
166
-	}
167
-
168
-	/* Handle MAD */
169
-	if ( ( response = ib_handle_mad ( gma, mad ) ) == NULL )
170
-		goto out;
171
-
172
-	/* Re-use I/O buffer for response */
173
-	memcpy ( mad, response, sizeof ( *mad ) );
174
-	DBGC ( gma, "GMA %p TX TID %08x%08x (%02x,%02x,%02x,%04x) status "
175
-	       "%04x\n", gma, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
176
-	       hdr->mgmt_class, hdr->class_version, hdr->method,
177
-	       ntohs ( hdr->attr_id ), ntohs ( hdr->status ) );
178
-	DBGC2_HDA ( gma, 0, mad, sizeof ( *mad ) );
179
-
180
-	/* Send MAD response, if applicable */
181
-	if ( ( rc = ib_post_send ( ibdev, qp, av,
182
-				   iob_disown ( iobuf ) ) ) != 0 ) {
183
-		DBGC ( gma, "GMA %p could not send MAD response: %s\n",
184
-		       gma, strerror ( rc ) );
185
-		goto out;
186
-	}
187
-
188
- out:
189
-	free_iob ( iobuf );
190
-}
191
-
192
-/** GMA completion operations */
193
-static struct ib_completion_queue_operations ib_gma_completion_ops = {
194
-	.complete_recv = ib_gma_complete_recv,
195
-};
196
-
197
-/**
198
- * Transmit MAD request
199
- *
200
- * @v gma		General management agent
201
- * @v request		MAD request
202
- * @ret rc		Return status code
203
- */
204
-static int ib_gma_send ( struct ib_gma *gma, struct ib_mad_request *request ) {
205
-	struct io_buffer *iobuf;
206
-	int rc;
207
-
208
-	DBGC ( gma, "GMA %p TX TID %08x%08x (%02x,%02x,%02x,%04x)\n",
209
-	       gma, ntohl ( request->mad.hdr.tid[0] ),
210
-	       ntohl ( request->mad.hdr.tid[1] ), request->mad.hdr.mgmt_class,
211
-	       request->mad.hdr.class_version, request->mad.hdr.method,
212
-	       ntohs ( request->mad.hdr.attr_id ) );
213
-	DBGC2_HDA ( gma, 0, &request->mad, sizeof ( request->mad ) );
214
-
215
-	/* Construct I/O buffer */
216
-	iobuf = alloc_iob ( sizeof ( request->mad ) );
217
-	if ( ! iobuf ) {
218
-		DBGC ( gma, "GMA %p could not allocate buffer for TID "
219
-		       "%08x%08x\n", gma, ntohl ( request->mad.hdr.tid[0] ),
220
-		       ntohl ( request->mad.hdr.tid[1] ) );
221
-		return -ENOMEM;
222
-	}
223
-	memcpy ( iob_put ( iobuf, sizeof ( request->mad ) ), &request->mad,
224
-		 sizeof ( request->mad ) );
225
-
226
-	/* Send I/O buffer */
227
-	if ( ( rc = ib_post_send ( gma->ibdev, gma->qp, &request->av,
228
-				   iobuf ) ) != 0 ) {
229
-		DBGC ( gma, "GMA %p could not send TID %08x%08x: %s\n",
230
-		       gma,  ntohl ( request->mad.hdr.tid[0] ),
231
-		       ntohl ( request->mad.hdr.tid[1] ), strerror ( rc ) );
232
-		free_iob ( iobuf );
233
-		return rc;
234
-	}
235
-
236
-	return 0;
237
-}
238
-
239
-/**
240
- * Handle MAD request timer expiry
241
- *
242
- * @v timer		Retry timer
243
- * @v expired		Failure indicator
244
- */
245
-static void ib_gma_timer_expired ( struct retry_timer *timer, int expired ) {
246
-	struct ib_mad_request *request =
247
-		container_of ( timer, struct ib_mad_request, timer );
248
-	struct ib_gma *gma = request->gma;
249
-
250
-	/* Abandon TID if we have tried too many times */
251
-	if ( expired ) {
252
-		DBGC ( gma, "GMA %p abandoning TID %08x%08x\n",
253
-		       gma, ntohl ( request->mad.hdr.tid[0] ),
254
-		       ntohl ( request->mad.hdr.tid[1] ) );
255
-		list_del ( &request->list );
256
-		free ( request );
257
-		return;
258
-	}
259
-
260
-	/* Restart retransmission timer */
261
-	start_timer ( timer );
262
-
263
-	/* Resend request */
264
-	ib_gma_send ( gma, request );
265
-}
266
-
267
-/**
268
- * Issue MAD request
269
- *
270
- * @v gma		General management agent
271
- * @v mad		MAD request
272
- * @v av		Destination address, or NULL for SM
273
- * @v retry		Request should be retried until a response arrives
274
- * @ret rc		Return status code
275
- */
276
-int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad,
277
-		     struct ib_address_vector *av, int retry ) {
278
-	struct ib_device *ibdev = gma->ibdev;
279
-	struct ib_mad_request *request;
280
-
281
-	/* Allocate and initialise structure */
282
-	request = zalloc ( sizeof ( *request ) );
283
-	if ( ! request ) {
284
-		DBGC ( gma, "GMA %p could not allocate MAD request\n", gma );
285
-		return -ENOMEM;
286
-	}
287
-	request->gma = gma;
288
-	request->timer.expired = ib_gma_timer_expired;
289
-
290
-	/* Determine address vector */
291
-	if ( av ) {
292
-		memcpy ( &request->av, av, sizeof ( request->av ) );
293
-	} else {
294
-		request->av.lid = ibdev->sm_lid;
295
-		request->av.sl = ibdev->sm_sl;
296
-		request->av.qpn = IB_QPN_GSI;
297
-		request->av.qkey = IB_QKEY_GSI;
298
-	}
299
-
300
-	/* Copy MAD body */
301
-	memcpy ( &request->mad, mad, sizeof ( request->mad ) );
302
-
303
-	/* Allocate TID */
304
-	request->mad.hdr.tid[0] = htonl ( IB_GMA_TID_MAGIC );
305
-	request->mad.hdr.tid[1] = htonl ( ++next_request_tid );
306
-
307
-	/* Send initial request.  Ignore errors; the retry timer will
308
-	 * take care of those we care about.
309
-	 */
310
-	ib_gma_send ( gma, request );
311
-
312
-	/* Add to list and start timer if applicable */
313
-	if ( retry ) {
314
-		list_add ( &request->list, &gma->requests );
315
-		start_timer ( &request->timer );
316
-	} else {
317
-		free ( request );
318
-	}
319
-
320
-	return 0;
321
-}
322
-
323
-/**
324
- * Create GMA
325
- *
326
- * @v ibdev		Infiniband device
327
- * @v type		Queue pair type
328
- * @ret gma		General management agent, or NULL
329
- */
330
-struct ib_gma * ib_create_gma ( struct ib_device *ibdev,
331
-				enum ib_queue_pair_type type ) {
332
-	struct ib_gma *gma;
333
-	int rc;
334
-
335
-	/* Allocate and initialise fields */
336
-	gma = zalloc ( sizeof ( *gma ) );
337
-	if ( ! gma )
338
-		goto err_alloc;
339
-	gma->ibdev = ibdev;
340
-	INIT_LIST_HEAD ( &gma->requests );
341
-
342
-	/* Create completion queue */
343
-	gma->cq = ib_create_cq ( ibdev, IB_GMA_NUM_CQES,
344
-				 &ib_gma_completion_ops );
345
-	if ( ! gma->cq ) {
346
-		DBGC ( gma, "GMA %p could not allocate completion queue\n",
347
-		       gma );
348
-		goto err_create_cq;
349
-	}
350
-
351
-	/* Create queue pair */
352
-	gma->qp = ib_create_qp ( ibdev, type, IB_GMA_NUM_SEND_WQES, gma->cq,
353
-				 IB_GMA_NUM_RECV_WQES, gma->cq );
354
-	if ( ! gma->qp ) {
355
-		DBGC ( gma, "GMA %p could not allocate queue pair\n", gma );
356
-		goto err_create_qp;
357
-	}
358
-	ib_qp_set_ownerdata ( gma->qp, gma );
359
-	DBGC ( gma, "GMA %p running on QPN %#lx\n", gma, gma->qp->qpn );
360
-
361
-	/* Set queue key */
362
-	gma->qp->qkey = ( ( type == IB_QPT_SMI ) ? IB_QKEY_SMI : IB_QKEY_GSI );
363
-	if ( ( rc = ib_modify_qp ( ibdev, gma->qp ) ) != 0 ) {
364
-		DBGC ( gma, "GMA %p could not set queue key: %s\n",
365
-		       gma, strerror ( rc ) );
366
-		goto err_modify_qp;
367
-	}
368
-
369
-	/* Fill receive ring */
370
-	ib_refill_recv ( ibdev, gma->qp );
371
-	return gma;
372
-
373
- err_modify_qp:
374
-	ib_destroy_qp ( ibdev, gma->qp );
375
- err_create_qp:
376
-	ib_destroy_cq ( ibdev, gma->cq );
377
- err_create_cq:
378
-	free ( gma );
379
- err_alloc:
380
-	return NULL;
381
-}
382
-
383
-/**
384
- * Destroy GMA
385
- *
386
- * @v gma		General management agent
387
- */
388
-void ib_destroy_gma ( struct ib_gma *gma ) {
389
-	struct ib_device *ibdev = gma->ibdev;
390
-	struct ib_mad_request *request;
391
-	struct ib_mad_request *tmp;
392
-
393
-	/* Flush any outstanding requests */
394
-	list_for_each_entry_safe ( request, tmp, &gma->requests, list ) {
395
-		stop_timer ( &request->timer );
396
-		list_del ( &request->list );
397
-		free ( request );
398
-	}
399
-
400
-	ib_destroy_qp ( ibdev, gma->qp );
401
-	ib_destroy_cq ( ibdev, gma->cq );
402
-	free ( gma );
403
-}

+ 114
- 134
src/net/infiniband/ib_mcast.c Näytä tiedosto

@@ -24,7 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
24 24
 #include <errno.h>
25 25
 #include <gpxe/list.h>
26 26
 #include <gpxe/infiniband.h>
27
-#include <gpxe/ib_gma.h>
27
+#include <gpxe/ib_mi.h>
28 28
 #include <gpxe/ib_mcast.h>
29 29
 
30 30
 /** @file
@@ -34,22 +34,19 @@ FILE_LICENCE ( GPL2_OR_LATER );
34 34
  */
35 35
 
36 36
 /**
37
- * Transmit multicast group membership request
37
+ * Generate multicast membership MAD
38 38
  *
39
- * @v gma		General management agent
39
+ * @v ibdev		Infiniband device
40 40
  * @v gid		Multicast GID
41 41
  * @v join		Join (rather than leave) group
42
- * @ret rc		Return status code
42
+ * @v mad		MAD to fill in
43 43
  */
44
-static int ib_mc_member_request ( struct ib_gma *gma, struct ib_gid *gid,
45
-				  int join ) {
46
-	union ib_mad mad;
47
-	struct ib_mad_sa *sa = &mad.sa;
48
-	int rc;
44
+static void ib_mcast_mad ( struct ib_device *ibdev, struct ib_gid *gid,
45
+			   int join, union ib_mad *mad ) {
46
+	struct ib_mad_sa *sa = &mad->sa;
49 47
 
50 48
 	/* Construct multicast membership record request */
51 49
 	memset ( sa, 0, sizeof ( *sa ) );
52
-	sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
53 50
 	sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
54 51
 	sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
55 52
 	sa->mad_hdr.method =
@@ -61,51 +58,123 @@ static int ib_mc_member_request ( struct ib_gma *gma, struct ib_gid *gid,
61 58
 	sa->sa_data.mc_member_record.scope__join_state = 1;
62 59
 	memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
63 60
 		 sizeof ( sa->sa_data.mc_member_record.mgid ) );
64
-	memcpy ( &sa->sa_data.mc_member_record.port_gid, &gma->ibdev->gid,
61
+	memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
65 62
 		 sizeof ( sa->sa_data.mc_member_record.port_gid ) );
63
+}
66 64
 
67
-	/* Issue multicast membership record request */
68
-	if ( ( rc = ib_gma_request ( gma, &mad, NULL, join ) ) != 0 ) {
69
-		DBGC ( gma, "GMA %p could not join group: %s\n",
70
-		       gma, strerror ( rc ) );
71
-		return rc;
65
+/**
66
+ * Handle multicast membership record join response
67
+ *
68
+ * @v ibdev		Infiniband device
69
+ * @v mi		Management interface
70
+ * @v madx		Management transaction
71
+ * @v rc		Status code
72
+ * @v mad		Received MAD (or NULL on error)
73
+ * @v av		Source address vector (or NULL on error)
74
+ */
75
+static void ib_mcast_complete ( struct ib_device *ibdev,
76
+				struct ib_mad_interface *mi __unused,
77
+				struct ib_mad_transaction *madx,
78
+				int rc, union ib_mad *mad,
79
+				struct ib_address_vector *av __unused ) {
80
+	struct ib_mc_membership *membership = ib_madx_get_ownerdata ( madx );
81
+	struct ib_queue_pair *qp = membership->qp;
82
+	struct ib_gid *gid = &membership->gid;
83
+	struct ib_mc_member_record *mc_member_record =
84
+		&mad->sa.sa_data.mc_member_record;
85
+	int joined;
86
+	unsigned long qkey;
87
+
88
+	/* Report failures */
89
+	if ( rc != 0 ) {
90
+		DBGC ( ibdev, "IBDEV %p QPN %lx join failed: %s\n",
91
+		       ibdev, qp->qpn, strerror ( rc ) );
92
+		goto out;
72 93
 	}
73 94
 
74
-	return 0;
95
+	/* Extract values from MAD */
96
+	joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
97
+	qkey = ntohl ( mc_member_record->qkey );
98
+	DBGC ( ibdev, "IBDEV %p QPN %lx %s %08x:%08x:%08x:%08x qkey %lx\n",
99
+	       ibdev, qp->qpn, ( joined ? "joined" : "left" ),
100
+	       ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
101
+	       ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ),
102
+	       qkey );
103
+
104
+	/* Set queue key */
105
+	qp->qkey = qkey;
106
+	if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
107
+		DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
108
+		       ibdev, qp->qpn, strerror ( rc ) );
109
+		goto out;
110
+	}
111
+
112
+ out:
113
+	/* Destroy the completed transaction */
114
+	ib_destroy_madx ( ibdev, mi, madx );
115
+	membership->madx = NULL;
116
+
117
+	/* Hand off to upper completion handler */
118
+	membership->complete ( ibdev, qp, membership, rc, mad );
75 119
 }
76 120
 
121
+/** Multicast membership management transaction completion operations */
122
+static struct ib_mad_transaction_operations ib_mcast_op = {
123
+	.complete = ib_mcast_complete,
124
+};
125
+
77 126
 /**
78 127
  * Join multicast group
79 128
  *
80 129
  * @v ibdev		Infiniband device
81 130
  * @v qp		Queue pair
82
- * @v gid		Multicast GID
131
+ * @v membership	Multicast group membership
132
+ * @v gid		Multicast GID to join
133
+ * @v joined		Join completion handler
83 134
  * @ret rc		Return status code
84 135
  */
85 136
 int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
86
-		    struct ib_gid *gid ) {
87
-	struct ib_gma *gma = ibdev->gma;
137
+		    struct ib_mc_membership *membership, struct ib_gid *gid,
138
+		    void ( * complete ) ( struct ib_device *ibdev,
139
+					  struct ib_queue_pair *qp,
140
+					  struct ib_mc_membership *membership,
141
+					  int rc, union ib_mad *mad ) ) {
142
+	union ib_mad mad;
88 143
 	int rc;
89 144
 
90
-	DBGC ( gma, "GMA %p QPN %lx joining %08x:%08x:%08x:%08x\n",
91
-	       gma, qp->qpn, ntohl ( gid->u.dwords[0] ),
145
+	DBGC ( ibdev, "IBDEV %p QPN %lx joining %08x:%08x:%08x:%08x\n",
146
+	       ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
92 147
 	       ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
93 148
 	       ntohl ( gid->u.dwords[3] ) );
94 149
 
150
+	/* Initialise structure */
151
+	membership->qp = qp;
152
+	memcpy ( &membership->gid, gid, sizeof ( membership->gid ) );
153
+	membership->complete = complete;
154
+
95 155
 	/* Attach queue pair to multicast GID */
96 156
 	if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
97
-		DBGC ( gma, "GMA %p could not attach: %s\n",
98
-		       gma, strerror ( rc ) );
157
+		DBGC ( ibdev, "IBDEV %p QPN %lx could not attach: %s\n",
158
+		       ibdev, qp->qpn, strerror ( rc ) );
99 159
 		goto err_mcast_attach;
100 160
 	}
101 161
 
102 162
 	/* Initiate multicast membership join */
103
-	if ( ( rc = ib_mc_member_request ( gma, gid, 1 ) ) != 0 )
104
-		goto err_mc_member_record;
163
+	ib_mcast_mad ( ibdev, gid, 1, &mad );
164
+	membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
165
+					    &ib_mcast_op );
166
+	if ( ! membership->madx ) {
167
+		DBGC ( ibdev, "IBDEV %p QPN %lx could not create join "
168
+		       "transaction\n", ibdev, qp->qpn );
169
+		rc = -ENOMEM;
170
+		goto err_create_madx;
171
+	}
172
+	ib_madx_set_ownerdata ( membership->madx, membership );
105 173
 
106 174
 	return 0;
107 175
 
108
- err_mc_member_record:
176
+	ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
177
+ err_create_madx:
109 178
 	ib_mcast_detach ( ibdev, qp, gid );
110 179
  err_mcast_attach:
111 180
 	return rc;
@@ -116,121 +185,32 @@ int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
116 185
  *
117 186
  * @v ibdev		Infiniband device
118 187
  * @v qp		Queue pair
119
- * @v gid		Multicast GID
188
+ * @v membership	Multicast group membership
120 189
  */
121 190
 void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
122
-		      struct ib_gid *gid ) {
123
-	struct ib_gma *gma = ibdev->gma;
191
+		      struct ib_mc_membership *membership ) {
192
+	struct ib_gid *gid = &membership->gid;
193
+	union ib_mad mad;
194
+	int rc;
124 195
 
125
-	DBGC ( gma, "GMA %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
126
-	       gma, qp->qpn, ntohl ( gid->u.dwords[0] ),
196
+	DBGC ( ibdev, "IBDEV %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
197
+	       ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
127 198
 	       ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
128 199
 	       ntohl ( gid->u.dwords[3] ) );
129 200
 
130
-	/* Detach queue pair from multicast GID */
131
-	ib_mcast_detach ( ibdev, qp, gid );
132
-
133
-	/* Initiate multicast membership leave */
134
-	ib_mc_member_request ( gma, gid, 0 );
135
-}
136
-
137
-/**
138
- * Handle multicast membership record join response
139
- *
140
- * @v gma		General management agent
141
- * @v mad		MAD
142
- * @ret mad		MAD response
143
- */
144
-static union ib_mad * ib_handle_mc_member_join ( struct ib_gma *gma,
145
-						 union ib_mad *mad ) {
146
-	struct ib_device *ibdev = gma->ibdev;
147
-	struct ib_mc_member_record *mc_member_record =
148
-		&mad->sa.sa_data.mc_member_record;
149
-	struct ib_queue_pair *qp;
150
-	struct ib_gid *gid;
151
-	unsigned long qkey;
152
-	int rc;
153
-
154
-	/* Ignore if not a success */
155
-	if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
156
-		DBGC ( gma, "GMA %p join failed with status %04x\n",
157
-		       gma, ntohs ( mad->hdr.status ) );
158
-		return NULL;
159
-	}
160
-
161
-	/* Extract MAD parameters */
162
-	gid = &mc_member_record->mgid;
163
-	qkey = ntohl ( mc_member_record->qkey );
164
-
165
-	/* Locate matching queue pair */
166
-	qp = ib_find_qp_mgid ( ibdev, gid );
167
-	if ( ! qp ) {
168
-		DBGC ( gma, "GMA %p has no QP to join %08x:%08x:%08x:%08x\n",
169
-		       gma, ntohl ( gid->u.dwords[0] ),
170
-		       ntohl ( gid->u.dwords[1] ),
171
-		       ntohl ( gid->u.dwords[2] ),
172
-		       ntohl ( gid->u.dwords[3] ) );
173
-		return NULL;
174
-	}
175
-	DBGC ( gma, "GMA %p QPN %lx joined %08x:%08x:%08x:%08x qkey %lx\n",
176
-	       gma, qp->qpn, ntohl ( gid->u.dwords[0] ),
177
-	       ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
178
-	       ntohl ( gid->u.dwords[3] ), qkey );
201
+	/* Detach from multicast GID */
202
+	ib_mcast_detach ( ibdev, qp, &membership->gid );
179 203
 
180
-	/* Set queue key */
181
-	qp->qkey = qkey;
182
-	if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
183
-		DBGC ( gma, "GMA %p QPN %lx could not modify qkey: %s\n",
184
-		       gma, qp->qpn, strerror ( rc ) );
185
-		return NULL;
204
+	/* Cancel multicast membership join, if applicable */
205
+	if ( membership->madx ) {
206
+		ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
207
+		membership->madx = NULL;
186 208
 	}
187 209
 
188
-	return NULL;
189
-}
190
-
191
-/**
192
- * Handle multicast membership record leave response
193
- *
194
- * @v gma		General management agent
195
- * @v mad		MAD
196
- * @v response		MAD response
197
- */
198
-static union ib_mad * ib_handle_mc_member_leave ( struct ib_gma *gma,
199
-						  union ib_mad *mad ) {
200
-	struct ib_mc_member_record *mc_member_record =
201
-		&mad->sa.sa_data.mc_member_record;
202
-	struct ib_gid *gid;
203
-
204
-	/* Ignore if not a success */
205
-	if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
206
-		DBGC ( gma, "GMA %p leave failed with status %04x\n",
207
-		       gma, ntohs ( mad->hdr.status ) );
208
-		return NULL;
210
+	/* Send a single group leave MAD */
211
+	ib_mcast_mad ( ibdev, &membership->gid, 0, &mad );
212
+	if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
213
+		DBGC ( ibdev, "IBDEV %p QPN %lx could not send leave request: "
214
+		       "%s\n", ibdev, qp->qpn, strerror ( rc ) );
209 215
 	}
210
-
211
-	/* Extract MAD parameters */
212
-	gid = &mc_member_record->mgid;
213
-	DBGC ( gma, "GMA %p left %08x:%08x:%08x:%08x\n", gma,
214
-	       ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
215
-	       ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ) );
216
-
217
-	return NULL;
218 216
 }
219
-
220
-/** Multicast membership record response handler */
221
-struct ib_gma_handler ib_mc_member_record_handlers[] __ib_gma_handler = {
222
-	{
223
-		.mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
224
-		.class_version = IB_SA_CLASS_VERSION,
225
-		.method = IB_MGMT_METHOD_GET_RESP,
226
-		.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC ),
227
-		.handle = ib_handle_mc_member_join,
228
-	},
229
-	{
230
-		.mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
231
-		.class_version = IB_SA_CLASS_VERSION,
232
-		.method = IB_SA_METHOD_DELETE_RESP,
233
-		.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC ),
234
-		.handle = ib_handle_mc_member_leave,
235
-	},
236
-};

+ 202
- 131
src/net/infiniband/ib_pathrec.c Näytä tiedosto

@@ -19,11 +19,12 @@
19 19
 FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21 21
 #include <stdint.h>
22
+#include <stdlib.h>
22 23
 #include <string.h>
23 24
 #include <byteswap.h>
24 25
 #include <errno.h>
25 26
 #include <gpxe/infiniband.h>
26
-#include <gpxe/ib_gma.h>
27
+#include <gpxe/ib_mi.h>
27 28
 #include <gpxe/ib_pathrec.h>
28 29
 
29 30
 /** @file
@@ -32,56 +33,162 @@ FILE_LICENCE ( GPL2_OR_LATER );
32 33
  *
33 34
  */
34 35
 
35
-/** Number of path record cache entries
36
+/**
37
+ * Handle path transaction completion
38
+ *
39
+ * @v ibdev		Infiniband device
40
+ * @v mi		Management interface
41
+ * @v madx		Management transaction
42
+ * @v rc		Status code
43
+ * @v mad		Received MAD (or NULL on error)
44
+ * @v av		Source address vector (or NULL on error)
45
+ */
46
+static void ib_path_complete ( struct ib_device *ibdev,
47
+			       struct ib_mad_interface *mi,
48
+			       struct ib_mad_transaction *madx,
49
+			       int rc, union ib_mad *mad,
50
+			       struct ib_address_vector *av __unused ) {
51
+	struct ib_path *path = ib_madx_get_ownerdata ( madx );
52
+	struct ib_gid *dgid = &path->av.gid;
53
+	struct ib_path_record *pathrec = &mad->sa.sa_data.path_record;
54
+
55
+	/* Report failures */
56
+	if ( rc != 0 ) {
57
+		DBGC ( ibdev, "IBDEV %p path lookup for %08x:%08x:%08x:%08x "
58
+		       "failed: %s\n", ibdev, htonl ( dgid->u.dwords[0] ),
59
+		       htonl ( dgid->u.dwords[1] ),
60
+		       htonl ( dgid->u.dwords[2] ),
61
+		       htonl ( dgid->u.dwords[3] ), strerror ( rc ) );
62
+		goto out;
63
+	}
64
+
65
+	/* Extract values from MAD */
66
+	path->av.lid = ntohs ( pathrec->dlid );
67
+	path->av.sl = ( pathrec->reserved__sl & 0x0f );
68
+	path->av.rate = ( pathrec->rate_selector__rate & 0x3f );
69
+	DBGC ( ibdev, "IBDEV %p path to %08x:%08x:%08x:%08x is %04x sl %d "
70
+	       "rate %d\n", ibdev, htonl ( dgid->u.dwords[0] ),
71
+	       htonl ( dgid->u.dwords[1] ), htonl ( dgid->u.dwords[2] ),
72
+	       htonl ( dgid->u.dwords[3] ), path->av.lid, path->av.sl,
73
+	       path->av.rate );
74
+
75
+ out:
76
+	/* Destroy the completed transaction */
77
+	ib_destroy_madx ( ibdev, mi, madx );
78
+	path->madx = NULL;
79
+
80
+	/* Hand off to upper completion handler */
81
+	path->op->complete ( ibdev, path, rc, &path->av );
82
+}
83
+
84
+/** Path transaction completion operations */
85
+static struct ib_mad_transaction_operations ib_path_op = {
86
+	.complete = ib_path_complete,
87
+};
88
+
89
+/**
90
+ * Create path
91
+ *
92
+ * @v ibdev		Infiniband device
93
+ * @v av		Address vector to complete
94
+ * @v op		Path operations
95
+ * @ret path		Path
96
+ */
97
+struct ib_path *
98
+ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
99
+		 struct ib_path_operations *op ) {
100
+	struct ib_path *path;
101
+	union ib_mad mad;
102
+	struct ib_mad_sa *sa = &mad.sa;
103
+
104
+	/* Allocate and initialise structure */
105
+	path = zalloc ( sizeof ( *path ) );
106
+	if ( ! path )
107
+		goto err_alloc_path;
108
+	path->ibdev = ibdev;
109
+	memcpy ( &path->av, av, sizeof ( path->av ) );
110
+	path->op = op;
111
+
112
+	/* Construct path request */
113
+	memset ( sa, 0, sizeof ( *sa ) );
114
+	sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
115
+	sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
116
+	sa->mad_hdr.method = IB_MGMT_METHOD_GET;
117
+	sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
118
+	sa->sa_hdr.comp_mask[1] =
119
+		htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
120
+	memcpy ( &sa->sa_data.path_record.dgid, &path->av.gid,
121
+		 sizeof ( sa->sa_data.path_record.dgid ) );
122
+	memcpy ( &sa->sa_data.path_record.sgid, &ibdev->gid,
123
+		 sizeof ( sa->sa_data.path_record.sgid ) );
124
+
125
+	/* Create management transaction */
126
+	path->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
127
+				      &ib_path_op );
128
+	if ( ! path->madx )
129
+		goto err_create_madx;
130
+	ib_madx_set_ownerdata ( path->madx, path );
131
+
132
+	return path;
133
+
134
+	ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
135
+ err_create_madx:
136
+	free ( path );
137
+ err_alloc_path:
138
+	return NULL;
139
+}
140
+
141
+/**
142
+ * Destroy path
143
+ *
144
+ * @v ibdev		Infiniband device
145
+ * @v path		Path
146
+ */
147
+void ib_destroy_path ( struct ib_device *ibdev, struct ib_path *path ) {
148
+
149
+	if ( path->madx )
150
+		ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
151
+	free ( path );
152
+}
153
+
154
+/** Number of path cache entries
36 155
  *
37 156
  * Must be a power of two.
38 157
  */
39 158
 #define IB_NUM_CACHED_PATHS 4
40 159
 
41
-/** A path record cache entry */
42
-struct ib_cached_path_record {
43
-	/** Infiniband device's port GID
44
-	 *
45
-	 * Used to disambiguate cache entries when we have multiple
46
-	 * Infiniband devices, without having to maintain a pointer to
47
-	 * the Infiniband device.
48
-	 */
49
-	struct ib_gid sgid;
50
-	/** Destination GID */
51
-	struct ib_gid dgid;
52
-	/** Destination LID */
53
-	unsigned int dlid;
54
-	/** Rate */
55
-	unsigned int rate;
56
-	/** Service level */
57
-	unsigned int sl;
160
+/** A cached path */
161
+struct ib_cached_path {
162
+	/** Path */
163
+	struct ib_path *path;
58 164
 };
59 165
 
60
-/** Path record cache */
61
-static struct ib_cached_path_record ib_path_cache[IB_NUM_CACHED_PATHS];
166
+/** Path cache */
167
+static struct ib_cached_path ib_path_cache[IB_NUM_CACHED_PATHS];
62 168
 
63
-/** Oldest path record cache entry index */
169
+/** Oldest path cache entry index */
64 170
 static unsigned int ib_path_cache_idx;
65 171
 
66 172
 /**
67
- * Find path record cache entry
173
+ * Find path cache entry
68 174
  *
69 175
  * @v ibdev		Infiniband device
70 176
  * @v dgid		Destination GID
71
- * @ret cached		Path record cache entry, or NULL
177
+ * @ret path		Path cache entry, or NULL
72 178
  */
73
-static struct ib_cached_path_record *
179
+static struct ib_cached_path *
74 180
 ib_find_path_cache_entry ( struct ib_device *ibdev, struct ib_gid *dgid ) {
75
-	struct ib_cached_path_record *cached;
181
+	struct ib_cached_path *cached;
76 182
 	unsigned int i;
77 183
 
78 184
 	for ( i = 0 ; i < IB_NUM_CACHED_PATHS ; i++ ) {
79 185
 		cached = &ib_path_cache[i];
80
-		if ( memcmp ( &cached->sgid, &ibdev->gid,
81
-			      sizeof ( cached->sgid ) ) != 0 )
186
+		if ( ! cached->path )
187
+			continue;
188
+		if ( cached->path->ibdev != ibdev )
82 189
 			continue;
83
-		if ( memcmp ( &cached->dgid, dgid,
84
-			      sizeof ( cached->dgid ) ) != 0 )
190
+		if ( memcmp ( &cached->path->av.gid, dgid,
191
+			      sizeof ( cached->path->av.gid ) ) != 0 )
85 192
 			continue;
86 193
 		return cached;
87 194
 	}
@@ -90,134 +197,98 @@ ib_find_path_cache_entry ( struct ib_device *ibdev, struct ib_gid *dgid ) {
90 197
 }
91 198
 
92 199
 /**
93
- * Resolve path record
200
+ * Handle cached path transaction completion
201
+ *
202
+ * @v ibdev		Infiniband device
203
+ * @v path		Path
204
+ * @v rc		Status code
205
+ * @v av		Address vector, or NULL on error
206
+ */
207
+static void ib_cached_path_complete ( struct ib_device *ibdev,
208
+				      struct ib_path *path, int rc,
209
+				      struct ib_address_vector *av __unused ) {
210
+	struct ib_cached_path *cached = ib_path_get_ownerdata ( path );
211
+
212
+	/* If the transaction failed, erase the cache entry */
213
+	if ( rc != 0 ) {
214
+		/* Destroy the old cache entry */
215
+		ib_destroy_path ( ibdev, path );
216
+		memset ( cached, 0, sizeof ( *cached ) );
217
+		return;
218
+	}
219
+
220
+	/* Do not destroy the completed transaction; we still need to
221
+	 * refer to the resolved path.
222
+	 */
223
+}
224
+
225
+/** Cached path transaction completion operations */
226
+static struct ib_path_operations ib_cached_path_op = {
227
+	.complete = ib_cached_path_complete,
228
+};
229
+
230
+/**
231
+ * Resolve path
94 232
  *
95 233
  * @v ibdev		Infiniband device
96 234
  * @v av		Address vector to complete
97 235
  * @ret rc		Return status code
236
+ *
237
+ * This provides a non-transactional way to resolve a path, via a
238
+ * cache similar to ARP.
98 239
  */
99
-int ib_resolve_path ( struct ib_device *ibdev,
100
-		      struct ib_address_vector *av ) {
101
-	struct ib_gma *gma = ibdev->gma;
240
+int ib_resolve_path ( struct ib_device *ibdev, struct ib_address_vector *av ) {
102 241
 	struct ib_gid *gid = &av->gid;
103
-	struct ib_cached_path_record *cached;
104
-	union ib_mad mad;
105
-	struct ib_mad_sa *sa = &mad.sa;
242
+	struct ib_cached_path *cached;
106 243
 	unsigned int cache_idx;
107
-	int rc;
108 244
 
109 245
 	/* Sanity check */
110 246
 	if ( ! av->gid_present ) {
111
-		DBGC ( gma, "GMA %p attempt to look up path record "
112
-		       "without GID\n", gma );
247
+		DBGC ( ibdev, "IBDEV %p attempt to look up path "
248
+		       "without GID\n", ibdev );
113 249
 		return -EINVAL;
114 250
 	}
115 251
 
116 252
 	/* Look in cache for a matching entry */
117 253
 	cached = ib_find_path_cache_entry ( ibdev, gid );
118
-	if ( cached && cached->dlid ) {
254
+	if ( cached && cached->path->av.lid ) {
119 255
 		/* Populated entry found */
120
-		av->lid = cached->dlid;
121
-		av->rate = cached->rate;
122
-		av->sl = cached->sl;
123
-		DBGC2 ( gma, "GMA %p cache hit for %08x:%08x:%08x:%08x\n",
124
-			gma, htonl ( gid->u.dwords[0] ),
256
+		av->lid = cached->path->av.lid;
257
+		av->rate = cached->path->av.rate;
258
+		av->sl = cached->path->av.sl;
259
+		DBGC2 ( ibdev, "IBDEV %p cache hit for %08x:%08x:%08x:%08x\n",
260
+			ibdev, htonl ( gid->u.dwords[0] ),
125 261
 			htonl ( gid->u.dwords[1] ), htonl ( gid->u.dwords[2] ),
126 262
 			htonl ( gid->u.dwords[3] ) );
127 263
 		return 0;
128 264
 	}
129
-	DBGC ( gma, "GMA %p cache miss for %08x:%08x:%08x:%08x%s\n", gma,
130
-	       htonl ( gid->u.dwords[0] ), htonl ( gid->u.dwords[1] ),
265
+	DBGC ( ibdev, "IBDEV %p cache miss for %08x:%08x:%08x:%08x%s\n",
266
+	       ibdev, htonl ( gid->u.dwords[0] ), htonl ( gid->u.dwords[1] ),
131 267
 	       htonl ( gid->u.dwords[2] ), htonl ( gid->u.dwords[3] ),
132 268
 	       ( cached ? " (in progress)" : "" ) );
133 269
 
134
-	/* If no unresolved entry was found, then create a new one */
135
-	if ( ! cached ) {
136
-		cache_idx = ( (ib_path_cache_idx++) % IB_NUM_CACHED_PATHS );
137
-		cached = &ib_path_cache[cache_idx];
138
-		memset ( cached, 0, sizeof ( *cached ) );
139
-		memcpy ( &cached->sgid, &ibdev->gid, sizeof ( cached->sgid ) );
140
-		memcpy ( &cached->dgid, gid, sizeof ( cached->dgid ) );
141
-	}
270
+	/* If lookup is already in progress, do nothing */
271
+	if ( cached )
272
+		return -ENOENT;
142 273
 
143
-	/* Construct path record request */
144
-	memset ( sa, 0, sizeof ( *sa ) );
145
-	sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
146
-	sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
147
-	sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
148
-	sa->mad_hdr.method = IB_MGMT_METHOD_GET;
149
-	sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
150
-	sa->sa_hdr.comp_mask[1] =
151
-		htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
152
-	memcpy ( &sa->sa_data.path_record.dgid, &cached->dgid,
153
-		 sizeof ( sa->sa_data.path_record.dgid ) );
154
-	memcpy ( &sa->sa_data.path_record.sgid, &cached->sgid,
155
-		 sizeof ( sa->sa_data.path_record.sgid ) );
274
+	/* Locate a new cache entry to use */
275
+	cache_idx = ( (ib_path_cache_idx++) % IB_NUM_CACHED_PATHS );
276
+	cached = &ib_path_cache[cache_idx];
277
+
278
+	/* Destroy the old cache entry */
279
+	if ( cached->path )
280
+		ib_destroy_path ( ibdev, cached->path );
281
+	memset ( cached, 0, sizeof ( *cached ) );
156 282
 
157
-	/* Issue path record request */
158
-	if ( ( rc = ib_gma_request ( gma, &mad, NULL, 1 ) ) != 0 ) {
159
-		DBGC ( gma, "GMA %p could not get path record: %s\n",
160
-		       gma, strerror ( rc ) );
161
-		return rc;
283
+	/* Create new path */
284
+	cached->path = ib_create_path ( ibdev, av, &ib_cached_path_op );
285
+	if ( ! cached->path ) {
286
+		DBGC ( ibdev, "IBDEV %p could not create path\n",
287
+		       ibdev );
288
+		return -ENOMEM;
162 289
 	}
290
+	ib_path_set_ownerdata ( cached->path, cached );
163 291
 
164 292
 	/* Not found yet */
165 293
 	return -ENOENT;
166 294
 }
167
-
168
-/**
169
- * Handle path record response
170
- *
171
- * @v gma		General management agent
172
- * @v mad		MAD
173
- * @ret response	MAD response
174
- */
175
-static union ib_mad * ib_handle_path_record ( struct ib_gma *gma,
176
-					      union ib_mad *mad ) {
177
-	struct ib_device *ibdev = gma->ibdev;
178
-	struct ib_path_record *path_record = &mad->sa.sa_data.path_record;
179
-	struct ib_gid *dgid = &path_record->dgid;
180
-	struct ib_cached_path_record *cached;
181
-	unsigned int dlid;
182
-	unsigned int sl;
183
-	unsigned int rate;
184
-
185
-	/* Ignore if not a success */
186
-	if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
187
-		DBGC ( gma, "GMA %p path record lookup failed with status "
188
-		       "%04x\n", gma, ntohs ( mad->hdr.status ) );
189
-		return NULL;
190
-	}
191
-
192
-	/* Extract values from MAD */
193
-	dlid = ntohs ( path_record->dlid );
194
-	sl = ( path_record->reserved__sl & 0x0f );
195
-	rate = ( path_record->rate_selector__rate & 0x3f );
196
-	DBGC ( gma, "GMA %p path to %08x:%08x:%08x:%08x is %04x sl %d "
197
-	       "rate %d\n", gma, htonl ( dgid->u.dwords[0] ),
198
-	       htonl ( dgid->u.dwords[1] ), htonl ( dgid->u.dwords[2] ),
199
-	       htonl ( dgid->u.dwords[3] ), dlid, sl, rate );
200
-
201
-	/* Look for a matching cache entry to fill in */
202
-	if ( ( cached = ib_find_path_cache_entry ( ibdev, dgid ) ) != NULL ) {
203
-		DBGC ( gma, "GMA %p cache add for %08x:%08x:%08x:%08x\n",
204
-		       gma, htonl ( dgid->u.dwords[0] ),
205
-		       htonl ( dgid->u.dwords[1] ),
206
-		       htonl ( dgid->u.dwords[2] ),
207
-		       htonl ( dgid->u.dwords[3] ) );
208
-		cached->dlid = dlid;
209
-		cached->rate = rate;
210
-		cached->sl = sl;
211
-	}
212
-
213
-	return NULL;
214
-}
215
-
216
-/** Path record response handler */
217
-struct ib_gma_handler ib_path_record_handler __ib_gma_handler = {
218
-	.mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
219
-	.class_version = IB_SA_CLASS_VERSION,
220
-	.method = IB_MGMT_METHOD_GET_RESP,
221
-	.attr_id = htons ( IB_SA_ATTR_PATH_REC ),
222
-	.handle = ib_handle_path_record,
223
-};

Loading…
Peruuta
Tallenna