1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. 3219820Sjeff * Copyright (c) 2005, 2006 Voltaire Inc. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directorY of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff * 33219820Sjeff * $Id$ 34219820Sjeff */ 35300676Shselasky 36300676Shselasky#define LINUXKPI_PARAM_PREFIX ib_madeye_ 37300676Shselasky 38219820Sjeff#include <linux/module.h> 39219820Sjeff#include <linux/device.h> 40219820Sjeff#include <linux/err.h> 41219820Sjeff 42219820Sjeff#include <rdma/ib_mad.h> 43219820Sjeff#include <rdma/ib_smi.h> 44219820Sjeff#include <rdma/ib_sa.h> 45219820Sjeff 46219820SjeffMODULE_AUTHOR("Sean Hefty"); 47219820SjeffMODULE_DESCRIPTION("InfiniBand MAD viewer"); 48219820SjeffMODULE_LICENSE("Dual BSD/GPL"); 49219820Sjeff 50219820Sjeffstatic void madeye_remove_one(struct ib_device *device); 51219820Sjeffstatic void madeye_add_one(struct ib_device *device); 52219820Sjeff 53219820Sjeffstatic struct ib_client madeye_client = { 54219820Sjeff .name = "madeye", 55219820Sjeff .add = madeye_add_one, 56219820Sjeff .remove = madeye_remove_one 57219820Sjeff}; 58219820Sjeff 59219820Sjeffstruct madeye_port { 60219820Sjeff struct ib_mad_agent *smi_agent; 61219820Sjeff struct ib_mad_agent *gsi_agent; 62219820Sjeff}; 63219820Sjeff 64219820Sjeffstatic int smp = 1; 65219820Sjeffstatic int gmp = 1; 66219820Sjeffstatic int mgmt_class = 0; 67219820Sjeffstatic int attr_id = 0; 68219820Sjeffstatic int data = 0; 69219820Sjeff 70219820Sjeffmodule_param(smp, int, 0444); 71219820Sjeffmodule_param(gmp, int, 0444); 72219820Sjeffmodule_param(mgmt_class, int, 0444); 73219820Sjeffmodule_param(attr_id, int, 0444); 74219820Sjeffmodule_param(data, int, 0444); 75219820Sjeff 76219820SjeffMODULE_PARM_DESC(smp, "Display all SMPs (default=1)"); 77219820SjeffMODULE_PARM_DESC(gmp, "Display all GMPs (default=1)"); 78219820SjeffMODULE_PARM_DESC(mgmt_class, "Display all MADs of specified class (default=0)"); 79219820SjeffMODULE_PARM_DESC(attr_id, "Display add MADs of specified attribute ID (default=0)"); 80219820SjeffMODULE_PARM_DESC(data, "Display data area of MADs (default=0)"); 81219820Sjeff 82219820Sjeffstatic char * get_class_name(u8 mgmt_class) 83219820Sjeff{ 84219820Sjeff switch(mgmt_class) { 85219820Sjeff case IB_MGMT_CLASS_SUBN_LID_ROUTED: 86219820Sjeff return "LID routed SMP"; 87219820Sjeff case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: 88219820Sjeff return "Directed route SMP"; 89219820Sjeff case IB_MGMT_CLASS_SUBN_ADM: 90219820Sjeff return "Subnet admin."; 91219820Sjeff case IB_MGMT_CLASS_PERF_MGMT: 92219820Sjeff return "Perf. mgmt."; 93219820Sjeff case IB_MGMT_CLASS_BM: 94219820Sjeff return "Baseboard mgmt."; 95219820Sjeff case IB_MGMT_CLASS_DEVICE_MGMT: 96219820Sjeff return "Device mgmt."; 97219820Sjeff case IB_MGMT_CLASS_CM: 98219820Sjeff return "Comm. mgmt."; 99219820Sjeff case IB_MGMT_CLASS_SNMP: 100219820Sjeff return "SNMP"; 101219820Sjeff default: 102219820Sjeff return "Unknown vendor/application"; 103219820Sjeff } 104219820Sjeff} 105219820Sjeff 106219820Sjeffstatic char * get_method_name(u8 mgmt_class, u8 method) 107219820Sjeff{ 108219820Sjeff switch(method) { 109219820Sjeff case IB_MGMT_METHOD_GET: 110219820Sjeff return "Get"; 111219820Sjeff case IB_MGMT_METHOD_SET: 112219820Sjeff return "Set"; 113219820Sjeff case IB_MGMT_METHOD_GET_RESP: 114219820Sjeff return "Get response"; 115219820Sjeff case IB_MGMT_METHOD_SEND: 116219820Sjeff return "Send"; 117219820Sjeff case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP: 118219820Sjeff return "Send response"; 119219820Sjeff case IB_MGMT_METHOD_TRAP: 120219820Sjeff return "Trap"; 121219820Sjeff case IB_MGMT_METHOD_REPORT: 122219820Sjeff return "Report"; 123219820Sjeff case IB_MGMT_METHOD_REPORT_RESP: 124219820Sjeff return "Report response"; 125219820Sjeff case IB_MGMT_METHOD_TRAP_REPRESS: 126219820Sjeff return "Trap repress"; 127219820Sjeff default: 128219820Sjeff break; 129219820Sjeff } 130219820Sjeff 131219820Sjeff switch (mgmt_class) { 132219820Sjeff case IB_MGMT_CLASS_SUBN_ADM: 133219820Sjeff switch (method) { 134219820Sjeff case IB_SA_METHOD_GET_TABLE: 135219820Sjeff return "Get table"; 136219820Sjeff case IB_SA_METHOD_GET_TABLE_RESP: 137219820Sjeff return "Get table response"; 138219820Sjeff case IB_SA_METHOD_DELETE: 139219820Sjeff return "Delete"; 140219820Sjeff case IB_SA_METHOD_DELETE_RESP: 141219820Sjeff return "Delete response"; 142219820Sjeff case IB_SA_METHOD_GET_MULTI: 143219820Sjeff return "Get Multi"; 144219820Sjeff case IB_SA_METHOD_GET_MULTI_RESP: 145219820Sjeff return "Get Multi response"; 146219820Sjeff case IB_SA_METHOD_GET_TRACE_TBL: 147219820Sjeff return "Get Trace Table response"; 148219820Sjeff default: 149219820Sjeff break; 150219820Sjeff } 151219820Sjeff default: 152219820Sjeff break; 153219820Sjeff } 154219820Sjeff 155219820Sjeff return "Unknown"; 156219820Sjeff} 157219820Sjeff 158219820Sjeffstatic void print_status_details(u16 status) 159219820Sjeff{ 160219820Sjeff if (status & 0x0001) 161219820Sjeff printk(" busy\n"); 162219820Sjeff if (status & 0x0002) 163219820Sjeff printk(" redirection required\n"); 164219820Sjeff switch((status & 0x001C) >> 2) { 165219820Sjeff case 1: 166219820Sjeff printk(" bad version\n"); 167219820Sjeff break; 168219820Sjeff case 2: 169219820Sjeff printk(" method not supported\n"); 170219820Sjeff break; 171219820Sjeff case 3: 172219820Sjeff printk(" method/attribute combo not supported\n"); 173219820Sjeff break; 174219820Sjeff case 7: 175219820Sjeff printk(" invalid attribute/modifier value\n"); 176219820Sjeff break; 177219820Sjeff } 178219820Sjeff} 179219820Sjeff 180219820Sjeffstatic char * get_sa_attr(__be16 attr) 181219820Sjeff{ 182219820Sjeff switch(attr) { 183219820Sjeff case IB_SA_ATTR_CLASS_PORTINFO: 184219820Sjeff return "Class Port Info"; 185219820Sjeff case IB_SA_ATTR_NOTICE: 186219820Sjeff return "Notice"; 187219820Sjeff case IB_SA_ATTR_INFORM_INFO: 188219820Sjeff return "Inform Info"; 189219820Sjeff case IB_SA_ATTR_NODE_REC: 190219820Sjeff return "Node Record"; 191219820Sjeff case IB_SA_ATTR_PORT_INFO_REC: 192219820Sjeff return "PortInfo Record"; 193219820Sjeff case IB_SA_ATTR_SL2VL_REC: 194219820Sjeff return "SL to VL Record"; 195219820Sjeff case IB_SA_ATTR_SWITCH_REC: 196219820Sjeff return "Switch Record"; 197219820Sjeff case IB_SA_ATTR_LINEAR_FDB_REC: 198219820Sjeff return "Linear FDB Record"; 199219820Sjeff case IB_SA_ATTR_RANDOM_FDB_REC: 200219820Sjeff return "Random FDB Record"; 201219820Sjeff case IB_SA_ATTR_MCAST_FDB_REC: 202219820Sjeff return "Multicast FDB Record"; 203219820Sjeff case IB_SA_ATTR_SM_INFO_REC: 204219820Sjeff return "SM Info Record"; 205219820Sjeff case IB_SA_ATTR_LINK_REC: 206219820Sjeff return "Link Record"; 207219820Sjeff case IB_SA_ATTR_GUID_INFO_REC: 208219820Sjeff return "Guid Info Record"; 209219820Sjeff case IB_SA_ATTR_SERVICE_REC: 210219820Sjeff return "Service Record"; 211219820Sjeff case IB_SA_ATTR_PARTITION_REC: 212219820Sjeff return "Partition Record"; 213219820Sjeff case IB_SA_ATTR_PATH_REC: 214219820Sjeff return "Path Record"; 215219820Sjeff case IB_SA_ATTR_VL_ARB_REC: 216219820Sjeff return "VL Arb Record"; 217219820Sjeff case IB_SA_ATTR_MC_MEMBER_REC: 218219820Sjeff return "MC Member Record"; 219219820Sjeff case IB_SA_ATTR_TRACE_REC: 220219820Sjeff return "Trace Record"; 221219820Sjeff case IB_SA_ATTR_MULTI_PATH_REC: 222219820Sjeff return "Multi Path Record"; 223219820Sjeff case IB_SA_ATTR_SERVICE_ASSOC_REC: 224219820Sjeff return "Service Assoc Record"; 225219820Sjeff case IB_SA_ATTR_INFORM_INFO_REC: 226219820Sjeff return "Inform Info Record"; 227219820Sjeff default: 228219820Sjeff return ""; 229219820Sjeff } 230219820Sjeff} 231219820Sjeff 232219820Sjeffstatic void print_mad_hdr(struct ib_mad_hdr *mad_hdr) 233219820Sjeff{ 234219820Sjeff printk("MAD version....0x%01x\n", mad_hdr->base_version); 235219820Sjeff printk("Class..........0x%01x (%s)\n", mad_hdr->mgmt_class, 236219820Sjeff get_class_name(mad_hdr->mgmt_class)); 237219820Sjeff printk("Class version..0x%01x\n", mad_hdr->class_version); 238219820Sjeff printk("Method.........0x%01x (%s)\n", mad_hdr->method, 239219820Sjeff get_method_name(mad_hdr->mgmt_class, mad_hdr->method)); 240219820Sjeff printk("Status.........0x%02x\n", be16_to_cpu(mad_hdr->status)); 241219820Sjeff if (mad_hdr->status) 242219820Sjeff print_status_details(be16_to_cpu(mad_hdr->status)); 243219820Sjeff printk("Class specific.0x%02x\n", be16_to_cpu(mad_hdr->class_specific)); 244219820Sjeff printk("Trans ID.......0x%llx\n", 245219820Sjeff (unsigned long long)be64_to_cpu(mad_hdr->tid)); 246219820Sjeff if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) 247219820Sjeff printk("Attr ID........0x%02x (%s)\n", 248219820Sjeff be16_to_cpu(mad_hdr->attr_id), 249219820Sjeff get_sa_attr(be16_to_cpu(mad_hdr->attr_id))); 250219820Sjeff else 251219820Sjeff printk("Attr ID........0x%02x\n", 252219820Sjeff be16_to_cpu(mad_hdr->attr_id)); 253219820Sjeff printk("Attr modifier..0x%04x\n", be32_to_cpu(mad_hdr->attr_mod)); 254219820Sjeff} 255219820Sjeff 256219820Sjeffstatic char * get_rmpp_type(u8 rmpp_type) 257219820Sjeff{ 258219820Sjeff switch (rmpp_type) { 259219820Sjeff case IB_MGMT_RMPP_TYPE_DATA: 260219820Sjeff return "Data"; 261219820Sjeff case IB_MGMT_RMPP_TYPE_ACK: 262219820Sjeff return "Ack"; 263219820Sjeff case IB_MGMT_RMPP_TYPE_STOP: 264219820Sjeff return "Stop"; 265219820Sjeff case IB_MGMT_RMPP_TYPE_ABORT: 266219820Sjeff return "Abort"; 267219820Sjeff default: 268219820Sjeff return "Unknown"; 269219820Sjeff } 270219820Sjeff} 271219820Sjeff 272219820Sjeffstatic char * get_rmpp_flags(u8 rmpp_flags) 273219820Sjeff{ 274219820Sjeff if (rmpp_flags & IB_MGMT_RMPP_FLAG_ACTIVE) 275219820Sjeff if (rmpp_flags & IB_MGMT_RMPP_FLAG_FIRST) 276219820Sjeff if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST) 277219820Sjeff return "Active - First & Last"; 278219820Sjeff else 279219820Sjeff return "Active - First"; 280219820Sjeff else 281219820Sjeff if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST) 282219820Sjeff return "Active - Last"; 283219820Sjeff else 284219820Sjeff return "Active"; 285219820Sjeff else 286219820Sjeff return "Inactive"; 287219820Sjeff} 288219820Sjeff 289219820Sjeffstatic void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr) 290219820Sjeff{ 291219820Sjeff printk("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version); 292219820Sjeff printk("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type, 293219820Sjeff get_rmpp_type(rmpp_hdr->rmpp_type)); 294219820Sjeff printk("RMPP RRespTime.0x%01x\n", ib_get_rmpp_resptime(rmpp_hdr)); 295219820Sjeff printk("RMPP flags.....0x%01x (%s)\n", ib_get_rmpp_flags(rmpp_hdr), 296219820Sjeff get_rmpp_flags(ib_get_rmpp_flags(rmpp_hdr))); 297219820Sjeff printk("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status); 298219820Sjeff printk("Seg number.....0x%04x\n", be32_to_cpu(rmpp_hdr->seg_num)); 299219820Sjeff switch (rmpp_hdr->rmpp_type) { 300219820Sjeff case IB_MGMT_RMPP_TYPE_DATA: 301219820Sjeff printk("Payload len....0x%04x\n", 302219820Sjeff be32_to_cpu(rmpp_hdr->paylen_newwin)); 303219820Sjeff break; 304219820Sjeff case IB_MGMT_RMPP_TYPE_ACK: 305219820Sjeff printk("New window.....0x%04x\n", 306219820Sjeff be32_to_cpu(rmpp_hdr->paylen_newwin)); 307219820Sjeff break; 308219820Sjeff default: 309219820Sjeff printk("Data 2.........0x%04x\n", 310219820Sjeff be32_to_cpu(rmpp_hdr->paylen_newwin)); 311219820Sjeff break; 312219820Sjeff } 313219820Sjeff} 314219820Sjeff 315219820Sjeffstatic char * get_smp_attr(__be16 attr) 316219820Sjeff{ 317219820Sjeff switch (attr) { 318219820Sjeff case IB_SMP_ATTR_NOTICE: 319219820Sjeff return "notice"; 320219820Sjeff case IB_SMP_ATTR_NODE_DESC: 321219820Sjeff return "node description"; 322219820Sjeff case IB_SMP_ATTR_NODE_INFO: 323219820Sjeff return "node info"; 324219820Sjeff case IB_SMP_ATTR_SWITCH_INFO: 325219820Sjeff return "switch info"; 326219820Sjeff case IB_SMP_ATTR_GUID_INFO: 327219820Sjeff return "GUID info"; 328219820Sjeff case IB_SMP_ATTR_PORT_INFO: 329219820Sjeff return "port info"; 330219820Sjeff case IB_SMP_ATTR_PKEY_TABLE: 331219820Sjeff return "pkey table"; 332219820Sjeff case IB_SMP_ATTR_SL_TO_VL_TABLE: 333219820Sjeff return "SL to VL table"; 334219820Sjeff case IB_SMP_ATTR_VL_ARB_TABLE: 335219820Sjeff return "VL arbitration table"; 336219820Sjeff case IB_SMP_ATTR_LINEAR_FORWARD_TABLE: 337219820Sjeff return "linear forwarding table"; 338219820Sjeff case IB_SMP_ATTR_RANDOM_FORWARD_TABLE: 339219820Sjeff return "random forward table"; 340219820Sjeff case IB_SMP_ATTR_MCAST_FORWARD_TABLE: 341219820Sjeff return "multicast forward table"; 342219820Sjeff case IB_SMP_ATTR_SM_INFO: 343219820Sjeff return "SM info"; 344219820Sjeff case IB_SMP_ATTR_VENDOR_DIAG: 345219820Sjeff return "vendor diags"; 346219820Sjeff case IB_SMP_ATTR_LED_INFO: 347219820Sjeff return "LED info"; 348219820Sjeff default: 349219820Sjeff return ""; 350219820Sjeff } 351219820Sjeff} 352219820Sjeff 353219820Sjeffstatic void print_smp(struct ib_smp *smp) 354219820Sjeff{ 355219820Sjeff int i; 356219820Sjeff 357219820Sjeff printk("MAD version....0x%01x\n", smp->base_version); 358219820Sjeff printk("Class..........0x%01x (%s)\n", smp->mgmt_class, 359219820Sjeff get_class_name(smp->mgmt_class)); 360219820Sjeff printk("Class version..0x%01x\n", smp->class_version); 361219820Sjeff printk("Method.........0x%01x (%s)\n", smp->method, 362219820Sjeff get_method_name(smp->mgmt_class, smp->method)); 363219820Sjeff printk("Status.........0x%02x\n", be16_to_cpu(smp->status)); 364219820Sjeff if (smp->status) 365219820Sjeff print_status_details(be16_to_cpu(smp->status)); 366219820Sjeff printk("Hop pointer....0x%01x\n", smp->hop_ptr); 367219820Sjeff printk("Hop counter....0x%01x\n", smp->hop_cnt); 368219820Sjeff printk("Trans ID.......0x%llx\n", 369219820Sjeff (unsigned long long)be64_to_cpu(smp->tid)); 370219820Sjeff printk("Attr ID........0x%02x (%s)\n", be16_to_cpu(smp->attr_id), 371219820Sjeff get_smp_attr(smp->attr_id)); 372219820Sjeff printk("Attr modifier..0x%04x\n", be32_to_cpu(smp->attr_mod)); 373219820Sjeff 374219820Sjeff printk("Mkey...........0x%llx\n", 375219820Sjeff (unsigned long long)be64_to_cpu(smp->mkey)); 376219820Sjeff printk("DR SLID........0x%02x\n", be16_to_cpu(smp->dr_slid)); 377219820Sjeff printk("DR DLID........0x%02x", be16_to_cpu(smp->dr_dlid)); 378219820Sjeff 379219820Sjeff if (data) { 380219820Sjeff for (i = 0; i < IB_SMP_DATA_SIZE; i++) { 381219820Sjeff if (i % 16 == 0) 382219820Sjeff printk("\nSMP Data......."); 383219820Sjeff printk("%01x ", smp->data[i]); 384219820Sjeff } 385219820Sjeff for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) { 386219820Sjeff if (i % 16 == 0) 387219820Sjeff printk("\nInitial path..."); 388219820Sjeff printk("%01x ", smp->initial_path[i]); 389219820Sjeff } 390219820Sjeff for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) { 391219820Sjeff if (i % 16 == 0) 392219820Sjeff printk("\nReturn path...."); 393219820Sjeff printk("%01x ", smp->return_path[i]); 394219820Sjeff } 395219820Sjeff } 396219820Sjeff printk("\n"); 397219820Sjeff} 398219820Sjeff 399219820Sjeffstatic void snoop_smi_handler(struct ib_mad_agent *mad_agent, 400219820Sjeff struct ib_mad_send_buf *send_buf, 401219820Sjeff struct ib_mad_send_wc *mad_send_wc) 402219820Sjeff{ 403219820Sjeff struct ib_mad_hdr *hdr = send_buf->mad; 404219820Sjeff 405219820Sjeff if (!smp && hdr->mgmt_class != mgmt_class) 406219820Sjeff return; 407219820Sjeff if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id) 408219820Sjeff return; 409219820Sjeff 410219820Sjeff printk("Madeye:sent SMP\n"); 411219820Sjeff print_smp(send_buf->mad); 412219820Sjeff} 413219820Sjeff 414219820Sjeffstatic void recv_smi_handler(struct ib_mad_agent *mad_agent, 415219820Sjeff struct ib_mad_recv_wc *mad_recv_wc) 416219820Sjeff{ 417219820Sjeff if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class) 418219820Sjeff return; 419219820Sjeff if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id) 420219820Sjeff return; 421219820Sjeff 422219820Sjeff printk("Madeye:recv SMP\n"); 423219820Sjeff print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr); 424219820Sjeff} 425219820Sjeff 426219820Sjeffstatic int is_rmpp_mad(struct ib_mad_hdr *mad_hdr) 427219820Sjeff{ 428219820Sjeff if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { 429219820Sjeff switch (mad_hdr->method) { 430219820Sjeff case IB_SA_METHOD_GET_TABLE: 431219820Sjeff case IB_SA_METHOD_GET_TABLE_RESP: 432219820Sjeff case IB_SA_METHOD_GET_MULTI_RESP: 433219820Sjeff return 1; 434219820Sjeff default: 435219820Sjeff break; 436219820Sjeff } 437219820Sjeff } else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && 438219820Sjeff (mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) 439219820Sjeff return 1; 440219820Sjeff 441219820Sjeff return 0; 442219820Sjeff} 443219820Sjeff 444219820Sjeffstatic void snoop_gsi_handler(struct ib_mad_agent *mad_agent, 445219820Sjeff struct ib_mad_send_buf *send_buf, 446219820Sjeff struct ib_mad_send_wc *mad_send_wc) 447219820Sjeff{ 448219820Sjeff struct ib_mad_hdr *hdr = send_buf->mad; 449219820Sjeff 450219820Sjeff if (!gmp && hdr->mgmt_class != mgmt_class) 451219820Sjeff return; 452219820Sjeff if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id) 453219820Sjeff return; 454219820Sjeff 455219820Sjeff printk("Madeye:sent GMP\n"); 456219820Sjeff print_mad_hdr(hdr); 457219820Sjeff 458219820Sjeff if (is_rmpp_mad(hdr)) 459219820Sjeff print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr); 460219820Sjeff} 461219820Sjeff 462219820Sjeffstatic void recv_gsi_handler(struct ib_mad_agent *mad_agent, 463219820Sjeff struct ib_mad_recv_wc *mad_recv_wc) 464219820Sjeff{ 465219820Sjeff struct ib_mad_hdr *hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; 466219820Sjeff struct ib_rmpp_mad *mad = NULL; 467219820Sjeff struct ib_sa_mad *sa_mad; 468219820Sjeff struct ib_vendor_mad *vendor_mad; 469219820Sjeff u8 *mad_data; 470219820Sjeff int i, j; 471219820Sjeff 472219820Sjeff if (!gmp && hdr->mgmt_class != mgmt_class) 473219820Sjeff return; 474219820Sjeff if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id) 475219820Sjeff return; 476219820Sjeff 477219820Sjeff printk("Madeye:recv GMP\n"); 478219820Sjeff print_mad_hdr(hdr); 479219820Sjeff 480219820Sjeff if (is_rmpp_mad(hdr)) { 481219820Sjeff mad = (struct ib_rmpp_mad *) hdr; 482219820Sjeff print_rmpp_hdr(&mad->rmpp_hdr); 483219820Sjeff } 484219820Sjeff 485219820Sjeff if (data) { 486219820Sjeff if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { 487219820Sjeff j = IB_MGMT_SA_DATA; 488219820Sjeff /* Display SA header */ 489219820Sjeff if (is_rmpp_mad(hdr) && 490219820Sjeff mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) 491219820Sjeff return; 492219820Sjeff sa_mad = (struct ib_sa_mad *) 493219820Sjeff &mad_recv_wc->recv_buf.mad; 494219820Sjeff mad_data = sa_mad->data; 495219820Sjeff } else { 496219820Sjeff if (is_rmpp_mad(hdr)) { 497219820Sjeff j = IB_MGMT_VENDOR_DATA; 498219820Sjeff /* Display OUI */ 499219820Sjeff vendor_mad = (struct ib_vendor_mad *) 500219820Sjeff &mad_recv_wc->recv_buf.mad; 501219820Sjeff printk("Vendor OUI......%01x %01x %01x\n", 502219820Sjeff vendor_mad->oui[0], 503219820Sjeff vendor_mad->oui[1], 504219820Sjeff vendor_mad->oui[2]); 505219820Sjeff mad_data = vendor_mad->data; 506219820Sjeff } else { 507219820Sjeff j = IB_MGMT_MAD_DATA; 508219820Sjeff mad_data = mad_recv_wc->recv_buf.mad->data; 509219820Sjeff } 510219820Sjeff } 511219820Sjeff for (i = 0; i < j; i++) { 512219820Sjeff if (i % 16 == 0) 513219820Sjeff printk("\nData..........."); 514219820Sjeff printk("%01x ", mad_data[i]); 515219820Sjeff } 516219820Sjeff printk("\n"); 517219820Sjeff } 518219820Sjeff} 519219820Sjeff 520219820Sjeffstatic void madeye_add_one(struct ib_device *device) 521219820Sjeff{ 522219820Sjeff struct madeye_port *port; 523219820Sjeff int reg_flags; 524219820Sjeff u8 i, s, e; 525219820Sjeff 526219820Sjeff if (device->node_type == RDMA_NODE_IB_SWITCH) { 527219820Sjeff s = 0; 528219820Sjeff e = 0; 529219820Sjeff } else { 530219820Sjeff s = 1; 531219820Sjeff e = device->phys_port_cnt; 532219820Sjeff } 533219820Sjeff 534219820Sjeff port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL); 535219820Sjeff if (!port) 536219820Sjeff goto out; 537219820Sjeff 538219820Sjeff reg_flags = IB_MAD_SNOOP_SEND_COMPLETIONS | IB_MAD_SNOOP_RECVS; 539219820Sjeff for (i = 0; i <= e - s; i++) { 540219820Sjeff port[i].smi_agent = ib_register_mad_snoop(device, i + s, 541219820Sjeff IB_QPT_SMI, 542219820Sjeff reg_flags, 543219820Sjeff snoop_smi_handler, 544219820Sjeff recv_smi_handler, 545219820Sjeff &port[i]); 546219820Sjeff port[i].gsi_agent = ib_register_mad_snoop(device, i + s, 547219820Sjeff IB_QPT_GSI, 548219820Sjeff reg_flags, 549219820Sjeff snoop_gsi_handler, 550219820Sjeff recv_gsi_handler, 551219820Sjeff &port[i]); 552219820Sjeff } 553219820Sjeff 554219820Sjeffout: 555219820Sjeff ib_set_client_data(device, &madeye_client, port); 556219820Sjeff} 557219820Sjeff 558219820Sjeffstatic void madeye_remove_one(struct ib_device *device) 559219820Sjeff{ 560219820Sjeff struct madeye_port *port; 561219820Sjeff int i, s, e; 562219820Sjeff 563219820Sjeff port = (struct madeye_port *) 564219820Sjeff ib_get_client_data(device, &madeye_client); 565219820Sjeff if (!port) 566219820Sjeff return; 567219820Sjeff 568219820Sjeff if (device->node_type == RDMA_NODE_IB_SWITCH) { 569219820Sjeff s = 0; 570219820Sjeff e = 0; 571219820Sjeff } else { 572219820Sjeff s = 1; 573219820Sjeff e = device->phys_port_cnt; 574219820Sjeff } 575219820Sjeff 576219820Sjeff for (i = 0; i <= e - s; i++) { 577219820Sjeff if (!IS_ERR(port[i].smi_agent)) 578219820Sjeff ib_unregister_mad_agent(port[i].smi_agent); 579219820Sjeff if (!IS_ERR(port[i].gsi_agent)) 580219820Sjeff ib_unregister_mad_agent(port[i].gsi_agent); 581219820Sjeff } 582219820Sjeff kfree(port); 583219820Sjeff} 584219820Sjeff 585219820Sjeffstatic int __init ib_madeye_init(void) 586219820Sjeff{ 587219820Sjeff return ib_register_client(&madeye_client); 588219820Sjeff} 589219820Sjeff 590219820Sjeffstatic void __exit ib_madeye_cleanup(void) 591219820Sjeff{ 592219820Sjeff ib_unregister_client(&madeye_client); 593219820Sjeff} 594219820Sjeff 595219820Sjeffmodule_init(ib_madeye_init); 596219820Sjeffmodule_exit(ib_madeye_cleanup); 597