From: Sean Hefty Date: Wed, 30 Jun 2010 23:44:42 +0000 (-0700) Subject: start of log X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=90f489da682eab610a4a4dca23152a8e2d20ab13;p=~shefty%2Frdma-dev.git start of log --- 90f489da682eab610a4a4dca23152a8e2d20ab13 diff --git a/meta b/meta new file mode 100644 index 00000000000..aff84de73e8 --- /dev/null +++ b/meta @@ -0,0 +1,7 @@ +Version: 1 +Previous: None +Head: 8b4c66dbc87344f6d26ef3272980cbdb6b3738be +Applied: + add-madeye: 8b4c66dbc87344f6d26ef3272980cbdb6b3738be +Unapplied: +Hidden: diff --git a/patches/add-madeye b/patches/add-madeye new file mode 100644 index 00000000000..2c752b8310e --- /dev/null +++ b/patches/add-madeye @@ -0,0 +1,673 @@ +Bottom: 1b06206738fe515efb908e738152eab699ef1320 +Top: 4af405df79ebfe83cf04f10f6830f086ba119286 +Author: Sean Hefty +Date: 2007-12-07 12:09:18 -0800 + +ib/mad: add MAD debug viewer + +add madeye + +Signed-off-by: Sean Hefty + + +--- + +diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig +index a193dfb..b6440fa 100644 +--- a/drivers/infiniband/Kconfig ++++ b/drivers/infiniband/Kconfig +@@ -53,4 +53,6 @@ source "drivers/infiniband/ulp/srp/Kconfig" + + source "drivers/infiniband/ulp/iser/Kconfig" + ++source "drivers/infiniband/util/madeye/Kconfig" ++ + endif # INFINIBAND +diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile +index 75f325e..e88c402 100644 +--- a/drivers/infiniband/Makefile ++++ b/drivers/infiniband/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/ + obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ + obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ + obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/ ++obj-$(CONFIG_INFINIBAND_MADEYE) += util/madeye/ +diff --git a/drivers/infiniband/util/madeye/Kconfig b/drivers/infiniband/util/madeye/Kconfig +new file mode 100644 +index 0000000..459ac49 +--- /dev/null ++++ b/drivers/infiniband/util/madeye/Kconfig +@@ -0,0 +1,5 @@ ++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/madeye/Makefile b/drivers/infiniband/util/madeye/Makefile +new file mode 100644 +index 0000000..8787ce8 +--- /dev/null ++++ b/drivers/infiniband/util/madeye/Makefile +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_INFINIBAND_MADEYE) += ib_madeye.o ++ ++ib_madeye-y := madeye.o +diff --git a/drivers/infiniband/util/madeye/madeye.c b/drivers/infiniband/util/madeye/madeye.c +new file mode 100644 +index 0000000..a0c86b9 +--- /dev/null ++++ b/drivers/infiniband/util/madeye/madeye.c +@@ -0,0 +1,613 @@ ++/* ++ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. ++ * Copyright (c) 2005 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "../../core/cm_msgs.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 all 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 char * get_cm_attr(__be16 attr) ++{ ++ switch(attr) { ++ case CM_REQ_ATTR_ID: ++ return "REQ"; ++ case CM_MRA_ATTR_ID: ++ return "MRA"; ++ case CM_REJ_ATTR_ID: ++ return "REJ"; ++ case CM_REP_ATTR_ID: ++ return "REP"; ++ case CM_RTU_ATTR_ID: ++ return "RTU"; ++ case CM_DREQ_ATTR_ID: ++ return "DREQ"; ++ case CM_DREP_ATTR_ID: ++ return "DREP"; ++ case CM_SIDR_REQ_ATTR_ID: ++ return "SIDR REQ"; ++ case CM_SIDR_REP_ATTR_ID: ++ return "SIDR REP"; ++ case CM_LAP_ATTR_ID: ++ return "LAP"; ++ case CM_APR_ATTR_ID: ++ return "APR"; ++ 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); ++ printk("Attr ID........0x%02x", be16_to_cpu(mad_hdr->attr_id)); ++ switch (mad_hdr->mgmt_class) { ++ case IB_MGMT_CLASS_SUBN_ADM: ++ printk(" (%s)", get_sa_attr(be16_to_cpu(mad_hdr->attr_id))); ++ break; ++ case IB_MGMT_CLASS_CM: ++ printk(" (%s)", get_cm_attr(mad_hdr->attr_id)); ++ break; ++ default: ++ break; ++ } ++ printk("\n"); ++ 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_data(char *msg, char *data, int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i++) { ++ if (i % 16 == 0) ++ printk("%s", msg); ++ printk("%.2x ", (unsigned char) data[i]); ++ if ((i < size - 1) && (i % 16 == 15)) ++ printk("\n"); ++ } ++ printk("\n"); ++} ++ ++static void print_smp(struct ib_smp *smp) ++{ ++ 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\n", be16_to_cpu(smp->dr_dlid)); ++ ++ if (data) { ++ print_data("SMP data.......", smp->data, IB_SMP_DATA_SIZE); ++ print_data("Initial path...", smp->initial_path, ++ IB_SMP_MAX_PATH_HOPS); ++ print_data("Return path....", smp->return_path, ++ IB_SMP_MAX_PATH_HOPS); ++ } ++} ++ ++static void print_sa_hdr(struct ib_sa_hdr *sa_hdr) ++{ ++ printk("SM key.........0x%llx\n", be64_to_cpu(sa_hdr->sm_key)); ++ printk("Attr offset....0x%02x\n", be16_to_cpu(sa_hdr->attr_offset)); ++ printk("Comp mask......0x%llx\n", be64_to_cpu(sa_hdr->comp_mask)); ++} ++ ++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) ++{ ++ return ((mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) || ++ ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && ++ (mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))); ++} ++ ++static void print_gsi_mad(struct ib_mad *mad) ++{ ++ struct ib_mad_hdr *hdr = &mad->mad_hdr; ++ struct ib_sa_mad *sa_mad; ++ struct ib_vendor_mad *vendor_mad; ++ ++ print_mad_hdr(hdr); ++ ++ if (is_rmpp_mad(hdr)) ++ print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr); ++ ++ if (data) { ++ if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { ++ sa_mad = (struct ib_sa_mad *) mad; ++ print_sa_hdr(&sa_mad->sa_hdr); ++ print_data("SA data........", sa_mad->data, ++ IB_MGMT_SA_DATA); ++ } else { ++ if (is_rmpp_mad(hdr)) { ++ vendor_mad = (struct ib_vendor_mad *) mad; ++ printk("Vendor OUI......%01x %01x %01x\n", ++ vendor_mad->oui[0], ++ vendor_mad->oui[1], ++ vendor_mad->oui[2]); ++ print_data("Vendor data....", vendor_mad->data, ++ IB_MGMT_VENDOR_DATA); ++ } else ++ print_data("MAD data.......", mad->data, ++ IB_MGMT_MAD_DATA); ++ } ++ } ++} ++ ++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_gsi_mad(send_buf->mad); ++} ++ ++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; ++ ++ if (!gmp && hdr->mgmt_class != mgmt_class) ++ return; ++ if (attr_id && hdr->attr_id != attr_id) ++ return; ++ ++ printk("Madeye:recv GMP\n"); ++ print_gsi_mad(mad_recv_wc->recv_buf.mad); ++} ++ ++static void madeye_add_one(struct ib_device *device) ++{ ++ struct madeye_port *port; ++ int reg_flags; ++ u8 i, s, e; ++ ++ if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) ++ return; ++ ++ 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 = 0; i <= e - s; i++) { ++ port[i].smi_agent = ib_register_mad_snoop(device, i + s, ++ IB_QPT_SMI, ++ reg_flags, ++ snoop_smi_handler, ++ recv_smi_handler, ++ &port[i]); ++ port[i].gsi_agent = ib_register_mad_snoop(device, i + s, ++ 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 = 0; i <= e - s; 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);