[openib-general] [PATCH] umad: pass timeouts to userspace

Roland Dreier roland at topspin.com
Mon Nov 15 09:09:12 PST 2004


OK, this adds a status and a timeout_ms field to struct ib_user_mad
and passes timeouts up to userspace.  Seem OK?

 - R.


Index: infiniband/include/ib_user_mad.h
===================================================================
--- infiniband/include/ib_user_mad.h	(revision 1223)
+++ infiniband/include/ib_user_mad.h	(working copy)
@@ -37,6 +37,10 @@
  * ib_user_mad - MAD packet
  * @data - Contents of MAD
  * @id - ID of agent MAD received with/to be sent with
+ * @status - 0 on successfuly receive, ETIMEDOUT if no response
+ *   received (transaction ID in data[] will be set to TID of original
+ *   request) (ignored on send)
+ * @timeout_ms - Milliseconds to wait for response (unset on receive)
  * @qpn - Remote QP number received from/to be sent to
  * @qkey - Remote Q_Key to be sent with (unset on receive)
  * @lid - Remote lid received from/to be sent to
@@ -54,6 +58,8 @@
 struct ib_user_mad {
 	__u8	data[256];
 	__u32	id;
+	__u32	status;
+	__u32	timeout_ms;
 	__u32	qpn;
 	__u32   qkey;
 	__u16	lid;
Index: infiniband/core/user_mad.c
===================================================================
--- infiniband/core/user_mad.c	(revision 1231)
+++ infiniband/core/user_mad.c	(working copy)
@@ -84,17 +84,50 @@
 static void ib_umad_add_one(struct ib_device *device);
 static void ib_umad_remove_one(struct ib_device *device);
 
+static int queue_packet(struct ib_umad_file *file,
+			struct ib_mad_agent *agent,
+			struct ib_umad_packet *packet)
+{
+	int ret = 1;
+
+	down_read(&file->agent_mutex);
+	for (packet->mad.id = 0;
+	     packet->mad.id < IB_UMAD_MAX_AGENTS;
+	     packet->mad.id++)
+		if (agent == file->agent[packet->mad.id]) {
+			spin_lock_irq(&file->recv_lock);
+			list_add_tail(&packet->list, &file->recv_list);
+			spin_unlock_irq(&file->recv_lock);
+			wake_up_interruptible(&file->recv_wait);
+			ret = 0;
+			break;
+		}
+
+	up_read(&file->agent_mutex);
+
+	return ret;
+}
+
 static void send_handler(struct ib_mad_agent *agent,
-			 struct ib_mad_send_wc *mad_send_wc)
+			 struct ib_mad_send_wc *send_wc)
 {
+	struct ib_umad_file *file = agent->context;
 	struct ib_umad_packet *packet =
-		(void *) (unsigned long) mad_send_wc->wr_id;
+		(void *) (unsigned long) send_wc->wr_id;
 
 	pci_unmap_single(agent->device->dma_device,
 			 pci_unmap_addr(packet, mapping),
 			 sizeof packet->mad.data,
 			 PCI_DMA_TODEVICE);
 	ib_destroy_ah(packet->ah);
+
+	if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
+		packet->mad.status = ETIMEDOUT;
+
+		if (!queue_packet(file, agent, packet))
+			return;
+	}
+		
 	kfree(packet);
 }
 
@@ -114,6 +147,7 @@
 	memset(packet, 0, sizeof *packet);
 
 	memcpy(packet->mad.data, mad_recv_wc->recv_buf->mad, sizeof packet->mad.data);
+	packet->mad.status        = 0;
 	packet->mad.qpn 	  = cpu_to_be32(mad_recv_wc->wc->src_qp);
 	packet->mad.lid 	  = cpu_to_be16(mad_recv_wc->wc->slid);
 	packet->mad.sl  	  = mad_recv_wc->wc->sl;
@@ -128,23 +162,9 @@
 		packet->mad.flow_label 	  = 0;
 	}
 
-	down_read(&file->agent_mutex);
-	for (packet->mad.id = 0;
-	     packet->mad.id < IB_UMAD_MAX_AGENTS;
-	     packet->mad.id++)
-		if (agent == file->agent[packet->mad.id]) {
-			spin_lock_irq(&file->recv_lock);
-			list_add_tail(&packet->list, &file->recv_list);
-			spin_unlock_irq(&file->recv_lock);
-			wake_up_interruptible(&file->recv_wait);
-			goto agent;
-		}
+	if (queue_packet(file, agent, packet))
+		kfree(packet);
 
-	kfree(packet);
-
-agent:
-	up_read(&file->agent_mutex);
-
 out:
 	ib_free_recv_mad(mad_recv_wc);
 }
@@ -259,6 +279,7 @@
 	wr.wr.ud.ah          = packet->ah;
 	wr.wr.ud.remote_qpn  = be32_to_cpu(packet->mad.qpn);
 	wr.wr.ud.remote_qkey = be32_to_cpu(packet->mad.qkey);
+	wr.wr.ud.timeout_ms  = packet->mad.timeout_ms;
 
 	wr.wr_id            = (unsigned long) packet;
 
Index: docs/user_mad.txt
===================================================================
--- docs/user_mad.txt	(revision 1223)
+++ docs/user_mad.txt	(working copy)
@@ -39,6 +39,10 @@
   fields will be filled in with information on the received MAD.  For
   example, the remote LID will be in mad.lid.
 
+  If a send times out, a receive will be generated with mad.status set
+  to ETIMEDOUT.  Otherwise when a MAD has been successfully received,
+  mad.status will be 0.
+
   poll()/select() may be used to wait until a MAD can be read.
 
 Sending MADs



More information about the general mailing list