]> Git Repo - J-linux.git/blob - drivers/infiniband/hw/mlx5/mad.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / infiniband / hw / mlx5 / mad.c
1 /*
2  * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <linux/mlx5/vport.h>
34 #include <rdma/ib_mad.h>
35 #include <rdma/ib_smi.h>
36 #include <rdma/ib_pma.h>
37 #include "mlx5_ib.h"
38 #include "cmd.h"
39
40 enum {
41         MLX5_IB_VENDOR_CLASS1 = 0x9,
42         MLX5_IB_VENDOR_CLASS2 = 0xa
43 };
44
45 static bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u32 port_num,
46                            struct ib_mad *in_mad)
47 {
48         if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED &&
49             in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
50                 return true;
51         return dev->port_caps[port_num - 1].has_smi;
52 }
53
54 static int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey,
55                         int ignore_bkey, u32 port, const struct ib_wc *in_wc,
56                         const struct ib_grh *in_grh, const void *in_mad,
57                         void *response_mad)
58 {
59         u8 op_modifier = 0;
60
61         if (!can_do_mad_ifc(dev, port, (struct ib_mad *)in_mad))
62                 return -EPERM;
63
64         /* Key check traps can't be generated unless we have in_wc to
65          * tell us where to send the trap.
66          */
67         if (ignore_mkey || !in_wc)
68                 op_modifier |= 0x1;
69         if (ignore_bkey || !in_wc)
70                 op_modifier |= 0x2;
71
72         return mlx5_cmd_mad_ifc(dev, in_mad, response_mad, op_modifier,
73                                 port);
74 }
75
76 static void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext,
77                                void *out)
78 {
79 #define MLX5_SUM_CNT(p, cntr1, cntr2)   \
80         (MLX5_GET64(query_vport_counter_out, p, cntr1) + \
81         MLX5_GET64(query_vport_counter_out, p, cntr2))
82
83         pma_cnt_ext->port_xmit_data =
84                 cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets,
85                                          transmitted_ib_multicast.octets) >> 2);
86         pma_cnt_ext->port_rcv_data =
87                 cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets,
88                                          received_ib_multicast.octets) >> 2);
89         pma_cnt_ext->port_xmit_packets =
90                 cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.packets,
91                                          transmitted_ib_multicast.packets));
92         pma_cnt_ext->port_rcv_packets =
93                 cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.packets,
94                                          received_ib_multicast.packets));
95         pma_cnt_ext->port_unicast_xmit_packets =
96                 MLX5_GET64_BE(query_vport_counter_out,
97                               out, transmitted_ib_unicast.packets);
98         pma_cnt_ext->port_unicast_rcv_packets =
99                 MLX5_GET64_BE(query_vport_counter_out,
100                               out, received_ib_unicast.packets);
101         pma_cnt_ext->port_multicast_xmit_packets =
102                 MLX5_GET64_BE(query_vport_counter_out,
103                               out, transmitted_ib_multicast.packets);
104         pma_cnt_ext->port_multicast_rcv_packets =
105                 MLX5_GET64_BE(query_vport_counter_out,
106                               out, received_ib_multicast.packets);
107 }
108
109 static void pma_cnt_assign(struct ib_pma_portcounters *pma_cnt,
110                            void *out)
111 {
112         /* Traffic counters will be reported in
113          * their 64bit form via ib_pma_portcounters_ext by default.
114          */
115         void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out,
116                                      counter_set);
117
118 #define MLX5_ASSIGN_PMA_CNTR(counter_var, counter_name) {               \
119         counter_var = MLX5_GET_BE(typeof(counter_var),                  \
120                                   ib_port_cntrs_grp_data_layout,        \
121                                   out_pma, counter_name);               \
122         }
123
124         MLX5_ASSIGN_PMA_CNTR(pma_cnt->symbol_error_counter,
125                              symbol_error_counter);
126         MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_error_recovery_counter,
127                              link_error_recovery_counter);
128         MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_downed_counter,
129                              link_downed_counter);
130         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_errors,
131                              port_rcv_errors);
132         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_remphys_errors,
133                              port_rcv_remote_physical_errors);
134         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_switch_relay_errors,
135                              port_rcv_switch_relay_errors);
136         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_discards,
137                              port_xmit_discards);
138         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_constraint_errors,
139                              port_xmit_constraint_errors);
140         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_wait,
141                              port_xmit_wait);
142         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_constraint_errors,
143                              port_rcv_constraint_errors);
144         MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_overrun_errors,
145                              link_overrun_errors);
146         MLX5_ASSIGN_PMA_CNTR(pma_cnt->vl15_dropped,
147                              vl_15_dropped);
148 }
149
150 static void pma_cnt_ext_assign_ppcnt(struct ib_pma_portcounters_ext *cnt_ext,
151                                      void *out)
152 {
153         void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out,
154                                      counter_set);
155
156 #define MLX5_GET_EXT_CNTR(counter_name)                 \
157         MLX5_GET64(ib_ext_port_cntrs_grp_data_layout,   \
158                    out_pma, counter_name##_high)
159
160         cnt_ext->port_xmit_data =
161                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_xmit_data) >> 2);
162         cnt_ext->port_rcv_data =
163                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_rcv_data) >> 2);
164
165         cnt_ext->port_xmit_packets =
166                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_xmit_pkts));
167         cnt_ext->port_rcv_packets =
168                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_rcv_pkts));
169
170         cnt_ext->port_unicast_xmit_packets =
171                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_unicast_xmit_pkts));
172         cnt_ext->port_unicast_rcv_packets =
173                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_unicast_rcv_pkts));
174
175         cnt_ext->port_multicast_xmit_packets =
176                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_multicast_xmit_pkts));
177         cnt_ext->port_multicast_rcv_packets =
178                 cpu_to_be64(MLX5_GET_EXT_CNTR(port_multicast_rcv_pkts));
179 }
180
181 static int query_ib_ppcnt(struct mlx5_core_dev *dev, u8 port_num, u8 plane_num,
182                           void *out, size_t sz, bool ext)
183 {
184         u32 *in;
185         int err;
186
187         in  = kvzalloc(sz, GFP_KERNEL);
188         if (!in) {
189                 err = -ENOMEM;
190                 return err;
191         }
192
193         MLX5_SET(ppcnt_reg, in, local_port, port_num);
194         MLX5_SET(ppcnt_reg, in, plane_ind, plane_num);
195
196         if (ext)
197                 MLX5_SET(ppcnt_reg, in, grp,
198                          MLX5_INFINIBAND_EXTENDED_PORT_COUNTERS_GROUP);
199         else
200                 MLX5_SET(ppcnt_reg, in, grp,
201                          MLX5_INFINIBAND_PORT_COUNTERS_GROUP);
202         err = mlx5_core_access_reg(dev, in, sz, out,
203                                    sz, MLX5_REG_PPCNT, 0, 0);
204
205         kvfree(in);
206         return err;
207 }
208
209 static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
210                            const struct ib_mad *in_mad, struct ib_mad *out_mad)
211 {
212         struct mlx5_core_dev *mdev;
213         bool native_port = true;
214         u32 mdev_port_num;
215         void *out_cnt;
216         int err;
217
218         mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
219         if (!mdev) {
220                 /* Fail to get the native port, likely due to 2nd port is still
221                  * unaffiliated. In such case default to 1st port and attached
222                  * PF device.
223                  */
224                 native_port = false;
225                 mdev = dev->mdev;
226                 mdev_port_num = 1;
227         }
228         if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
229             !mlx5_core_mp_enabled(mdev) &&
230             dev->ib_dev.type != RDMA_DEVICE_TYPE_SMI) {
231                 /* set local port to one for Function-Per-Port HCA. */
232                 mdev = dev->mdev;
233                 mdev_port_num = 1;
234         }
235
236         /* Declaring support of extended counters */
237         if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
238                 struct ib_class_port_info cpi = {};
239
240                 cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
241                 memcpy((out_mad->data + 40), &cpi, sizeof(cpi));
242                 err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
243                 goto done;
244         }
245
246         if (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT) {
247                 struct ib_pma_portcounters_ext *pma_cnt_ext =
248                         (struct ib_pma_portcounters_ext *)(out_mad->data + 40);
249                 int sz = max(MLX5_ST_SZ_BYTES(query_vport_counter_out),
250                              MLX5_ST_SZ_BYTES(ppcnt_reg));
251
252                 out_cnt = kvzalloc(sz, GFP_KERNEL);
253                 if (!out_cnt) {
254                         err = IB_MAD_RESULT_FAILURE;
255                         goto done;
256                 }
257
258                 if (dev->ib_dev.type == RDMA_DEVICE_TYPE_SMI) {
259                         err = query_ib_ppcnt(mdev, mdev_port_num,
260                                              port_num, out_cnt, sz, 1);
261                         if (!err)
262                                 pma_cnt_ext_assign_ppcnt(pma_cnt_ext, out_cnt);
263                 } else {
264                         err = mlx5_core_query_vport_counter(mdev, 0, 0,
265                                                             mdev_port_num,
266                                                             out_cnt);
267                         if (!err)
268                                 pma_cnt_ext_assign(pma_cnt_ext, out_cnt);
269                 }
270         } else {
271                 struct ib_pma_portcounters *pma_cnt =
272                         (struct ib_pma_portcounters *)(out_mad->data + 40);
273                 int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
274
275                 out_cnt = kvzalloc(sz, GFP_KERNEL);
276                 if (!out_cnt) {
277                         err = IB_MAD_RESULT_FAILURE;
278                         goto done;
279                 }
280
281                 if (dev->ib_dev.type == RDMA_DEVICE_TYPE_SMI)
282                         err = query_ib_ppcnt(mdev, mdev_port_num, port_num,
283                                              out_cnt, sz, 0);
284                 else
285                         err = query_ib_ppcnt(mdev, mdev_port_num, 0,
286                                              out_cnt, sz, 0);
287
288                 if (!err)
289                         pma_cnt_assign(pma_cnt, out_cnt);
290         }
291         kvfree(out_cnt);
292         err = err ? IB_MAD_RESULT_FAILURE :
293                     IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
294 done:
295         if (native_port)
296                 mlx5_ib_put_native_port_mdev(dev, port_num);
297         return err;
298 }
299
300 int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u32 port_num,
301                         const struct ib_wc *in_wc, const struct ib_grh *in_grh,
302                         const struct ib_mad *in, struct ib_mad *out,
303                         size_t *out_mad_size, u16 *out_mad_pkey_index)
304 {
305         struct mlx5_ib_dev *dev = to_mdev(ibdev);
306         u8 mgmt_class = in->mad_hdr.mgmt_class;
307         u8 method = in->mad_hdr.method;
308         u16 slid;
309         int err;
310
311         slid = in_wc ? ib_lid_cpu16(in_wc->slid) :
312                        be16_to_cpu(IB_LID_PERMISSIVE);
313
314         if (method == IB_MGMT_METHOD_TRAP && !slid)
315                 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
316
317         switch (mgmt_class) {
318         case IB_MGMT_CLASS_SUBN_LID_ROUTED:
319         case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: {
320                 if (method != IB_MGMT_METHOD_GET &&
321                     method != IB_MGMT_METHOD_SET &&
322                     method != IB_MGMT_METHOD_TRAP_REPRESS)
323                         return IB_MAD_RESULT_SUCCESS;
324
325                 /* Don't process SMInfo queries -- the SMA can't handle them.
326                  */
327                 if (in->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
328                         return IB_MAD_RESULT_SUCCESS;
329         } break;
330         case IB_MGMT_CLASS_PERF_MGMT:
331                 if (MLX5_CAP_GEN(dev->mdev, vport_counters) &&
332                     method == IB_MGMT_METHOD_GET)
333                         return process_pma_cmd(dev, port_num, in, out);
334                 fallthrough;
335         case MLX5_IB_VENDOR_CLASS1:
336         case MLX5_IB_VENDOR_CLASS2:
337         case IB_MGMT_CLASS_CONG_MGMT: {
338                 if (method != IB_MGMT_METHOD_GET &&
339                     method != IB_MGMT_METHOD_SET)
340                         return IB_MAD_RESULT_SUCCESS;
341         } break;
342         default:
343                 return IB_MAD_RESULT_SUCCESS;
344         }
345
346         err = mlx5_MAD_IFC(to_mdev(ibdev), mad_flags & IB_MAD_IGNORE_MKEY,
347                            mad_flags & IB_MAD_IGNORE_BKEY, port_num, in_wc,
348                            in_grh, in, out);
349         if (err)
350                 return IB_MAD_RESULT_FAILURE;
351
352         /* set return bit in status of directed route responses */
353         if (mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
354                 out->mad_hdr.status |= cpu_to_be16(1 << 15);
355
356         if (method == IB_MGMT_METHOD_TRAP_REPRESS)
357                 /* no response for trap repress */
358                 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
359
360         return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
361 }
362
363 int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, unsigned int port)
364 {
365         struct ib_smp *in_mad;
366         struct ib_smp *out_mad;
367         int err = -ENOMEM;
368         u16 packet_error;
369
370         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
371         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
372         if (!in_mad || !out_mad)
373                 goto out;
374
375         ib_init_query_mad(in_mad);
376         in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
377         in_mad->attr_mod = cpu_to_be32(port);
378
379         err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
380
381         packet_error = be16_to_cpu(out_mad->status);
382
383         dev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ?
384                 MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
385
386 out:
387         kfree(in_mad);
388         kfree(out_mad);
389         return err;
390 }
391
392 static int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev,
393                                                  struct ib_smp *out_mad)
394 {
395         struct ib_smp *in_mad;
396         int err;
397
398         in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
399         if (!in_mad)
400                 return -ENOMEM;
401
402         ib_init_query_mad(in_mad);
403         in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
404
405         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad,
406                            out_mad);
407
408         kfree(in_mad);
409         return err;
410 }
411
412 int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev,
413                                          __be64 *sys_image_guid)
414 {
415         struct ib_smp *out_mad;
416         int err;
417
418         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
419         if (!out_mad)
420                 return -ENOMEM;
421
422         err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
423         if (err)
424                 goto out;
425
426         memcpy(sys_image_guid, out_mad->data + 4, 8);
427
428 out:
429         kfree(out_mad);
430
431         return err;
432 }
433
434 int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev,
435                                  u16 *max_pkeys)
436 {
437         struct ib_smp *out_mad;
438         int err;
439
440         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
441         if (!out_mad)
442                 return -ENOMEM;
443
444         err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
445         if (err)
446                 goto out;
447
448         *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28));
449
450 out:
451         kfree(out_mad);
452
453         return err;
454 }
455
456 int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev,
457                                  u32 *vendor_id)
458 {
459         struct ib_smp *out_mad;
460         int err;
461
462         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
463         if (!out_mad)
464                 return -ENOMEM;
465
466         err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
467         if (err)
468                 goto out;
469
470         *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff;
471
472 out:
473         kfree(out_mad);
474
475         return err;
476 }
477
478 int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
479 {
480         struct ib_smp *in_mad;
481         struct ib_smp *out_mad;
482         int err = -ENOMEM;
483
484         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
485         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
486         if (!in_mad || !out_mad)
487                 goto out;
488
489         ib_init_query_mad(in_mad);
490         in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
491
492         err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
493         if (err)
494                 goto out;
495
496         memcpy(node_desc, out_mad->data, IB_DEVICE_NODE_DESC_MAX);
497 out:
498         kfree(in_mad);
499         kfree(out_mad);
500         return err;
501 }
502
503 int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid)
504 {
505         struct ib_smp *in_mad;
506         struct ib_smp *out_mad;
507         int err = -ENOMEM;
508
509         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
510         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
511         if (!in_mad || !out_mad)
512                 goto out;
513
514         ib_init_query_mad(in_mad);
515         in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
516
517         err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
518         if (err)
519                 goto out;
520
521         memcpy(node_guid, out_mad->data + 12, 8);
522 out:
523         kfree(in_mad);
524         kfree(out_mad);
525         return err;
526 }
527
528 int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u32 port, u16 index,
529                             u16 *pkey)
530 {
531         struct ib_smp *in_mad;
532         struct ib_smp *out_mad;
533         int err = -ENOMEM;
534
535         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
536         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
537         if (!in_mad || !out_mad)
538                 goto out;
539
540         ib_init_query_mad(in_mad);
541         in_mad->attr_id  = IB_SMP_ATTR_PKEY_TABLE;
542         in_mad->attr_mod = cpu_to_be32(index / 32);
543
544         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
545                            out_mad);
546         if (err)
547                 goto out;
548
549         *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]);
550
551 out:
552         kfree(in_mad);
553         kfree(out_mad);
554         return err;
555 }
556
557 int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u32 port, int index,
558                             union ib_gid *gid)
559 {
560         struct ib_smp *in_mad;
561         struct ib_smp *out_mad;
562         int err = -ENOMEM;
563
564         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
565         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
566         if (!in_mad || !out_mad)
567                 goto out;
568
569         ib_init_query_mad(in_mad);
570         in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
571         in_mad->attr_mod = cpu_to_be32(port);
572
573         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
574                            out_mad);
575         if (err)
576                 goto out;
577
578         memcpy(gid->raw, out_mad->data + 8, 8);
579
580         ib_init_query_mad(in_mad);
581         in_mad->attr_id  = IB_SMP_ATTR_GUID_INFO;
582         in_mad->attr_mod = cpu_to_be32(index / 8);
583
584         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
585                            out_mad);
586         if (err)
587                 goto out;
588
589         memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
590
591 out:
592         kfree(in_mad);
593         kfree(out_mad);
594         return err;
595 }
596
597 int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u32 port,
598                             struct ib_port_attr *props)
599 {
600         struct mlx5_ib_dev *dev = to_mdev(ibdev);
601         struct mlx5_core_dev *mdev = dev->mdev;
602         struct ib_smp *in_mad;
603         struct ib_smp *out_mad;
604         int ext_active_speed;
605         int err = -ENOMEM;
606
607         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
608         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
609         if (!in_mad || !out_mad)
610                 goto out;
611
612         /* props being zeroed by the caller, avoid zeroing it here */
613
614         ib_init_query_mad(in_mad);
615         in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
616         in_mad->attr_mod = cpu_to_be32(port);
617
618         err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad);
619         if (err) {
620                 mlx5_ib_warn(dev, "err %d\n", err);
621                 goto out;
622         }
623
624         props->lid              = be16_to_cpup((__be16 *)(out_mad->data + 16));
625         props->lmc              = out_mad->data[34] & 0x7;
626         props->sm_lid           = be16_to_cpup((__be16 *)(out_mad->data + 18));
627         props->sm_sl            = out_mad->data[36] & 0xf;
628         props->state            = out_mad->data[32] & 0xf;
629         props->phys_state       = out_mad->data[33] >> 4;
630         props->port_cap_flags   = be32_to_cpup((__be32 *)(out_mad->data + 20));
631         props->gid_tbl_len      = out_mad->data[50];
632         props->max_msg_sz       = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
633         props->pkey_tbl_len     = dev->pkey_table_len;
634         props->bad_pkey_cntr    = be16_to_cpup((__be16 *)(out_mad->data + 46));
635         props->qkey_viol_cntr   = be16_to_cpup((__be16 *)(out_mad->data + 48));
636         props->active_width     = out_mad->data[31] & 0xf;
637         props->active_speed     = out_mad->data[35] >> 4;
638         props->max_mtu          = out_mad->data[41] & 0xf;
639         props->active_mtu       = out_mad->data[36] >> 4;
640         props->subnet_timeout   = out_mad->data[51] & 0x1f;
641         props->max_vl_num       = out_mad->data[37] >> 4;
642         props->init_type_reply  = out_mad->data[41] >> 4;
643
644         if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP) {
645                 props->port_cap_flags2 =
646                         be16_to_cpup((__be16 *)(out_mad->data + 60));
647
648                 if (props->port_cap_flags2 & IB_PORT_LINK_WIDTH_2X_SUP)
649                         props->active_width = out_mad->data[31] & 0x1f;
650         }
651
652         /* Check if extended speeds (EDR/FDR/...) are supported */
653         if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
654                 ext_active_speed = out_mad->data[62] >> 4;
655
656                 switch (ext_active_speed) {
657                 case 1:
658                         props->active_speed = 16; /* FDR */
659                         break;
660                 case 2:
661                         props->active_speed = 32; /* EDR */
662                         break;
663                 case 4:
664                         if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
665                             props->port_cap_flags2 & IB_PORT_LINK_SPEED_HDR_SUP)
666                                 props->active_speed = IB_SPEED_HDR;
667                         break;
668                 case 8:
669                         if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
670                             props->port_cap_flags2 & IB_PORT_LINK_SPEED_NDR_SUP)
671                                 props->active_speed = IB_SPEED_NDR;
672                         break;
673                 }
674         }
675
676         /* Check if extended speeds 2 (XDR/...) are supported */
677         if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
678             props->port_cap_flags2 & IB_PORT_EXTENDED_SPEEDS2_SUP) {
679                 ext_active_speed = (out_mad->data[56] >> 4) & 0x6;
680
681                 switch (ext_active_speed) {
682                 case 2:
683                         if (props->port_cap_flags2 & IB_PORT_LINK_SPEED_XDR_SUP)
684                                 props->active_speed = IB_SPEED_XDR;
685                         break;
686                 }
687         }
688
689         /* If reported active speed is QDR, check if is FDR-10 */
690         if (props->active_speed == 4) {
691                 if (dev->port_caps[port - 1].ext_port_cap &
692                     MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
693                         ib_init_query_mad(in_mad);
694                         in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
695                         in_mad->attr_mod = cpu_to_be32(port);
696
697                         err = mlx5_MAD_IFC(dev, 1, 1, port,
698                                            NULL, NULL, in_mad, out_mad);
699                         if (err)
700                                 goto out;
701
702                         /* Checking LinkSpeedActive for FDR-10 */
703                         if (out_mad->data[15] & 0x1)
704                                 props->active_speed = 8;
705                 }
706         }
707
708 out:
709         kfree(in_mad);
710         kfree(out_mad);
711
712         return err;
713 }
This page took 0.10791 seconds and 4 git commands to generate.