[openib-general] [PATCH v3] user_mad: Add receive side RMPP support

Hal Rosenstock halr at voltaire.com
Fri Jul 1 11:31:26 PDT 2005


user_mad: Add receive side RMPP support
This change involves another ABI_VERSION change.

[NOTE: Please do not commit. This needs to be coordinated with a 
change to userspace.]

Signed-off-by: Hal Rosenstock <halr at voltaire.com>

Index: infiniband/include/ib_user_mad.h
===================================================================
--- infiniband/include/ib_user_mad.h	(revision 2757)
+++ infiniband/include/ib_user_mad.h	(working copy)
@@ -43,7 +43,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define IB_USER_MAD_ABI_VERSION	4
+#define IB_USER_MAD_ABI_VERSION	5
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -78,6 +78,7 @@
 	__u32	status;
 	__u32	timeout_ms;
 	__u32	retries;
+	__u32	length;
 	__u32	qpn;
 	__u32   qkey;
 	__u16	lid;
Index: infiniband/core/user_mad.c
===================================================================
--- infiniband/core/user_mad.c	(revision 2760)
+++ infiniband/core/user_mad.c	(working copy)
@@ -176,7 +176,7 @@
 	if (mad_recv_wc->wc->status != IB_WC_SUCCESS)
 		goto out;
 
-	length = 256;	/* until RMPP is supported */
+	length = mad_recv_wc->mad_len; 
 	packet = kmalloc(sizeof *packet + length, GFP_KERNEL);
 	if (!packet)
 		goto out;
@@ -184,8 +184,10 @@
 	memset(packet, 0, sizeof *packet + length);
 	packet->length = length;
 
-	memcpy(packet->mad.data, mad_recv_wc->recv_buf.mad, length);
+	ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data);
+
 	packet->mad.hdr.status    = 0;
+	packet->mad.hdr.length    = length + sizeof (struct ib_user_mad);
 	packet->mad.hdr.qpn 	  = cpu_to_be32(mad_recv_wc->wc->src_qp);
 	packet->mad.hdr.lid 	  = cpu_to_be16(mad_recv_wc->wc->slid);
 	packet->mad.hdr.sl  	  = mad_recv_wc->wc->sl;
@@ -214,7 +216,7 @@
 	struct ib_umad_packet *packet;
 	ssize_t ret;
 
-	if (count < sizeof (struct ib_user_mad) + 256) /* until RMPP supported */ 
+	if (count < sizeof (struct ib_user_mad) + sizeof (struct ib_mad))
 		return -EINVAL;
 
 	spin_lock_irq(&file->recv_lock);
@@ -237,9 +239,14 @@
 
 	spin_unlock_irq(&file->recv_lock);
 
-	if (count < packet->length + sizeof (struct ib_user_mad))
-		ret = -EINVAL;
-	else if (copy_to_user(buf, &packet->mad,
+	if (count < packet->length + sizeof (struct ib_user_mad)) {
+		/* Return length needed (and first RMPP segment) if too small */
+		if (copy_to_user(buf, &packet->mad,
+				 sizeof (struct ib_user_mad) + sizeof (struct ib_mad)))
+			ret = -EFAULT;
+		else
+			ret = -ENOSPC;
+	} else if (copy_to_user(buf, &packet->mad,
 			      packet->length + sizeof (struct ib_user_mad)))
 		ret = -EFAULT;
 	else
Index: docs/user_mad.txt
===================================================================
--- docs/user_mad.txt	(revision 2757)
+++ docs/user_mad.txt	(working copy)
@@ -28,16 +28,38 @@
 
 Receiving MADs
 
-  MADs are received using read().  The receive side does not currently
-  support RMPP so the buffer passed to read() must be at least one
+  MADs are received using read().  The receive side now supports
+  RMPP. The buffer passed to read() must be at least one 
   struct ib_user_mad + 256 bytes. For example:
 
+  If the buffer passed is not large enough to hold the received
+  MAD (RMPP), the errno is set to ENOSPC and the length of the
+  buffer needed is set in mad.length.
+
+  Example for normal MAD (non RMPP) reads:
 	struct ib_user_mad *mad;
 	mad = malloc(sizeof *mad + 256);
 	ret = read(fd, mad, sizeof *mad + 256);
-	if (ret != sizeof mad + 256)
+	if (ret != sizeof mad + 256) {
 		perror("read");
+		free(mad);
+	}
 
+  Example for RMPP reads:
+	struct ib_user_mad *mad;
+	mad = malloc(sizeof *mad + 256);
+	ret = read(fd, mad, sizeof *mad + 256);
+	if (ret == -ENOSPC)) {
+		length = mad.length;
+		free(mad);
+		mad = malloc(sizeof *mad + length);
+		ret = read(fd, mad, sizeof *mad + length);
+	}
+	if (ret < 0) {
+		perror("read");
+		free(mad);
+	}
+
   In addition to the actual MAD contents, the other struct ib_user_mad
   fields will be filled in with information on the received MAD.  For
   example, the remote LID will be in mad.lid.






More information about the general mailing list