GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / infiniband / sw / rdmavt / mad.c
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