[openib-general] [PATCH] mthca/mad/agent process_mad changes (both branches)

Hal Rosenstock halr at voltaire.com
Wed Nov 3 13:54:34 PST 2004


mthca/mad/agent changes to eliminate snoop_mad and use process_mad to
give mthca driver first crack at received MAD and change agents to be
send only (and not register for receives which are now handled by
mthca).

There are some more optimizations that can be made but this is a working
start. I will do some of this hopefully tomorrow but outgoing SMI is my
primary goal (to incorporate it into ib_post_send_mad). Once that is
done, the changes to the MAD layer for SM support are usable AFAIK.

Index: openib-candidate/src/linux-kernel/infiniband/access/agent.c
===================================================================
---
openib-candidate/src/linux-kernel/infiniband/access/agent.c	(revision
1125)
+++ openib-candidate/src/linux-kernel/infiniband/access/agent.c	(working
copy)
@@ -29,7 +29,6 @@
 #include <asm/bug.h>
 
 
-
 static spinlock_t ib_agent_port_list_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(ib_agent_port_list);
 
@@ -37,9 +36,9 @@
  * Fixup a directed route SMP for sending.  Return 0 if the SMP should
be
  * discarded.
  */
-static int smi_handle_dr_smp_send(struct ib_smp *smp,
-				  u8 node_type,
-				  int port_num)
+int smi_handle_dr_smp_send(struct ib_smp *smp,
+			   u8 node_type,
+			   int port_num)
 {
 	u8 hop_ptr, hop_cnt;
 
@@ -111,23 +110,6 @@
 }
 
 /*
- * Sender side handling of outgoing SMPs.  Fixup the SMP as required by
- * the spec.  Return 0 if the SMP should be dropped.
- */
-static int smi_handle_smp_send(struct ib_smp *smp,
-			       u8 node_type,
-			       int port_num)
-{
-	switch (smp->mgmt_class)
-	{
-	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		return smi_handle_dr_smp_send(smp, node_type, port_num);
-	default: 	/* LR SM class */
-		return 1;
-	}
-}
-
-/*
  * Return 1 if the SMP should be handled by the local SMA via
process_mad.
  */
 static inline int smi_check_local_smp(struct ib_mad_agent *mad_agent,
@@ -145,10 +127,10 @@
  * Adjust information for a received SMP.  Return 0 if the SMP should
be
  * dropped.
  */
-static int smi_handle_dr_smp_recv(struct ib_smp *smp,
-				  u8 node_type,
-				  int port_num,
-				  int phys_port_cnt)
+int smi_handle_dr_smp_recv(struct ib_smp *smp,
+			   u8 node_type,
+			   int port_num,
+			   int phys_port_cnt)
 {
 	u8 hop_ptr, hop_cnt;
 
@@ -221,29 +203,10 @@
 }
 
 /*
- * Receive side handling SMPs.  Save receive information as required by
- * the spec.  Return 0 if the SMP should be dropped.
- */
-static int smi_handle_smp_recv(struct ib_smp *smp,
-			       u8 node_type,
-			       int port_num,
-			       int phys_port_cnt)
-{
-	switch (smp->mgmt_class)
-	{
-	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		return smi_handle_dr_smp_recv(smp, node_type,
-					      port_num, phys_port_cnt);
-	default:	/* LR SM class */
-		return 1;
-	}
-}
-
-/*
  * Return 1 if the received DR SMP should be forwarded to the send
queue.
  * Return 0 if the SMP should be completed up the stack.
  */
-static int smi_check_forward_dr_smp(struct ib_smp *smp)
+int smi_check_forward_dr_smp(struct ib_smp *smp)
 {
 	u8 hop_ptr, hop_cnt;
 
@@ -274,31 +237,6 @@
 	return 0;
 }
 
-/*
- * Return 1 if the received SMP should be forwarded to the send queue.
- * Return 0 if the SMP should be completed up the stack.
- */
-static int smi_check_forward_smp(struct ib_smp *smp)
-{
-	switch (smp->mgmt_class)
-	{
-	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		return smi_check_forward_dr_smp(smp);
-	default:	/* LR SM class */
-		return 1;
-	}
-}
-
-static int mad_process_local(struct ib_mad_agent *mad_agent,
-			     struct ib_mad *mad,
-			     struct ib_mad *mad_response,
-			     u16 slid)
-{
-	return mad_agent->device->process_mad(mad_agent->device, 0,
-					      mad_agent->port_num,
-					      slid, mad, mad_response);
-}
-
 static inline struct ib_agent_port_private *
 __ib_get_agent_mad(struct ib_device *device, int port_num,
 		   struct ib_mad_agent *mad_agent)
@@ -339,12 +277,28 @@
 	return entry;
 }
 
-int agent_mad_send(struct ib_mad_agent *mad_agent,
-		   struct ib_mad *mad,
-		   struct ib_grh *grh,
-		   struct ib_mad_recv_wc *mad_recv_wc)
+int smi_check_local_dr_smp(struct ib_smp *smp,
+			   struct ib_device *device,
+			   int port_num)
 {
 	struct ib_agent_port_private *port_priv;
+
+	port_priv = ib_get_agent_mad(device, port_num, NULL);
+	if (!port_priv) {
+		printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d not
open\n",
+		       device->name, port_num);
+		return 1;
+	}
+
+	return smi_check_local_smp(port_priv->dr_smp_agent, smp);
+}
+
+static int agent_mad_send(struct ib_mad_agent *mad_agent,
+			  struct ib_mad *mad,
+			  struct ib_grh *grh,
+			  struct ib_mad_recv_wc *mad_recv_wc)
+{
+	struct ib_agent_port_private *port_priv;
 	struct ib_agent_send_wr *agent_send_wr;
 	struct ib_sge gather_list;
 	struct ib_send_wr send_wr;
@@ -445,114 +399,41 @@
 	return ret;
 }
 
