diff options
Diffstat (limited to 'drivers/infiniband/hw/mlx5/mad.c')
-rw-r--r-- | drivers/infiniband/hw/mlx5/mad.c | 315 |
1 files changed, 310 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c index 9cf9a37bb5ff..b84d13a487cc 100644 --- a/drivers/infiniband/hw/mlx5/mad.c +++ b/drivers/infiniband/hw/mlx5/mad.c | |||
@@ -41,8 +41,8 @@ enum { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, | 43 | int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, |
44 | u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 44 | u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
45 | void *in_mad, void *response_mad) | 45 | const void *in_mad, void *response_mad) |
46 | { | 46 | { |
47 | u8 op_modifier = 0; | 47 | u8 op_modifier = 0; |
48 | 48 | ||
@@ -58,11 +58,19 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, | |||
58 | } | 58 | } |
59 | 59 | ||
60 | int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 60 | int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
61 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 61 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
62 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 62 | const struct ib_mad_hdr *in, size_t in_mad_size, |
63 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
64 | u16 *out_mad_pkey_index) | ||
63 | { | 65 | { |
64 | u16 slid; | 66 | u16 slid; |
65 | int err; | 67 | int err; |
68 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
69 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
70 | |||
71 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
72 | *out_mad_size != sizeof(*out_mad))) | ||
73 | return IB_MAD_RESULT_FAILURE; | ||
66 | 74 | ||
67 | slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); | 75 | slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); |
68 | 76 | ||
@@ -129,7 +137,7 @@ int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port) | |||
129 | 137 | ||
130 | packet_error = be16_to_cpu(out_mad->status); | 138 | packet_error = be16_to_cpu(out_mad->status); |
131 | 139 | ||
132 | dev->mdev->caps.gen.ext_port_cap[port - 1] = (!err && !packet_error) ? | 140 | dev->mdev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ? |
133 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; | 141 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; |
134 | 142 | ||
135 | out: | 143 | out: |
@@ -137,3 +145,300 @@ out: | |||
137 | kfree(out_mad); | 145 | kfree(out_mad); |
138 | return err; | 146 | return err; |
139 | } | 147 | } |
148 | |||
149 | int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev, | ||
150 | struct ib_smp *out_mad) | ||
151 | { | ||
152 | struct ib_smp *in_mad = NULL; | ||
153 | int err = -ENOMEM; | ||
154 | |||
155 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
156 | if (!in_mad) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | init_query_mad(in_mad); | ||
160 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
161 | |||
162 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, | ||
163 | out_mad); | ||
164 | |||
165 | kfree(in_mad); | ||
166 | return err; | ||
167 | } | ||
168 | |||
169 | int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev, | ||
170 | __be64 *sys_image_guid) | ||
171 | { | ||
172 | struct ib_smp *out_mad = NULL; | ||
173 | int err = -ENOMEM; | ||
174 | |||
175 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
176 | if (!out_mad) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); | ||
180 | if (err) | ||
181 | goto out; | ||
182 | |||
183 | memcpy(sys_image_guid, out_mad->data + 4, 8); | ||
184 | |||
185 | out: | ||
186 | kfree(out_mad); | ||
187 | |||
188 | return err; | ||
189 | } | ||
190 | |||
191 | int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev, | ||
192 | u16 *max_pkeys) | ||
193 | { | ||
194 | struct ib_smp *out_mad = NULL; | ||
195 | int err = -ENOMEM; | ||
196 | |||
197 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
198 | if (!out_mad) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); | ||
202 | if (err) | ||
203 | goto out; | ||
204 | |||
205 | *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28)); | ||
206 | |||
207 | out: | ||
208 | kfree(out_mad); | ||
209 | |||
210 | return err; | ||
211 | } | ||
212 | |||
213 | int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev, | ||
214 | u32 *vendor_id) | ||
215 | { | ||
216 | struct ib_smp *out_mad = NULL; | ||
217 | int err = -ENOMEM; | ||
218 | |||
219 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
220 | if (!out_mad) | ||
221 | return -ENOMEM; | ||
222 | |||
223 | err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); | ||
224 | if (err) | ||
225 | goto out; | ||
226 | |||
227 | *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff; | ||
228 | |||
229 | out: | ||
230 | kfree(out_mad); | ||
231 | |||
232 | return err; | ||
233 | } | ||
234 | |||
235 | int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc) | ||
236 | { | ||
237 | struct ib_smp *in_mad = NULL; | ||
238 | struct ib_smp *out_mad = NULL; | ||
239 | int err = -ENOMEM; | ||
240 | |||
241 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
242 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
243 | if (!in_mad || !out_mad) | ||
244 | goto out; | ||
245 | |||
246 | init_query_mad(in_mad); | ||
247 | in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; | ||
248 | |||
249 | err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | ||
250 | if (err) | ||
251 | goto out; | ||
252 | |||
253 | memcpy(node_desc, out_mad->data, 64); | ||
254 | out: | ||
255 | kfree(in_mad); | ||
256 | kfree(out_mad); | ||
257 | return err; | ||
258 | } | ||
259 | |||
260 | int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid) | ||
261 | { | ||
262 | struct ib_smp *in_mad = NULL; | ||
263 | struct ib_smp *out_mad = NULL; | ||
264 | int err = -ENOMEM; | ||
265 | |||
266 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
267 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
268 | if (!in_mad || !out_mad) | ||
269 | goto out; | ||
270 | |||
271 | init_query_mad(in_mad); | ||
272 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
273 | |||
274 | err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | ||
275 | if (err) | ||
276 | goto out; | ||
277 | |||
278 | memcpy(node_guid, out_mad->data + 12, 8); | ||
279 | out: | ||
280 | kfree(in_mad); | ||
281 | kfree(out_mad); | ||
282 | return err; | ||
283 | } | ||
284 | |||
285 | int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index, | ||
286 | u16 *pkey) | ||
287 | { | ||
288 | struct ib_smp *in_mad = NULL; | ||
289 | struct ib_smp *out_mad = NULL; | ||
290 | int err = -ENOMEM; | ||
291 | |||
292 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
293 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
294 | if (!in_mad || !out_mad) | ||
295 | goto out; | ||
296 | |||
297 | init_query_mad(in_mad); | ||
298 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | ||
299 | in_mad->attr_mod = cpu_to_be32(index / 32); | ||
300 | |||
301 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, | ||
302 | out_mad); | ||
303 | if (err) | ||
304 | goto out; | ||
305 | |||
306 | *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]); | ||
307 | |||
308 | out: | ||
309 | kfree(in_mad); | ||
310 | kfree(out_mad); | ||
311 | return err; | ||
312 | } | ||
313 | |||
314 | int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index, | ||
315 | union ib_gid *gid) | ||
316 | { | ||
317 | struct ib_smp *in_mad = NULL; | ||
318 | struct ib_smp *out_mad = NULL; | ||
319 | int err = -ENOMEM; | ||
320 | |||
321 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
322 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
323 | if (!in_mad || !out_mad) | ||
324 | goto out; | ||
325 | |||
326 | init_query_mad(in_mad); | ||
327 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
328 | in_mad->attr_mod = cpu_to_be32(port); | ||
329 | |||
330 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, | ||
331 | out_mad); | ||
332 | if (err) | ||
333 | goto out; | ||
334 | |||
335 | memcpy(gid->raw, out_mad->data + 8, 8); | ||
336 | |||
337 | init_query_mad(in_mad); | ||
338 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | ||
339 | in_mad->attr_mod = cpu_to_be32(index / 8); | ||
340 | |||
341 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, | ||
342 | out_mad); | ||
343 | if (err) | ||
344 | goto out; | ||
345 | |||
346 | memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); | ||
347 | |||
348 | out: | ||
349 | kfree(in_mad); | ||
350 | kfree(out_mad); | ||
351 | return err; | ||
352 | } | ||
353 | |||
354 | int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port, | ||
355 | struct ib_port_attr *props) | ||
356 | { | ||
357 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
358 | struct mlx5_core_dev *mdev = dev->mdev; | ||
359 | struct ib_smp *in_mad = NULL; | ||
360 | struct ib_smp *out_mad = NULL; | ||
361 | int ext_active_speed; | ||
362 | int err = -ENOMEM; | ||
363 | |||
364 | if (port < 1 || port > MLX5_CAP_GEN(mdev, num_ports)) { | ||
365 | mlx5_ib_warn(dev, "invalid port number %d\n", port); | ||
366 | return -EINVAL; | ||
367 | } | ||
368 | |||
369 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
370 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
371 | if (!in_mad || !out_mad) | ||
372 | goto out; | ||
373 | |||
374 | memset(props, 0, sizeof(*props)); | ||
375 | |||
376 | init_query_mad(in_mad); | ||
377 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
378 | in_mad->attr_mod = cpu_to_be32(port); | ||
379 | |||
380 | err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad); | ||
381 | if (err) { | ||
382 | mlx5_ib_warn(dev, "err %d\n", err); | ||
383 | goto out; | ||
384 | } | ||
385 | |||
386 | props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16)); | ||
387 | props->lmc = out_mad->data[34] & 0x7; | ||
388 | props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18)); | ||
389 | props->sm_sl = out_mad->data[36] & 0xf; | ||
390 | props->state = out_mad->data[32] & 0xf; | ||
391 | props->phys_state = out_mad->data[33] >> 4; | ||
392 | props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20)); | ||
393 | props->gid_tbl_len = out_mad->data[50]; | ||
394 | props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg); | ||
395 | props->pkey_tbl_len = mdev->port_caps[port - 1].pkey_table_len; | ||
396 | props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46)); | ||
397 | props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48)); | ||
398 | props->active_width = out_mad->data[31] & 0xf; | ||
399 | props->active_speed = out_mad->data[35] >> 4; | ||
400 | props->max_mtu = out_mad->data[41] & 0xf; | ||
401 | props->active_mtu = out_mad->data[36] >> 4; | ||
402 | props->subnet_timeout = out_mad->data[51] & 0x1f; | ||
403 | props->max_vl_num = out_mad->data[37] >> 4; | ||
404 | props->init_type_reply = out_mad->data[41] >> 4; | ||
405 | |||
406 | /* Check if extended speeds (EDR/FDR/...) are supported */ | ||
407 | if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) { | ||
408 | ext_active_speed = out_mad->data[62] >> 4; | ||
409 | |||
410 | switch (ext_active_speed) { | ||
411 | case 1: | ||
412 | props->active_speed = 16; /* FDR */ | ||
413 | break; | ||
414 | case 2: | ||
415 | props->active_speed = 32; /* EDR */ | ||
416 | break; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | /* If reported active speed is QDR, check if is FDR-10 */ | ||
421 | if (props->active_speed == 4) { | ||
422 | if (mdev->port_caps[port - 1].ext_port_cap & | ||
423 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) { | ||
424 | init_query_mad(in_mad); | ||
425 | in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; | ||
426 | in_mad->attr_mod = cpu_to_be32(port); | ||
427 | |||
428 | err = mlx5_MAD_IFC(dev, 1, 1, port, | ||
429 | NULL, NULL, in_mad, out_mad); | ||
430 | if (err) | ||
431 | goto out; | ||
432 | |||
433 | /* Checking LinkSpeedActive for FDR-10 */ | ||
434 | if (out_mad->data[15] & 0x1) | ||
435 | props->active_speed = 8; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | out: | ||
440 | kfree(in_mad); | ||
441 | kfree(out_mad); | ||
442 | |||
443 | return err; | ||
444 | } | ||