15a2cc190SJeff Kirsher /* 25a2cc190SJeff Kirsher * Copyright (c) 2007 Mellanox Technologies. All rights reserved. 35a2cc190SJeff Kirsher * 45a2cc190SJeff Kirsher * This software is available to you under a choice of one of two 55a2cc190SJeff Kirsher * licenses. You may choose to be licensed under the terms of the GNU 65a2cc190SJeff Kirsher * General Public License (GPL) Version 2, available from the file 75a2cc190SJeff Kirsher * COPYING in the main directory of this source tree, or the 85a2cc190SJeff Kirsher * OpenIB.org BSD license below: 95a2cc190SJeff Kirsher * 105a2cc190SJeff Kirsher * Redistribution and use in source and binary forms, with or 115a2cc190SJeff Kirsher * without modification, are permitted provided that the following 125a2cc190SJeff Kirsher * conditions are met: 135a2cc190SJeff Kirsher * 145a2cc190SJeff Kirsher * - Redistributions of source code must retain the above 155a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 165a2cc190SJeff Kirsher * disclaimer. 175a2cc190SJeff Kirsher * 185a2cc190SJeff Kirsher * - Redistributions in binary form must reproduce the above 195a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 205a2cc190SJeff Kirsher * disclaimer in the documentation and/or other materials 215a2cc190SJeff Kirsher * provided with the distribution. 225a2cc190SJeff Kirsher * 235a2cc190SJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 245a2cc190SJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 255a2cc190SJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 265a2cc190SJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 275a2cc190SJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 285a2cc190SJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 295a2cc190SJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 305a2cc190SJeff Kirsher * SOFTWARE. 315a2cc190SJeff Kirsher */ 325a2cc190SJeff Kirsher 335a2cc190SJeff Kirsher #include <linux/errno.h> 345a2cc190SJeff Kirsher #include <linux/if_ether.h> 35ee40fa06SPaul Gortmaker #include <linux/export.h> 365a2cc190SJeff Kirsher 375a2cc190SJeff Kirsher #include <linux/mlx4/cmd.h> 385a2cc190SJeff Kirsher 395a2cc190SJeff Kirsher #include "mlx4.h" 405a2cc190SJeff Kirsher 415a2cc190SJeff Kirsher #define MLX4_MAC_VALID (1ull << 63) 425a2cc190SJeff Kirsher #define MLX4_MAC_MASK 0xffffffffffffULL 435a2cc190SJeff Kirsher 445a2cc190SJeff Kirsher #define MLX4_VLAN_VALID (1u << 31) 455a2cc190SJeff Kirsher #define MLX4_VLAN_MASK 0xfff 465a2cc190SJeff Kirsher 475a2cc190SJeff Kirsher void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table) 485a2cc190SJeff Kirsher { 495a2cc190SJeff Kirsher int i; 505a2cc190SJeff Kirsher 515a2cc190SJeff Kirsher mutex_init(&table->mutex); 525a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 535a2cc190SJeff Kirsher table->entries[i] = 0; 545a2cc190SJeff Kirsher table->refs[i] = 0; 555a2cc190SJeff Kirsher } 565a2cc190SJeff Kirsher table->max = 1 << dev->caps.log_num_macs; 575a2cc190SJeff Kirsher table->total = 0; 585a2cc190SJeff Kirsher } 595a2cc190SJeff Kirsher 605a2cc190SJeff Kirsher void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) 615a2cc190SJeff Kirsher { 625a2cc190SJeff Kirsher int i; 635a2cc190SJeff Kirsher 645a2cc190SJeff Kirsher mutex_init(&table->mutex); 655a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) { 665a2cc190SJeff Kirsher table->entries[i] = 0; 675a2cc190SJeff Kirsher table->refs[i] = 0; 685a2cc190SJeff Kirsher } 69e72ebf5aSYevgeny Petrilin table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR; 705a2cc190SJeff Kirsher table->total = 0; 715a2cc190SJeff Kirsher } 725a2cc190SJeff Kirsher 73ffe455adSEugenia Emantayev static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) 745a2cc190SJeff Kirsher { 755a2cc190SJeff Kirsher struct mlx4_qp qp; 765a2cc190SJeff Kirsher u8 gid[16] = {0}; 775a2cc190SJeff Kirsher int err; 785a2cc190SJeff Kirsher 795a2cc190SJeff Kirsher qp.qpn = *qpn; 805a2cc190SJeff Kirsher 815a2cc190SJeff Kirsher mac &= 0xffffffffffffULL; 825a2cc190SJeff Kirsher mac = cpu_to_be64(mac << 16); 835a2cc190SJeff Kirsher memcpy(&gid[10], &mac, ETH_ALEN); 845a2cc190SJeff Kirsher gid[5] = port; 855a2cc190SJeff Kirsher gid[7] = MLX4_UC_STEER << 1; 865a2cc190SJeff Kirsher 87ffe455adSEugenia Emantayev err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); 88ffe455adSEugenia Emantayev if (err) 89ffe455adSEugenia Emantayev mlx4_warn(dev, "Failed Attaching Unicast\n"); 905a2cc190SJeff Kirsher 915a2cc190SJeff Kirsher return err; 925a2cc190SJeff Kirsher } 935a2cc190SJeff Kirsher 945a2cc190SJeff Kirsher static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, 95ffe455adSEugenia Emantayev u64 mac, int qpn) 965a2cc190SJeff Kirsher { 975a2cc190SJeff Kirsher struct mlx4_qp qp; 985a2cc190SJeff Kirsher u8 gid[16] = {0}; 995a2cc190SJeff Kirsher 1005a2cc190SJeff Kirsher qp.qpn = qpn; 1015a2cc190SJeff Kirsher mac &= 0xffffffffffffULL; 1025a2cc190SJeff Kirsher mac = cpu_to_be64(mac << 16); 1035a2cc190SJeff Kirsher memcpy(&gid[10], &mac, ETH_ALEN); 1045a2cc190SJeff Kirsher gid[5] = port; 1055a2cc190SJeff Kirsher gid[7] = MLX4_UC_STEER << 1; 1065a2cc190SJeff Kirsher 107ffe455adSEugenia Emantayev mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); 1085a2cc190SJeff Kirsher } 1095a2cc190SJeff Kirsher 1105a2cc190SJeff Kirsher static int validate_index(struct mlx4_dev *dev, 1115a2cc190SJeff Kirsher struct mlx4_mac_table *table, int index) 1125a2cc190SJeff Kirsher { 1135a2cc190SJeff Kirsher int err = 0; 1145a2cc190SJeff Kirsher 1155a2cc190SJeff Kirsher if (index < 0 || index >= table->max || !table->entries[index]) { 1165a2cc190SJeff Kirsher mlx4_warn(dev, "No valid Mac entry for the given index\n"); 1175a2cc190SJeff Kirsher err = -EINVAL; 1185a2cc190SJeff Kirsher } 1195a2cc190SJeff Kirsher return err; 1205a2cc190SJeff Kirsher } 1215a2cc190SJeff Kirsher 1225a2cc190SJeff Kirsher static int find_index(struct mlx4_dev *dev, 1235a2cc190SJeff Kirsher struct mlx4_mac_table *table, u64 mac) 1245a2cc190SJeff Kirsher { 1255a2cc190SJeff Kirsher int i; 126ffe455adSEugenia Emantayev 1275a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 128ffe455adSEugenia Emantayev if ((mac & MLX4_MAC_MASK) == 129ffe455adSEugenia Emantayev (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) 1305a2cc190SJeff Kirsher return i; 1315a2cc190SJeff Kirsher } 1325a2cc190SJeff Kirsher /* Mac not found */ 1335a2cc190SJeff Kirsher return -EINVAL; 1345a2cc190SJeff Kirsher } 1355a2cc190SJeff Kirsher 136ffe455adSEugenia Emantayev int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) 1375a2cc190SJeff Kirsher { 1385a2cc190SJeff Kirsher struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 1395a2cc190SJeff Kirsher struct mlx4_mac_entry *entry; 140ffe455adSEugenia Emantayev int index = 0; 141ffe455adSEugenia Emantayev int err = 0; 142ffe455adSEugenia Emantayev 143ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n", 144ffe455adSEugenia Emantayev (unsigned long long) mac); 145ffe455adSEugenia Emantayev index = mlx4_register_mac(dev, port, mac); 146ffe455adSEugenia Emantayev if (index < 0) { 147ffe455adSEugenia Emantayev err = index; 148ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 149ffe455adSEugenia Emantayev (unsigned long long) mac); 150ffe455adSEugenia Emantayev return err; 151ffe455adSEugenia Emantayev } 152ffe455adSEugenia Emantayev 153ffe455adSEugenia Emantayev if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) { 154ffe455adSEugenia Emantayev *qpn = info->base_qpn + index; 155ffe455adSEugenia Emantayev return 0; 156ffe455adSEugenia Emantayev } 157ffe455adSEugenia Emantayev 158ffe455adSEugenia Emantayev err = mlx4_qp_reserve_range(dev, 1, 1, qpn); 159ffe455adSEugenia Emantayev mlx4_dbg(dev, "Reserved qp %d\n", *qpn); 160ffe455adSEugenia Emantayev if (err) { 161ffe455adSEugenia Emantayev mlx4_err(dev, "Failed to reserve qp for mac registration\n"); 162ffe455adSEugenia Emantayev goto qp_err; 163ffe455adSEugenia Emantayev } 164ffe455adSEugenia Emantayev 165ffe455adSEugenia Emantayev err = mlx4_uc_steer_add(dev, port, mac, qpn); 166ffe455adSEugenia Emantayev if (err) 167ffe455adSEugenia Emantayev goto steer_err; 168ffe455adSEugenia Emantayev 169ffe455adSEugenia Emantayev entry = kmalloc(sizeof *entry, GFP_KERNEL); 170ffe455adSEugenia Emantayev if (!entry) { 171ffe455adSEugenia Emantayev err = -ENOMEM; 172ffe455adSEugenia Emantayev goto alloc_err; 173ffe455adSEugenia Emantayev } 174ffe455adSEugenia Emantayev entry->mac = mac; 175ffe455adSEugenia Emantayev err = radix_tree_insert(&info->mac_tree, *qpn, entry); 176ffe455adSEugenia Emantayev if (err) 177ffe455adSEugenia Emantayev goto insert_err; 178ffe455adSEugenia Emantayev return 0; 179ffe455adSEugenia Emantayev 180ffe455adSEugenia Emantayev insert_err: 181ffe455adSEugenia Emantayev kfree(entry); 182ffe455adSEugenia Emantayev 183ffe455adSEugenia Emantayev alloc_err: 184ffe455adSEugenia Emantayev mlx4_uc_steer_release(dev, port, mac, *qpn); 185ffe455adSEugenia Emantayev 186ffe455adSEugenia Emantayev steer_err: 187ffe455adSEugenia Emantayev mlx4_qp_release_range(dev, *qpn, 1); 188ffe455adSEugenia Emantayev 189ffe455adSEugenia Emantayev qp_err: 190ffe455adSEugenia Emantayev mlx4_unregister_mac(dev, port, mac); 191ffe455adSEugenia Emantayev return err; 192ffe455adSEugenia Emantayev } 193ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_get_eth_qp); 194ffe455adSEugenia Emantayev 195ffe455adSEugenia Emantayev void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn) 196ffe455adSEugenia Emantayev { 197ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 198ffe455adSEugenia Emantayev struct mlx4_mac_entry *entry; 199ffe455adSEugenia Emantayev 200ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for deleting\n", 201ffe455adSEugenia Emantayev (unsigned long long) mac); 202ffe455adSEugenia Emantayev mlx4_unregister_mac(dev, port, mac); 2035a2cc190SJeff Kirsher 2045a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { 2055a2cc190SJeff Kirsher entry = radix_tree_lookup(&info->mac_tree, qpn); 2065a2cc190SJeff Kirsher if (entry) { 207ffe455adSEugenia Emantayev mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," 208ffe455adSEugenia Emantayev " qpn %d\n", port, 209ffe455adSEugenia Emantayev (unsigned long long) mac, qpn); 210ffe455adSEugenia Emantayev mlx4_uc_steer_release(dev, port, entry->mac, qpn); 211ffe455adSEugenia Emantayev mlx4_qp_release_range(dev, qpn, 1); 2125a2cc190SJeff Kirsher radix_tree_delete(&info->mac_tree, qpn); 2135a2cc190SJeff Kirsher kfree(entry); 2145a2cc190SJeff Kirsher } 2155a2cc190SJeff Kirsher } 216ffe455adSEugenia Emantayev } 217ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_put_eth_qp); 218ffe455adSEugenia Emantayev 219ffe455adSEugenia Emantayev static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, 220ffe455adSEugenia Emantayev __be64 *entries) 221ffe455adSEugenia Emantayev { 222ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 223ffe455adSEugenia Emantayev u32 in_mod; 224ffe455adSEugenia Emantayev int err; 225ffe455adSEugenia Emantayev 226ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 227ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 228ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 229ffe455adSEugenia Emantayev 230ffe455adSEugenia Emantayev memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); 231ffe455adSEugenia Emantayev 232ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; 233ffe455adSEugenia Emantayev 234ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 235ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 236ffe455adSEugenia Emantayev 237ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 238ffe455adSEugenia Emantayev return err; 239ffe455adSEugenia Emantayev } 240ffe455adSEugenia Emantayev 241ffe455adSEugenia Emantayev int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 242ffe455adSEugenia Emantayev { 243ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 244ffe455adSEugenia Emantayev struct mlx4_mac_table *table = &info->mac_table; 245ffe455adSEugenia Emantayev int i, err = 0; 246ffe455adSEugenia Emantayev int free = -1; 247ffe455adSEugenia Emantayev 248ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", 249ffe455adSEugenia Emantayev (unsigned long long) mac, port); 250ffe455adSEugenia Emantayev 251ffe455adSEugenia Emantayev mutex_lock(&table->mutex); 252ffe455adSEugenia Emantayev for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 253ffe455adSEugenia Emantayev if (free < 0 && !table->entries[i]) { 254ffe455adSEugenia Emantayev free = i; 255ffe455adSEugenia Emantayev continue; 256ffe455adSEugenia Emantayev } 257ffe455adSEugenia Emantayev 258ffe455adSEugenia Emantayev if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 259ffe455adSEugenia Emantayev /* MAC already registered, Must not have duplicates */ 260ffe455adSEugenia Emantayev err = -EEXIST; 261ffe455adSEugenia Emantayev goto out; 262ffe455adSEugenia Emantayev } 263ffe455adSEugenia Emantayev } 264ffe455adSEugenia Emantayev 265ffe455adSEugenia Emantayev mlx4_dbg(dev, "Free MAC index is %d\n", free); 266ffe455adSEugenia Emantayev 267ffe455adSEugenia Emantayev if (table->total == table->max) { 268ffe455adSEugenia Emantayev /* No free mac entries */ 269ffe455adSEugenia Emantayev err = -ENOSPC; 270ffe455adSEugenia Emantayev goto out; 271ffe455adSEugenia Emantayev } 272ffe455adSEugenia Emantayev 273ffe455adSEugenia Emantayev /* Register new MAC */ 274ffe455adSEugenia Emantayev table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); 275ffe455adSEugenia Emantayev 276ffe455adSEugenia Emantayev err = mlx4_set_port_mac_table(dev, port, table->entries); 277ffe455adSEugenia Emantayev if (unlikely(err)) { 278ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 279ffe455adSEugenia Emantayev (unsigned long long) mac); 280ffe455adSEugenia Emantayev table->entries[free] = 0; 281ffe455adSEugenia Emantayev goto out; 282ffe455adSEugenia Emantayev } 283ffe455adSEugenia Emantayev 284ffe455adSEugenia Emantayev err = free; 285ffe455adSEugenia Emantayev ++table->total; 286ffe455adSEugenia Emantayev out: 287ffe455adSEugenia Emantayev mutex_unlock(&table->mutex); 288ffe455adSEugenia Emantayev return err; 289ffe455adSEugenia Emantayev } 290ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(__mlx4_register_mac); 291ffe455adSEugenia Emantayev 292ffe455adSEugenia Emantayev int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 293ffe455adSEugenia Emantayev { 294ffe455adSEugenia Emantayev u64 out_param; 295ffe455adSEugenia Emantayev int err; 296ffe455adSEugenia Emantayev 297ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 298ffe455adSEugenia Emantayev set_param_l(&out_param, port); 299ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 300ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 301ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 302ffe455adSEugenia Emantayev if (err) 303ffe455adSEugenia Emantayev return err; 304ffe455adSEugenia Emantayev 305ffe455adSEugenia Emantayev return get_param_l(&out_param); 306ffe455adSEugenia Emantayev } 307ffe455adSEugenia Emantayev return __mlx4_register_mac(dev, port, mac); 308ffe455adSEugenia Emantayev } 309ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_register_mac); 310ffe455adSEugenia Emantayev 311ffe455adSEugenia Emantayev 312ffe455adSEugenia Emantayev void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 313ffe455adSEugenia Emantayev { 314ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 315ffe455adSEugenia Emantayev struct mlx4_mac_table *table = &info->mac_table; 316ffe455adSEugenia Emantayev int index; 317ffe455adSEugenia Emantayev 318ffe455adSEugenia Emantayev index = find_index(dev, table, mac); 3195a2cc190SJeff Kirsher 3205a2cc190SJeff Kirsher mutex_lock(&table->mutex); 3215a2cc190SJeff Kirsher 3225a2cc190SJeff Kirsher if (validate_index(dev, table, index)) 3235a2cc190SJeff Kirsher goto out; 3245a2cc190SJeff Kirsher 3255a2cc190SJeff Kirsher table->entries[index] = 0; 3265a2cc190SJeff Kirsher mlx4_set_port_mac_table(dev, port, table->entries); 3275a2cc190SJeff Kirsher --table->total; 3285a2cc190SJeff Kirsher out: 3295a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 3305a2cc190SJeff Kirsher } 331ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); 332ffe455adSEugenia Emantayev 333ffe455adSEugenia Emantayev void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 334ffe455adSEugenia Emantayev { 335ffe455adSEugenia Emantayev u64 out_param; 336ffe455adSEugenia Emantayev int err; 337ffe455adSEugenia Emantayev 338ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 339ffe455adSEugenia Emantayev set_param_l(&out_param, port); 340ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 341ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, 342ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 343ffe455adSEugenia Emantayev return; 344ffe455adSEugenia Emantayev } 345ffe455adSEugenia Emantayev __mlx4_unregister_mac(dev, port, mac); 346ffe455adSEugenia Emantayev return; 347ffe455adSEugenia Emantayev } 3485a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_unregister_mac); 3495a2cc190SJeff Kirsher 350ffe455adSEugenia Emantayev int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) 3515a2cc190SJeff Kirsher { 3525a2cc190SJeff Kirsher struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 3535a2cc190SJeff Kirsher struct mlx4_mac_table *table = &info->mac_table; 3545a2cc190SJeff Kirsher struct mlx4_mac_entry *entry; 355ffe455adSEugenia Emantayev int index = qpn - info->base_qpn; 356ffe455adSEugenia Emantayev int err = 0; 3575a2cc190SJeff Kirsher 3585a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { 3595a2cc190SJeff Kirsher entry = radix_tree_lookup(&info->mac_tree, qpn); 3605a2cc190SJeff Kirsher if (!entry) 3615a2cc190SJeff Kirsher return -EINVAL; 362ffe455adSEugenia Emantayev mlx4_uc_steer_release(dev, port, entry->mac, qpn); 363ffe455adSEugenia Emantayev mlx4_unregister_mac(dev, port, entry->mac); 3645a2cc190SJeff Kirsher entry->mac = new_mac; 365ffe455adSEugenia Emantayev mlx4_register_mac(dev, port, new_mac); 366ffe455adSEugenia Emantayev err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn); 3675a2cc190SJeff Kirsher return err; 3685a2cc190SJeff Kirsher } 3695a2cc190SJeff Kirsher 370ffe455adSEugenia Emantayev /* CX1 doesn't support multi-functions */ 3715a2cc190SJeff Kirsher mutex_lock(&table->mutex); 3725a2cc190SJeff Kirsher 3735a2cc190SJeff Kirsher err = validate_index(dev, table, index); 3745a2cc190SJeff Kirsher if (err) 3755a2cc190SJeff Kirsher goto out; 3765a2cc190SJeff Kirsher 3775a2cc190SJeff Kirsher table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID); 3785a2cc190SJeff Kirsher 3795a2cc190SJeff Kirsher err = mlx4_set_port_mac_table(dev, port, table->entries); 3805a2cc190SJeff Kirsher if (unlikely(err)) { 381ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 382ffe455adSEugenia Emantayev (unsigned long long) new_mac); 3835a2cc190SJeff Kirsher table->entries[index] = 0; 3845a2cc190SJeff Kirsher } 3855a2cc190SJeff Kirsher out: 3865a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 3875a2cc190SJeff Kirsher return err; 3885a2cc190SJeff Kirsher } 3895a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_replace_mac); 390ffe455adSEugenia Emantayev 3915a2cc190SJeff Kirsher static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, 3925a2cc190SJeff Kirsher __be32 *entries) 3935a2cc190SJeff Kirsher { 3945a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 3955a2cc190SJeff Kirsher u32 in_mod; 3965a2cc190SJeff Kirsher int err; 3975a2cc190SJeff Kirsher 3985a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 3995a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 4005a2cc190SJeff Kirsher return PTR_ERR(mailbox); 4015a2cc190SJeff Kirsher 4025a2cc190SJeff Kirsher memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); 4035a2cc190SJeff Kirsher in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; 4045a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 405f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 4065a2cc190SJeff Kirsher 4075a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 4085a2cc190SJeff Kirsher 4095a2cc190SJeff Kirsher return err; 4105a2cc190SJeff Kirsher } 4115a2cc190SJeff Kirsher 4125a2cc190SJeff Kirsher int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) 4135a2cc190SJeff Kirsher { 4145a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 4155a2cc190SJeff Kirsher int i; 4165a2cc190SJeff Kirsher 4175a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) { 4185a2cc190SJeff Kirsher if (table->refs[i] && 4195a2cc190SJeff Kirsher (vid == (MLX4_VLAN_MASK & 4205a2cc190SJeff Kirsher be32_to_cpu(table->entries[i])))) { 4215a2cc190SJeff Kirsher /* VLAN already registered, increase reference count */ 4225a2cc190SJeff Kirsher *idx = i; 4235a2cc190SJeff Kirsher return 0; 4245a2cc190SJeff Kirsher } 4255a2cc190SJeff Kirsher } 4265a2cc190SJeff Kirsher 4275a2cc190SJeff Kirsher return -ENOENT; 4285a2cc190SJeff Kirsher } 4295a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); 4305a2cc190SJeff Kirsher 431ffe455adSEugenia Emantayev static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, 432ffe455adSEugenia Emantayev int *index) 4335a2cc190SJeff Kirsher { 4345a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 4355a2cc190SJeff Kirsher int i, err = 0; 4365a2cc190SJeff Kirsher int free = -1; 4375a2cc190SJeff Kirsher 4385a2cc190SJeff Kirsher mutex_lock(&table->mutex); 439e72ebf5aSYevgeny Petrilin 440e72ebf5aSYevgeny Petrilin if (table->total == table->max) { 441e72ebf5aSYevgeny Petrilin /* No free vlan entries */ 442e72ebf5aSYevgeny Petrilin err = -ENOSPC; 443e72ebf5aSYevgeny Petrilin goto out; 444e72ebf5aSYevgeny Petrilin } 445e72ebf5aSYevgeny Petrilin 4465a2cc190SJeff Kirsher for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { 4475a2cc190SJeff Kirsher if (free < 0 && (table->refs[i] == 0)) { 4485a2cc190SJeff Kirsher free = i; 4495a2cc190SJeff Kirsher continue; 4505a2cc190SJeff Kirsher } 4515a2cc190SJeff Kirsher 4525a2cc190SJeff Kirsher if (table->refs[i] && 4535a2cc190SJeff Kirsher (vlan == (MLX4_VLAN_MASK & 4545a2cc190SJeff Kirsher be32_to_cpu(table->entries[i])))) { 4555a2cc190SJeff Kirsher /* Vlan already registered, increase references count */ 4565a2cc190SJeff Kirsher *index = i; 4575a2cc190SJeff Kirsher ++table->refs[i]; 4585a2cc190SJeff Kirsher goto out; 4595a2cc190SJeff Kirsher } 4605a2cc190SJeff Kirsher } 4615a2cc190SJeff Kirsher 4625a2cc190SJeff Kirsher if (free < 0) { 4635a2cc190SJeff Kirsher err = -ENOMEM; 4645a2cc190SJeff Kirsher goto out; 4655a2cc190SJeff Kirsher } 4665a2cc190SJeff Kirsher 467ffe455adSEugenia Emantayev /* Register new VLAN */ 4685a2cc190SJeff Kirsher table->refs[free] = 1; 4695a2cc190SJeff Kirsher table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); 4705a2cc190SJeff Kirsher 4715a2cc190SJeff Kirsher err = mlx4_set_port_vlan_table(dev, port, table->entries); 4725a2cc190SJeff Kirsher if (unlikely(err)) { 4735a2cc190SJeff Kirsher mlx4_warn(dev, "Failed adding vlan: %u\n", vlan); 4745a2cc190SJeff Kirsher table->refs[free] = 0; 4755a2cc190SJeff Kirsher table->entries[free] = 0; 4765a2cc190SJeff Kirsher goto out; 4775a2cc190SJeff Kirsher } 4785a2cc190SJeff Kirsher 4795a2cc190SJeff Kirsher *index = free; 4805a2cc190SJeff Kirsher ++table->total; 4815a2cc190SJeff Kirsher out: 4825a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 4835a2cc190SJeff Kirsher return err; 4845a2cc190SJeff Kirsher } 485ffe455adSEugenia Emantayev 486ffe455adSEugenia Emantayev int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) 487ffe455adSEugenia Emantayev { 488ffe455adSEugenia Emantayev u64 out_param; 489ffe455adSEugenia Emantayev int err; 490ffe455adSEugenia Emantayev 491ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 492ffe455adSEugenia Emantayev set_param_l(&out_param, port); 493ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, 494ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 495ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 496ffe455adSEugenia Emantayev if (!err) 497ffe455adSEugenia Emantayev *index = get_param_l(&out_param); 498ffe455adSEugenia Emantayev 499ffe455adSEugenia Emantayev return err; 500ffe455adSEugenia Emantayev } 501ffe455adSEugenia Emantayev return __mlx4_register_vlan(dev, port, vlan, index); 502ffe455adSEugenia Emantayev } 5035a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_register_vlan); 5045a2cc190SJeff Kirsher 505ffe455adSEugenia Emantayev static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) 5065a2cc190SJeff Kirsher { 5075a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 5085a2cc190SJeff Kirsher 5095a2cc190SJeff Kirsher if (index < MLX4_VLAN_REGULAR) { 5105a2cc190SJeff Kirsher mlx4_warn(dev, "Trying to free special vlan index %d\n", index); 5115a2cc190SJeff Kirsher return; 5125a2cc190SJeff Kirsher } 5135a2cc190SJeff Kirsher 5145a2cc190SJeff Kirsher mutex_lock(&table->mutex); 5155a2cc190SJeff Kirsher if (!table->refs[index]) { 5165a2cc190SJeff Kirsher mlx4_warn(dev, "No vlan entry for index %d\n", index); 5175a2cc190SJeff Kirsher goto out; 5185a2cc190SJeff Kirsher } 5195a2cc190SJeff Kirsher if (--table->refs[index]) { 5205a2cc190SJeff Kirsher mlx4_dbg(dev, "Have more references for index %d," 5215a2cc190SJeff Kirsher "no need to modify vlan table\n", index); 5225a2cc190SJeff Kirsher goto out; 5235a2cc190SJeff Kirsher } 5245a2cc190SJeff Kirsher table->entries[index] = 0; 5255a2cc190SJeff Kirsher mlx4_set_port_vlan_table(dev, port, table->entries); 5265a2cc190SJeff Kirsher --table->total; 5275a2cc190SJeff Kirsher out: 5285a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 5295a2cc190SJeff Kirsher } 530ffe455adSEugenia Emantayev 531ffe455adSEugenia Emantayev void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) 532ffe455adSEugenia Emantayev { 533ffe455adSEugenia Emantayev u64 in_param; 534ffe455adSEugenia Emantayev int err; 535ffe455adSEugenia Emantayev 536ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 537ffe455adSEugenia Emantayev set_param_l(&in_param, port); 538ffe455adSEugenia Emantayev err = mlx4_cmd(dev, in_param, RES_VLAN, RES_OP_RESERVE_AND_MAP, 539ffe455adSEugenia Emantayev MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, 540ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 541ffe455adSEugenia Emantayev if (!err) 542ffe455adSEugenia Emantayev mlx4_warn(dev, "Failed freeing vlan at index:%d\n", 543ffe455adSEugenia Emantayev index); 544ffe455adSEugenia Emantayev 545ffe455adSEugenia Emantayev return; 546ffe455adSEugenia Emantayev } 547ffe455adSEugenia Emantayev __mlx4_unregister_vlan(dev, port, index); 548ffe455adSEugenia Emantayev } 5495a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); 5505a2cc190SJeff Kirsher 5515a2cc190SJeff Kirsher int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) 5525a2cc190SJeff Kirsher { 5535a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 5545a2cc190SJeff Kirsher u8 *inbuf, *outbuf; 5555a2cc190SJeff Kirsher int err; 5565a2cc190SJeff Kirsher 5575a2cc190SJeff Kirsher inmailbox = mlx4_alloc_cmd_mailbox(dev); 5585a2cc190SJeff Kirsher if (IS_ERR(inmailbox)) 5595a2cc190SJeff Kirsher return PTR_ERR(inmailbox); 5605a2cc190SJeff Kirsher 5615a2cc190SJeff Kirsher outmailbox = mlx4_alloc_cmd_mailbox(dev); 5625a2cc190SJeff Kirsher if (IS_ERR(outmailbox)) { 5635a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, inmailbox); 5645a2cc190SJeff Kirsher return PTR_ERR(outmailbox); 5655a2cc190SJeff Kirsher } 5665a2cc190SJeff Kirsher 5675a2cc190SJeff Kirsher inbuf = inmailbox->buf; 5685a2cc190SJeff Kirsher outbuf = outmailbox->buf; 5695a2cc190SJeff Kirsher memset(inbuf, 0, 256); 5705a2cc190SJeff Kirsher memset(outbuf, 0, 256); 5715a2cc190SJeff Kirsher inbuf[0] = 1; 5725a2cc190SJeff Kirsher inbuf[1] = 1; 5735a2cc190SJeff Kirsher inbuf[2] = 1; 5745a2cc190SJeff Kirsher inbuf[3] = 1; 5755a2cc190SJeff Kirsher *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015); 5765a2cc190SJeff Kirsher *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); 5775a2cc190SJeff Kirsher 5785a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, 579f9baff50SJack Morgenstein MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 580f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 5815a2cc190SJeff Kirsher if (!err) 5825a2cc190SJeff Kirsher *caps = *(__be32 *) (outbuf + 84); 5835a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, inmailbox); 5845a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, outmailbox); 5855a2cc190SJeff Kirsher return err; 5865a2cc190SJeff Kirsher } 5875a2cc190SJeff Kirsher 588f470f8d4SLinus Torvalds int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port) 589f470f8d4SLinus Torvalds { 590f470f8d4SLinus Torvalds struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 591f470f8d4SLinus Torvalds u8 *inbuf, *outbuf; 592f470f8d4SLinus Torvalds int err, packet_error; 593f470f8d4SLinus Torvalds 594f470f8d4SLinus Torvalds inmailbox = mlx4_alloc_cmd_mailbox(dev); 595f470f8d4SLinus Torvalds if (IS_ERR(inmailbox)) 596f470f8d4SLinus Torvalds return PTR_ERR(inmailbox); 597f470f8d4SLinus Torvalds 598f470f8d4SLinus Torvalds outmailbox = mlx4_alloc_cmd_mailbox(dev); 599f470f8d4SLinus Torvalds if (IS_ERR(outmailbox)) { 600f470f8d4SLinus Torvalds mlx4_free_cmd_mailbox(dev, inmailbox); 601f470f8d4SLinus Torvalds return PTR_ERR(outmailbox); 602f470f8d4SLinus Torvalds } 603f470f8d4SLinus Torvalds 604f470f8d4SLinus Torvalds inbuf = inmailbox->buf; 605f470f8d4SLinus Torvalds outbuf = outmailbox->buf; 606f470f8d4SLinus Torvalds memset(inbuf, 0, 256); 607f470f8d4SLinus Torvalds memset(outbuf, 0, 256); 608f470f8d4SLinus Torvalds inbuf[0] = 1; 609f470f8d4SLinus Torvalds inbuf[1] = 1; 610f470f8d4SLinus Torvalds inbuf[2] = 1; 611f470f8d4SLinus Torvalds inbuf[3] = 1; 612f470f8d4SLinus Torvalds 613f470f8d4SLinus Torvalds *(__be16 *) (&inbuf[16]) = MLX4_ATTR_EXTENDED_PORT_INFO; 614f470f8d4SLinus Torvalds *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); 615f470f8d4SLinus Torvalds 616f470f8d4SLinus Torvalds err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, 617f9baff50SJack Morgenstein MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 618f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 619f470f8d4SLinus Torvalds 620f470f8d4SLinus Torvalds packet_error = be16_to_cpu(*(__be16 *) (outbuf + 4)); 621f470f8d4SLinus Torvalds 622f470f8d4SLinus Torvalds dev->caps.ext_port_cap[port] = (!err && !packet_error) ? 623f470f8d4SLinus Torvalds MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO 624f470f8d4SLinus Torvalds : 0; 625f470f8d4SLinus Torvalds 626f470f8d4SLinus Torvalds mlx4_free_cmd_mailbox(dev, inmailbox); 627f470f8d4SLinus Torvalds mlx4_free_cmd_mailbox(dev, outmailbox); 628f470f8d4SLinus Torvalds return err; 629f470f8d4SLinus Torvalds } 630f470f8d4SLinus Torvalds 631ffe455adSEugenia Emantayev static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, 632ffe455adSEugenia Emantayev u8 op_mod, struct mlx4_cmd_mailbox *inbox) 633ffe455adSEugenia Emantayev { 634ffe455adSEugenia Emantayev struct mlx4_priv *priv = mlx4_priv(dev); 635ffe455adSEugenia Emantayev struct mlx4_port_info *port_info; 636ffe455adSEugenia Emantayev struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; 637ffe455adSEugenia Emantayev struct mlx4_slave_state *slave_st = &master->slave_state[slave]; 638ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *qpn_context; 639ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *gen_context; 640ffe455adSEugenia Emantayev int reset_qkey_viols; 641ffe455adSEugenia Emantayev int port; 642ffe455adSEugenia Emantayev int is_eth; 643ffe455adSEugenia Emantayev u32 in_modifier; 644ffe455adSEugenia Emantayev u32 promisc; 645ffe455adSEugenia Emantayev u16 mtu, prev_mtu; 646ffe455adSEugenia Emantayev int err; 647ffe455adSEugenia Emantayev int i; 648ffe455adSEugenia Emantayev __be32 agg_cap_mask; 649ffe455adSEugenia Emantayev __be32 slave_cap_mask; 650ffe455adSEugenia Emantayev __be32 new_cap_mask; 651ffe455adSEugenia Emantayev 652ffe455adSEugenia Emantayev port = in_mod & 0xff; 653ffe455adSEugenia Emantayev in_modifier = in_mod >> 8; 654ffe455adSEugenia Emantayev is_eth = op_mod; 655ffe455adSEugenia Emantayev port_info = &priv->port[port]; 656ffe455adSEugenia Emantayev 657ffe455adSEugenia Emantayev /* Slaves cannot perform SET_PORT operations except changing MTU */ 658ffe455adSEugenia Emantayev if (is_eth) { 659ffe455adSEugenia Emantayev if (slave != dev->caps.function && 660ffe455adSEugenia Emantayev in_modifier != MLX4_SET_PORT_GENERAL) { 661ffe455adSEugenia Emantayev mlx4_warn(dev, "denying SET_PORT for slave:%d\n", 662ffe455adSEugenia Emantayev slave); 663ffe455adSEugenia Emantayev return -EINVAL; 664ffe455adSEugenia Emantayev } 665ffe455adSEugenia Emantayev switch (in_modifier) { 666ffe455adSEugenia Emantayev case MLX4_SET_PORT_RQP_CALC: 667ffe455adSEugenia Emantayev qpn_context = inbox->buf; 668ffe455adSEugenia Emantayev qpn_context->base_qpn = 669ffe455adSEugenia Emantayev cpu_to_be32(port_info->base_qpn); 670ffe455adSEugenia Emantayev qpn_context->n_mac = 0x7; 671ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->promisc) >> 672ffe455adSEugenia Emantayev SET_PORT_PROMISC_SHIFT; 673ffe455adSEugenia Emantayev qpn_context->promisc = cpu_to_be32( 674ffe455adSEugenia Emantayev promisc << SET_PORT_PROMISC_SHIFT | 675ffe455adSEugenia Emantayev port_info->base_qpn); 676ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->mcast) >> 677ffe455adSEugenia Emantayev SET_PORT_MC_PROMISC_SHIFT; 678ffe455adSEugenia Emantayev qpn_context->mcast = cpu_to_be32( 679ffe455adSEugenia Emantayev promisc << SET_PORT_MC_PROMISC_SHIFT | 680ffe455adSEugenia Emantayev port_info->base_qpn); 681ffe455adSEugenia Emantayev break; 682ffe455adSEugenia Emantayev case MLX4_SET_PORT_GENERAL: 683ffe455adSEugenia Emantayev gen_context = inbox->buf; 684ffe455adSEugenia Emantayev /* Mtu is configured as the max MTU among all the 685ffe455adSEugenia Emantayev * the functions on the port. */ 686ffe455adSEugenia Emantayev mtu = be16_to_cpu(gen_context->mtu); 687ffe455adSEugenia Emantayev mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]); 688ffe455adSEugenia Emantayev prev_mtu = slave_st->mtu[port]; 689ffe455adSEugenia Emantayev slave_st->mtu[port] = mtu; 690ffe455adSEugenia Emantayev if (mtu > master->max_mtu[port]) 691ffe455adSEugenia Emantayev master->max_mtu[port] = mtu; 692ffe455adSEugenia Emantayev if (mtu < prev_mtu && prev_mtu == 693ffe455adSEugenia Emantayev master->max_mtu[port]) { 694ffe455adSEugenia Emantayev slave_st->mtu[port] = mtu; 695ffe455adSEugenia Emantayev master->max_mtu[port] = mtu; 696ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) { 697ffe455adSEugenia Emantayev master->max_mtu[port] = 698ffe455adSEugenia Emantayev max(master->max_mtu[port], 699ffe455adSEugenia Emantayev master->slave_state[i].mtu[port]); 700ffe455adSEugenia Emantayev } 701ffe455adSEugenia Emantayev } 702ffe455adSEugenia Emantayev 703ffe455adSEugenia Emantayev gen_context->mtu = cpu_to_be16(master->max_mtu[port]); 704ffe455adSEugenia Emantayev break; 705ffe455adSEugenia Emantayev } 706ffe455adSEugenia Emantayev return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, 707ffe455adSEugenia Emantayev MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 708ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 709ffe455adSEugenia Emantayev } 710ffe455adSEugenia Emantayev 711ffe455adSEugenia Emantayev /* For IB, we only consider: 712ffe455adSEugenia Emantayev * - The capability mask, which is set to the aggregate of all 713ffe455adSEugenia Emantayev * slave function capabilities 714ffe455adSEugenia Emantayev * - The QKey violatin counter - reset according to each request. 715ffe455adSEugenia Emantayev */ 716ffe455adSEugenia Emantayev 717ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 718ffe455adSEugenia Emantayev reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; 719ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[2]; 720ffe455adSEugenia Emantayev } else { 721ffe455adSEugenia Emantayev reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; 722ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[1]; 723ffe455adSEugenia Emantayev } 724ffe455adSEugenia Emantayev 725ffe455adSEugenia Emantayev agg_cap_mask = 0; 726ffe455adSEugenia Emantayev slave_cap_mask = 727ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; 728ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; 729ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) 730ffe455adSEugenia Emantayev agg_cap_mask |= 731ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[i].ib_cap_mask[port]; 732ffe455adSEugenia Emantayev 733ffe455adSEugenia Emantayev /* only clear mailbox for guests. Master may be setting 734ffe455adSEugenia Emantayev * MTU or PKEY table size 735ffe455adSEugenia Emantayev */ 736ffe455adSEugenia Emantayev if (slave != dev->caps.function) 737ffe455adSEugenia Emantayev memset(inbox->buf, 0, 256); 738ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 739ffe455adSEugenia Emantayev *(u8 *) inbox->buf = !!reset_qkey_viols << 6; 740ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[2] = agg_cap_mask; 741ffe455adSEugenia Emantayev } else { 742ffe455adSEugenia Emantayev ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; 743ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[1] = agg_cap_mask; 744ffe455adSEugenia Emantayev } 745ffe455adSEugenia Emantayev 746ffe455adSEugenia Emantayev err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, 747ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 748ffe455adSEugenia Emantayev if (err) 749ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = 750ffe455adSEugenia Emantayev slave_cap_mask; 751ffe455adSEugenia Emantayev return err; 752ffe455adSEugenia Emantayev } 753ffe455adSEugenia Emantayev 754ffe455adSEugenia Emantayev int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, 755ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 756ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 757ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 758ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 759ffe455adSEugenia Emantayev { 760ffe455adSEugenia Emantayev return mlx4_common_set_port(dev, slave, vhcr->in_modifier, 761ffe455adSEugenia Emantayev vhcr->op_modifier, inbox); 762ffe455adSEugenia Emantayev } 763ffe455adSEugenia Emantayev 7645a2cc190SJeff Kirsher int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) 7655a2cc190SJeff Kirsher { 7665a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 7675a2cc190SJeff Kirsher int err; 7685a2cc190SJeff Kirsher 7695a2cc190SJeff Kirsher if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) 7705a2cc190SJeff Kirsher return 0; 7715a2cc190SJeff Kirsher 7725a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 7735a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 7745a2cc190SJeff Kirsher return PTR_ERR(mailbox); 7755a2cc190SJeff Kirsher 7765a2cc190SJeff Kirsher memset(mailbox->buf, 0, 256); 7775a2cc190SJeff Kirsher 7785a2cc190SJeff Kirsher ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; 7795a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 780f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 7815a2cc190SJeff Kirsher 7825a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 7835a2cc190SJeff Kirsher return err; 7845a2cc190SJeff Kirsher } 785ffe455adSEugenia Emantayev 786ffe455adSEugenia Emantayev static int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 787ffe455adSEugenia Emantayev u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 788ffe455adSEugenia Emantayev { 789ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 790ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *context; 791ffe455adSEugenia Emantayev int err; 792ffe455adSEugenia Emantayev u32 in_mod; 793ffe455adSEugenia Emantayev 794ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 795ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 796ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 797ffe455adSEugenia Emantayev context = mailbox->buf; 798ffe455adSEugenia Emantayev memset(context, 0, sizeof *context); 799ffe455adSEugenia Emantayev 800ffe455adSEugenia Emantayev context->flags = SET_PORT_GEN_ALL_VALID; 801ffe455adSEugenia Emantayev context->mtu = cpu_to_be16(mtu); 802ffe455adSEugenia Emantayev context->pptx = (pptx * (!pfctx)) << 7; 803ffe455adSEugenia Emantayev context->pfctx = pfctx; 804ffe455adSEugenia Emantayev context->pprx = (pprx * (!pfcrx)) << 7; 805ffe455adSEugenia Emantayev context->pfcrx = pfcrx; 806ffe455adSEugenia Emantayev 807ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 808ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 809ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 810ffe455adSEugenia Emantayev 811ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 812ffe455adSEugenia Emantayev return err; 813ffe455adSEugenia Emantayev } 814ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_general); 815ffe455adSEugenia Emantayev 816ffe455adSEugenia Emantayev static int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 817ffe455adSEugenia Emantayev u8 promisc) 818ffe455adSEugenia Emantayev { 819ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 820ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *context; 821ffe455adSEugenia Emantayev int err; 822ffe455adSEugenia Emantayev u32 in_mod; 823ffe455adSEugenia Emantayev u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? 824ffe455adSEugenia Emantayev MCAST_DIRECT : MCAST_DEFAULT; 825ffe455adSEugenia Emantayev 826ffe455adSEugenia Emantayev if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && 827ffe455adSEugenia Emantayev dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) 828ffe455adSEugenia Emantayev return 0; 829ffe455adSEugenia Emantayev 830ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 831ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 832ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 833ffe455adSEugenia Emantayev context = mailbox->buf; 834ffe455adSEugenia Emantayev memset(context, 0, sizeof *context); 835ffe455adSEugenia Emantayev 836ffe455adSEugenia Emantayev context->base_qpn = cpu_to_be32(base_qpn); 837ffe455adSEugenia Emantayev context->n_mac = dev->caps.log_num_macs; 838ffe455adSEugenia Emantayev context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | 839ffe455adSEugenia Emantayev base_qpn); 840ffe455adSEugenia Emantayev context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | 841ffe455adSEugenia Emantayev base_qpn); 842ffe455adSEugenia Emantayev context->intra_no_vlan = 0; 843ffe455adSEugenia Emantayev context->no_vlan = MLX4_NO_VLAN_IDX; 844ffe455adSEugenia Emantayev context->intra_vlan_miss = 0; 845ffe455adSEugenia Emantayev context->vlan_miss = MLX4_VLAN_MISS_IDX; 846ffe455adSEugenia Emantayev 847ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 848ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 849ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 850ffe455adSEugenia Emantayev 851ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 852ffe455adSEugenia Emantayev return err; 853ffe455adSEugenia Emantayev } 854ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); 855ffe455adSEugenia Emantayev 856ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, 857ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 858ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 859ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 860ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 861ffe455adSEugenia Emantayev { 862ffe455adSEugenia Emantayev int err = 0; 863ffe455adSEugenia Emantayev 864ffe455adSEugenia Emantayev return err; 865ffe455adSEugenia Emantayev } 866ffe455adSEugenia Emantayev 867ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 868ffe455adSEugenia Emantayev u64 mac, u64 clear, u8 mode) 869ffe455adSEugenia Emantayev { 870ffe455adSEugenia Emantayev return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 871ffe455adSEugenia Emantayev MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, 872ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 873ffe455adSEugenia Emantayev } 874ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); 875ffe455adSEugenia Emantayev 876ffe455adSEugenia Emantayev int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, 877ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 878ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 879ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 880ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 881ffe455adSEugenia Emantayev { 882ffe455adSEugenia Emantayev int err = 0; 883ffe455adSEugenia Emantayev 884ffe455adSEugenia Emantayev return err; 885ffe455adSEugenia Emantayev } 886ffe455adSEugenia Emantayev 887ffe455adSEugenia Emantayev int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, 888ffe455adSEugenia Emantayev u32 in_mod, struct mlx4_cmd_mailbox *outbox) 889ffe455adSEugenia Emantayev { 890ffe455adSEugenia Emantayev return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, 891ffe455adSEugenia Emantayev MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, 892ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 893ffe455adSEugenia Emantayev } 894ffe455adSEugenia Emantayev 895ffe455adSEugenia Emantayev int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, 896ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 897ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 898ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 899ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 900ffe455adSEugenia Emantayev { 901ffe455adSEugenia Emantayev return mlx4_common_dump_eth_stats(dev, slave, 902ffe455adSEugenia Emantayev vhcr->in_modifier, outbox); 903ffe455adSEugenia Emantayev } 904