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 4793ece0c1SEugenia Emantayev #define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL 4893ece0c1SEugenia Emantayev #define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL 4993ece0c1SEugenia Emantayev #define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL 5093ece0c1SEugenia Emantayev #define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL 5193ece0c1SEugenia Emantayev 525a2cc190SJeff Kirsher void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table) 535a2cc190SJeff Kirsher { 545a2cc190SJeff Kirsher int i; 555a2cc190SJeff Kirsher 565a2cc190SJeff Kirsher mutex_init(&table->mutex); 575a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 585a2cc190SJeff Kirsher table->entries[i] = 0; 595a2cc190SJeff Kirsher table->refs[i] = 0; 605a2cc190SJeff Kirsher } 615a2cc190SJeff Kirsher table->max = 1 << dev->caps.log_num_macs; 625a2cc190SJeff Kirsher table->total = 0; 635a2cc190SJeff Kirsher } 645a2cc190SJeff Kirsher 655a2cc190SJeff Kirsher void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) 665a2cc190SJeff Kirsher { 675a2cc190SJeff Kirsher int i; 685a2cc190SJeff Kirsher 695a2cc190SJeff Kirsher mutex_init(&table->mutex); 705a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) { 715a2cc190SJeff Kirsher table->entries[i] = 0; 725a2cc190SJeff Kirsher table->refs[i] = 0; 735a2cc190SJeff Kirsher } 74e72ebf5aSYevgeny Petrilin table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR; 755a2cc190SJeff Kirsher table->total = 0; 765a2cc190SJeff Kirsher } 775a2cc190SJeff Kirsher 78ffe455adSEugenia Emantayev static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) 795a2cc190SJeff Kirsher { 805a2cc190SJeff Kirsher struct mlx4_qp qp; 815a2cc190SJeff Kirsher u8 gid[16] = {0}; 822ab573c5SYevgeny Petrilin __be64 be_mac; 835a2cc190SJeff Kirsher int err; 845a2cc190SJeff Kirsher 855a2cc190SJeff Kirsher qp.qpn = *qpn; 865a2cc190SJeff Kirsher 875a2cc190SJeff Kirsher mac &= 0xffffffffffffULL; 882ab573c5SYevgeny Petrilin be_mac = cpu_to_be64(mac << 16); 892ab573c5SYevgeny Petrilin memcpy(&gid[10], &be_mac, ETH_ALEN); 905a2cc190SJeff Kirsher gid[5] = port; 915a2cc190SJeff Kirsher 92ffe455adSEugenia Emantayev err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); 93ffe455adSEugenia Emantayev if (err) 94ffe455adSEugenia Emantayev mlx4_warn(dev, "Failed Attaching Unicast\n"); 955a2cc190SJeff Kirsher 965a2cc190SJeff Kirsher return err; 975a2cc190SJeff Kirsher } 985a2cc190SJeff Kirsher 995a2cc190SJeff Kirsher static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, 100ffe455adSEugenia Emantayev u64 mac, int qpn) 1015a2cc190SJeff Kirsher { 1025a2cc190SJeff Kirsher struct mlx4_qp qp; 1035a2cc190SJeff Kirsher u8 gid[16] = {0}; 1042ab573c5SYevgeny Petrilin __be64 be_mac; 1055a2cc190SJeff Kirsher 1065a2cc190SJeff Kirsher qp.qpn = qpn; 1075a2cc190SJeff Kirsher mac &= 0xffffffffffffULL; 1082ab573c5SYevgeny Petrilin be_mac = cpu_to_be64(mac << 16); 1092ab573c5SYevgeny Petrilin memcpy(&gid[10], &be_mac, ETH_ALEN); 1105a2cc190SJeff Kirsher gid[5] = port; 1115a2cc190SJeff Kirsher 112ffe455adSEugenia Emantayev mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); 1135a2cc190SJeff Kirsher } 1145a2cc190SJeff Kirsher 1155a2cc190SJeff Kirsher static int validate_index(struct mlx4_dev *dev, 1165a2cc190SJeff Kirsher struct mlx4_mac_table *table, int index) 1175a2cc190SJeff Kirsher { 1185a2cc190SJeff Kirsher int err = 0; 1195a2cc190SJeff Kirsher 1205a2cc190SJeff Kirsher if (index < 0 || index >= table->max || !table->entries[index]) { 1215a2cc190SJeff Kirsher mlx4_warn(dev, "No valid Mac entry for the given index\n"); 1225a2cc190SJeff Kirsher err = -EINVAL; 1235a2cc190SJeff Kirsher } 1245a2cc190SJeff Kirsher return err; 1255a2cc190SJeff Kirsher } 1265a2cc190SJeff Kirsher 1275a2cc190SJeff Kirsher static int find_index(struct mlx4_dev *dev, 1285a2cc190SJeff Kirsher struct mlx4_mac_table *table, u64 mac) 1295a2cc190SJeff Kirsher { 1305a2cc190SJeff Kirsher int i; 131ffe455adSEugenia Emantayev 1325a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 133ffe455adSEugenia Emantayev if ((mac & MLX4_MAC_MASK) == 134ffe455adSEugenia Emantayev (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) 1355a2cc190SJeff Kirsher return i; 1365a2cc190SJeff Kirsher } 1375a2cc190SJeff Kirsher /* Mac not found */ 1385a2cc190SJeff Kirsher return -EINVAL; 1395a2cc190SJeff Kirsher } 1405a2cc190SJeff Kirsher 141ffe455adSEugenia Emantayev int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) 1425a2cc190SJeff Kirsher { 1435a2cc190SJeff Kirsher struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 1445a2cc190SJeff Kirsher struct mlx4_mac_entry *entry; 145ffe455adSEugenia Emantayev int index = 0; 146ffe455adSEugenia Emantayev int err = 0; 147ffe455adSEugenia Emantayev 148ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n", 149ffe455adSEugenia Emantayev (unsigned long long) mac); 150ffe455adSEugenia Emantayev index = mlx4_register_mac(dev, port, mac); 151ffe455adSEugenia Emantayev if (index < 0) { 152ffe455adSEugenia Emantayev err = index; 153ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 154ffe455adSEugenia Emantayev (unsigned long long) mac); 155ffe455adSEugenia Emantayev return err; 156ffe455adSEugenia Emantayev } 157ffe455adSEugenia Emantayev 158ffe455adSEugenia Emantayev if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) { 159ffe455adSEugenia Emantayev *qpn = info->base_qpn + index; 160ffe455adSEugenia Emantayev return 0; 161ffe455adSEugenia Emantayev } 162ffe455adSEugenia Emantayev 163ffe455adSEugenia Emantayev err = mlx4_qp_reserve_range(dev, 1, 1, qpn); 164ffe455adSEugenia Emantayev mlx4_dbg(dev, "Reserved qp %d\n", *qpn); 165ffe455adSEugenia Emantayev if (err) { 166ffe455adSEugenia Emantayev mlx4_err(dev, "Failed to reserve qp for mac registration\n"); 167ffe455adSEugenia Emantayev goto qp_err; 168ffe455adSEugenia Emantayev } 169ffe455adSEugenia Emantayev 170ffe455adSEugenia Emantayev err = mlx4_uc_steer_add(dev, port, mac, qpn); 171ffe455adSEugenia Emantayev if (err) 172ffe455adSEugenia Emantayev goto steer_err; 173ffe455adSEugenia Emantayev 174ffe455adSEugenia Emantayev entry = kmalloc(sizeof *entry, GFP_KERNEL); 175ffe455adSEugenia Emantayev if (!entry) { 176ffe455adSEugenia Emantayev err = -ENOMEM; 177ffe455adSEugenia Emantayev goto alloc_err; 178ffe455adSEugenia Emantayev } 179ffe455adSEugenia Emantayev entry->mac = mac; 180ffe455adSEugenia Emantayev err = radix_tree_insert(&info->mac_tree, *qpn, entry); 181ffe455adSEugenia Emantayev if (err) 182ffe455adSEugenia Emantayev goto insert_err; 183ffe455adSEugenia Emantayev return 0; 184ffe455adSEugenia Emantayev 185ffe455adSEugenia Emantayev insert_err: 186ffe455adSEugenia Emantayev kfree(entry); 187ffe455adSEugenia Emantayev 188ffe455adSEugenia Emantayev alloc_err: 189ffe455adSEugenia Emantayev mlx4_uc_steer_release(dev, port, mac, *qpn); 190ffe455adSEugenia Emantayev 191ffe455adSEugenia Emantayev steer_err: 192ffe455adSEugenia Emantayev mlx4_qp_release_range(dev, *qpn, 1); 193ffe455adSEugenia Emantayev 194ffe455adSEugenia Emantayev qp_err: 195ffe455adSEugenia Emantayev mlx4_unregister_mac(dev, port, mac); 196ffe455adSEugenia Emantayev return err; 197ffe455adSEugenia Emantayev } 198ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_get_eth_qp); 199ffe455adSEugenia Emantayev 200ffe455adSEugenia Emantayev void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn) 201ffe455adSEugenia Emantayev { 202ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 203ffe455adSEugenia Emantayev struct mlx4_mac_entry *entry; 204ffe455adSEugenia Emantayev 205ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for deleting\n", 206ffe455adSEugenia Emantayev (unsigned long long) mac); 207ffe455adSEugenia Emantayev mlx4_unregister_mac(dev, port, mac); 2085a2cc190SJeff Kirsher 2095a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { 2105a2cc190SJeff Kirsher entry = radix_tree_lookup(&info->mac_tree, qpn); 2115a2cc190SJeff Kirsher if (entry) { 212ffe455adSEugenia Emantayev mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," 213ffe455adSEugenia Emantayev " qpn %d\n", port, 214ffe455adSEugenia Emantayev (unsigned long long) mac, qpn); 215ffe455adSEugenia Emantayev mlx4_uc_steer_release(dev, port, entry->mac, qpn); 216ffe455adSEugenia Emantayev mlx4_qp_release_range(dev, qpn, 1); 2175a2cc190SJeff Kirsher radix_tree_delete(&info->mac_tree, qpn); 2185a2cc190SJeff Kirsher kfree(entry); 2195a2cc190SJeff Kirsher } 2205a2cc190SJeff Kirsher } 221ffe455adSEugenia Emantayev } 222ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_put_eth_qp); 223ffe455adSEugenia Emantayev 224ffe455adSEugenia Emantayev static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, 225ffe455adSEugenia Emantayev __be64 *entries) 226ffe455adSEugenia Emantayev { 227ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 228ffe455adSEugenia Emantayev u32 in_mod; 229ffe455adSEugenia Emantayev int err; 230ffe455adSEugenia Emantayev 231ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 232ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 233ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 234ffe455adSEugenia Emantayev 235ffe455adSEugenia Emantayev memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); 236ffe455adSEugenia Emantayev 237ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; 238ffe455adSEugenia Emantayev 239ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 240ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 241ffe455adSEugenia Emantayev 242ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 243ffe455adSEugenia Emantayev return err; 244ffe455adSEugenia Emantayev } 245ffe455adSEugenia Emantayev 246ffe455adSEugenia Emantayev int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 247ffe455adSEugenia Emantayev { 248ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 249ffe455adSEugenia Emantayev struct mlx4_mac_table *table = &info->mac_table; 250ffe455adSEugenia Emantayev int i, err = 0; 251ffe455adSEugenia Emantayev int free = -1; 252ffe455adSEugenia Emantayev 253ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", 254ffe455adSEugenia Emantayev (unsigned long long) mac, port); 255ffe455adSEugenia Emantayev 256ffe455adSEugenia Emantayev mutex_lock(&table->mutex); 257ffe455adSEugenia Emantayev for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 258ffe455adSEugenia Emantayev if (free < 0 && !table->entries[i]) { 259ffe455adSEugenia Emantayev free = i; 260ffe455adSEugenia Emantayev continue; 261ffe455adSEugenia Emantayev } 262ffe455adSEugenia Emantayev 263ffe455adSEugenia Emantayev if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 264ffe455adSEugenia Emantayev /* MAC already registered, Must not have duplicates */ 265ffe455adSEugenia Emantayev err = -EEXIST; 266ffe455adSEugenia Emantayev goto out; 267ffe455adSEugenia Emantayev } 268ffe455adSEugenia Emantayev } 269ffe455adSEugenia Emantayev 270ffe455adSEugenia Emantayev mlx4_dbg(dev, "Free MAC index is %d\n", free); 271ffe455adSEugenia Emantayev 272ffe455adSEugenia Emantayev if (table->total == table->max) { 273ffe455adSEugenia Emantayev /* No free mac entries */ 274ffe455adSEugenia Emantayev err = -ENOSPC; 275ffe455adSEugenia Emantayev goto out; 276ffe455adSEugenia Emantayev } 277ffe455adSEugenia Emantayev 278ffe455adSEugenia Emantayev /* Register new MAC */ 279ffe455adSEugenia Emantayev table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); 280ffe455adSEugenia Emantayev 281ffe455adSEugenia Emantayev err = mlx4_set_port_mac_table(dev, port, table->entries); 282ffe455adSEugenia Emantayev if (unlikely(err)) { 283ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 284ffe455adSEugenia Emantayev (unsigned long long) mac); 285ffe455adSEugenia Emantayev table->entries[free] = 0; 286ffe455adSEugenia Emantayev goto out; 287ffe455adSEugenia Emantayev } 288ffe455adSEugenia Emantayev 289ffe455adSEugenia Emantayev err = free; 290ffe455adSEugenia Emantayev ++table->total; 291ffe455adSEugenia Emantayev out: 292ffe455adSEugenia Emantayev mutex_unlock(&table->mutex); 293ffe455adSEugenia Emantayev return err; 294ffe455adSEugenia Emantayev } 295ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(__mlx4_register_mac); 296ffe455adSEugenia Emantayev 297ffe455adSEugenia Emantayev int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 298ffe455adSEugenia Emantayev { 299ffe455adSEugenia Emantayev u64 out_param; 300ffe455adSEugenia Emantayev int err; 301ffe455adSEugenia Emantayev 302ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 303ffe455adSEugenia Emantayev set_param_l(&out_param, port); 304ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 305ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 306ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 307ffe455adSEugenia Emantayev if (err) 308ffe455adSEugenia Emantayev return err; 309ffe455adSEugenia Emantayev 310ffe455adSEugenia Emantayev return get_param_l(&out_param); 311ffe455adSEugenia Emantayev } 312ffe455adSEugenia Emantayev return __mlx4_register_mac(dev, port, mac); 313ffe455adSEugenia Emantayev } 314ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_register_mac); 315ffe455adSEugenia Emantayev 316ffe455adSEugenia Emantayev 317ffe455adSEugenia Emantayev void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 318ffe455adSEugenia Emantayev { 319ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 320ffe455adSEugenia Emantayev struct mlx4_mac_table *table = &info->mac_table; 321ffe455adSEugenia Emantayev int index; 322ffe455adSEugenia Emantayev 323ffe455adSEugenia Emantayev index = find_index(dev, table, mac); 3245a2cc190SJeff Kirsher 3255a2cc190SJeff Kirsher mutex_lock(&table->mutex); 3265a2cc190SJeff Kirsher 3275a2cc190SJeff Kirsher if (validate_index(dev, table, index)) 3285a2cc190SJeff Kirsher goto out; 3295a2cc190SJeff Kirsher 3305a2cc190SJeff Kirsher table->entries[index] = 0; 3315a2cc190SJeff Kirsher mlx4_set_port_mac_table(dev, port, table->entries); 3325a2cc190SJeff Kirsher --table->total; 3335a2cc190SJeff Kirsher out: 3345a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 3355a2cc190SJeff Kirsher } 336ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); 337ffe455adSEugenia Emantayev 338ffe455adSEugenia Emantayev void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 339ffe455adSEugenia Emantayev { 340ffe455adSEugenia Emantayev u64 out_param; 341ffe455adSEugenia Emantayev int err; 342ffe455adSEugenia Emantayev 343ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 344ffe455adSEugenia Emantayev set_param_l(&out_param, port); 345ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 346ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, 347ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 348ffe455adSEugenia Emantayev return; 349ffe455adSEugenia Emantayev } 350ffe455adSEugenia Emantayev __mlx4_unregister_mac(dev, port, mac); 351ffe455adSEugenia Emantayev return; 352ffe455adSEugenia Emantayev } 3535a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_unregister_mac); 3545a2cc190SJeff Kirsher 355ffe455adSEugenia Emantayev int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) 3565a2cc190SJeff Kirsher { 3575a2cc190SJeff Kirsher struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 3585a2cc190SJeff Kirsher struct mlx4_mac_table *table = &info->mac_table; 3595a2cc190SJeff Kirsher struct mlx4_mac_entry *entry; 360ffe455adSEugenia Emantayev int index = qpn - info->base_qpn; 361ffe455adSEugenia Emantayev int err = 0; 3625a2cc190SJeff Kirsher 3635a2cc190SJeff Kirsher if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { 3645a2cc190SJeff Kirsher entry = radix_tree_lookup(&info->mac_tree, qpn); 3655a2cc190SJeff Kirsher if (!entry) 3665a2cc190SJeff Kirsher return -EINVAL; 367ffe455adSEugenia Emantayev mlx4_uc_steer_release(dev, port, entry->mac, qpn); 368ffe455adSEugenia Emantayev mlx4_unregister_mac(dev, port, entry->mac); 3695a2cc190SJeff Kirsher entry->mac = new_mac; 370ffe455adSEugenia Emantayev mlx4_register_mac(dev, port, new_mac); 371ffe455adSEugenia Emantayev err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn); 3725a2cc190SJeff Kirsher return err; 3735a2cc190SJeff Kirsher } 3745a2cc190SJeff Kirsher 375ffe455adSEugenia Emantayev /* CX1 doesn't support multi-functions */ 3765a2cc190SJeff Kirsher mutex_lock(&table->mutex); 3775a2cc190SJeff Kirsher 3785a2cc190SJeff Kirsher err = validate_index(dev, table, index); 3795a2cc190SJeff Kirsher if (err) 3805a2cc190SJeff Kirsher goto out; 3815a2cc190SJeff Kirsher 3825a2cc190SJeff Kirsher table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID); 3835a2cc190SJeff Kirsher 3845a2cc190SJeff Kirsher err = mlx4_set_port_mac_table(dev, port, table->entries); 3855a2cc190SJeff Kirsher if (unlikely(err)) { 386ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 387ffe455adSEugenia Emantayev (unsigned long long) new_mac); 3885a2cc190SJeff Kirsher table->entries[index] = 0; 3895a2cc190SJeff Kirsher } 3905a2cc190SJeff Kirsher out: 3915a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 3925a2cc190SJeff Kirsher return err; 3935a2cc190SJeff Kirsher } 3945a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_replace_mac); 395ffe455adSEugenia Emantayev 3965a2cc190SJeff Kirsher static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, 3975a2cc190SJeff Kirsher __be32 *entries) 3985a2cc190SJeff Kirsher { 3995a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 4005a2cc190SJeff Kirsher u32 in_mod; 4015a2cc190SJeff Kirsher int err; 4025a2cc190SJeff Kirsher 4035a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 4045a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 4055a2cc190SJeff Kirsher return PTR_ERR(mailbox); 4065a2cc190SJeff Kirsher 4075a2cc190SJeff Kirsher memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); 4085a2cc190SJeff Kirsher in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; 4095a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 410f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 4115a2cc190SJeff Kirsher 4125a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 4135a2cc190SJeff Kirsher 4145a2cc190SJeff Kirsher return err; 4155a2cc190SJeff Kirsher } 4165a2cc190SJeff Kirsher 4175a2cc190SJeff Kirsher int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) 4185a2cc190SJeff Kirsher { 4195a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 4205a2cc190SJeff Kirsher int i; 4215a2cc190SJeff Kirsher 4225a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) { 4235a2cc190SJeff Kirsher if (table->refs[i] && 4245a2cc190SJeff Kirsher (vid == (MLX4_VLAN_MASK & 4255a2cc190SJeff Kirsher be32_to_cpu(table->entries[i])))) { 4265a2cc190SJeff Kirsher /* VLAN already registered, increase reference count */ 4275a2cc190SJeff Kirsher *idx = i; 4285a2cc190SJeff Kirsher return 0; 4295a2cc190SJeff Kirsher } 4305a2cc190SJeff Kirsher } 4315a2cc190SJeff Kirsher 4325a2cc190SJeff Kirsher return -ENOENT; 4335a2cc190SJeff Kirsher } 4345a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); 4355a2cc190SJeff Kirsher 436ffe455adSEugenia Emantayev static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, 437ffe455adSEugenia Emantayev int *index) 4385a2cc190SJeff Kirsher { 4395a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 4405a2cc190SJeff Kirsher int i, err = 0; 4415a2cc190SJeff Kirsher int free = -1; 4425a2cc190SJeff Kirsher 4435a2cc190SJeff Kirsher mutex_lock(&table->mutex); 444e72ebf5aSYevgeny Petrilin 445e72ebf5aSYevgeny Petrilin if (table->total == table->max) { 446e72ebf5aSYevgeny Petrilin /* No free vlan entries */ 447e72ebf5aSYevgeny Petrilin err = -ENOSPC; 448e72ebf5aSYevgeny Petrilin goto out; 449e72ebf5aSYevgeny Petrilin } 450e72ebf5aSYevgeny Petrilin 4515a2cc190SJeff Kirsher for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { 4525a2cc190SJeff Kirsher if (free < 0 && (table->refs[i] == 0)) { 4535a2cc190SJeff Kirsher free = i; 4545a2cc190SJeff Kirsher continue; 4555a2cc190SJeff Kirsher } 4565a2cc190SJeff Kirsher 4575a2cc190SJeff Kirsher if (table->refs[i] && 4585a2cc190SJeff Kirsher (vlan == (MLX4_VLAN_MASK & 4595a2cc190SJeff Kirsher be32_to_cpu(table->entries[i])))) { 4605a2cc190SJeff Kirsher /* Vlan already registered, increase references count */ 4615a2cc190SJeff Kirsher *index = i; 4625a2cc190SJeff Kirsher ++table->refs[i]; 4635a2cc190SJeff Kirsher goto out; 4645a2cc190SJeff Kirsher } 4655a2cc190SJeff Kirsher } 4665a2cc190SJeff Kirsher 4675a2cc190SJeff Kirsher if (free < 0) { 4685a2cc190SJeff Kirsher err = -ENOMEM; 4695a2cc190SJeff Kirsher goto out; 4705a2cc190SJeff Kirsher } 4715a2cc190SJeff Kirsher 472ffe455adSEugenia Emantayev /* Register new VLAN */ 4735a2cc190SJeff Kirsher table->refs[free] = 1; 4745a2cc190SJeff Kirsher table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); 4755a2cc190SJeff Kirsher 4765a2cc190SJeff Kirsher err = mlx4_set_port_vlan_table(dev, port, table->entries); 4775a2cc190SJeff Kirsher if (unlikely(err)) { 4785a2cc190SJeff Kirsher mlx4_warn(dev, "Failed adding vlan: %u\n", vlan); 4795a2cc190SJeff Kirsher table->refs[free] = 0; 4805a2cc190SJeff Kirsher table->entries[free] = 0; 4815a2cc190SJeff Kirsher goto out; 4825a2cc190SJeff Kirsher } 4835a2cc190SJeff Kirsher 4845a2cc190SJeff Kirsher *index = free; 4855a2cc190SJeff Kirsher ++table->total; 4865a2cc190SJeff Kirsher out: 4875a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 4885a2cc190SJeff Kirsher return err; 4895a2cc190SJeff Kirsher } 490ffe455adSEugenia Emantayev 491ffe455adSEugenia Emantayev int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) 492ffe455adSEugenia Emantayev { 493ffe455adSEugenia Emantayev u64 out_param; 494ffe455adSEugenia Emantayev int err; 495ffe455adSEugenia Emantayev 496ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 497ffe455adSEugenia Emantayev set_param_l(&out_param, port); 498ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, 499ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 500ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 501ffe455adSEugenia Emantayev if (!err) 502ffe455adSEugenia Emantayev *index = get_param_l(&out_param); 503ffe455adSEugenia Emantayev 504ffe455adSEugenia Emantayev return err; 505ffe455adSEugenia Emantayev } 506ffe455adSEugenia Emantayev return __mlx4_register_vlan(dev, port, vlan, index); 507ffe455adSEugenia Emantayev } 5085a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_register_vlan); 5095a2cc190SJeff Kirsher 510ffe455adSEugenia Emantayev static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) 5115a2cc190SJeff Kirsher { 5125a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 5135a2cc190SJeff Kirsher 5145a2cc190SJeff Kirsher if (index < MLX4_VLAN_REGULAR) { 5155a2cc190SJeff Kirsher mlx4_warn(dev, "Trying to free special vlan index %d\n", index); 5165a2cc190SJeff Kirsher return; 5175a2cc190SJeff Kirsher } 5185a2cc190SJeff Kirsher 5195a2cc190SJeff Kirsher mutex_lock(&table->mutex); 5205a2cc190SJeff Kirsher if (!table->refs[index]) { 5215a2cc190SJeff Kirsher mlx4_warn(dev, "No vlan entry for index %d\n", index); 5225a2cc190SJeff Kirsher goto out; 5235a2cc190SJeff Kirsher } 5245a2cc190SJeff Kirsher if (--table->refs[index]) { 5255a2cc190SJeff Kirsher mlx4_dbg(dev, "Have more references for index %d," 5265a2cc190SJeff Kirsher "no need to modify vlan table\n", index); 5275a2cc190SJeff Kirsher goto out; 5285a2cc190SJeff Kirsher } 5295a2cc190SJeff Kirsher table->entries[index] = 0; 5305a2cc190SJeff Kirsher mlx4_set_port_vlan_table(dev, port, table->entries); 5315a2cc190SJeff Kirsher --table->total; 5325a2cc190SJeff Kirsher out: 5335a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 5345a2cc190SJeff Kirsher } 535ffe455adSEugenia Emantayev 536ffe455adSEugenia Emantayev void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) 537ffe455adSEugenia Emantayev { 538ffe455adSEugenia Emantayev u64 in_param; 539ffe455adSEugenia Emantayev int err; 540ffe455adSEugenia Emantayev 541ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 542ffe455adSEugenia Emantayev set_param_l(&in_param, port); 543ffe455adSEugenia Emantayev err = mlx4_cmd(dev, in_param, RES_VLAN, RES_OP_RESERVE_AND_MAP, 544ffe455adSEugenia Emantayev MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, 545ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 546ffe455adSEugenia Emantayev if (!err) 547ffe455adSEugenia Emantayev mlx4_warn(dev, "Failed freeing vlan at index:%d\n", 548ffe455adSEugenia Emantayev index); 549ffe455adSEugenia Emantayev 550ffe455adSEugenia Emantayev return; 551ffe455adSEugenia Emantayev } 552ffe455adSEugenia Emantayev __mlx4_unregister_vlan(dev, port, index); 553ffe455adSEugenia Emantayev } 5545a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); 5555a2cc190SJeff Kirsher 5565a2cc190SJeff Kirsher int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) 5575a2cc190SJeff Kirsher { 5585a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 5595a2cc190SJeff Kirsher u8 *inbuf, *outbuf; 5605a2cc190SJeff Kirsher int err; 5615a2cc190SJeff Kirsher 5625a2cc190SJeff Kirsher inmailbox = mlx4_alloc_cmd_mailbox(dev); 5635a2cc190SJeff Kirsher if (IS_ERR(inmailbox)) 5645a2cc190SJeff Kirsher return PTR_ERR(inmailbox); 5655a2cc190SJeff Kirsher 5665a2cc190SJeff Kirsher outmailbox = mlx4_alloc_cmd_mailbox(dev); 5675a2cc190SJeff Kirsher if (IS_ERR(outmailbox)) { 5685a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, inmailbox); 5695a2cc190SJeff Kirsher return PTR_ERR(outmailbox); 5705a2cc190SJeff Kirsher } 5715a2cc190SJeff Kirsher 5725a2cc190SJeff Kirsher inbuf = inmailbox->buf; 5735a2cc190SJeff Kirsher outbuf = outmailbox->buf; 5745a2cc190SJeff Kirsher memset(inbuf, 0, 256); 5755a2cc190SJeff Kirsher memset(outbuf, 0, 256); 5765a2cc190SJeff Kirsher inbuf[0] = 1; 5775a2cc190SJeff Kirsher inbuf[1] = 1; 5785a2cc190SJeff Kirsher inbuf[2] = 1; 5795a2cc190SJeff Kirsher inbuf[3] = 1; 5805a2cc190SJeff Kirsher *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015); 5815a2cc190SJeff Kirsher *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); 5825a2cc190SJeff Kirsher 5835a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, 584f9baff50SJack Morgenstein MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 585f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 5865a2cc190SJeff Kirsher if (!err) 5875a2cc190SJeff Kirsher *caps = *(__be32 *) (outbuf + 84); 5885a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, inmailbox); 5895a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, outmailbox); 5905a2cc190SJeff Kirsher return err; 5915a2cc190SJeff Kirsher } 5925a2cc190SJeff Kirsher 593ffe455adSEugenia Emantayev static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, 594ffe455adSEugenia Emantayev u8 op_mod, struct mlx4_cmd_mailbox *inbox) 595ffe455adSEugenia Emantayev { 596ffe455adSEugenia Emantayev struct mlx4_priv *priv = mlx4_priv(dev); 597ffe455adSEugenia Emantayev struct mlx4_port_info *port_info; 598ffe455adSEugenia Emantayev struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; 599ffe455adSEugenia Emantayev struct mlx4_slave_state *slave_st = &master->slave_state[slave]; 600ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *qpn_context; 601ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *gen_context; 602ffe455adSEugenia Emantayev int reset_qkey_viols; 603ffe455adSEugenia Emantayev int port; 604ffe455adSEugenia Emantayev int is_eth; 605ffe455adSEugenia Emantayev u32 in_modifier; 606ffe455adSEugenia Emantayev u32 promisc; 607ffe455adSEugenia Emantayev u16 mtu, prev_mtu; 608ffe455adSEugenia Emantayev int err; 609ffe455adSEugenia Emantayev int i; 610ffe455adSEugenia Emantayev __be32 agg_cap_mask; 611ffe455adSEugenia Emantayev __be32 slave_cap_mask; 612ffe455adSEugenia Emantayev __be32 new_cap_mask; 613ffe455adSEugenia Emantayev 614ffe455adSEugenia Emantayev port = in_mod & 0xff; 615ffe455adSEugenia Emantayev in_modifier = in_mod >> 8; 616ffe455adSEugenia Emantayev is_eth = op_mod; 617ffe455adSEugenia Emantayev port_info = &priv->port[port]; 618ffe455adSEugenia Emantayev 619ffe455adSEugenia Emantayev /* Slaves cannot perform SET_PORT operations except changing MTU */ 620ffe455adSEugenia Emantayev if (is_eth) { 621ffe455adSEugenia Emantayev if (slave != dev->caps.function && 622ffe455adSEugenia Emantayev in_modifier != MLX4_SET_PORT_GENERAL) { 623ffe455adSEugenia Emantayev mlx4_warn(dev, "denying SET_PORT for slave:%d\n", 624ffe455adSEugenia Emantayev slave); 625ffe455adSEugenia Emantayev return -EINVAL; 626ffe455adSEugenia Emantayev } 627ffe455adSEugenia Emantayev switch (in_modifier) { 628ffe455adSEugenia Emantayev case MLX4_SET_PORT_RQP_CALC: 629ffe455adSEugenia Emantayev qpn_context = inbox->buf; 630ffe455adSEugenia Emantayev qpn_context->base_qpn = 631ffe455adSEugenia Emantayev cpu_to_be32(port_info->base_qpn); 632ffe455adSEugenia Emantayev qpn_context->n_mac = 0x7; 633ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->promisc) >> 634ffe455adSEugenia Emantayev SET_PORT_PROMISC_SHIFT; 635ffe455adSEugenia Emantayev qpn_context->promisc = cpu_to_be32( 636ffe455adSEugenia Emantayev promisc << SET_PORT_PROMISC_SHIFT | 637ffe455adSEugenia Emantayev port_info->base_qpn); 638ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->mcast) >> 639ffe455adSEugenia Emantayev SET_PORT_MC_PROMISC_SHIFT; 640ffe455adSEugenia Emantayev qpn_context->mcast = cpu_to_be32( 641ffe455adSEugenia Emantayev promisc << SET_PORT_MC_PROMISC_SHIFT | 642ffe455adSEugenia Emantayev port_info->base_qpn); 643ffe455adSEugenia Emantayev break; 644ffe455adSEugenia Emantayev case MLX4_SET_PORT_GENERAL: 645ffe455adSEugenia Emantayev gen_context = inbox->buf; 646ffe455adSEugenia Emantayev /* Mtu is configured as the max MTU among all the 647ffe455adSEugenia Emantayev * the functions on the port. */ 648ffe455adSEugenia Emantayev mtu = be16_to_cpu(gen_context->mtu); 649ffe455adSEugenia Emantayev mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]); 650ffe455adSEugenia Emantayev prev_mtu = slave_st->mtu[port]; 651ffe455adSEugenia Emantayev slave_st->mtu[port] = mtu; 652ffe455adSEugenia Emantayev if (mtu > master->max_mtu[port]) 653ffe455adSEugenia Emantayev master->max_mtu[port] = mtu; 654ffe455adSEugenia Emantayev if (mtu < prev_mtu && prev_mtu == 655ffe455adSEugenia Emantayev master->max_mtu[port]) { 656ffe455adSEugenia Emantayev slave_st->mtu[port] = mtu; 657ffe455adSEugenia Emantayev master->max_mtu[port] = mtu; 658ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) { 659ffe455adSEugenia Emantayev master->max_mtu[port] = 660ffe455adSEugenia Emantayev max(master->max_mtu[port], 661ffe455adSEugenia Emantayev master->slave_state[i].mtu[port]); 662ffe455adSEugenia Emantayev } 663ffe455adSEugenia Emantayev } 664ffe455adSEugenia Emantayev 665ffe455adSEugenia Emantayev gen_context->mtu = cpu_to_be16(master->max_mtu[port]); 666ffe455adSEugenia Emantayev break; 667ffe455adSEugenia Emantayev } 668ffe455adSEugenia Emantayev return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, 669ffe455adSEugenia Emantayev MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 670ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 671ffe455adSEugenia Emantayev } 672ffe455adSEugenia Emantayev 673ffe455adSEugenia Emantayev /* For IB, we only consider: 674ffe455adSEugenia Emantayev * - The capability mask, which is set to the aggregate of all 675ffe455adSEugenia Emantayev * slave function capabilities 676ffe455adSEugenia Emantayev * - The QKey violatin counter - reset according to each request. 677ffe455adSEugenia Emantayev */ 678ffe455adSEugenia Emantayev 679ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 680ffe455adSEugenia Emantayev reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; 681ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[2]; 682ffe455adSEugenia Emantayev } else { 683ffe455adSEugenia Emantayev reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; 684ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[1]; 685ffe455adSEugenia Emantayev } 686ffe455adSEugenia Emantayev 687ffe455adSEugenia Emantayev agg_cap_mask = 0; 688ffe455adSEugenia Emantayev slave_cap_mask = 689ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; 690ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; 691ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) 692ffe455adSEugenia Emantayev agg_cap_mask |= 693ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[i].ib_cap_mask[port]; 694ffe455adSEugenia Emantayev 695ffe455adSEugenia Emantayev /* only clear mailbox for guests. Master may be setting 696ffe455adSEugenia Emantayev * MTU or PKEY table size 697ffe455adSEugenia Emantayev */ 698ffe455adSEugenia Emantayev if (slave != dev->caps.function) 699ffe455adSEugenia Emantayev memset(inbox->buf, 0, 256); 700ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 701ffe455adSEugenia Emantayev *(u8 *) inbox->buf = !!reset_qkey_viols << 6; 702ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[2] = agg_cap_mask; 703ffe455adSEugenia Emantayev } else { 704ffe455adSEugenia Emantayev ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; 705ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[1] = agg_cap_mask; 706ffe455adSEugenia Emantayev } 707ffe455adSEugenia Emantayev 708ffe455adSEugenia Emantayev err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, 709ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 710ffe455adSEugenia Emantayev if (err) 711ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = 712ffe455adSEugenia Emantayev slave_cap_mask; 713ffe455adSEugenia Emantayev return err; 714ffe455adSEugenia Emantayev } 715ffe455adSEugenia Emantayev 716ffe455adSEugenia Emantayev int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, 717ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 718ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 719ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 720ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 721ffe455adSEugenia Emantayev { 722ffe455adSEugenia Emantayev return mlx4_common_set_port(dev, slave, vhcr->in_modifier, 723ffe455adSEugenia Emantayev vhcr->op_modifier, inbox); 724ffe455adSEugenia Emantayev } 725ffe455adSEugenia Emantayev 726096335b3SOr Gerlitz /* bit locations for set port command with zero op modifier */ 727096335b3SOr Gerlitz enum { 728096335b3SOr Gerlitz MLX4_SET_PORT_VL_CAP = 4, /* bits 7:4 */ 729096335b3SOr Gerlitz MLX4_SET_PORT_MTU_CAP = 12, /* bits 15:12 */ 730096335b3SOr Gerlitz MLX4_CHANGE_PORT_VL_CAP = 21, 731096335b3SOr Gerlitz MLX4_CHANGE_PORT_MTU_CAP = 22, 732096335b3SOr Gerlitz }; 733096335b3SOr Gerlitz 7345a2cc190SJeff Kirsher int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) 7355a2cc190SJeff Kirsher { 7365a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 737096335b3SOr Gerlitz int err, vl_cap; 7385a2cc190SJeff Kirsher 7395a2cc190SJeff Kirsher if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) 7405a2cc190SJeff Kirsher return 0; 7415a2cc190SJeff Kirsher 7425a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 7435a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 7445a2cc190SJeff Kirsher return PTR_ERR(mailbox); 7455a2cc190SJeff Kirsher 7465a2cc190SJeff Kirsher memset(mailbox->buf, 0, 256); 7475a2cc190SJeff Kirsher 7485a2cc190SJeff Kirsher ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; 749096335b3SOr Gerlitz 750096335b3SOr Gerlitz /* IB VL CAP enum isn't used by the firmware, just numerical values */ 751096335b3SOr Gerlitz for (vl_cap = 8; vl_cap >= 1; vl_cap >>= 1) { 752096335b3SOr Gerlitz ((__be32 *) mailbox->buf)[0] = cpu_to_be32( 753096335b3SOr Gerlitz (1 << MLX4_CHANGE_PORT_MTU_CAP) | 754096335b3SOr Gerlitz (1 << MLX4_CHANGE_PORT_VL_CAP) | 755096335b3SOr Gerlitz (dev->caps.port_ib_mtu[port] << MLX4_SET_PORT_MTU_CAP) | 756096335b3SOr Gerlitz (vl_cap << MLX4_SET_PORT_VL_CAP)); 7575a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 758f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 759096335b3SOr Gerlitz if (err != -ENOMEM) 760096335b3SOr Gerlitz break; 761096335b3SOr Gerlitz } 7625a2cc190SJeff Kirsher 7635a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 7645a2cc190SJeff Kirsher return err; 7655a2cc190SJeff Kirsher } 766ffe455adSEugenia Emantayev 767cb9ffb76SJoerg Roedel int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 768ffe455adSEugenia Emantayev u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 769ffe455adSEugenia Emantayev { 770ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 771ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *context; 772ffe455adSEugenia Emantayev int err; 773ffe455adSEugenia Emantayev u32 in_mod; 774ffe455adSEugenia Emantayev 775ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 776ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 777ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 778ffe455adSEugenia Emantayev context = mailbox->buf; 779ffe455adSEugenia Emantayev memset(context, 0, sizeof *context); 780ffe455adSEugenia Emantayev 781ffe455adSEugenia Emantayev context->flags = SET_PORT_GEN_ALL_VALID; 782ffe455adSEugenia Emantayev context->mtu = cpu_to_be16(mtu); 783ffe455adSEugenia Emantayev context->pptx = (pptx * (!pfctx)) << 7; 784ffe455adSEugenia Emantayev context->pfctx = pfctx; 785ffe455adSEugenia Emantayev context->pprx = (pprx * (!pfcrx)) << 7; 786ffe455adSEugenia Emantayev context->pfcrx = pfcrx; 787ffe455adSEugenia Emantayev 788ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 789ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 790ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 791ffe455adSEugenia Emantayev 792ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 793ffe455adSEugenia Emantayev return err; 794ffe455adSEugenia Emantayev } 795ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_general); 796ffe455adSEugenia Emantayev 797cb9ffb76SJoerg Roedel int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 798ffe455adSEugenia Emantayev u8 promisc) 799ffe455adSEugenia Emantayev { 800ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 801ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *context; 802ffe455adSEugenia Emantayev int err; 803ffe455adSEugenia Emantayev u32 in_mod; 804ffe455adSEugenia Emantayev u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? 805ffe455adSEugenia Emantayev MCAST_DIRECT : MCAST_DEFAULT; 806ffe455adSEugenia Emantayev 807ffe455adSEugenia Emantayev if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && 808ffe455adSEugenia Emantayev dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) 809ffe455adSEugenia Emantayev return 0; 810ffe455adSEugenia Emantayev 811ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 812ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 813ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 814ffe455adSEugenia Emantayev context = mailbox->buf; 815ffe455adSEugenia Emantayev memset(context, 0, sizeof *context); 816ffe455adSEugenia Emantayev 817ffe455adSEugenia Emantayev context->base_qpn = cpu_to_be32(base_qpn); 818ffe455adSEugenia Emantayev context->n_mac = dev->caps.log_num_macs; 819ffe455adSEugenia Emantayev context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | 820ffe455adSEugenia Emantayev base_qpn); 821ffe455adSEugenia Emantayev context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | 822ffe455adSEugenia Emantayev base_qpn); 823ffe455adSEugenia Emantayev context->intra_no_vlan = 0; 824ffe455adSEugenia Emantayev context->no_vlan = MLX4_NO_VLAN_IDX; 825ffe455adSEugenia Emantayev context->intra_vlan_miss = 0; 826ffe455adSEugenia Emantayev context->vlan_miss = MLX4_VLAN_MISS_IDX; 827ffe455adSEugenia Emantayev 828ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 829ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 830ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 831ffe455adSEugenia Emantayev 832ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 833ffe455adSEugenia Emantayev return err; 834ffe455adSEugenia Emantayev } 835ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); 836ffe455adSEugenia Emantayev 837e5395e92SAmir Vadai int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc) 838e5395e92SAmir Vadai { 839e5395e92SAmir Vadai struct mlx4_cmd_mailbox *mailbox; 840e5395e92SAmir Vadai struct mlx4_set_port_prio2tc_context *context; 841e5395e92SAmir Vadai int err; 842e5395e92SAmir Vadai u32 in_mod; 843e5395e92SAmir Vadai int i; 844e5395e92SAmir Vadai 845e5395e92SAmir Vadai mailbox = mlx4_alloc_cmd_mailbox(dev); 846e5395e92SAmir Vadai if (IS_ERR(mailbox)) 847e5395e92SAmir Vadai return PTR_ERR(mailbox); 848e5395e92SAmir Vadai context = mailbox->buf; 849e5395e92SAmir Vadai memset(context, 0, sizeof *context); 850e5395e92SAmir Vadai 851e5395e92SAmir Vadai for (i = 0; i < MLX4_NUM_UP; i += 2) 852e5395e92SAmir Vadai context->prio2tc[i >> 1] = prio2tc[i] << 4 | prio2tc[i + 1]; 853e5395e92SAmir Vadai 854e5395e92SAmir Vadai in_mod = MLX4_SET_PORT_PRIO2TC << 8 | port; 855e5395e92SAmir Vadai err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 856e5395e92SAmir Vadai MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 857e5395e92SAmir Vadai 858e5395e92SAmir Vadai mlx4_free_cmd_mailbox(dev, mailbox); 859e5395e92SAmir Vadai return err; 860e5395e92SAmir Vadai } 861e5395e92SAmir Vadai EXPORT_SYMBOL(mlx4_SET_PORT_PRIO2TC); 862e5395e92SAmir Vadai 863e5395e92SAmir Vadai int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw, 864e5395e92SAmir Vadai u8 *pg, u16 *ratelimit) 865e5395e92SAmir Vadai { 866e5395e92SAmir Vadai struct mlx4_cmd_mailbox *mailbox; 867e5395e92SAmir Vadai struct mlx4_set_port_scheduler_context *context; 868e5395e92SAmir Vadai int err; 869e5395e92SAmir Vadai u32 in_mod; 870e5395e92SAmir Vadai int i; 871e5395e92SAmir Vadai 872e5395e92SAmir Vadai mailbox = mlx4_alloc_cmd_mailbox(dev); 873e5395e92SAmir Vadai if (IS_ERR(mailbox)) 874e5395e92SAmir Vadai return PTR_ERR(mailbox); 875e5395e92SAmir Vadai context = mailbox->buf; 876e5395e92SAmir Vadai memset(context, 0, sizeof *context); 877e5395e92SAmir Vadai 878e5395e92SAmir Vadai for (i = 0; i < MLX4_NUM_TC; i++) { 879e5395e92SAmir Vadai struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i]; 880e5395e92SAmir Vadai u16 r = ratelimit && ratelimit[i] ? ratelimit[i] : 881e5395e92SAmir Vadai MLX4_RATELIMIT_DEFAULT; 882e5395e92SAmir Vadai 883e5395e92SAmir Vadai tc->pg = htons(pg[i]); 884e5395e92SAmir Vadai tc->bw_precentage = htons(tc_tx_bw[i]); 885e5395e92SAmir Vadai 886e5395e92SAmir Vadai tc->max_bw_units = htons(MLX4_RATELIMIT_UNITS); 887e5395e92SAmir Vadai tc->max_bw_value = htons(r); 888e5395e92SAmir Vadai } 889e5395e92SAmir Vadai 890e5395e92SAmir Vadai in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port; 891e5395e92SAmir Vadai err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 892e5395e92SAmir Vadai MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 893e5395e92SAmir Vadai 894e5395e92SAmir Vadai mlx4_free_cmd_mailbox(dev, mailbox); 895e5395e92SAmir Vadai return err; 896e5395e92SAmir Vadai } 897e5395e92SAmir Vadai EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER); 898e5395e92SAmir Vadai 899ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, 900ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 901ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 902ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 903ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 904ffe455adSEugenia Emantayev { 905ffe455adSEugenia Emantayev int err = 0; 906ffe455adSEugenia Emantayev 907ffe455adSEugenia Emantayev return err; 908ffe455adSEugenia Emantayev } 909ffe455adSEugenia Emantayev 910ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 911ffe455adSEugenia Emantayev u64 mac, u64 clear, u8 mode) 912ffe455adSEugenia Emantayev { 913ffe455adSEugenia Emantayev return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 914ffe455adSEugenia Emantayev MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, 915ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 916ffe455adSEugenia Emantayev } 917ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); 918ffe455adSEugenia Emantayev 919ffe455adSEugenia Emantayev int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, 920ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 921ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 922ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 923ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 924ffe455adSEugenia Emantayev { 925ffe455adSEugenia Emantayev int err = 0; 926ffe455adSEugenia Emantayev 927ffe455adSEugenia Emantayev return err; 928ffe455adSEugenia Emantayev } 929ffe455adSEugenia Emantayev 930ffe455adSEugenia Emantayev int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, 931ffe455adSEugenia Emantayev u32 in_mod, struct mlx4_cmd_mailbox *outbox) 932ffe455adSEugenia Emantayev { 933ffe455adSEugenia Emantayev return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, 934ffe455adSEugenia Emantayev MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, 935ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 936ffe455adSEugenia Emantayev } 937ffe455adSEugenia Emantayev 938ffe455adSEugenia Emantayev int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, 939ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 940ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 941ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 942ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 943ffe455adSEugenia Emantayev { 94435fb9afbSEugenia Emantayev if (slave != dev->caps.function) 94535fb9afbSEugenia Emantayev return 0; 946ffe455adSEugenia Emantayev return mlx4_common_dump_eth_stats(dev, slave, 947ffe455adSEugenia Emantayev vhcr->in_modifier, outbox); 948ffe455adSEugenia Emantayev } 94993ece0c1SEugenia Emantayev 95093ece0c1SEugenia Emantayev void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap) 95193ece0c1SEugenia Emantayev { 95293ece0c1SEugenia Emantayev if (!mlx4_is_mfunc(dev)) { 95393ece0c1SEugenia Emantayev *stats_bitmap = 0; 95493ece0c1SEugenia Emantayev return; 95593ece0c1SEugenia Emantayev } 95693ece0c1SEugenia Emantayev 95793ece0c1SEugenia Emantayev *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK | 95893ece0c1SEugenia Emantayev MLX4_STATS_TRAFFIC_DROPS_MASK | 95993ece0c1SEugenia Emantayev MLX4_STATS_PORT_COUNTERS_MASK); 96093ece0c1SEugenia Emantayev 96193ece0c1SEugenia Emantayev if (mlx4_is_master(dev)) 96293ece0c1SEugenia Emantayev *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK; 96393ece0c1SEugenia Emantayev } 96493ece0c1SEugenia Emantayev EXPORT_SYMBOL(mlx4_set_stats_bitmap); 965