summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-07-07 17:01:51 +0200
committerMichael Brown2009-07-18 00:06:34 +0200
commit3c77fe73a559ef223fb459ed82b7aaea44e1693a (patch)
tree99e95ea9e09b145309118498a4281f21eb4c09d1
parent[infiniband] Make qkey and rate optional parameters to ib_post_send() (diff)
downloadipxe-3c77fe73a559ef223fb459ed82b7aaea44e1693a.tar.gz
ipxe-3c77fe73a559ef223fb459ed82b7aaea44e1693a.tar.xz
ipxe-3c77fe73a559ef223fb459ed82b7aaea44e1693a.zip
[infiniband] Allow for sending MADs via GMA without retransmission
-rw-r--r--src/include/gpxe/ib_gma.h2
-rw-r--r--src/net/infiniband/ib_gma.c80
-rw-r--r--src/net/infiniband/ib_pathrec.c2
3 files changed, 54 insertions, 30 deletions
diff --git a/src/include/gpxe/ib_gma.h b/src/include/gpxe/ib_gma.h
index c305a3a1..c921e251 100644
--- a/src/include/gpxe/ib_gma.h
+++ b/src/include/gpxe/ib_gma.h
@@ -63,7 +63,7 @@ struct ib_gma {
};
extern int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad,
- struct ib_address_vector *av );
+ struct ib_address_vector *av, int retry );
extern int ib_create_gma ( struct ib_gma *gma, struct ib_device *ibdev,
unsigned long qkey );
extern void ib_destroy_gma ( struct ib_gma *gma );
diff --git a/src/net/infiniband/ib_gma.c b/src/net/infiniband/ib_gma.c
index d599ea32..56c0fe95 100644
--- a/src/net/infiniband/ib_gma.c
+++ b/src/net/infiniband/ib_gma.c
@@ -237,29 +237,16 @@ static struct ib_completion_queue_operations ib_gma_completion_ops = {
};
/**
- * Handle MAD request timer expiry
+ * Transmit MAD request
*
- * @v timer Retry timer
- * @v expired Failure indicator
+ * @v gma General management agent
+ * @v request MAD request
+ * @ret rc Return status code
*/
-static void ib_gma_timer_expired ( struct retry_timer *timer, int expired ) {
- struct ib_mad_request *request =
- container_of ( timer, struct ib_mad_request, timer );
- struct ib_gma *gma = request->gma;
- struct ib_device *ibdev = gma->ibdev;
+static int ib_gma_send ( struct ib_gma *gma, struct ib_mad_request *request ) {
struct io_buffer *iobuf;
int rc;
- /* Abandon TID if we have tried too many times */
- if ( expired ) {
- DBGC ( gma, "GMA %p abandoning TID %08x%08x\n",
- gma, ntohl ( request->mad.hdr.tid[0] ),
- ntohl ( request->mad.hdr.tid[1] ) );
- list_del ( &request->list );
- free ( request );
- return;
- }
-
DBGC ( gma, "GMA %p TX TID %08x%08x (%02x,%02x,%02x,%04x)\n",
gma, ntohl ( request->mad.hdr.tid[0] ),
ntohl ( request->mad.hdr.tid[1] ), request->mad.hdr.mgmt_class,
@@ -267,29 +254,56 @@ static void ib_gma_timer_expired ( struct retry_timer *timer, int expired ) {
ntohs ( request->mad.hdr.attr_id ) );
DBGC2_HDA ( gma, 0, &request->mad, sizeof ( request->mad ) );
- /* Restart retransmission timer */
- start_timer ( timer );
-
/* Construct I/O buffer */
iobuf = alloc_iob ( sizeof ( request->mad ) );
if ( ! iobuf ) {
DBGC ( gma, "GMA %p could not allocate buffer for TID "
"%08x%08x\n", gma, ntohl ( request->mad.hdr.tid[0] ),
ntohl ( request->mad.hdr.tid[1] ) );
- return;
+ return -ENOMEM;
}
memcpy ( iob_put ( iobuf, sizeof ( request->mad ) ), &request->mad,
sizeof ( request->mad ) );
- /* Post send request */
- if ( ( rc = ib_post_send ( ibdev, gma->qp, &request->av,
+ /* Send I/O buffer */
+ if ( ( rc = ib_post_send ( gma->ibdev, gma->qp, &request->av,
iobuf ) ) != 0 ) {
DBGC ( gma, "GMA %p could not send TID %08x%08x: %s\n",
gma, ntohl ( request->mad.hdr.tid[0] ),
ntohl ( request->mad.hdr.tid[1] ), strerror ( rc ) );
free_iob ( iobuf );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle MAD request timer expiry
+ *
+ * @v timer Retry timer
+ * @v expired Failure indicator
+ */
+static void ib_gma_timer_expired ( struct retry_timer *timer, int expired ) {
+ struct ib_mad_request *request =
+ container_of ( timer, struct ib_mad_request, timer );
+ struct ib_gma *gma = request->gma;
+
+ /* Abandon TID if we have tried too many times */
+ if ( expired ) {
+ DBGC ( gma, "GMA %p abandoning TID %08x%08x\n",
+ gma, ntohl ( request->mad.hdr.tid[0] ),
+ ntohl ( request->mad.hdr.tid[1] ) );
+ list_del ( &request->list );
+ free ( request );
return;
}
+
+ /* Restart retransmission timer */
+ start_timer ( timer );
+
+ /* Resend request */
+ ib_gma_send ( gma, request );
}
/**
@@ -298,10 +312,11 @@ static void ib_gma_timer_expired ( struct retry_timer *timer, int expired ) {
* @v gma General management agent
* @v mad MAD request
* @v av Destination address, or NULL for SM
+ * @v retry Request should be retried until a response arrives
* @ret rc Return status code
*/
int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad,
- struct ib_address_vector *av ) {
+ struct ib_address_vector *av, int retry ) {
struct ib_device *ibdev = gma->ibdev;
struct ib_mad_request *request;
@@ -312,7 +327,6 @@ int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad,
return -ENOMEM;
}
request->gma = gma;
- list_add ( &request->list, &gma->requests );
request->timer.expired = ib_gma_timer_expired;
/* Determine address vector */
@@ -332,8 +346,18 @@ int ib_gma_request ( struct ib_gma *gma, union ib_mad *mad,
request->mad.hdr.tid[0] = htonl ( IB_GMA_TID_MAGIC );
request->mad.hdr.tid[1] = htonl ( ++next_request_tid );
- /* Start timer to initiate transmission */
- start_timer_nodelay ( &request->timer );
+ /* Send initial request. Ignore errors; the retry timer will
+ * take care of those we care about.
+ */
+ ib_gma_send ( gma, request );
+
+ /* Add to list and start timer if applicable */
+ if ( retry ) {
+ list_add ( &request->list, &gma->requests );
+ start_timer ( &request->timer );
+ } else {
+ free ( request );
+ }
return 0;
}
diff --git a/src/net/infiniband/ib_pathrec.c b/src/net/infiniband/ib_pathrec.c
index 89622d98..06101670 100644
--- a/src/net/infiniband/ib_pathrec.c
+++ b/src/net/infiniband/ib_pathrec.c
@@ -154,7 +154,7 @@ int ib_resolve_path ( struct ib_device *ibdev,
sizeof ( sa->sa_data.path_record.sgid ) );
/* Issue path record request */
- if ( ( rc = ib_gma_request ( &ibdev->gma, &mad, NULL ) ) != 0 ) {
+ if ( ( rc = ib_gma_request ( &ibdev->gma, &mad, NULL, 1 ) ) != 0 ) {
DBGC ( ibdev, "IBDEV %p could not get path record: %s\n",
ibdev, strerror ( rc ) );
return rc;