port.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*
  2. * Copyright (c) 2007 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/errno.h>
  33. #include <linux/if_ether.h>
  34. #include <linux/mlx4/cmd.h>
  35. #include "mlx4.h"
  36. #define MLX4_MAC_VALID (1ull << 63)
  37. #define MLX4_MAC_MASK 0xffffffffffffULL
  38. #define MLX4_VLAN_VALID (1u << 31)
  39. #define MLX4_VLAN_MASK 0xfff
  40. void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
  41. {
  42. int i;
  43. mutex_init(&table->mutex);
  44. for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
  45. table->entries[i] = 0;
  46. table->refs[i] = 0;
  47. }
  48. table->max = 1 << dev->caps.log_num_macs;
  49. table->total = 0;
  50. }
  51. void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
  52. {
  53. int i;
  54. mutex_init(&table->mutex);
  55. for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
  56. table->entries[i] = 0;
  57. table->refs[i] = 0;
  58. }
  59. table->max = 1 << dev->caps.log_num_vlans;
  60. table->total = 0;
  61. }
  62. static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
  63. __be64 *entries)
  64. {
  65. struct mlx4_cmd_mailbox *mailbox;
  66. u32 in_mod;
  67. int err;
  68. mailbox = mlx4_alloc_cmd_mailbox(dev);
  69. if (IS_ERR(mailbox))
  70. return PTR_ERR(mailbox);
  71. memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE);
  72. in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port;
  73. err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
  74. MLX4_CMD_TIME_CLASS_B);
  75. mlx4_free_cmd_mailbox(dev, mailbox);
  76. return err;
  77. }
  78. static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port,
  79. u64 mac, int *qpn, u8 reserve)
  80. {
  81. struct mlx4_qp qp;
  82. u8 gid[16] = {0};
  83. int err;
  84. if (reserve) {
  85. err = mlx4_qp_reserve_range(dev, 1, 1, qpn);
  86. if (err) {
  87. mlx4_err(dev, "Failed to reserve qp for mac registration\n");
  88. return err;
  89. }
  90. }
  91. qp.qpn = *qpn;
  92. mac &= 0xffffffffffffULL;
  93. mac = cpu_to_be64(mac << 16);
  94. memcpy(&gid[10], &mac, ETH_ALEN);
  95. gid[5] = port;
  96. gid[7] = MLX4_UC_STEER << 1;
  97. err = mlx4_qp_attach_common(dev, &qp, gid, 0,
  98. MLX4_PROT_ETH, MLX4_UC_STEER);
  99. if (err && reserve)
  100. mlx4_qp_release_range(dev, *qpn, 1);
  101. return err;
  102. }
  103. static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port,
  104. u64 mac, int qpn, u8 free)
  105. {
  106. struct mlx4_qp qp;
  107. u8 gid[16] = {0};
  108. qp.qpn = qpn;
  109. mac &= 0xffffffffffffULL;
  110. mac = cpu_to_be64(mac << 16);
  111. memcpy(&gid[10], &mac, ETH_ALEN);
  112. gid[5] = port;
  113. gid[7] = MLX4_UC_STEER << 1;
  114. mlx4_qp_detach_common(dev, &qp, gid, MLX4_PROT_ETH, MLX4_UC_STEER);
  115. if (free)
  116. mlx4_qp_release_range(dev, qpn, 1);
  117. }
  118. int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
  119. {
  120. struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
  121. struct mlx4_mac_table *table = &info->mac_table;
  122. struct mlx4_mac_entry *entry;
  123. int i, err = 0;
  124. int free = -1;
  125. if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
  126. err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
  127. if (!err) {
  128. entry = kmalloc(sizeof *entry, GFP_KERNEL);
  129. if (!entry) {
  130. mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
  131. return -ENOMEM;
  132. }
  133. entry->mac = mac;
  134. err = radix_tree_insert(&info->mac_tree, *qpn, entry);
  135. if (err) {
  136. mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
  137. return err;
  138. }
  139. } else
  140. return err;
  141. }
  142. mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
  143. mutex_lock(&table->mutex);
  144. for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
  145. if (free < 0 && !table->refs[i]) {
  146. free = i;
  147. continue;
  148. }
  149. if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
  150. /* MAC already registered, increase references count */
  151. ++table->refs[i];
  152. goto out;
  153. }
  154. }
  155. if (free < 0) {
  156. err = -ENOMEM;
  157. goto out;
  158. }
  159. mlx4_dbg(dev, "Free MAC index is %d\n", free);
  160. if (table->total == table->max) {
  161. /* No free mac entries */
  162. err = -ENOSPC;
  163. goto out;
  164. }
  165. /* Register new MAC */
  166. table->refs[free] = 1;
  167. table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID);
  168. err = mlx4_set_port_mac_table(dev, port, table->entries);
  169. if (unlikely(err)) {
  170. mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac);
  171. table->refs[free] = 0;
  172. table->entries[free] = 0;
  173. goto out;
  174. }
  175. if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
  176. *qpn = info->base_qpn + free;
  177. ++table->total;
  178. out:
  179. mutex_unlock(&table->mutex);
  180. return err;
  181. }
  182. EXPORT_SYMBOL_GPL(mlx4_register_mac);
  183. static int validate_index(struct mlx4_dev *dev,
  184. struct mlx4_mac_table *table, int index)
  185. {
  186. int err = 0;
  187. if (index < 0 || index >= table->max || !table->entries[index]) {
  188. mlx4_warn(dev, "No valid Mac entry for the given index\n");
  189. err = -EINVAL;
  190. }
  191. return err;
  192. }
  193. static int find_index(struct mlx4_dev *dev,
  194. struct mlx4_mac_table *table, u64 mac)
  195. {
  196. int i;
  197. for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
  198. if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i])))
  199. return i;
  200. }
  201. /* Mac not found */
  202. return -EINVAL;
  203. }
  204. void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
  205. {
  206. struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
  207. struct mlx4_mac_table *table = &info->mac_table;
  208. int index = qpn - info->base_qpn;
  209. struct mlx4_mac_entry *entry;
  210. if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
  211. entry = radix_tree_lookup(&info->mac_tree, qpn);
  212. if (entry) {
  213. mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1);
  214. radix_tree_delete(&info->mac_tree, qpn);
  215. index = find_index(dev, table, entry->mac);
  216. kfree(entry);
  217. }
  218. }
  219. mutex_lock(&table->mutex);
  220. if (validate_index(dev, table, index))
  221. goto out;
  222. /* Check whether this address has reference count */
  223. if (!(--table->refs[index])) {
  224. table->entries[index] = 0;
  225. mlx4_set_port_mac_table(dev, port, table->entries);
  226. --table->total;
  227. }
  228. out:
  229. mutex_unlock(&table->mutex);
  230. }
  231. EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
  232. int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap)
  233. {
  234. struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
  235. struct mlx4_mac_table *table = &info->mac_table;
  236. int index = qpn - info->base_qpn;
  237. struct mlx4_mac_entry *entry;
  238. int err;
  239. if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
  240. entry = radix_tree_lookup(&info->mac_tree, qpn);
  241. if (!entry)
  242. return -EINVAL;
  243. index = find_index(dev, table, entry->mac);
  244. mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0);
  245. entry->mac = new_mac;
  246. err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0);
  247. if (err || index < 0)
  248. return err;
  249. }
  250. mutex_lock(&table->mutex);
  251. err = validate_index(dev, table, index);
  252. if (err)
  253. goto out;
  254. table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID);
  255. err = mlx4_set_port_mac_table(dev, port, table->entries);
  256. if (unlikely(err)) {
  257. mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac);
  258. table->entries[index] = 0;
  259. }
  260. out:
  261. mutex_unlock(&table->mutex);
  262. return err;
  263. }
  264. EXPORT_SYMBOL_GPL(mlx4_replace_mac);
  265. static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
  266. __be32 *entries)
  267. {
  268. struct mlx4_cmd_mailbox *mailbox;
  269. u32 in_mod;
  270. int err;
  271. mailbox = mlx4_alloc_cmd_mailbox(dev);
  272. if (IS_ERR(mailbox))
  273. return PTR_ERR(mailbox);
  274. memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE);
  275. in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port;
  276. err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
  277. MLX4_CMD_TIME_CLASS_B);
  278. mlx4_free_cmd_mailbox(dev, mailbox);
  279. return err;
  280. }
  281. int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
  282. {
  283. struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
  284. int i;
  285. for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) {
  286. if (table->refs[i] &&
  287. (vid == (MLX4_VLAN_MASK &
  288. be32_to_cpu(table->entries[i])))) {
  289. /* VLAN already registered, increase reference count */
  290. *idx = i;
  291. return 0;
  292. }
  293. }
  294. return -ENOENT;
  295. }
  296. EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
  297. int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
  298. {
  299. struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
  300. int i, err = 0;
  301. int free = -1;
  302. mutex_lock(&table->mutex);
  303. for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
  304. if (free < 0 && (table->refs[i] == 0)) {
  305. free = i;
  306. continue;
  307. }
  308. if (table->refs[i] &&
  309. (vlan == (MLX4_VLAN_MASK &
  310. be32_to_cpu(table->entries[i])))) {
  311. /* Vlan already registered, increase references count */
  312. *index = i;
  313. ++table->refs[i];
  314. goto out;
  315. }
  316. }
  317. if (free < 0) {
  318. err = -ENOMEM;
  319. goto out;
  320. }
  321. if (table->total == table->max) {
  322. /* No free vlan entries */
  323. err = -ENOSPC;
  324. goto out;
  325. }
  326. /* Register new MAC */
  327. table->refs[free] = 1;
  328. table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
  329. err = mlx4_set_port_vlan_table(dev, port, table->entries);
  330. if (unlikely(err)) {
  331. mlx4_warn(dev, "Failed adding vlan: %u\n", vlan);
  332. table->refs[free] = 0;
  333. table->entries[free] = 0;
  334. goto out;
  335. }
  336. *index = free;
  337. ++table->total;
  338. out:
  339. mutex_unlock(&table->mutex);
  340. return err;
  341. }
  342. EXPORT_SYMBOL_GPL(mlx4_register_vlan);
  343. void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
  344. {
  345. struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
  346. if (index < MLX4_VLAN_REGULAR) {
  347. mlx4_warn(dev, "Trying to free special vlan index %d\n", index);
  348. return;
  349. }
  350. mutex_lock(&table->mutex);
  351. if (!table->refs[index]) {
  352. mlx4_warn(dev, "No vlan entry for index %d\n", index);
  353. goto out;
  354. }
  355. if (--table->refs[index]) {
  356. mlx4_dbg(dev, "Have more references for index %d,"
  357. "no need to modify vlan table\n", index);
  358. goto out;
  359. }
  360. table->entries[index] = 0;
  361. mlx4_set_port_vlan_table(dev, port, table->entries);
  362. --table->total;
  363. out:
  364. mutex_unlock(&table->mutex);
  365. }
  366. EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
  367. int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
  368. {
  369. struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
  370. u8 *inbuf, *outbuf;
  371. int err;
  372. inmailbox = mlx4_alloc_cmd_mailbox(dev);
  373. if (IS_ERR(inmailbox))
  374. return PTR_ERR(inmailbox);
  375. outmailbox = mlx4_alloc_cmd_mailbox(dev);
  376. if (IS_ERR(outmailbox)) {
  377. mlx4_free_cmd_mailbox(dev, inmailbox);
  378. return PTR_ERR(outmailbox);
  379. }
  380. inbuf = inmailbox->buf;
  381. outbuf = outmailbox->buf;
  382. memset(inbuf, 0, 256);
  383. memset(outbuf, 0, 256);
  384. inbuf[0] = 1;
  385. inbuf[1] = 1;
  386. inbuf[2] = 1;
  387. inbuf[3] = 1;
  388. *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015);
  389. *(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
  390. err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
  391. MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C);
  392. if (!err)
  393. *caps = *(__be32 *) (outbuf + 84);
  394. mlx4_free_cmd_mailbox(dev, inmailbox);
  395. mlx4_free_cmd_mailbox(dev, outmailbox);
  396. return err;
  397. }
  398. int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
  399. {
  400. struct mlx4_cmd_mailbox *mailbox;
  401. int err;
  402. if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
  403. return 0;
  404. mailbox = mlx4_alloc_cmd_mailbox(dev);
  405. if (IS_ERR(mailbox))
  406. return PTR_ERR(mailbox);
  407. memset(mailbox->buf, 0, 256);
  408. ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
  409. err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
  410. MLX4_CMD_TIME_CLASS_B);
  411. mlx4_free_cmd_mailbox(dev, mailbox);
  412. return err;
  413. }