[openib-general] [PATCH] use wait_list for MADs waiting for a response
Sean Hefty
Thu Oct 7 15:21:28 PDT 2004
This patch uses a wait_list to store MADs waiting for a response.
- Sean
-- Index: access/ib_mad_priv.h
===================================================================
--- access/ib_mad_priv.h (revision 958)
+++ access/ib_mad_priv.h (working copy)
@@ -108,6 +108,7 @@
spinlock_t lock;
struct list_head send_list;
+ struct list_head wait_list;
atomic_t refcount;
wait_queue_head_t wait;
Index: access/ib_mad.c
===================================================================
--- access/ib_mad.c (revision 958)
+++ access/ib_mad.c (working copy)
@@ -232,6 +232,7 @@
spin_lock_init(&mad_agent_priv->lock);
INIT_LIST_HEAD(&mad_agent_priv->send_list);
+ INIT_LIST_HEAD(&mad_agent_priv->wait_list);
atomic_set(&mad_agent_priv->refcount, 1);
init_waitqueue_head(&mad_agent_priv->wait);
mad_agent_priv->port_priv = port_priv;
@@ -259,7 +260,12 @@
mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
agent);
- /* Cleanup pending receives for this agent !!! */
+ /* Note that we could still be handling received MADs. */
+
+ /*
+ * Canceling all sends results in dropping received response MADs,
+ * preventing us from queuing additional work.
+ */
cancel_mads(mad_agent_priv);
spin_lock_irqsave(&mad_agent_priv->port_priv->reg_lock, flags);
@@ -267,6 +273,8 @@
list_del(&mad_agent_priv->agent_list);
spin_unlock_irqrestore(&mad_agent_priv->port_priv->reg_lock, flags);
+ /* Cleanup pending RMPP receives for this agent !!! */
+
atomic_dec(&mad_agent_priv->refcount);
wait_event(mad_agent_priv->wait,
!atomic_read(&mad_agent_priv->refcount));
@@ -784,6 +792,16 @@
{
struct ib_mad_send_wr_private *mad_send_wr;
+ list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
+ agent_list) {
+ if (mad_send_wr->tid == tid)
+ return mad_send_wr;
+ }
+
+ /*
+ * It's possible to receive the response before we've been notified
+ * that the send has completed.
+ */
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) {
if (mad_send_wr->tid == tid && mad_send_wr->timeout) {
@@ -932,6 +950,28 @@
return;
}
+static void wait_for_response(struct ib_mad_agent_private *mad_agent_priv,
+ struct ib_mad_send_wr_private *mad_send_wr )
+{
+ struct ib_mad_send_wr_private *temp_mad_send_wr;
+ struct list_head *list_item;
+ unsigned long delay;
+
+ list_del(&mad_send_wr->agent_list);
+
+ delay = mad_send_wr->timeout;
+ mad_send_wr->timeout += jiffies;
+
+ list_for_each_prev(list_item, &mad_agent_priv->wait_list) {
+ temp_mad_send_wr = list_entry(list_item,
+ struct ib_mad_send_wr_private,
+ agent_list);
+ if (time_after(mad_send_wr->timeout, temp_mad_send_wr->timeout))
+ break;
+ }
+ list_add(&mad_send_wr->agent_list, list_item);
+}
+
/*
* Process a send work completion.
*/
@@ -951,12 +991,11 @@
mad_send_wr->refcount -= (mad_send_wr->timeout > 0);
}
- /*
- * Leave sends with timeouts on the send list
- * until either matching response is received
- * or timeout occurs
- */
if (--mad_send_wr->refcount > 0) {
+ if (mad_send_wr->refcount == 1 && mad_send_wr->timeout &&
+ mad_send_wr->status == IB_WC_SUCCESS) {
+ wait_for_response(mad_agent_priv, mad_send_wr);
+ }
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
return;
}
@@ -1067,18 +1106,14 @@
spin_lock_irqsave(&mad_agent_priv->lock, flags);
list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
&mad_agent_priv->send_list, agent_list) {
-
- if (mad_send_wr->status == IB_WC_SUCCESS)
+ if (mad_send_wr->status == IB_WC_SUCCESS) {
+ mad_send_wr->status = IB_WC_WR_FLUSH_ERR;
mad_send_wr->refcount -= (mad_send_wr->timeout > 0);
-
- if (mad_send_wr->refcount == 0) {
- list_del(&mad_send_wr->agent_list);
- list_add_tail(&mad_send_wr->agent_list,
- &cancel_list);
- } else {
- mad_send_wr->status = IB_WC_WR_FLUSH_ERR;
}
}
+
+ /* Empty wait list to prevent receives from finding a request. */
+ list_splice_init(&mad_agent_priv->wait_list, &cancel_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
/* Report all cancelled requests */
@@ -1087,14 +1122,12 @@
list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
&cancel_list, agent_list) {
-
mad_send_wc.wr_id = mad_send_wr->wr_id;
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc);
list_del(&mad_send_wr->agent_list);
kfree(mad_send_wr);
-
atomic_dec(&mad_agent_priv->refcount);
}
}
@@ -1105,6 +1138,12 @@
{
struct ib_mad_send_wr_private *mad_send_wr;
+ list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
+ agent_list) {
+ if (mad_send_wr->wr_id == wr_id)
+ return mad_send_wr;
+ }
+
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) {
if (mad_send_wr->wr_id == wr_id)
More information about the openib-general mailing list