[openfabrics-ewg] [PATCH] drivers/infiniband: madeye integration

Sasha Khapyorsky sashak at voltaire.com
Wed Feb 14 08:24:07 PST 2007


This integrates madeye debug module into the tree.

Signed-off-by: Sasha Khapyorsky <sashak at voltaire.com>
---
 drivers/infiniband/Kconfig       |    2 +
 drivers/infiniband/Makefile      |    1 +
 drivers/infiniband/util/Kconfig  |    6 +
 drivers/infiniband/util/Makefile |    3 +
 drivers/infiniband/util/madeye.c |  590 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 602 insertions(+), 0 deletions(-)
 create mode 100644 drivers/infiniband/util/Kconfig
 create mode 100644 drivers/infiniband/util/Makefile
 create mode 100644 drivers/infiniband/util/madeye.c

diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 712e5e2..de8e39f 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -50,4 +50,6 @@ source "drivers/infiniband/ulp/sdp/Kconfig"
 
 source "drivers/infiniband/ulp/vnic/Kconfig"
 
+source "drivers/infiniband/util/Kconfig"
+
 endmenu
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index 57f2616..a7d1dc2 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_INFINIBAND_SRP)		+= ulp/srp/
 obj-$(CONFIG_INFINIBAND_ISER)		+= ulp/iser/
 obj-$(CONFIG_INFINIBAND_SDP)		+= ulp/sdp/
 obj-$(CONFIG_INFINIBAND_VNIC)		+= ulp/vnic/
