1 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause 2 /* 3 * Copyright(c) 2016 Intel Corporation. 4 */ 5 6 #include <rdma/ib_mad.h> 7 #include "mad.h" 8 #include "vt.h" 9 10 /** 11 * rvt_process_mad - process an incoming MAD packet 12 * @ibdev: the infiniband device this packet came in on 13 * @mad_flags: MAD flags 14 * @port_num: the port number this packet came in on, 1 based from ib core 15 * @in_wc: the work completion entry for this packet 16 * @in_grh: the global route header for this packet 17 * @in: the incoming MAD 18 * @in_mad_size: size of the incoming MAD reply 19 * @out: any outgoing MAD reply 20 * @out_mad_size: size of the outgoing MAD reply 21 * @out_mad_pkey_index: unused 22 * 23 * Note that the verbs framework has already done the MAD sanity checks, 24 * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE 25 * MADs. 26 * 27 * This is called by the ib_mad module. 28 * 29 * Return: IB_MAD_RESULT_SUCCESS or error 30 */ 31 int rvt_process_mad(struct ib_device *ibdev, int mad_flags, u32 port_num, 32 const struct ib_wc *in_wc, const struct ib_grh *in_grh, 33 const struct ib_mad_hdr *in, size_t in_mad_size, 34 struct ib_mad_hdr *out, size_t *out_mad_size, 35 u16 *out_mad_pkey_index) 36 { 37 /* 38 * MAD processing is quite different between hfi1 and qib. Therefore 39 * this is expected to be provided by the driver. Other drivers in the 40 * future may choose to implement this but it should not be made into a 41 * requirement. 42 */ 43 return IB_MAD_RESULT_FAILURE; 44 } 45 46 static void rvt_send_mad_handler(struct ib_mad_agent *agent, 47 struct ib_mad_send_wc *mad_send_wc) 48 { 49 ib_free_send_mad(mad_send_wc->send_buf); 50 } 51 52 /** 53 * rvt_create_mad_agents - create mad agents 54 * @rdi: rvt dev struct 55 * 56 * If driver needs to be notified of mad agent creation then call back 57 * 58 * Return 0 on success 59 */ 60 int rvt_create_mad_agents(struct rvt_dev_info *rdi) 61 { 62 struct ib_mad_agent *agent; 63 struct rvt_ibport *rvp; 64 int p; 65 int ret; 66 67 for (p = 0; p < rdi->dparms.nports; p++) { 68 rvp = rdi->ports[p]; 69 agent = ib_register_mad_agent(&rdi->ibdev, p + 1, 70 IB_QPT_SMI, 71 NULL, 0, rvt_send_mad_handler, 72 NULL, NULL, 0); 73 if (IS_ERR(agent)) { 74 ret = PTR_ERR(agent); 75 goto err; 76 } 77 78 rvp->send_agent = agent; 79 80 if (rdi->driver_f.notify_create_mad_agent) 81 rdi->driver_f.notify_create_mad_agent(rdi, p); 82 } 83 84 return 0; 85 86 err: 87 for (p = 0; p < rdi->dparms.nports; p++) { 88 rvp = rdi->ports[p]; 89 if (rvp->send_agent) { 90 agent = rvp->send_agent; 91 rvp->send_agent = NULL; 92 ib_unregister_mad_agent(agent); 93 if (rdi->driver_f.notify_free_mad_agent) 94 rdi->driver_f.notify_free_mad_agent(rdi, p); 95 } 96 } 97 98 return ret; 99 } 100 101 /** 102 * rvt_free_mad_agents - free up mad agents 103 * @rdi: rvt dev struct 104 * 105 * If driver needs notification of mad agent removal make the call back 106 */ 107 void rvt_free_mad_agents(struct rvt_dev_info *rdi) 108 { 109 struct ib_mad_agent *agent; 110 struct rvt_ibport *rvp; 111 int p; 112 113 for (p = 0; p < rdi->dparms.nports; p++) { 114 rvp = rdi->ports[p]; 115 if (rvp->send_agent) { 116 agent = rvp->send_agent; 117 rvp->send_agent = NULL; 118 ib_unregister_mad_agent(agent); 119 } 120 if (rvp->sm_ah) { 121 rdma_destroy_ah(&rvp->sm_ah->ibah, 122 RDMA_DESTROY_AH_SLEEPABLE); 123 rvp->sm_ah = NULL; 124 } 125 126 if (rdi->driver_f.notify_free_mad_agent) 127 rdi->driver_f.notify_free_mad_agent(rdi, p); 128 } 129 } 130 131