mad.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. #include <linux/mlx5/cmd.h>
  33. #include <rdma/ib_mad.h>
  34. #include <rdma/ib_smi.h>
  35. #include "mlx5_ib.h"
  36. enum {
  37. MLX5_IB_VENDOR_CLASS1 = 0x9,
  38. MLX5_IB_VENDOR_CLASS2 = 0xa
  39. };
  40. int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
  41. u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
  42. const void *in_mad, void *response_mad)
  43. {
  44. u8 op_modifier = 0;
  45. /* Key check traps can't be generated unless we have in_wc to
  46. * tell us where to send the trap.
  47. */
  48. if (ignore_mkey || !in_wc)
  49. op_modifier |= 0x1;
  50. if (ignore_bkey || !in_wc)
  51. op_modifier |= 0x2;
  52. return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port);
  53. }
  54. int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
  55. const struct ib_wc *in_wc, const struct ib_grh *in_grh,
  56. const struct ib_mad_hdr *in, size_t in_mad_size,
  57. struct ib_mad_hdr *out, size_t *out_mad_size,
  58. u16 *out_mad_pkey_index)
  59. {
  60. u16 slid;
  61. int err;
  62. const struct ib_mad *in_mad = (const struct ib_mad *)in;
  63. struct ib_mad *out_mad = (struct ib_mad *)out;
  64. if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
  65. *out_mad_size != sizeof(*out_mad)))
  66. return IB_MAD_RESULT_FAILURE;
  67. slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
  68. if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0)
  69. return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
  70. if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||
  71. in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
  72. if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET &&
  73. in_mad->mad_hdr.method != IB_MGMT_METHOD_SET &&
  74. in_mad->mad_hdr.method != IB_MGMT_METHOD_TRAP_REPRESS)
  75. return IB_MAD_RESULT_SUCCESS;
  76. /* Don't process SMInfo queries -- the SMA can't handle them.
  77. */
  78. if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
  79. return IB_MAD_RESULT_SUCCESS;
  80. } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
  81. in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS1 ||
  82. in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS2 ||
  83. in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_CONG_MGMT) {
  84. if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET &&
  85. in_mad->mad_hdr.method != IB_MGMT_METHOD_SET)
  86. return IB_MAD_RESULT_SUCCESS;
  87. } else {
  88. return IB_MAD_RESULT_SUCCESS;
  89. }
  90. err = mlx5_MAD_IFC(to_mdev(ibdev),
  91. mad_flags & IB_MAD_IGNORE_MKEY,
  92. mad_flags & IB_MAD_IGNORE_BKEY,
  93. port_num, in_wc, in_grh, in_mad, out_mad);
  94. if (err)
  95. return IB_MAD_RESULT_FAILURE;
  96. /* set return bit in status of directed route responses */
  97. if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
  98. out_mad->mad_hdr.status |= cpu_to_be16(1 << 15);
  99. if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS)
  100. /* no response for trap repress */
  101. return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
  102. return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
  103. }
  104. int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port)
  105. {
  106. struct ib_smp *in_mad = NULL;
  107. struct ib_smp *out_mad = NULL;
  108. int err = -ENOMEM;
  109. u16 packet_error;
  110. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  111. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  112. if (!in_mad || !out_mad)
  113. goto out;
  114. init_query_mad(in_mad);
  115. in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
  116. in_mad->attr_mod = cpu_to_be32(port);
  117. err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
  118. packet_error = be16_to_cpu(out_mad->status);
  119. dev->mdev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ?
  120. MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
  121. out:
  122. kfree(in_mad);
  123. kfree(out_mad);
  124. return err;
  125. }
  126. int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev,
  127. struct ib_smp *out_mad)
  128. {
  129. struct ib_smp *in_mad = NULL;
  130. int err = -ENOMEM;
  131. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  132. if (!in_mad)
  133. return -ENOMEM;
  134. init_query_mad(in_mad);
  135. in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
  136. err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad,
  137. out_mad);
  138. kfree(in_mad);
  139. return err;
  140. }
  141. int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev,
  142. __be64 *sys_image_guid)
  143. {
  144. struct ib_smp *out_mad = NULL;
  145. int err = -ENOMEM;
  146. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  147. if (!out_mad)
  148. return -ENOMEM;
  149. err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
  150. if (err)
  151. goto out;
  152. memcpy(sys_image_guid, out_mad->data + 4, 8);
  153. out:
  154. kfree(out_mad);
  155. return err;
  156. }
  157. int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev,
  158. u16 *max_pkeys)
  159. {
  160. struct ib_smp *out_mad = NULL;
  161. int err = -ENOMEM;
  162. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  163. if (!out_mad)
  164. return -ENOMEM;
  165. err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
  166. if (err)
  167. goto out;
  168. *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28));
  169. out:
  170. kfree(out_mad);
  171. return err;
  172. }
  173. int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev,
  174. u32 *vendor_id)
  175. {
  176. struct ib_smp *out_mad = NULL;
  177. int err = -ENOMEM;
  178. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  179. if (!out_mad)
  180. return -ENOMEM;
  181. err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
  182. if (err)
  183. goto out;
  184. *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff;
  185. out:
  186. kfree(out_mad);
  187. return err;
  188. }
  189. int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
  190. {
  191. struct ib_smp *in_mad = NULL;
  192. struct ib_smp *out_mad = NULL;
  193. int err = -ENOMEM;
  194. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  195. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  196. if (!in_mad || !out_mad)
  197. goto out;
  198. init_query_mad(in_mad);
  199. in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
  200. err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
  201. if (err)
  202. goto out;
  203. memcpy(node_desc, out_mad->data, 64);
  204. out:
  205. kfree(in_mad);
  206. kfree(out_mad);
  207. return err;
  208. }
  209. int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid)
  210. {
  211. struct ib_smp *in_mad = NULL;
  212. struct ib_smp *out_mad = NULL;
  213. int err = -ENOMEM;
  214. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  215. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  216. if (!in_mad || !out_mad)
  217. goto out;
  218. init_query_mad(in_mad);
  219. in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
  220. err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
  221. if (err)
  222. goto out;
  223. memcpy(node_guid, out_mad->data + 12, 8);
  224. out:
  225. kfree(in_mad);
  226. kfree(out_mad);
  227. return err;
  228. }
  229. int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index,
  230. u16 *pkey)
  231. {
  232. struct ib_smp *in_mad = NULL;
  233. struct ib_smp *out_mad = NULL;
  234. int err = -ENOMEM;
  235. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  236. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  237. if (!in_mad || !out_mad)
  238. goto out;
  239. init_query_mad(in_mad);
  240. in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
  241. in_mad->attr_mod = cpu_to_be32(index / 32);
  242. err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
  243. out_mad);
  244. if (err)
  245. goto out;
  246. *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]);
  247. out:
  248. kfree(in_mad);
  249. kfree(out_mad);
  250. return err;
  251. }
  252. int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index,
  253. union ib_gid *gid)
  254. {
  255. struct ib_smp *in_mad = NULL;
  256. struct ib_smp *out_mad = NULL;
  257. int err = -ENOMEM;
  258. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  259. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  260. if (!in_mad || !out_mad)
  261. goto out;
  262. init_query_mad(in_mad);
  263. in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
  264. in_mad->attr_mod = cpu_to_be32(port);
  265. err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
  266. out_mad);
  267. if (err)
  268. goto out;
  269. memcpy(gid->raw, out_mad->data + 8, 8);
  270. init_query_mad(in_mad);
  271. in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
  272. in_mad->attr_mod = cpu_to_be32(index / 8);
  273. err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
  274. out_mad);
  275. if (err)
  276. goto out;
  277. memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
  278. out:
  279. kfree(in_mad);
  280. kfree(out_mad);
  281. return err;
  282. }
  283. int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port,
  284. struct ib_port_attr *props)
  285. {
  286. struct mlx5_ib_dev *dev = to_mdev(ibdev);
  287. struct mlx5_core_dev *mdev = dev->mdev;
  288. struct ib_smp *in_mad = NULL;
  289. struct ib_smp *out_mad = NULL;
  290. int ext_active_speed;
  291. int err = -ENOMEM;
  292. if (port < 1 || port > MLX5_CAP_GEN(mdev, num_ports)) {
  293. mlx5_ib_warn(dev, "invalid port number %d\n", port);
  294. return -EINVAL;
  295. }
  296. in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  297. out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  298. if (!in_mad || !out_mad)
  299. goto out;
  300. memset(props, 0, sizeof(*props));
  301. init_query_mad(in_mad);
  302. in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
  303. in_mad->attr_mod = cpu_to_be32(port);
  304. err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad);
  305. if (err) {
  306. mlx5_ib_warn(dev, "err %d\n", err);
  307. goto out;
  308. }
  309. props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16));
  310. props->lmc = out_mad->data[34] & 0x7;
  311. props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18));
  312. props->sm_sl = out_mad->data[36] & 0xf;
  313. props->state = out_mad->data[32] & 0xf;
  314. props->phys_state = out_mad->data[33] >> 4;
  315. props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20));
  316. props->gid_tbl_len = out_mad->data[50];
  317. props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
  318. props->pkey_tbl_len = mdev->port_caps[port - 1].pkey_table_len;
  319. props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46));
  320. props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48));
  321. props->active_width = out_mad->data[31] & 0xf;
  322. props->active_speed = out_mad->data[35] >> 4;
  323. props->max_mtu = out_mad->data[41] & 0xf;
  324. props->active_mtu = out_mad->data[36] >> 4;
  325. props->subnet_timeout = out_mad->data[51] & 0x1f;
  326. props->max_vl_num = out_mad->data[37] >> 4;
  327. props->init_type_reply = out_mad->data[41] >> 4;
  328. /* Check if extended speeds (EDR/FDR/...) are supported */
  329. if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
  330. ext_active_speed = out_mad->data[62] >> 4;
  331. switch (ext_active_speed) {
  332. case 1:
  333. props->active_speed = 16; /* FDR */
  334. break;
  335. case 2:
  336. props->active_speed = 32; /* EDR */
  337. break;
  338. }
  339. }
  340. /* If reported active speed is QDR, check if is FDR-10 */
  341. if (props->active_speed == 4) {
  342. if (mdev->port_caps[port - 1].ext_port_cap &
  343. MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
  344. init_query_mad(in_mad);
  345. in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
  346. in_mad->attr_mod = cpu_to_be32(port);
  347. err = mlx5_MAD_IFC(dev, 1, 1, port,
  348. NULL, NULL, in_mad, out_mad);
  349. if (err)
  350. goto out;
  351. /* Checking LinkSpeedActive for FDR-10 */
  352. if (out_mad->data[15] & 0x1)
  353. props->active_speed = 8;
  354. }
  355. }
  356. out:
  357. kfree(in_mad);
  358. kfree(out_mad);
  359. return err;
  360. }