+obj-$(CONFIG_INFINIBAND_MADEYE)		+= util/
diff --git a/drivers/infiniband/util/Kconfig b/drivers/infiniband/util/Kconfig
new file mode 100644
index 0000000..5e98eaa
--- /dev/null
+++ b/drivers/infiniband/util/Kconfig
@@ -0,0 +1,6 @@
+config INFINIBAND_MADEYE
+	tristate "MAD debug viewer for InfiniBand"
+	depends on INFINIBAND
+	---help---
+	  Prints sent and received MADs on QP 0/1 for debugging.
+
diff --git a/drivers/infiniband/util/Makefile b/drivers/infiniband/util/Makefile
new file mode 100644
index 0000000..caf9471
--- /dev/null
+++ b/drivers/infiniband/util/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INFINIBAND_MADEYE)	+= ib_madeye.o
+
+ib_madeye-y := madeye.o
diff --git a/drivers/infiniband/util/madeye.c b/drivers/infiniband/util/madeye.c
new file mode 100644
index 0000000..2a76d45
--- /dev/null
+++ b/drivers/infiniband/util/madeye.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2005, 2006 Voltaire Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directorY of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_sa.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("InfiniBand MAD viewer");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static void madeye_remove_one(struct ib_device *device);
+static void madeye_add_one(struct ib_device *device);
+
+static struct ib_client madeye_client = {
+	.name   = "madeye",
+	.add    = madeye_add_one,
+	.remove = madeye_remove_one
+};
+
+struct madeye_port {
+	struct ib_mad_agent *smi_agent;
+	struct ib_mad_agent *gsi_agent;
+};
+
+static int smp = 1;
+static int gmp = 1;
+static int mgmt_class = 0;
+static int attr_id = 0;
+static int data = 0;
+
+module_param(smp, int, 0444);
+module_param(gmp, int, 0444);
+module_param(mgmt_class, int, 0444);
+module_param(attr_id, int, 0444);
+module_param(data, int, 0444);
+
+MODULE_PARM_DESC(smp, "Display all SMPs (default=1)");
+MODULE_PARM_DESC(gmp, "Display all GMPs (default=1)");
+MODULE_PARM_DESC(mgmt_class, "Display all MADs of specified class (default=0)");
+MODULE_PARM_DESC(attr_id, "Display add MADs of specified attribute ID (default=0)");
+MODULE_PARM_DESC(data, "Display data area of MADs (default=0)");
+
+static char * get_class_name(u8 mgmt_class)
+{
+	switch(mgmt_class) {
+	case IB_MGMT_CLASS_SUBN_LID_ROUTED:
+		return "LID routed SMP";
+	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
+		return "Directed route SMP";
+	case IB_MGMT_CLASS_SUBN_ADM:
+		return "Subnet admin.";
+	case IB_MGMT_CLASS_PERF_MGMT:
+		return "Perf. mgmt.";
+	case IB_MGMT_CLASS_BM:
+		return "Baseboard mgmt.";
+	case IB_MGMT_CLASS_DEVICE_MGMT:
+		return "Device mgmt.";
+	case IB_MGMT_CLASS_CM:
+		return "Comm. mgmt.";
+	case IB_MGMT_CLASS_SNMP:
+		return "SNMP";
+	default:
+		return "Unknown vendor/application";
+	}
+}
+
+static char * get_method_name(u8 mgmt_class, u8 method)
+{
+	switch(method) {
+	case IB_MGMT_METHOD_GET:
+		return "Get";
+	case IB_MGMT_METHOD_SET:
+		return "Set";
+	case IB_MGMT_METHOD_GET_RESP:
+		return "Get response";
+	case IB_MGMT_METHOD_SEND:
+		return "Send";
+	case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP:
+		return "Send response";
+	case IB_MGMT_METHOD_TRAP:
+		return "Trap";
+	case IB_MGMT_METHOD_REPORT:
+		return "Report";
+	case IB_MGMT_METHOD_REPORT_RESP:
+		return "Report response";
+	case IB_MGMT_METHOD_TRAP_REPRESS:
+		return "Trap repress";
+	default:
+		break;
+	}
+
+	switch (mgmt_class) {
+	case IB_MGMT_CLASS_SUBN_ADM:
+		switch (method) {
+		case IB_SA_METHOD_GET_TABLE:
+			return "Get table";
+		case IB_SA_METHOD_GET_TABLE_RESP:
+			return "Get table response";
+		case IB_SA_METHOD_DELETE:
+			return "Delete";
+		case IB_SA_METHOD_DELETE_RESP:
+			return "Delete response";
+		case IB_SA_METHOD_GET_MULTI:
+			return "Get Multi";
+		case IB_SA_METHOD_GET_MULTI_RESP:
+			return "Get Multi response";
+		case IB_SA_METHOD_GET_TRACE_TBL:
+			return "Get Trace Table response";
+		default:
+			break;
+		}
+	default:
+		break;
+	}
+
+	return "Unknown";
+}
+
+static void print_status_details(u16 status)
+{
+	if (status & 0x0001)
+		printk("               busy\n");
+	if (status & 0x0002)
+		printk("               redirection required\n");
+	switch((status & 0x001C) >> 2) {
+	case 1:
+		printk("               bad version\n");
+		break;
+	case 2:
+		printk("               method not supported\n");
+		break;
+	case 3:
+		printk("               method/attribute combo not supported\n");
+		break;
+	case 7:
+		printk("               invalid attribute/modifier value\n");
+		break;
+	}
+}
+
+static char * get_sa_attr(__be16 attr)
+{
+	switch(attr) {
+	case IB_SA_ATTR_CLASS_PORTINFO:
+		return "Class Port Info";
+	case IB_SA_ATTR_NOTICE:
+		return "Notice";
+	case IB_SA_ATTR_INFORM_INFO:
+		return "Inform Info";
+	case IB_SA_ATTR_NODE_REC:
+		return "Node Record";
+	case IB_SA_ATTR_PORT_INFO_REC:
+		return "PortInfo Record";
+	case IB_SA_ATTR_SL2VL_REC:
+		return "SL to VL Record";
+	case IB_SA_ATTR_SWITCH_REC:
+		return "Switch Record";
+	case IB_SA_ATTR_LINEAR_FDB_REC:
+		return "Linear FDB Record";
+	case IB_SA_ATTR_RANDOM_FDB_REC:
+		return "Random FDB Record";
+	case IB_SA_ATTR_MCAST_FDB_REC:
+		return "Multicast FDB Record";
+	case IB_SA_ATTR_SM_INFO_REC:
+		return "SM Info Record";
+	case IB_SA_ATTR_LINK_REC:
+		return "Link Record";
+	case IB_SA_ATTR_GUID_INFO_REC:
+		return "Guid Info Record";
+	case IB_SA_ATTR_SERVICE_REC:
+		return "Service Record";
+	case IB_SA_ATTR_PARTITION_REC:
+		return "Partition Record";
+	case IB_SA_ATTR_PATH_REC:
+		return "Path Record";
+	case IB_SA_ATTR_VL_ARB_REC:
+		return "VL Arb Record";
+	case IB_SA_ATTR_MC_MEMBER_REC:
+		return "MC Member Record";
+	case IB_SA_ATTR_TRACE_REC:
+		return "Trace Record";
+	case IB_SA_ATTR_MULTI_PATH_REC:
+		return "Multi Path Record";
+	case IB_SA_ATTR_SERVICE_ASSOC_REC:
+		return "Service Assoc Record";
+	case IB_SA_ATTR_INFORM_INFO_REC:
+		return "Inform Info Record";
+	default:
+		return "";
+	}
+}
+
+static void print_mad_hdr(struct ib_mad_hdr *mad_hdr)
+{
+	printk("MAD version....0x%01x\n", mad_hdr->base_version);
+	printk("Class..........0x%01x (%s)\n", mad_hdr->mgmt_class,
+	       get_class_name(mad_hdr->mgmt_class));
+	printk("Class version..0x%01x\n", mad_hdr->class_version);
+	printk("Method.........0x%01x (%s)\n", mad_hdr->method,
+	       get_method_name(mad_hdr->mgmt_class, mad_hdr->method));
+	printk("Status.........0x%02x\n", be16_to_cpu(mad_hdr->status));
+	if (mad_hdr->status)
+		print_status_details(be16_to_cpu(mad_hdr->status));
+	printk("Class specific.0x%02x\n", be16_to_cpu(mad_hdr->class_specific));
+	printk("Trans ID.......0x%llx\n", mad_hdr->tid);
+	if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
+		printk("Attr ID........0x%02x (%s)\n",
+		       be16_to_cpu(mad_hdr->attr_id),
+		       get_sa_attr(be16_to_cpu(mad_hdr->attr_id)));
+	else
+		printk("Attr ID........0x%02x\n",
+		       be16_to_cpu(mad_hdr->attr_id));
+	printk("Attr modifier..0x%04x\n", be32_to_cpu(mad_hdr->attr_mod));
+}
+
+static char * get_rmpp_type(u8 rmpp_type)
+{
+	switch (rmpp_type) {
+	case IB_MGMT_RMPP_TYPE_DATA:
+		return "Data";
+	case IB_MGMT_RMPP_TYPE_ACK:
+		return "Ack";
+	case IB_MGMT_RMPP_TYPE_STOP:
+		return "Stop";
+	case IB_MGMT_RMPP_TYPE_ABORT:
+		return "Abort";
+	default:
+		return "Unknown";
+	}
+}
+
+static char * get_rmpp_flags(u8 rmpp_flags)
+{
+	if (rmpp_flags & IB_MGMT_RMPP_FLAG_ACTIVE)
+		if (rmpp_flags & IB_MGMT_RMPP_FLAG_FIRST)
+			if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
+				return "Active - First & Last";
+			else
+				return "Active - First";
+		else
+			if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
+				return "Active - Last";
+			else
+				return "Active";
+	else
+		return "Inactive";
+}
+
+static void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr)
+{
+	printk("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version);
+	printk("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type,
+	       get_rmpp_type(rmpp_hdr->rmpp_type));
+	printk("RMPP RRespTime.0x%01x\n", ib_get_rmpp_resptime(rmpp_hdr));
+	printk("RMPP flags.....0x%01x (%s)\n", ib_get_rmpp_flags(rmpp_hdr),
+	       get_rmpp_flags(ib_get_rmpp_flags(rmpp_hdr)));
+	printk("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status);
+	printk("Seg number.....0x%04x\n", be32_to_cpu(rmpp_hdr->seg_num));
+	switch (rmpp_hdr->rmpp_type) {
+	case IB_MGMT_RMPP_TYPE_DATA:
+		printk("Payload len....0x%04x\n",
+		       be32_to_cpu(rmpp_hdr->paylen_newwin));
+		break;
+	case IB_MGMT_RMPP_TYPE_ACK:
+		printk("New window.....0x%04x\n",
+		       be32_to_cpu(rmpp_hdr->paylen_newwin));
+		break;
+	default:
+		printk("Data 2.........0x%04x\n",
+		       be32_to_cpu(rmpp_hdr->paylen_newwin));
+		break;
+	}
+}
+
+static char * get_smp_attr(__be16 attr)
+{
+	switch (attr) {
+	case IB_SMP_ATTR_NOTICE:
+		return "notice";
+	case IB_SMP_ATTR_NODE_DESC:
+		return "node description";
+	case IB_SMP_ATTR_NODE_INFO:
+		return "node info";
+	case IB_SMP_ATTR_SWITCH_INFO:
+		return "switch info";
+	case IB_SMP_ATTR_GUID_INFO:
+		return "GUID info";
+	case IB_SMP_ATTR_PORT_INFO:
+		return "port info";
+	case IB_SMP_ATTR_PKEY_TABLE:
+		return "pkey table";
+	case IB_SMP_ATTR_SL_TO_VL_TABLE:
+		return "SL to VL table";
+	case IB_SMP_ATTR_VL_ARB_TABLE:
+		return "VL arbitration table";
+	case IB_SMP_ATTR_LINEAR_FORWARD_TABLE:
+		return "linear forwarding table";
+	case IB_SMP_ATTR_RANDOM_FORWARD_TABLE:
+		return "random forward table";
+	case IB_SMP_ATTR_MCAST_FORWARD_TABLE:
+		return "multicast forward table";
+	case IB_SMP_ATTR_SM_INFO:
+		return "SM info";
+	case IB_SMP_ATTR_VENDOR_DIAG:
+		return "vendor diags";
+	case IB_SMP_ATTR_LED_INFO:
+		return "LED info";
+	default:
+		return "";
+	}
+}
+
+static void print_smp(struct ib_smp *smp)
+{
+	int i;
+
+	printk("MAD version....0x%01x\n", smp->base_version);
+	printk("Class..........0x%01x (%s)\n", smp->mgmt_class,
+	       get_class_name(smp->mgmt_class));
+	printk("Class version..0x%01x\n", smp->class_version);
+	printk("Method.........0x%01x (%s)\n", smp->method,
+	       get_method_name(smp->mgmt_class, smp->method));
+	printk("Status.........0x%02x\n", be16_to_cpu(smp->status));
+	if (smp->status)
+		print_status_details(be16_to_cpu(smp->status));
+	printk("Hop pointer...0x%01x\n", smp->hop_ptr);
+	printk("Hop counter...0x%01x\n", smp->hop_cnt);
+	printk("Trans ID.......0x%llx\n", smp->tid);
+	printk("Attr ID........0x%02x (%s)\n", be16_to_cpu(smp->attr_id),
+		get_smp_attr(smp->attr_id));
+	printk("Attr modifier..0x%04x\n", be32_to_cpu(smp->attr_mod));
+
+	printk("Mkey...........0x%llx\n", be64_to_cpu(smp->mkey));
+	printk("DR SLID........0x%02x\n", be16_to_cpu(smp->dr_slid));
+	printk("DR DLID........0x%02x", be16_to_cpu(smp->dr_dlid));
+
+	if (data) {
+		for (i = 0; i < IB_SMP_DATA_SIZE; i++) {
+			if (i % 16 == 0)
+				printk("\nSMP Data.......");
+			printk("%01x ", smp->data[i]);
+		}
+		for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
+			if (i % 16 == 0)
+				printk("\nInitial path...");
+			printk("%01x ", smp->initial_path[i]);
+		}
+		for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
+			if (i % 16 == 0)
+				printk("\nReturn path....");
+			printk("%01x ", smp->return_path[i]);
+		}
+	}
+	printk("\n");
+}
+
+static void snoop_smi_handler(struct ib_mad_agent *mad_agent,
+			      struct ib_mad_send_buf *send_buf,
+			      struct ib_mad_send_wc *mad_send_wc)
+{
+	struct ib_mad_hdr *hdr = send_buf->mad;
+
+	if (!smp && hdr->mgmt_class != mgmt_class)
+		return;
+	if (attr_id && hdr->attr_id != attr_id)
+		return;
+
+	printk("Madeye:sent SMP\n");
+	print_smp(send_buf->mad);
+}
+
+static void recv_smi_handler(struct ib_mad_agent *mad_agent,
+			     struct ib_mad_recv_wc *mad_recv_wc)
+{
+	if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class)
+		return;
+	if (attr_id && mad_recv_wc->recv_buf.mad->mad_hdr.attr_id != attr_id)
+		return;
+
+	printk("Madeye:recv SMP\n");
+	print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr);
+}
+
+static int is_rmpp_mad(struct ib_mad_hdr *mad_hdr)
+{
+	if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
+		switch (mad_hdr->method) {
+		case IB_SA_METHOD_GET_TABLE:
+		case IB_SA_METHOD_GET_TABLE_RESP:
+		case IB_SA_METHOD_GET_MULTI_RESP:
+			return 1;
+		default:
+			break;
+		}
+	} else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
+		   (mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
+		return 1;
+
+	return 0;
+}
+
+static void snoop_gsi_handler(struct ib_mad_agent *mad_agent,
+			      struct ib_mad_send_buf *send_buf,
+			      struct ib_mad_send_wc *mad_send_wc)
+{
+	struct ib_mad_hdr *hdr = send_buf->mad;
+
+	if (!gmp && hdr->mgmt_class != mgmt_class)
+		return;
+	if (attr_id && hdr->attr_id != attr_id)
+		return;
+
+	printk("Madeye:sent GMP\n");
+	print_mad_hdr(hdr);
+
+	if (is_rmpp_mad(hdr))
+		print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr);
+}
+
+static void recv_gsi_handler(struct ib_mad_agent *mad_agent,
+			     struct ib_mad_recv_wc *mad_recv_wc)
+{
+	struct ib_mad_hdr *hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
+	struct ib_rmpp_mad *mad = NULL;
+	struct ib_sa_mad *sa_mad;
+	struct ib_vendor_mad *vendor_mad;
+	u8 *mad_data;
+	int i, j;
+
+	if (!gmp && hdr->mgmt_class != mgmt_class)
+		return;
+	if (attr_id && mad_recv_wc->recv_buf.mad->mad_hdr.attr_id != attr_id)
+		return;
+
+	printk("Madeye:recv GMP\n");
+	print_mad_hdr(hdr);
+
+	if (is_rmpp_mad(hdr)) {
+		mad = (struct ib_rmpp_mad *) hdr;
+		print_rmpp_hdr(&mad->rmpp_hdr);
+	}
+
+	if (data) {
+		if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
+			j = IB_MGMT_SA_DATA;
+			/* Display SA header */
+			if (is_rmpp_mad(hdr) &&
+			    mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
+				return;
+			sa_mad = (struct ib_sa_mad *)
+				 &mad_recv_wc->recv_buf.mad;
+			mad_data = sa_mad->data;
+		} else {
+			if (is_rmpp_mad(hdr)) {
+				j = IB_MGMT_VENDOR_DATA;
+				/* Display OUI */
+				vendor_mad = (struct ib_vendor_mad *)
+					     &mad_recv_wc->recv_buf.mad;
+				printk("Vendor OUI......%01x %01x %01x\n",
+					vendor_mad->oui[0],
+					vendor_mad->oui[1],
+					vendor_mad->oui[2]);
+				mad_data = vendor_mad->data;
+			} else {
+				j = IB_MGMT_MAD_DATA;
+				mad_data = mad_recv_wc->recv_buf.mad->data;
+			}
+		}
+		for (i = 0; i < j; i++) {
+			if (i % 16 == 0)
+				printk("\nData...........");
+			printk("%01x ", mad_data[i]);
+		}
+		printk("\n");
+	}
+}
+
+static void madeye_add_one(struct ib_device *device)
+{
+	struct madeye_port *port;
+	int reg_flags;
+	u8 i, s, e;
+
+	if (device->node_type == RDMA_NODE_IB_SWITCH) {
+		s = 0;
+		e = 0;
+	} else {
+		s = 1;
+		e = device->phys_port_cnt;
+	}
+
+	port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL);
+	if (!port)
+		goto out;
+
+	reg_flags = IB_MAD_SNOOP_SEND_COMPLETIONS | IB_MAD_SNOOP_RECVS;
+	for (i = s; i <= e; i++) {
+		port[i].smi_agent = ib_register_mad_snoop(device, i,
+							  IB_QPT_SMI,
+							  reg_flags,
+							  snoop_smi_handler,
+							  recv_smi_handler,
+							  &port[i]);
+		port[i].gsi_agent = ib_register_mad_snoop(device, i,
+							  IB_QPT_GSI,
+							  reg_flags,
+							  snoop_gsi_handler,
+							  recv_gsi_handler,
+							  &port[i]);
+	}
+
+out:
+	ib_set_client_data(device, &madeye_client, port);
+}
+
+static void madeye_remove_one(struct ib_device *device)
+{
+	struct madeye_port *port;
+	int i, s, e;
+
+	port = (struct madeye_port *)
+		ib_get_client_data(device, &madeye_client);
+	if (!port)
+		return;
+
+	if (device->node_type == RDMA_NODE_IB_SWITCH) {
+		s = 0;
+		e = 0;
+	} else {
+		s = 1;
+		e = device->phys_port_cnt;
+	}
+
+	for (i = s; i <= e; i++) {
+		if (!IS_ERR(port[i].smi_agent))
+			ib_unregister_mad_agent(port[i].smi_agent);
+		if (!IS_ERR(port[i].gsi_agent))
+			ib_unregister_mad_agent(port[i].gsi_agent);
+	}
+	kfree(port);
+}
+
+static int __init ib_madeye_init(void)
+{
+	return ib_register_client(&madeye_client);
+}
+
+static void __exit ib_madeye_cleanup(void)
+{
+	ib_unregister_client(&madeye_client);
+}
+
+module_init(ib_madeye_init);
+module_exit(ib_madeye_cleanup);
-- 
1.5.0.rc2.g73a2





More information about the ewg mailing list