[image] Allow for zero embedded images
[people/asdlkf/gpxe.git] / src / drivers / net / mlx_ipoib / ib_mad.c
1 /*
2   This software is available to you under a choice of one of two
3   licenses.  You may choose to be licensed under the terms of the GNU
4   General Public License (GPL) Version 2, available at
5   <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
6   license, available in the LICENSE.TXT file accompanying this
7   software.  These details are also available at
8   <http://openib.org/license.html>.
9
10   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   SOFTWARE.
18
19   Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.
20 */
21
22 #include "ib_mad.h"
23 #include "mad_attrib.h"
24 #include "cmdif.h"
25 #include "ib_driver.h"
26
27 #define TID_START 0x1234
28 #define TID_INC 117
29
30 static u32 next_tid = TID_START;
31
32 /*
33  *  get_port_info
34  *
35  *      query the local device for the portinfo attribute
36  *
37  *      port(in) port number to query
38  *  buf(out) buffer to hold the result
39  */
40 static int get_port_info(__u8 port, struct port_info_st *buf, __u16 * status)
41 {
42         union port_info_mad_u *inprm;
43         union port_info_mad_u *outprm;
44         int rc;
45
46         inprm = get_inprm_buf();
47         outprm = get_outprm_buf();
48         memset(inprm, 0, sizeof *inprm);
49
50         inprm->mad.mad_hdr.method = IB_MGMT_METHOD_GET;
51         inprm->mad.mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
52         inprm->mad.mad_hdr.class_version = 1;
53         inprm->mad.mad_hdr.base_version = IB_MGMT_BASE_VERSION;
54         inprm->mad.mad_hdr.attr_id = IB_SMP_ATTR_PORT_INFO;
55         inprm->mad.mad_hdr.attr_mod = port;
56
57         rc = cmd_mad_ifc(inprm, (struct ib_mad_st *)outprm, port);
58         if (!rc) {
59                 memcpy(buf, &outprm->mad.port_info,
60                        sizeof(outprm->mad.port_info));
61                 *status = inprm->mad.mad_hdr.status;
62                 if (!(*status)) {
63                         ib_data.sm_lid = outprm->mad.port_info.mastersm_lid;
64                         memcpy(&ib_data.port_gid.raw[0],
65                                outprm->mad.port_info.gid_prefix, 8);
66                         cpu_to_be_buf(&ib_data.port_gid.raw[0], 8);
67                 }
68         }
69         return rc;
70 }
71
72 /*
73  *  get_guid_info
74  *
75  *      query the local device for the guidinfo attribute
76  *
77  *  buf(out) buffer to hold the result
78  */
79 static int get_guid_info(__u16 * status)
80 {
81         union guid_info_mad_u *inprm;
82         union guid_info_mad_u *outprm;
83         int rc;
84
85         inprm = get_inprm_buf();
86         outprm = get_outprm_buf();
87         memset(inprm, 0, sizeof *inprm);
88
89         inprm->mad.mad_hdr.method = IB_MGMT_METHOD_GET;
90         inprm->mad.mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
91         inprm->mad.mad_hdr.class_version = 1;
92         inprm->mad.mad_hdr.base_version = IB_MGMT_BASE_VERSION;
93         inprm->mad.mad_hdr.attr_id = IB_SMP_ATTR_GUID_INFO;
94         inprm->mad.mad_hdr.attr_mod = 0;
95
96         rc = cmd_mad_ifc(inprm, (struct ib_mad_st *)outprm, ib_data.port);
97         if (!rc) {
98                 *status = inprm->mad.mad_hdr.status;
99                 if (!(*status)) {
100                         memcpy(&ib_data.port_gid.raw[8],
101                                &outprm->mad.guid_info.gid_tbl[0], 8);
102                         cpu_to_be_buf(&ib_data.port_gid.raw[8], 8);
103                 }
104         }
105         return rc;
106 }
107
108 static int get_pkey_tbl(struct pkey_tbl_st *pkey_tbl, __u16 * status)
109 {
110         union pkey_tbl_mad_u *inprm;
111         union pkey_tbl_mad_u *outprm;
112         int rc;
113
114         inprm = get_inprm_buf();
115         outprm = get_outprm_buf();
116         memset(inprm, 0, sizeof *inprm);
117         memset(outprm, 0, sizeof *outprm);
118
119         inprm->mad.mad_hdr.method = IB_MGMT_METHOD_GET;
120         inprm->mad.mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
121         inprm->mad.mad_hdr.class_version = 1;
122         inprm->mad.mad_hdr.base_version = IB_MGMT_BASE_VERSION;
123         inprm->mad.mad_hdr.attr_id = IB_SMP_ATTR_PKEY_TABLE;
124         inprm->mad.mad_hdr.attr_mod = 0;
125
126         rc = cmd_mad_ifc(inprm, (struct ib_mad_st *)outprm, 1);
127         if (!rc) {
128                 if (pkey_tbl)
129                         memcpy(pkey_tbl, &outprm->mad.pkey_tbl, 2);
130                 *status = inprm->mad.mad_hdr.status;
131                 if (!(*status)) {
132                         ib_data.pkey = outprm->mad.pkey_tbl.pkey_tbl[0][1];
133                         ib_data.bcast_gid.raw[4] =
134                             outprm->mad.pkey_tbl.pkey_tbl[0][1] >> 8;
135                         ib_data.bcast_gid.raw[5] =
136                             outprm->mad.pkey_tbl.pkey_tbl[0][1] & 0xff;
137                 }
138         }
139         return rc;
140 }
141
142 static int join_mc_group(__u32 * qkey_p, __u16 * mlid_p, __u8 join)
143 {
144         struct mc_member_mad_st *mad, *rcv_mad;
145         void *snd_wqe;
146         void *tmp_wqe;
147         udqp_t qp;
148         void *av;
149         int rc;
150         u32 tid;
151         void *rcv_wqe;
152         int is_good;
153
154         qp = ib_data.mads_qp;
155
156         snd_wqe = alloc_send_wqe(qp);
157         if (!snd_wqe) {
158                 eprintf("");
159                 return -1;
160         }
161         tprintf("allocated snd_wqe=0x%lx", snd_wqe);
162
163         mad = get_send_wqe_buf(snd_wqe, 0);
164         memset(mad, 0, 256);
165
166         av = alloc_ud_av();
167         if (!av) {
168                 eprintf("");
169                 free_wqe(snd_wqe);
170                 return -1;
171         }
172         modify_av_params(av, ib_data.sm_lid, 0, 0, 0, NULL, SA_QPN);
173
174         prep_send_wqe_buf(qp, av, snd_wqe, NULL, 0, 256, 0);
175
176         mad->mad_hdr.method = join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE;
177         mad->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
178         mad->mad_hdr.class_version = 2;
179         mad->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
180         mad->mad_hdr.attr_id = IB_SA_ATTR_MC_MEMBER_REC;
181         tid = next_tid;
182         next_tid += TID_INC;
183         mad->mad_hdr.tid[1] = tid;
184
185         mad->sa_hdr.comp_mask[1] = IB_SA_MCMEMBER_REC_MGID |
186             IB_SA_MCMEMBER_REC_PORT_GID | IB_SA_MCMEMBER_REC_JOIN_STATE;
187
188         mad->mc_member.combined4 |= (1 << 24);  /*mad->mc_member.join_state = 1; */
189
190         be_to_cpu_buf(mad, sizeof *mad);
191         memcpy(mad->mc_member.mgid, ib_data.bcast_gid.raw, 16);
192         memcpy(mad->mc_member.port_gid, ib_data.port_gid.raw, 16);
193
194         rc = post_send_req(qp, snd_wqe, 1);
195         if (rc) {
196                 eprintf("");
197                 free_ud_av(av);
198                 free_wqe(snd_wqe);
199                 return -1;
200         }
201
202         tprintf("");
203         /* poll the CQ to get the completions
204            on the send and the expected receive */
205
206         /* send completion */
207         rc = poll_cqe_tout(ib_data.mads_snd_cq, SEND_CQE_POLL_TOUT, &tmp_wqe,
208                            &is_good);
209         if (rc) {
210                 eprintf("");
211                 return -1;
212         }
213
214         if (tmp_wqe != snd_wqe) {
215                 eprintf("");
216                 return -1;
217         }
218
219         if (free_wqe(snd_wqe)) {
220                 eprintf("");
221                 return -1;
222         }
223         free_ud_av(av);
224
225         if (!is_good) {
226                 eprintf("");
227                 return -1;
228         }
229
230         /* receive completion */
231         rc = poll_cqe_tout(ib_data.mads_rcv_cq, SA_RESP_POLL_TOUT, &rcv_wqe,
232                            &is_good);
233         if (rc) {
234                 eprintf("");
235                 return -1;
236         }
237
238         if (is_good) {
239                 rcv_mad = get_rcv_wqe_buf(rcv_wqe, 1);
240                 be_to_cpu_buf(rcv_mad, sizeof *rcv_mad);
241                 if (rcv_mad->mad_hdr.tid[1] == tid) {
242                         /* that's our response */
243                         if (mad->mad_hdr.status == 0) {
244                                 /* good response - save results */
245                                 *qkey_p = rcv_mad->mc_member.q_key;
246                                 *mlid_p = rcv_mad->mc_member.combined1 >> 16;   // rcv_mad->mc_member.mlid;
247                         } else {
248                                 /* join failed */
249                                 eprintf("");
250                                 return -1;
251                         }
252                 } else {
253                         /* not our response */
254                         eprintf("");
255                         return -1;
256                 }
257         }
258
259         if (free_wqe(rcv_wqe)) {
260                 eprintf("");
261                 return -1;
262         }
263
264         return is_good ? 0 : -1;
265 }
266
267 static int get_path_record(union ib_gid_u *dgid, __u16 * dlid_p, u8 * sl_p,
268                            u8 * rate_p)
269 {
270         struct path_record_mad_st *mad, *rcv_mad;
271         void *snd_wqe;
272         udqp_t qp;
273         ud_av_t av;
274         void *tmp_wqe;
275         void *rcv_wqe;
276         u32 tid;
277         int rc;
278         int is_good;
279
280         tprintf("gid=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
281                 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
282                 dgid->raw[0], dgid->raw[1], dgid->raw[2], dgid->raw[3],
283                 dgid->raw[4], dgid->raw[5], dgid->raw[6], dgid->raw[7],
284                 dgid->raw[8], dgid->raw[9], dgid->raw[10], dgid->raw[11],
285                 dgid->raw[12], dgid->raw[13], dgid->raw[14], dgid->raw[15]);
286         qp = ib_data.mads_qp;
287
288         snd_wqe = alloc_send_wqe(qp);
289         if (!snd_wqe) {
290                 eprintf("");
291                 return -1;
292         }
293
294         mad = get_send_wqe_buf(snd_wqe, 0);
295         memset(mad, 0, 256);
296
297         av = alloc_ud_av();
298         if (!av) {
299                 eprintf("");
300                 free_wqe(snd_wqe);
301                 return -1;
302         }
303         modify_av_params(av, ib_data.sm_lid, 0, 0, 0, NULL, SA_QPN);
304
305         prep_send_wqe_buf(qp, av, snd_wqe, NULL, 0, 256, 0);
306
307         mad->mad_hdr.method = IB_MGMT_METHOD_GET;
308         mad->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
309         mad->mad_hdr.class_version = 2;
310         mad->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
311         mad->mad_hdr.attr_id = IB_SA_ATTR_PATH_REC;
312         tid = next_tid;
313         next_tid += TID_INC;
314         mad->mad_hdr.tid[1] = tid;
315
316         memcpy(mad->path_record.dgid.raw, dgid->raw, 16);
317         cpu_to_be_buf(mad->path_record.dgid.raw, 16);
318
319         mad->sa_hdr.comp_mask[1] = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID;
320
321         cpu_to_be_buf(mad, sizeof *mad);
322         memcpy(mad->path_record.sgid.raw, ib_data.port_gid.raw, 16);
323
324         rc = post_send_req(qp, snd_wqe, 1);
325         if (rc) {
326                 eprintf("");
327                 free_ud_av(av);
328                 free_wqe(snd_wqe);
329                 return rc;
330         }
331
332         /* poll the CQ to get the completions
333            on the send and the expected receive */
334
335         /* send completion */
336         rc = poll_cqe_tout(ib_data.mads_snd_cq, SEND_CQE_POLL_TOUT, &tmp_wqe,
337                            &is_good);
338         if (rc) {
339                 eprintf("");
340                 return -1;
341         }
342
343         if (tmp_wqe != snd_wqe) {
344                 eprintf("");
345                 return -1;
346         }
347
348         if (free_wqe(snd_wqe)) {
349                 eprintf("");
350                 return -1;
351         }
352         free_ud_av(av);
353
354         if (!is_good) {
355                 eprintf("");
356                 return -1;
357         }
358
359         /* receive completion */
360         rc = poll_cqe_tout(ib_data.mads_rcv_cq, SA_RESP_POLL_TOUT, &rcv_wqe,
361                            &is_good);
362         if (rc) {
363                 eprintf("");
364                 return -1;
365         }
366
367         if (is_good) {
368                 rcv_mad = get_rcv_wqe_buf(rcv_wqe, 1);
369                 be_to_cpu_buf(rcv_mad, sizeof *rcv_mad);
370                 if (rcv_mad->mad_hdr.tid[1] == tid) {
371                         /* that's our response */
372                         if (mad->mad_hdr.status == 0) {
373                                 /* good response - save results */
374                                 *dlid_p = rcv_mad->path_record.dlid;
375                                 *sl_p = (rcv_mad->path_record.combined3 >> 16) & 0xf;   //  rcv_mad->path_record.sl;
376                                 *rate_p = rcv_mad->path_record.combined3 & 0x3f;        //rcv_mad->path_record.rate;
377                         } else {
378                                 /* join failed */
379                                 eprintf("");
380                                 return -1;
381                         }
382                 } else {
383                         /* not our response */
384                         eprintf("");
385                         return -1;
386                 }
387         }
388
389         if (free_wqe(rcv_wqe)) {
390                 eprintf("");
391                 return -1;
392         }
393
394         tprintf("");
395         return is_good ? 0 : -1;
396 }