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