-int smi_send_smp(struct ib_mad_agent *mad_agent,
-		 struct ib_smp *smp,
-		 struct ib_mad_recv_wc *mad_recv_wc,
-		 u16 slid,
-		 int phys_port_cnt)
+int agent_send(struct ib_mad *mad,
+	       struct ib_grh *grh,
+	       struct ib_wc *wc,
+	       struct ib_device *device,
+	       int port_num)
 {
-	struct ib_mad *smp_response;
-	int ret;
+	struct ib_agent_port_private *port_priv;
+	struct ib_mad_agent *mad_agent;
+	struct ib_mad_recv_wc mad_recv_wc;
 
-	if (!smi_handle_smp_send(smp, mad_agent->device->node_type,
-				 mad_agent->port_num)) {
-		/* SMI failed send */
-		return 0;
-	}
-
-	if (smi_check_local_smp(mad_agent, smp)) {
-		smp_response = kmalloc(sizeof(struct ib_mad), GFP_KERNEL);
-		if (!smp_response)
-			return 0;
-
-		ret = mad_process_local(mad_agent, (struct ib_mad *)smp,
-					smp_response, slid);
-		if (ret & IB_MAD_RESULT_SUCCESS) {
-			if (!smi_handle_smp_recv((struct ib_smp *)smp_response,
-						 mad_agent->device->node_type,
-						 mad_agent->port_num,
-						 phys_port_cnt)) {
-				/* SMI failed receive */
-				kfree(smp_response);
-				return 0;
-			}
-			if (agent_mad_send(mad_agent, smp_response,
-					   NULL, mad_recv_wc))
-				kfree(smp_response);
-		} else
-			kfree(smp_response);
+	port_priv = ib_get_agent_mad(device, port_num, NULL);
+	if (!port_priv) {
+		printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n",
+		       device->name, port_num);
 		return 1;
 	}
 
-	/* Post the send on the QP */
-	return 1;
-}
-
-int agent_mad_response(struct ib_mad_agent *mad_agent,
-		       struct ib_mad *mad,
-		       struct ib_mad_recv_wc *mad_recv_wc,
-		       u16 slid)
-{
-	struct ib_mad *response;
-	struct ib_grh *grh;
-	int ret;
-
-	response = kmalloc(sizeof(struct ib_mad), GFP_KERNEL);
-	if (!response)
-		return 0;
-
-	ret = mad_process_local(mad_agent, mad, response, slid);
-	if (ret & IB_MAD_RESULT_SUCCESS) {
-		grh = (void *)mad - sizeof(struct ib_grh);
-		agent_mad_send(mad_agent, response, grh, mad_recv_wc);
-	} else
-		kfree(response);
-	return 1;
-}
-
-int agent_recv_mad(struct ib_mad_agent *mad_agent,
-		   struct ib_mad *mad,
-		   struct ib_mad_recv_wc *mad_recv_wc,
-		   int phys_port_cnt)
-{
-	int port_num;
-
-	/* SM Directed Route or LID Routed class */
-	if (mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ||
-	    mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED) {
-		if (mad_agent->device->node_type != IB_NODE_SWITCH)
-			port_num = mad_agent->port_num;
-		else
-			port_num = mad_recv_wc->wc->port_num;
-		if (!smi_handle_smp_recv((struct ib_smp *)mad,
-					 mad_agent->device->node_type,
-					 port_num, phys_port_cnt)) {
-			/* SMI failed receive */
-			return 0;
-		}
-
-		if (smi_check_forward_smp((struct ib_smp *)mad)) {
-			smi_send_smp(mad_agent,
-				    (struct ib_smp *)mad,
-				     mad_recv_wc,
-				     mad_recv_wc->wc->slid,
-				     phys_port_cnt);
-			return 0;
-		}
-
-	} else {
-		/* PerfMgmt class */
-		if (mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
-			agent_mad_response(mad_agent, mad, mad_recv_wc,
-					   mad_recv_wc->wc->slid);
-		} else {
-			printk(KERN_ERR "agent_recv_mad: Unexpected mgmt class 0x%x
received\n", mad->mad_hdr.mgmt_class);
-		}
-		return 0;
+	/* Get mad agent based on mgmt_class in MAD */
+	switch (mad->mad_hdr.mgmt_class) {
+		case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
+			mad_agent = port_priv->dr_smp_agent;
+			break;
+		case IB_MGMT_CLASS_SUBN_LID_ROUTED:
+			mad_agent = port_priv->lr_smp_agent;
+			break;
+		case IB_MGMT_CLASS_PERF_MGMT:
+			mad_agent = port_priv->perf_mgmt_agent;
+			break;
+		default:
+			return 1;
 	}
 
-	/* Complete receive up stack */
-	return 1;
+	/* Other fields don't matter so should change signature to just use wc
*/
+	mad_recv_wc.wc = wc;
+	return agent_mad_send(mad_agent, mad, grh, &mad_recv_wc);
 }
 
 static void agent_send_handler(struct ib_mad_agent *mad_agent,
@@ -603,26 +484,6 @@
 	kfree(agent_send_wr->mad);
 }
 
-static void agent_recv_handler(struct ib_mad_agent *mad_agent,
-			       struct ib_mad_recv_wc *mad_recv_wc)
-{
-	struct ib_agent_port_private *port_priv;
-
-	/* Find matching MAD agent */
-	port_priv = ib_get_agent_mad(NULL, 0, mad_agent);
-	if (!port_priv) {
-		printk(KERN_ERR SPFX "agent_recv_handler: no matching MAD agent
%p\n",
-		       mad_agent);
-	} else {
-		agent_recv_mad(mad_agent, 
-			       mad_recv_wc->recv_buf->mad,
-			       mad_recv_wc, port_priv->phys_port_cnt);
-	}
-
-	/* Free received MAD */
-	ib_free_recv_mad(mad_recv_wc);
-}
-
 int ib_agent_port_open(struct ib_device *device, int port_num,
 			      int phys_port_cnt)
 {
@@ -663,19 +524,12 @@
 	reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE;
 	reg_req.mgmt_class_version = 1;
 
-	/* SMA needs to receive Get, Set, and TrapRepress methods */
-	bitmap_zero((unsigned long *)&reg_req.method_mask,
IB_MGMT_MAX_METHODS);
-	set_bit(IB_MGMT_METHOD_GET, (unsigned long *)&reg_req.method_mask);
-	set_bit(IB_MGMT_METHOD_SET, (unsigned long *)&reg_req.method_mask);
-	set_bit(IB_MGMT_METHOD_TRAP_REPRESS, 
-		(unsigned long *)&reg_req.method_mask);
-
 	port_priv->dr_smp_agent = ib_register_mad_agent(device, port_num,
 							IB_QPT_SMI,
-						       &reg_req, 0,
+							NULL, 0,
 						       &agent_send_handler,
-						       &agent_recv_handler,
-							NULL);
+							NULL, NULL);
+
 	if (IS_ERR(port_priv->dr_smp_agent)) {
 		ret = PTR_ERR(port_priv->dr_smp_agent);
 		goto error2;
@@ -685,10 +539,9 @@
 	reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
 	port_priv->lr_smp_agent = ib_register_mad_agent(device, port_num,
 							IB_QPT_SMI,
-						       &reg_req, 0,
+							NULL, 0,
 						       &agent_send_handler,
-						       &agent_recv_handler,
-							NULL);
+							NULL, NULL);
 	if (IS_ERR(port_priv->lr_smp_agent)) {
 		ret = PTR_ERR(port_priv->lr_smp_agent);
 		goto error3;
@@ -696,14 +549,11 @@
 
         /* Obtain MAD agent for PerfMgmt class */
         reg_req.mgmt_class = IB_MGMT_CLASS_PERF_MGMT;
-	clear_bit(IB_MGMT_METHOD_TRAP_REPRESS,
-		  (unsigned long *)&reg_req.method_mask);
-        port_priv->perf_mgmt_agent = ib_register_mad_agent(device,
port_num,
+	port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
 							   IB_QPT_GSI,
-						  	  &reg_req, 0,
+							   NULL, 0,
 							  &agent_send_handler,
-							  &agent_recv_handler,
-							   NULL);
+							   NULL, NULL);
 	if (IS_ERR(port_priv->perf_mgmt_agent)) {
 		ret = PTR_ERR(port_priv->perf_mgmt_agent);
 		goto error4;
Index: openib-candidate/src/linux-kernel/infiniband/access/mad.c
===================================================================
--- openib-candidate/src/linux-kernel/infiniband/access/mad.c	(revision
1124)
+++ openib-candidate/src/linux-kernel/infiniband/access/mad.c	(working
copy)
@@ -781,21 +781,13 @@
 			goto out;
 		}
 		version = port_priv->version[mad->mad_hdr.class_version];
-		if (!version) {
-			printk(KERN_ERR PFX "MAD received on port %d for class "
-			       "version %d with no client\n",
-			       port_priv->port_num, mad->mad_hdr.class_version);
+		if (!version)
 			goto out;
-		}
 		class = version->method_table[convert_mgmt_class(
 						mad->mad_hdr.mgmt_class)];
 		if (class)
 			mad_agent = class->agent[mad->mad_hdr.method &
 						 ~IB_MGMT_METHOD_RESP];
-		else
-			printk(KERN_ERR PFX "MAD received on port %d for class "
-			       "%d with no client\n",
-			       port_priv->port_num, mad->mad_hdr.mgmt_class);
 	}
 
 out:
@@ -808,9 +800,7 @@
 			       "%p on port %d\n",
 			       &mad_agent->agent, port_priv->port_num);
 		}
