162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2016 Intel Corporation. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <rdma/ib_mad.h> 762306a36Sopenharmony_ci#include "mad.h" 862306a36Sopenharmony_ci#include "vt.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/** 1162306a36Sopenharmony_ci * rvt_process_mad - process an incoming MAD packet 1262306a36Sopenharmony_ci * @ibdev: the infiniband device this packet came in on 1362306a36Sopenharmony_ci * @mad_flags: MAD flags 1462306a36Sopenharmony_ci * @port_num: the port number this packet came in on, 1 based from ib core 1562306a36Sopenharmony_ci * @in_wc: the work completion entry for this packet 1662306a36Sopenharmony_ci * @in_grh: the global route header for this packet 1762306a36Sopenharmony_ci * @in: the incoming MAD 1862306a36Sopenharmony_ci * @in_mad_size: size of the incoming MAD reply 1962306a36Sopenharmony_ci * @out: any outgoing MAD reply 2062306a36Sopenharmony_ci * @out_mad_size: size of the outgoing MAD reply 2162306a36Sopenharmony_ci * @out_mad_pkey_index: unused 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Note that the verbs framework has already done the MAD sanity checks, 2462306a36Sopenharmony_ci * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE 2562306a36Sopenharmony_ci * MADs. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * This is called by the ib_mad module. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Return: IB_MAD_RESULT_SUCCESS or error 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ciint rvt_process_mad(struct ib_device *ibdev, int mad_flags, u32 port_num, 3262306a36Sopenharmony_ci const struct ib_wc *in_wc, const struct ib_grh *in_grh, 3362306a36Sopenharmony_ci const struct ib_mad_hdr *in, size_t in_mad_size, 3462306a36Sopenharmony_ci struct ib_mad_hdr *out, size_t *out_mad_size, 3562306a36Sopenharmony_ci u16 *out_mad_pkey_index) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci /* 3862306a36Sopenharmony_ci * MAD processing is quite different between hfi1 and qib. Therefore 3962306a36Sopenharmony_ci * this is expected to be provided by the driver. Other drivers in the 4062306a36Sopenharmony_ci * future may choose to implement this but it should not be made into a 4162306a36Sopenharmony_ci * requirement. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci return IB_MAD_RESULT_FAILURE; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic void rvt_send_mad_handler(struct ib_mad_agent *agent, 4762306a36Sopenharmony_ci struct ib_mad_send_wc *mad_send_wc) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci ib_free_send_mad(mad_send_wc->send_buf); 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/** 5362306a36Sopenharmony_ci * rvt_create_mad_agents - create mad agents 5462306a36Sopenharmony_ci * @rdi: rvt dev struct 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * If driver needs to be notified of mad agent creation then call back 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * Return 0 on success 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ciint rvt_create_mad_agents(struct rvt_dev_info *rdi) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct ib_mad_agent *agent; 6362306a36Sopenharmony_ci struct rvt_ibport *rvp; 6462306a36Sopenharmony_ci int p; 6562306a36Sopenharmony_ci int ret; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci for (p = 0; p < rdi->dparms.nports; p++) { 6862306a36Sopenharmony_ci rvp = rdi->ports[p]; 6962306a36Sopenharmony_ci agent = ib_register_mad_agent(&rdi->ibdev, p + 1, 7062306a36Sopenharmony_ci IB_QPT_SMI, 7162306a36Sopenharmony_ci NULL, 0, rvt_send_mad_handler, 7262306a36Sopenharmony_ci NULL, NULL, 0); 7362306a36Sopenharmony_ci if (IS_ERR(agent)) { 7462306a36Sopenharmony_ci ret = PTR_ERR(agent); 7562306a36Sopenharmony_ci goto err; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci rvp->send_agent = agent; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (rdi->driver_f.notify_create_mad_agent) 8162306a36Sopenharmony_ci rdi->driver_f.notify_create_mad_agent(rdi, p); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cierr: 8762306a36Sopenharmony_ci for (p = 0; p < rdi->dparms.nports; p++) { 8862306a36Sopenharmony_ci rvp = rdi->ports[p]; 8962306a36Sopenharmony_ci if (rvp->send_agent) { 9062306a36Sopenharmony_ci agent = rvp->send_agent; 9162306a36Sopenharmony_ci rvp->send_agent = NULL; 9262306a36Sopenharmony_ci ib_unregister_mad_agent(agent); 9362306a36Sopenharmony_ci if (rdi->driver_f.notify_free_mad_agent) 9462306a36Sopenharmony_ci rdi->driver_f.notify_free_mad_agent(rdi, p); 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci return ret; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/** 10262306a36Sopenharmony_ci * rvt_free_mad_agents - free up mad agents 10362306a36Sopenharmony_ci * @rdi: rvt dev struct 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * If driver needs notification of mad agent removal make the call back 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_civoid rvt_free_mad_agents(struct rvt_dev_info *rdi) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct ib_mad_agent *agent; 11062306a36Sopenharmony_ci struct rvt_ibport *rvp; 11162306a36Sopenharmony_ci int p; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci for (p = 0; p < rdi->dparms.nports; p++) { 11462306a36Sopenharmony_ci rvp = rdi->ports[p]; 11562306a36Sopenharmony_ci if (rvp->send_agent) { 11662306a36Sopenharmony_ci agent = rvp->send_agent; 11762306a36Sopenharmony_ci rvp->send_agent = NULL; 11862306a36Sopenharmony_ci ib_unregister_mad_agent(agent); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci if (rvp->sm_ah) { 12162306a36Sopenharmony_ci rdma_destroy_ah(&rvp->sm_ah->ibah, 12262306a36Sopenharmony_ci RDMA_DESTROY_AH_SLEEPABLE); 12362306a36Sopenharmony_ci rvp->sm_ah = NULL; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (rdi->driver_f.notify_free_mad_agent) 12762306a36Sopenharmony_ci rdi->driver_f.notify_free_mad_agent(rdi, p); 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 131