-	} else
-		printk(KERN_NOTICE PFX "No matching mad agent found for "
-		       "received MAD on port %d\n", port_priv->port_num);
+	}
 
 	spin_unlock_irqrestore(&port_priv->reg_lock, flags);
 
@@ -934,6 +924,23 @@
 	}
 }
 
+extern int smi_handle_dr_smp_recv(struct ib_smp *smp,
+				  u8 node_type,
+				  int port_num,
+				  int phys_port_cnt);
+extern int smi_check_forward_dr_smp(struct ib_smp *smp);
+extern int smi_handle_dr_smp_send(struct ib_smp *smp,
+				  u8 node_type,
+				  int port_num);
+extern int smi_check_local_dr_smp(struct ib_smp *smp,
+				  struct ib_device *device,
+				  int port_num);
+extern int agent_send(struct ib_mad *mad,
+		      struct ib_grh *grh,
+		      struct ib_wc *wc,
+		      struct ib_device *device,
+		      int port_num);
+
 static void ib_mad_recv_done_handler(struct ib_mad_port_private
*port_priv,
 				     struct ib_wc *wc)
 {
@@ -942,6 +949,7 @@
 	struct ib_mad_private *recv;
 	struct ib_mad_list_head *mad_list;
 	struct ib_mad_agent_private *mad_agent;
+	struct ib_smp *smp;
 	int solicited;
 
 	mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id;
@@ -968,14 +976,69 @@
 	if (!validate_mad(recv->header.recv_buf.mad, qp_info->qp->qp_num))
 		goto out;
 
-	/* Snoop MAD ? */
-	if (port_priv->device->snoop_mad)
-		if (port_priv->device->snoop_mad(port_priv->device,
-						 (u8)port_priv->port_num,
-						 wc->slid,
-						 recv->header.recv_buf.mad))
+	if (recv->header.recv_buf.mad->mad_hdr.mgmt_class ==
+	    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+		smp = (struct ib_smp *)recv->header.recv_buf.mad;
+		if (!smi_handle_dr_smp_recv(smp,
+					    port_priv->device->node_type,
+					    port_priv->port_num,
+					    port_priv->phys_port_cnt))
 			goto out;
+		if (!smi_check_forward_dr_smp(smp))
+			goto out;
+		if (!smi_handle_dr_smp_send(smp,
+					    port_priv->device->node_type,
+					    port_priv->port_num))
+			goto out;
+		if (!smi_check_local_dr_smp(smp,
+					    port_priv->device,
+					    port_priv->port_num))
+			goto out;
+	}
 
+	/* Give driver "right of first refusal" on incoming MAD */
+	if (port_priv->device->process_mad) {
+		struct ib_mad *response;
+		struct ib_grh *grh;
+		int ret;
+
+		response = kmalloc(sizeof(struct ib_mad), GFP_KERNEL);
+		if (!response) {
+			printk(KERN_ERR PFX "No memory for response MAD\n");
+			/* Is it better to assume that it wouldn't be processed ? */
+			goto out;
+		}
+
+		ret = port_priv->device->process_mad(port_priv->device, 0,
+						     port_priv->port_num,
+						     wc->slid,
+						     recv->header.recv_buf.mad,
+						     response);
+		if ((ret & IB_MAD_RESULT_SUCCESS) &&
+		    (ret & IB_MAD_RESULT_REPLY)) {
+			if (response->mad_hdr.mgmt_class ==
+			    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+				if (!smi_handle_dr_smp_recv(
+						(struct ib_smp *)response,
+						port_priv->device->node_type,
+						port_priv->port_num,
+						port_priv->phys_port_cnt)) {
+					kfree(response);
+					goto out;
+				}
+			}
+			/* Send response */
+			grh = (void *)recv->header.recv_buf.mad - sizeof(struct ib_grh);
+			if (agent_send(response, grh, wc,
+				       port_priv->device,
+				       port_priv->port_num)) {
+				kfree(response);
+				goto out;
+			}
+		} else
+			kfree(response);
+	}
+
 	/* Determine corresponding MAD agent for incoming receive MAD */
 	solicited = solicited_mad(recv->header.recv_buf.mad);
 	mad_agent = find_mad_agent(port_priv, recv->header.recv_buf.mad,
@@ -1673,7 +1736,9 @@
  * Open the port
  * Create the QP, PD, MR, and CQ if needed
  */
-static int ib_mad_port_open(struct ib_device *device, int port_num)
+static int ib_mad_port_open(struct ib_device *device,
+			    int port_num,
+			    int num_ports)
 {
 	int ret, cq_size;
 	u64 iova = 0;
@@ -1702,6 +1767,7 @@
 	memset(port_priv, 0, sizeof *port_priv);
 	port_priv->device = device;
 	port_priv->port_num = port_num;
+	port_priv->phys_port_cnt = num_ports;
 	spin_lock_init(&port_priv->reg_lock);
 
 	cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
@@ -1836,7 +1902,7 @@
 		cur_port = 1;
 	}
 	for (i = 0; i < num_ports; i++, cur_port++) {
-		ret = ib_mad_port_open(device, cur_port);
+		ret = ib_mad_port_open(device, cur_port, num_ports);
 		if (ret) {
 			printk(KERN_ERR PFX "Couldn't open %s port %d\n",
 			       device->name, cur_port);
Index: openib-candidate/src/linux-kernel/infiniband/access/mad_priv.h
===================================================================
---
openib-candidate/src/linux-kernel/infiniband/access/mad_priv.h	(revision
1119)
+++
openib-candidate/src/linux-kernel/infiniband/access/mad_priv.h	(working
copy)
@@ -156,6 +156,7 @@
 	struct list_head port_list;
 	struct ib_device *device;
 	int port_num;
+	int phys_port_cnt;
 	struct ib_cq *cq;
 	struct ib_pd *pd;
 	struct ib_mr *mr;
Index: openib-candidate/src/linux-kernel/infiniband/include/ib_verbs.h
===================================================================
---
openib-candidate/src/linux-kernel/infiniband/include/ib_verbs.h	(revision 1108)
+++
openib-candidate/src/linux-kernel/infiniband/include/ib_verbs.h	(working
copy)
@@ -640,14 +640,10 @@
 enum ib_mad_result {
 	IB_MAD_RESULT_FAILURE  = 0,      /* (!SUCCESS is the important flag)
*/
 	IB_MAD_RESULT_SUCCESS  = 1 << 0, /* MAD was successfully processed  
*/
-	IB_MAD_RESULT_REPLY    = 1 << 1  /* Reply packet needs to be sent   
*/
+	IB_MAD_RESULT_REPLY    = 1 << 1, /* Reply packet needs to be sent   
*/
+	IB_MAD_RESULT_CONSUMED = 1 << 2  /* Packet consumed: stop processing
*/
 };
 
-enum ib_snoop_mad_result {
-	IB_SNOOP_MAD_IGNORED,
-	IB_SNOOP_MAD_CONSUMED
-};
-
 #define IB_DEVICE_NAME_MAX	64
 
 struct ib_device {
Index: roland-merge/src/linux-kernel/infiniband/include/ib_verbs.h
===================================================================
---
roland-merge/src/linux-kernel/infiniband/include/ib_verbs.h	(revision
1125)
+++ roland-merge/src/linux-kernel/infiniband/include/ib_verbs.h	(working
copy)
@@ -656,14 +656,10 @@
 enum ib_mad_result {
 	IB_MAD_RESULT_FAILURE  = 0,      /* (!SUCCESS is the important flag)
*/
 	IB_MAD_RESULT_SUCCESS  = 1 << 0, /* MAD was successfully processed  
*/
-	IB_MAD_RESULT_REPLY    = 1 << 1  /* Reply packet needs to be sent   
*/
+	IB_MAD_RESULT_REPLY    = 1 << 1, /* Reply packet needs to be sent   
*/
+	IB_MAD_RESULT_CONSUMED = 1 << 2  /* Packet consumed: stop processing
*/
 };
 
-enum ib_snoop_mad_result {
-	IB_SNOOP_MAD_IGNORED,
-	IB_SNOOP_MAD_CONSUMED
-};
-
 #define IB_DEVICE_NAME_MAX 64
 
 struct ib_device {
Index: roland-merge/src/linux-kernel/infiniband/core/agent.c
===================================================================
--- roland-merge/src/linux-kernel/infiniband/core/agent.c	(revision
1125)
+++ roland-merge/src/linux-kernel/infiniband/core/agent.c	(working copy)
@@ -29,7 +29,6 @@
 #include <asm/bug.h>
 
 
-
 static spinlock_t ib_agent_port_list_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(ib_agent_port_list);
 
@@ -37,9 +36,9 @@
  * Fixup a directed route SMP for sending.  Return 0 if the SMP should
be
  * discarded.
  */
-static int smi_handle_dr_smp_send(struct ib_smp *smp,
-				  u8 node_type,
-				  int port_num)
+int smi_handle_dr_smp_send(struct ib_smp *smp,
+			   u8 node_type,
+			   int port_num)
 {
 	u8 hop_ptr, hop_cnt;
 
@@ -111,23 +110,6 @@
 }
 
 /*
- * Sender side handling of outgoing SMPs.  Fixup the SMP as required by
- * the spec.  Return 0 if the SMP should be dropped.
- */
-static int smi_handle_smp_send(struct ib_smp *smp,
-			       u8 node_type,
-			       int port_num)
-{
-	switch (smp->mgmt_class)
-	{
-	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		return smi_handle_dr_smp_send(smp, node_type, port_num);
-	default: 	/* LR SM class */
-		return 1;
-	}
-}
-
-/*
  * Return 1 if the SMP should be handled by the local SMA via
process_mad.
  */
 static inline int smi_check_local_smp(struct ib_mad_agent *mad_agent,
@@ -145,10 +127,10 @@
  * Adjust information for a received SMP.  Return 0 if the SMP should
be
  * dropped.
  */
-static int smi_handle_dr_smp_recv(struct ib_smp *smp,
-				  u8 node_type,
-				  int port_num,
-				  int phys_port_cnt)
+int smi_handle_dr_smp_recv(struct ib_smp *smp,
+			   u8 node_type,
+			   int port_num,
+			   int phys_port_cnt)
 {
 	u8 hop_ptr, hop_cnt;
 
@@ -221,29 +203,10 @@
 }
 
 /*
- * Receive side handling SMPs.  Save receive information as required by
- * the spec.  Return 0 if the SMP should be dropped.
- */
-static int smi_handle_smp_recv(struct ib_smp *smp,
-			       u8 node_type,
-			       int port_num,
-			       int phys_port_cnt)
-{
-	switch (smp->mgmt_class)
-	{
-	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		return smi_handle_dr_smp_recv(smp, node_type,
-					      port_num, phys_port_cnt);
-	default:	/* LR SM class */
-		return 1;
-	}
-}
-
-/*
  * Return 1 if the received DR SMP should be forwarded to the send
queue.
  * Return 0 if the SMP should be completed up the stack.
  */
-static int smi_check_forward_dr_smp(struct ib_smp *smp)
+int smi_check_forward_dr_smp(struct ib_smp *smp)
 {
 	u8 hop_ptr, hop_cnt;
 
@@ -274,31 +237,6 @@
 	return 0;
 }
 
-/*
- * Return 1 if the received SMP should be forwarded to the send queue.
- * Return 0 if the SMP should be completed up the stack.
- */
-static int smi_check_forward_smp(struct ib_smp *smp)
-{
-	switch (smp->mgmt_class)
-	{
-	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		return smi_check_forward_dr_smp(smp);
-	default:	/* LR SM class */
-		return 1;
-	}
-}
-
-static int mad_process_local(struct ib_mad_agent *mad_agent,
-			     struct ib_mad *mad,
-			     struct ib_mad *mad_response,
-			     u16 slid)
-{
-	return mad_agent->device->process_mad(mad_agent->device, 0,
-					      mad_agent->port_num,
-					      slid, mad, mad_response);
-}
-
 static inline struct ib_agent_port_private *
 __ib_get_agent_mad(struct ib_device *device, int port_num,
 		   struct ib_mad_agent *mad_agent)
@@ -339,30 +277,47 @@
 	return entry;
 }
 
-void agent_mad_send(struct ib_mad_agent *mad_agent,
-		    struct ib_mad *mad,
-		    struct ib_grh *grh,
-		    struct ib_mad_recv_wc *mad_recv_wc)
+int smi_check_local_dr_smp(struct ib_smp *smp,
+			   struct ib_device *device,
+			   int port_num)
 {
 	struct ib_agent_port_private *port_priv;
+
+	port_priv = ib_get_agent_mad(device, port_num, NULL);
+	if (!port_priv) {
+		printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d not
open\n",
+		       device->name, port_num);
+		return 1;
+	}
+
+	return smi_check_local_smp(port_priv->dr_smp_agent, smp);
+}
+
+static int agent_mad_send(struct ib_mad_agent *mad_agent,
+			  struct ib_mad *mad,
+			  struct ib_grh *grh,
+			  struct ib_mad_recv_wc *mad_recv_wc)
+{
+	struct ib_agent_port_private *port_priv;
 	struct ib_agent_send_wr *agent_send_wr;
 	struct ib_sge gather_list;
 	struct ib_send_wr send_wr;
 	struct ib_send_wr *bad_send_wr;
 	struct ib_ah_attr ah_attr;
 	unsigned long flags;
+	int ret = 1;
 
 	/* Find matching MAD agent */
 	port_priv = ib_get_agent_mad(NULL, 0, mad_agent);
 	if (!port_priv) {
 		printk(KERN_ERR SPFX "agent_mad_send: no matching MAD agent %p\n",
 		       mad_agent);
-		return;
+		goto out;
 	}
 
 	agent_send_wr = kmalloc(sizeof(*agent_send_wr), GFP_KERNEL);
 	if (!agent_send_wr)
-		return;
+		goto out;
 	agent_send_wr->mad = mad;
 
 	/* PCI mapping */
@@ -406,8 +361,8 @@
 	agent_send_wr->ah = ib_create_ah(mad_agent->qp->pd, &ah_attr);
 	if (IS_ERR(agent_send_wr->ah)) {
 		printk(KERN_ERR SPFX "No memory for address handle\n");
-		kfree(mad);
-		return;
+		kfree(agent_send_wr);
+		goto out;
 	}
                                                                                 
 	send_wr.wr.ud.ah = agent_send_wr->ah;
@@ -432,120 +387,53 @@
 				 sizeof(struct ib_mad),
 				 PCI_DMA_TODEVICE);
 		ib_destroy_ah(agent_send_wr->ah);
+		kfree(agent_send_wr);
 	} else {
 		list_add_tail(&agent_send_wr->send_list,
 			      &port_priv->send_posted_list);
 		spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
+		ret = 0;
 	}
+
+out:
+	return ret;
 }
 
-int smi_send_smp(struct ib_mad_agent *mad_agent,
-		 struct ib_smp *smp,
-		 struct ib_mad_recv_wc *mad_recv_wc,
-		 u16 slid,
-		 int phys_port_cnt)
+int agent_send(struct ib_mad *mad,
+	       struct ib_grh *grh,
+	       struct ib_wc *wc,
+	       struct ib_device *device,
+	       int port_num)
 {
-	struct ib_mad *smp_response;
-	int ret;
+	struct ib_agent_port_private *port_priv;
+	struct ib_mad_agent *mad_agent;
+	struct ib_mad_recv_wc mad_recv_wc;
 
-	if (!smi_handle_smp_send(smp, mad_agent->device->node_type,
-				 mad_agent->port_num)) {
-		/* SMI failed send */
-		return 0;
-	}
-
-	if (smi_check_local_smp(mad_agent, smp)) {
-		smp_response = kmalloc(sizeof(struct ib_mad), GFP_KERNEL);
-		if (!smp_response)
-			return 0;
-
-		ret = mad_process_local(mad_agent, (struct ib_mad *)smp,
-					smp_response, slid);
-		if (ret & IB_MAD_RESULT_SUCCESS) {
-			if (!smi_handle_smp_recv((struct ib_smp *)smp_response,
-						 mad_agent->device->node_type,
-						 mad_agent->port_num,
-						 phys_port_cnt)) {
-				/* SMI failed receive */
-				kfree(smp_response);
-				return 0;
-			}
-			agent_mad_send(mad_agent, smp_response,
-				       NULL, mad_recv_wc);
-		} else
-			kfree(smp_response);
+	port_priv = ib_get_agent_mad(device, port_num, NULL);
+	if (!port_priv) {
+		printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n",
+		       device->name, port_num);
 		return 1;
 	}
 
-	/* Post the send on the QP */
-	return 1;
-}
-
-int agent_mad_response(struct ib_mad_agent *mad_agent,
-		       struct ib_mad *mad,
-		       struct ib_mad_recv_wc *mad_recv_wc,
-		       u16 slid)
-{
-	struct ib_mad *response;
-	struct ib_grh *grh;
-	int ret;
-
-	response = kmalloc(sizeof(struct ib_mad), GFP_KERNEL);
-	if (!response)
-		return 0;
-
-	ret = mad_process_local(mad_agent, mad, response, slid);
-	if (ret & IB_MAD_RESULT_SUCCESS) {
-		grh = (void *)mad - sizeof(struct ib_grh);
-		agent_mad_send(mad_agent, response, grh, mad_recv_wc);
-	} else
-		kfree(response);
-	return 1;
-}
-
-int agent_recv_mad(struct ib_mad_agent *mad_agent,
-		   struct ib_mad *mad,
-		   struct ib_mad_recv_wc *mad_recv_wc,
-		   int phys_port_cnt)
-{
-	int port_num;
-
-	/* SM Directed Route or LID Routed class */
-	if (mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ||
-	    mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED) {
-		if (mad_agent->device->node_type != IB_NODE_SWITCH)
-			port_num = mad_agent->port_num;
-		else
-			port_num = mad_recv_wc->wc->port_num;
-		if (!smi_handle_smp_recv((struct ib_smp *)mad,
-					 mad_agent->device->node_type,
-					 port_num, phys_port_cnt)) {
-			/* SMI failed receive */
-			return 0;
-		}
-
-		if (smi_check_forward_smp((struct ib_smp *)mad)) {
-			smi_send_smp(mad_agent,
-				    (struct ib_smp *)mad,
-				     mad_recv_wc,
-				     mad_recv_wc->wc->slid,
-				     phys_port_cnt);
-			return 0;
-		}
-
-	} else {
-		/* PerfMgmt class */
-		if (mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
-			agent_mad_response(mad_agent, mad, mad_recv_wc,
-					   mad_recv_wc->wc->slid);
-		} else {
-			printk(KERN_ERR "agent_recv_mad: Unexpected mgmt class 0x%x
received\n", mad->mad_hdr.mgmt_class);
-		}
-		return 0;
+	/* Get mad agent based on mgmt_class in MAD */
+	switch (mad->mad_hdr.mgmt_class) {
+		case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
+			mad_agent = port_priv->dr_smp_agent;
+			break;
+		case IB_MGMT_CLASS_SUBN_LID_ROUTED:
+			mad_agent = port_priv->lr_smp_agent;
+			break;
+		case IB_MGMT_CLASS_PERF_MGMT:
+			mad_agent = port_priv->perf_mgmt_agent;
+			break;
+		default:
+			return 1;
 	}
 
-	/* Complete receive up stack */
-	return 1;
+	/* Other fields don't matter so should change signature to just use wc
*/
+	mad_recv_wc.wc = wc;
+	return agent_mad_send(mad_agent, mad, grh, &mad_recv_wc);
 }
 
 static void agent_send_handler(struct ib_mad_agent *mad_agent,
@@ -596,26 +484,6 @@
 	kfree(agent_send_wr->mad);
 }
 
-static void agent_recv_handler(struct ib_mad_agent *mad_agent,
-			       struct ib_mad_recv_wc *mad_recv_wc)
-{
-	struct ib_agent_port_private *port_priv;
-
-	/* Find matching MAD agent */
-	port_priv = ib_get_agent_mad(NULL, 0, mad_agent);
-	if (!port_priv) {
-		printk(KERN_ERR SPFX "agent_recv_handler: no matching MAD agent
%p\n",
-		       mad_agent);
-	} else {
-		agent_recv_mad(mad_agent, 
-			       mad_recv_wc->recv_buf->mad,
-			       mad_recv_wc, port_priv->phys_port_cnt);
-	}
-
-	/* Free received MAD */
-	ib_free_recv_mad(mad_recv_wc);
-}
-
 int ib_agent_port_open(struct ib_device *device, int port_num,
 			      int phys_port_cnt)
 {
@@ -656,19 +524,12 @@
 	reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE;
 	reg_req.mgmt_class_version = 1;
 
-	/* SMA needs to receive Get, Set, and TrapRepress methods */
-	bitmap_zero((unsigned long *)&reg_req.method_mask,
IB_MGMT_MAX_METHODS);
-	set_bit(IB_MGMT_METHOD_GET, (unsigned long *)&reg_req.method_mask);
-	set_bit(IB_MGMT_METHOD_SET, (unsigned long *)&reg_req.method_mask);
-	set_bit(IB_MGMT_METHOD_TRAP_REPRESS, 
-		(unsigned long *)&reg_req.method_mask);
-
 	port_priv->dr_smp_agent = ib_register_mad_agent(device, port_num,
 							IB_QPT_SMI,
-						       &reg_req, 0,
+							NULL, 0,
 						       &agent_send_handler,
-						       &agent_recv_handler,
-							NULL);
+							NULL, NULL);
+
 	if (IS_ERR(port_priv->dr_smp_agent)) {
 		ret = PTR_ERR(port_priv->dr_smp_agent);
 		goto error2;
@@ -678,10 +539,9 @@
 	reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
 	port_priv->lr_smp_agent = ib_register_mad_agent(device, port_num,
 							IB_QPT_SMI,
-						       &reg_req, 0,
+							NULL, 0,
 						       &agent_send_handler,
-						       &agent_recv_handler,
-							NULL);
+							NULL, NULL);
 	if (IS_ERR(port_priv->lr_smp_agent)) {
 		ret = PTR_ERR(port_priv->lr_smp_agent);
 		goto error3;
@@ -689,14 +549,11 @@
 
         /* Obtain MAD agent for PerfMgmt class */
         reg_req.mgmt_class = IB_MGMT_CLASS_PERF_MGMT;
-	clear_bit(IB_MGMT_METHOD_TRAP_REPRESS,
-		  (unsigned long *)&reg_req.method_mask);
-        port_priv->perf_mgmt_agent = ib_register_mad_agent(device,
port_num,
+	port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
 							   IB_QPT_GSI,
-						  	  &reg_req, 0,
+							   NULL, 0,
 							  &agent_send_handler,
-							  &agent_recv_handler,
-							   NULL);
+							   NULL, NULL);
 	if (IS_ERR(port_priv->perf_mgmt_agent)) {
 		ret = PTR_ERR(port_priv->perf_mgmt_agent);
 		goto error4;
Index: roland-merge/src/linux-kernel/infiniband/core/mad.c
===================================================================
--- roland-merge/src/linux-kernel/infiniband/core/mad.c	(revision 1125)
+++ roland-merge/src/linux-kernel/infiniband/core/mad.c	(working copy)
@@ -747,13 +747,16 @@
 	       struct ib_mad *mad,
 	       int solicited)
 {
-	struct ib_mad_agent_private *entry, *mad_agent = NULL;
-	struct ib_mad_mgmt_class_table *version;
-	struct ib_mad_mgmt_method_table *class;
-	u32 hi_tid;
+	struct ib_mad_agent_private *mad_agent = NULL;
+	unsigned long flags;
 
+	spin_lock_irqsave(&port_priv->reg_lock, flags);
+
 	/* Whether MAD was solicited determines type of routing to MAD client
*/
 	if (solicited) {
+		u32 hi_tid;
+		struct ib_mad_agent_private *entry;
+
 		/* Routing is based on high 32 bits of transaction ID of MAD  */
 		hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32;
 		list_for_each_entry(entry, &port_priv->agent_list, agent_list) {
@@ -762,12 +765,14 @@
 				break;
 			}
 		}
-		if (!mad_agent) {
+		if (!mad_agent)
 			printk(KERN_ERR PFX "No client 0x%x for received MAD "
-			       "on port %d\n", hi_tid, port_priv->port_num);
-			goto out;
-		}
+			       "on port %d\n",
+			       hi_tid, port_priv->port_num);
 	} else {
+		struct ib_mad_mgmt_class_table *version;
+		struct ib_mad_mgmt_method_table *class;
+
 		/* Routing is based on version, class, and method */
 		if (mad->mad_hdr.class_version >= MAX_MGMT_VERSION) {
 			printk(KERN_ERR PFX "MAD received with unsupported "
@@ -776,32 +781,29 @@
 			goto out;
 		}
 		version = port_priv->version[mad->mad_hdr.class_version];
-		if (!version) {
-			printk(KERN_ERR PFX "MAD received on port %d for class "
-			       "version %d with no client\n",
-			       port_priv->port_num, mad->mad_hdr.class_version);
+		if (!version)
 			goto out;
-		}
 		class = version->method_table[convert_mgmt_class(
 						mad->mad_hdr.mgmt_class)];
-		if (!class) {
-			printk(KERN_ERR PFX "MAD received on port %d for class "
-			       "%d with no client\n",
-			       port_priv->port_num, mad->mad_hdr.mgmt_class);
-			goto out;
-		}
-		mad_agent = class->agent[mad->mad_hdr.method &
-					 ~IB_MGMT_METHOD_RESP];		
+		if (class)
+			mad_agent = class->agent[mad->mad_hdr.method &
+						 ~IB_MGMT_METHOD_RESP];
 	}
 
 out:
-	if (mad_agent && !mad_agent->agent.recv_handler) {
-		printk(KERN_ERR PFX "No receive handler for client "
-		       "%p on port %d\n",
-		       &mad_agent->agent, port_priv->port_num);
-		mad_agent = NULL;
+	if (mad_agent) {
+		if (mad_agent->agent.recv_handler)
+			atomic_inc(&mad_agent->refcount);
+		else {
+			mad_agent = NULL;
+			printk(KERN_ERR PFX "No receive handler for client "
+			       "%p on port %d\n",
+			       &mad_agent->agent, port_priv->port_num);
+		}
 	}
 
+	spin_unlock_irqrestore(&port_priv->reg_lock, flags);
+
 	return mad_agent;
 }
 
@@ -922,6 +924,23 @@
 	}
 }
 
+extern int smi_handle_dr_smp_recv(struct ib_smp *smp,
+				  u8 node_type,
+				  int port_num,
+				  int phys_port_cnt);
+extern int smi_check_forward_dr_smp(struct ib_smp *smp);
+extern int smi_handle_dr_smp_send(struct ib_smp *smp,
+				  u8 node_type,
+				  int port_num);
+extern int smi_check_local_dr_smp(struct ib_smp *smp,
+				  struct ib_device *device,
+				  int port_num);
+extern int agent_send(struct ib_mad *mad,
+		      struct ib_grh *grh,
+		      struct ib_wc *wc,
+		      struct ib_device *device,
+		      int port_num);
+
 static void ib_mad_recv_done_handler(struct ib_mad_port_private
*port_priv,
 				     struct ib_wc *wc)
 {
@@ -929,9 +948,9 @@
 	struct ib_mad_private_header *mad_priv_hdr;
 	struct ib_mad_private *recv;
 	struct ib_mad_list_head *mad_list;
-	struct ib_mad_agent_private *mad_agent = NULL;
+	struct ib_mad_agent_private *mad_agent;
+	struct ib_smp *smp;
 	int solicited;
-	unsigned long flags;
 
 	mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id;
 	qp_info = mad_list->mad_queue->qp_info;
@@ -957,31 +976,80 @@
 	if (!validate_mad(recv->header.recv_buf.mad, qp_info->qp->qp_num))
 		goto out;
 
-	/* Snoop MAD ? */
-	if (port_priv->device->snoop_mad)
-		if (port_priv->device->snoop_mad(port_priv->device,
-						 (u8)port_priv->port_num,
-						 wc->slid,
-						 recv->header.recv_buf.mad))
+	if (recv->header.recv_buf.mad->mad_hdr.mgmt_class ==
+	    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+		smp = (struct ib_smp *)recv->header.recv_buf.mad;
+		if (!smi_handle_dr_smp_recv(smp,
+					    port_priv->device->node_type,
+					    port_priv->port_num,
+					    port_priv->phys_port_cnt))
 			goto out;
+		if (!smi_check_forward_dr_smp(smp))
+			goto out;
+		if (!smi_handle_dr_smp_send(smp,
+					    port_priv->device->node_type,
+					    port_priv->port_num))
+			goto out;
+		if (!smi_check_local_dr_smp(smp,
+					    port_priv->device,
+					    port_priv->port_num))
+			goto out;
+	}
 
-	spin_lock_irqsave(&port_priv->reg_lock, flags);
+	/* Give driver "right of first refusal" on incoming MAD */
+	if (port_priv->device->process_mad) {
+		struct ib_mad *response;
+		struct ib_grh *grh;
+		int ret;
+
+		response = kmalloc(sizeof(struct ib_mad), GFP_KERNEL);
+		if (!response) {
+			printk(KERN_ERR PFX "No memory for response MAD\n");
+			/* Is it better to assume that it wouldn't be processed ? */
+			goto out;
+		}
+
+		ret = port_priv->device->process_mad(port_priv->device, 0,
+						     port_priv->port_num,
+						     wc->slid,
+						     recv->header.recv_buf.mad,
+						     response);
+		if ((ret & IB_MAD_RESULT_SUCCESS) &&
+		    (ret & IB_MAD_RESULT_REPLY)) {
+			if (response->mad_hdr.mgmt_class ==
+			    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+				if (!smi_handle_dr_smp_recv(
+						(struct ib_smp *)response,
+						port_priv->device->node_type,
+						port_priv->port_num,
+						port_priv->phys_port_cnt)) {
+					kfree(response);
+					goto out;
+				}
+			}
+			/* Send response */
+			grh = (void *)recv->header.recv_buf.mad - sizeof(struct ib_grh);
+			if (agent_send(response, grh, wc,
+				       port_priv->device,
+				       port_priv->port_num)) {
+				kfree(response);
+				goto out;
+			}
+		} else
+			kfree(response);
+	}
+
 	/* Determine corresponding MAD agent for incoming receive MAD */
 	solicited = solicited_mad(recv->header.recv_buf.mad);
 	mad_agent = find_mad_agent(port_priv, recv->header.recv_buf.mad,
 				   solicited);
-	if (!mad_agent) {
-		spin_unlock_irqrestore(&port_priv->reg_lock, flags);
-		printk(KERN_NOTICE PFX "No matching mad agent found for "
-		       "received MAD on port %d\n", port_priv->port_num);
-	} else {
-		atomic_inc(&mad_agent->refcount);
-		spin_unlock_irqrestore(&port_priv->reg_lock, flags);
+	if (mad_agent) {
 		ib_mad_complete_recv(mad_agent, recv, solicited);
+		recv = NULL;	/* recv is freed up via ib_mad_complete_recv */
 	}
 
 out:
-	if (!mad_agent) {
+	if (recv) {
 		/* Should this case be optimized ? */
 		kmem_cache_free(ib_mad_cache, recv);
 	}
@@ -1668,7 +1736,9 @@
  * Open the port
  * Create the QP, PD, MR, and CQ if needed
  */
-static int ib_mad_port_open(struct ib_device *device, int port_num)
+static int ib_mad_port_open(struct ib_device *device,
+			    int port_num,
+			    int num_ports)
 {
 	int ret, cq_size;
 	u64 iova = 0;
@@ -1697,6 +1767,7 @@
 	memset(port_priv, 0, sizeof *port_priv);
 	port_priv->device = device;
 	port_priv->port_num = port_num;
+	port_priv->phys_port_cnt = num_ports;
 	spin_lock_init(&port_priv->reg_lock);
 
 	cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
@@ -1831,7 +1902,7 @@
 		cur_port = 1;
 	}
 	for (i = 0; i < num_ports; i++, cur_port++) {
-		ret = ib_mad_port_open(device, cur_port);
+		ret = ib_mad_port_open(device, cur_port, num_ports);
 		if (ret) {
 			printk(KERN_ERR PFX "Couldn't open %s port %d\n",
 			       device->name, cur_port);
Index: roland-merge/src/linux-kernel/infiniband/core/mad_priv.h
===================================================================
--- roland-merge/src/linux-kernel/infiniband/core/mad_priv.h	(revision
1125)
+++ roland-merge/src/linux-kernel/infiniband/core/mad_priv.h	(working
copy)
@@ -156,6 +156,7 @@
 	struct list_head port_list;
 	struct ib_device *device;
 	int port_num;
+	int phys_port_cnt;
 	struct ib_cq *cq;
 	struct ib_pd *pd;
 	struct ib_mr *mr;
Index: roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_dev.h
===================================================================
---
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_dev.h	(revision
1125)
+++
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_dev.h	(working
copy)
@@ -349,10 +349,6 @@
 		      u16 slid,
 		      struct ib_mad *in_mad,
 		      struct ib_mad *out_mad);
-enum ib_snoop_mad_result mthca_snoop_mad(struct ib_device *ibdev,
-					 u8 port_num,
-					 u16 slid,
-					 struct ib_mad *mad);
 
 static inline struct mthca_dev *to_mdev(struct ib_device *ibdev)
 {
Index:
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_provider.c
===================================================================
---
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_provider.c	(revision 1125)
+++
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_provider.c	(working copy)
@@ -600,7 +600,6 @@
 	dev->ib_dev.attach_mcast         = mthca_multicast_attach;
 	dev->ib_dev.detach_mcast         = mthca_multicast_detach;
 	dev->ib_dev.process_mad          = mthca_process_mad;
-	dev->ib_dev.snoop_mad            = mthca_snoop_mad;
 
 	ret = ib_register_device(&dev->ib_dev);
 	if (ret)
Index: roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_mad.c
===================================================================
---
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_mad.c	(revision
1125)
+++
roland-merge/src/linux-kernel/infiniband/hw/mthca/mthca_mad.c	(working
copy)
@@ -79,6 +79,16 @@
 	int err;
 	u8 status;
 
+	/* Forward locally generated traps to the SM */
+	if (in_mad->mad_hdr.mgmt_class	== IB_MGMT_CLASS_SUBN_LID_ROUTED &&
+	    in_mad->mad_hdr.method	== IB_MGMT_METHOD_TRAP		 &&
+	    slid			== 0) {
+
+		/* XXX: forward locally generated MAD to SM */
+
+		return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
+	}
+
 	/*
 	 * Only handle SM gets, sets and trap represses for SM class
 	 *
@@ -137,21 +147,6 @@
 	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
 }
 
-enum ib_snoop_mad_result mthca_snoop_mad(struct ib_device *ibdev,
-					 u8 port_num,
-					 u16 slid,
-					 struct ib_mad *mad)
-{
-	if (mad->mad_hdr.method     != IB_MGMT_METHOD_TRAP               ||
-	    mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ||
-	    slid                    != 0)
-		return IB_SNOOP_MAD_IGNORED;
-
-	/* XXX: forward locally generated MAD to SM */
-
-	return IB_SNOOP_MAD_CONSUMED;
-}
-
 /*
  * Local Variables:
  * c-file-style: "linux"






More information about the general mailing list