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}; 825a2cc190SJeff Kirsher int err; 835a2cc190SJeff Kirsher 845a2cc190SJeff Kirsher qp.qpn = *qpn; 855a2cc190SJeff Kirsher 865a2cc190SJeff Kirsher mac &= 0xffffffffffffULL; 875a2cc190SJeff Kirsher mac = cpu_to_be64(mac << 16); 885a2cc190SJeff Kirsher memcpy(&gid[10], &mac, ETH_ALEN); 895a2cc190SJeff Kirsher gid[5] = port; 905a2cc190SJeff Kirsher gid[7] = MLX4_UC_STEER << 1; 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}; 1045a2cc190SJeff Kirsher 1055a2cc190SJeff Kirsher qp.qpn = qpn; 1065a2cc190SJeff Kirsher mac &= 0xffffffffffffULL; 1075a2cc190SJeff Kirsher mac = cpu_to_be64(mac << 16); 1085a2cc190SJeff Kirsher memcpy(&gid[10], &mac, ETH_ALEN); 1095a2cc190SJeff Kirsher gid[5] = port; 1105a2cc190SJeff Kirsher gid[7] = MLX4_UC_STEER << 1; 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 593f470f8d4SLinus Torvalds int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port) 594f470f8d4SLinus Torvalds { 595f470f8d4SLinus Torvalds struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 596f470f8d4SLinus Torvalds u8 *inbuf, *outbuf; 597f470f8d4SLinus Torvalds int err, packet_error; 598f470f8d4SLinus Torvalds 599f470f8d4SLinus Torvalds inmailbox = mlx4_alloc_cmd_mailbox(dev); 600f470f8d4SLinus Torvalds if (IS_ERR(inmailbox)) 601f470f8d4SLinus Torvalds return PTR_ERR(inmailbox); 602f470f8d4SLinus Torvalds 603f470f8d4SLinus Torvalds outmailbox = mlx4_alloc_cmd_mailbox(dev); 604f470f8d4SLinus Torvalds if (IS_ERR(outmailbox)) { 605f470f8d4SLinus Torvalds mlx4_free_cmd_mailbox(dev, inmailbox); 606f470f8d4SLinus Torvalds return PTR_ERR(outmailbox); 607f470f8d4SLinus Torvalds } 608f470f8d4SLinus Torvalds 609f470f8d4SLinus Torvalds inbuf = inmailbox->buf; 610f470f8d4SLinus Torvalds outbuf = outmailbox->buf; 611f470f8d4SLinus Torvalds memset(inbuf, 0, 256); 612f470f8d4SLinus Torvalds memset(outbuf, 0, 256); 613f470f8d4SLinus Torvalds inbuf[0] = 1; 614f470f8d4SLinus Torvalds inbuf[1] = 1; 615f470f8d4SLinus Torvalds inbuf[2] = 1; 616f470f8d4SLinus Torvalds inbuf[3] = 1; 617f470f8d4SLinus Torvalds 618f470f8d4SLinus Torvalds *(__be16 *) (&inbuf[16]) = MLX4_ATTR_EXTENDED_PORT_INFO; 619f470f8d4SLinus Torvalds *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); 620f470f8d4SLinus Torvalds 621f470f8d4SLinus Torvalds err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, 622f9baff50SJack Morgenstein MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 623f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 624f470f8d4SLinus Torvalds 625f470f8d4SLinus Torvalds packet_error = be16_to_cpu(*(__be16 *) (outbuf + 4)); 626f470f8d4SLinus Torvalds 627f470f8d4SLinus Torvalds dev->caps.ext_port_cap[port] = (!err && !packet_error) ? 628f470f8d4SLinus Torvalds MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO 629f470f8d4SLinus Torvalds : 0; 630f470f8d4SLinus Torvalds 631f470f8d4SLinus Torvalds mlx4_free_cmd_mailbox(dev, inmailbox); 632f470f8d4SLinus Torvalds mlx4_free_cmd_mailbox(dev, outmailbox); 633f470f8d4SLinus Torvalds return err; 634f470f8d4SLinus Torvalds } 635f470f8d4SLinus Torvalds 636ffe455adSEugenia Emantayev static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, 637ffe455adSEugenia Emantayev u8 op_mod, struct mlx4_cmd_mailbox *inbox) 638ffe455adSEugenia Emantayev { 639ffe455adSEugenia Emantayev struct mlx4_priv *priv = mlx4_priv(dev); 640ffe455adSEugenia Emantayev struct mlx4_port_info *port_info; 641ffe455adSEugenia Emantayev struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; 642ffe455adSEugenia Emantayev struct mlx4_slave_state *slave_st = &master->slave_state[slave]; 643ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *qpn_context; 644ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *gen_context; 645ffe455adSEugenia Emantayev int reset_qkey_viols; 646ffe455adSEugenia Emantayev int port; 647ffe455adSEugenia Emantayev int is_eth; 648ffe455adSEugenia Emantayev u32 in_modifier; 649ffe455adSEugenia Emantayev u32 promisc; 650ffe455adSEugenia Emantayev u16 mtu, prev_mtu; 651ffe455adSEugenia Emantayev int err; 652ffe455adSEugenia Emantayev int i; 653ffe455adSEugenia Emantayev __be32 agg_cap_mask; 654ffe455adSEugenia Emantayev __be32 slave_cap_mask; 655ffe455adSEugenia Emantayev __be32 new_cap_mask; 656ffe455adSEugenia Emantayev 657ffe455adSEugenia Emantayev port = in_mod & 0xff; 658ffe455adSEugenia Emantayev in_modifier = in_mod >> 8; 659ffe455adSEugenia Emantayev is_eth = op_mod; 660ffe455adSEugenia Emantayev port_info = &priv->port[port]; 661ffe455adSEugenia Emantayev 662ffe455adSEugenia Emantayev /* Slaves cannot perform SET_PORT operations except changing MTU */ 663ffe455adSEugenia Emantayev if (is_eth) { 664ffe455adSEugenia Emantayev if (slave != dev->caps.function && 665ffe455adSEugenia Emantayev in_modifier != MLX4_SET_PORT_GENERAL) { 666ffe455adSEugenia Emantayev mlx4_warn(dev, "denying SET_PORT for slave:%d\n", 667ffe455adSEugenia Emantayev slave); 668ffe455adSEugenia Emantayev return -EINVAL; 669ffe455adSEugenia Emantayev } 670ffe455adSEugenia Emantayev switch (in_modifier) { 671ffe455adSEugenia Emantayev case MLX4_SET_PORT_RQP_CALC: 672ffe455adSEugenia Emantayev qpn_context = inbox->buf; 673ffe455adSEugenia Emantayev qpn_context->base_qpn = 674ffe455adSEugenia Emantayev cpu_to_be32(port_info->base_qpn); 675ffe455adSEugenia Emantayev qpn_context->n_mac = 0x7; 676ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->promisc) >> 677ffe455adSEugenia Emantayev SET_PORT_PROMISC_SHIFT; 678ffe455adSEugenia Emantayev qpn_context->promisc = cpu_to_be32( 679ffe455adSEugenia Emantayev promisc << SET_PORT_PROMISC_SHIFT | 680ffe455adSEugenia Emantayev port_info->base_qpn); 681ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->mcast) >> 682ffe455adSEugenia Emantayev SET_PORT_MC_PROMISC_SHIFT; 683ffe455adSEugenia Emantayev qpn_context->mcast = cpu_to_be32( 684ffe455adSEugenia Emantayev promisc << SET_PORT_MC_PROMISC_SHIFT | 685ffe455adSEugenia Emantayev port_info->base_qpn); 686ffe455adSEugenia Emantayev break; 687ffe455adSEugenia Emantayev case MLX4_SET_PORT_GENERAL: 688ffe455adSEugenia Emantayev gen_context = inbox->buf; 689ffe455adSEugenia Emantayev /* Mtu is configured as the max MTU among all the 690ffe455adSEugenia Emantayev * the functions on the port. */ 691ffe455adSEugenia Emantayev mtu = be16_to_cpu(gen_context->mtu); 692ffe455adSEugenia Emantayev mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]); 693ffe455adSEugenia Emantayev prev_mtu = slave_st->mtu[port]; 694ffe455adSEugenia Emantayev slave_st->mtu[port] = mtu; 695ffe455adSEugenia Emantayev if (mtu > master->max_mtu[port]) 696ffe455adSEugenia Emantayev master->max_mtu[port] = mtu; 697ffe455adSEugenia Emantayev if (mtu < prev_mtu && prev_mtu == 698ffe455adSEugenia Emantayev master->max_mtu[port]) { 699ffe455adSEugenia Emantayev slave_st->mtu[port] = mtu; 700ffe455adSEugenia Emantayev master->max_mtu[port] = mtu; 701ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) { 702ffe455adSEugenia Emantayev master->max_mtu[port] = 703ffe455adSEugenia Emantayev max(master->max_mtu[port], 704ffe455adSEugenia Emantayev master->slave_state[i].mtu[port]); 705ffe455adSEugenia Emantayev } 706ffe455adSEugenia Emantayev } 707ffe455adSEugenia Emantayev 708ffe455adSEugenia Emantayev gen_context->mtu = cpu_to_be16(master->max_mtu[port]); 709ffe455adSEugenia Emantayev break; 710ffe455adSEugenia Emantayev } 711ffe455adSEugenia Emantayev return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, 712ffe455adSEugenia Emantayev MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 713ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 714ffe455adSEugenia Emantayev } 715ffe455adSEugenia Emantayev 716ffe455adSEugenia Emantayev /* For IB, we only consider: 717ffe455adSEugenia Emantayev * - The capability mask, which is set to the aggregate of all 718ffe455adSEugenia Emantayev * slave function capabilities 719ffe455adSEugenia Emantayev * - The QKey violatin counter - reset according to each request. 720ffe455adSEugenia Emantayev */ 721ffe455adSEugenia Emantayev 722ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 723ffe455adSEugenia Emantayev reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; 724ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[2]; 725ffe455adSEugenia Emantayev } else { 726ffe455adSEugenia Emantayev reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; 727ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[1]; 728ffe455adSEugenia Emantayev } 729ffe455adSEugenia Emantayev 730ffe455adSEugenia Emantayev agg_cap_mask = 0; 731ffe455adSEugenia Emantayev slave_cap_mask = 732ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; 733ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; 734ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) 735ffe455adSEugenia Emantayev agg_cap_mask |= 736ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[i].ib_cap_mask[port]; 737ffe455adSEugenia Emantayev 738ffe455adSEugenia Emantayev /* only clear mailbox for guests. Master may be setting 739ffe455adSEugenia Emantayev * MTU or PKEY table size 740ffe455adSEugenia Emantayev */ 741ffe455adSEugenia Emantayev if (slave != dev->caps.function) 742ffe455adSEugenia Emantayev memset(inbox->buf, 0, 256); 743ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 744ffe455adSEugenia Emantayev *(u8 *) inbox->buf = !!reset_qkey_viols << 6; 745ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[2] = agg_cap_mask; 746ffe455adSEugenia Emantayev } else { 747ffe455adSEugenia Emantayev ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; 748ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[1] = agg_cap_mask; 749ffe455adSEugenia Emantayev } 750ffe455adSEugenia Emantayev 751ffe455adSEugenia Emantayev err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, 752ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 753ffe455adSEugenia Emantayev if (err) 754ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = 755ffe455adSEugenia Emantayev slave_cap_mask; 756ffe455adSEugenia Emantayev return err; 757ffe455adSEugenia Emantayev } 758ffe455adSEugenia Emantayev 759ffe455adSEugenia Emantayev int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, 760ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 761ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 762ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 763ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 764ffe455adSEugenia Emantayev { 765ffe455adSEugenia Emantayev return mlx4_common_set_port(dev, slave, vhcr->in_modifier, 766ffe455adSEugenia Emantayev vhcr->op_modifier, inbox); 767ffe455adSEugenia Emantayev } 768ffe455adSEugenia Emantayev 7695a2cc190SJeff Kirsher int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) 7705a2cc190SJeff Kirsher { 7715a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 7725a2cc190SJeff Kirsher int err; 7735a2cc190SJeff Kirsher 7745a2cc190SJeff Kirsher if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) 7755a2cc190SJeff Kirsher return 0; 7765a2cc190SJeff Kirsher 7775a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 7785a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 7795a2cc190SJeff Kirsher return PTR_ERR(mailbox); 7805a2cc190SJeff Kirsher 7815a2cc190SJeff Kirsher memset(mailbox->buf, 0, 256); 7825a2cc190SJeff Kirsher 7835a2cc190SJeff Kirsher ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; 7845a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 785f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 7865a2cc190SJeff Kirsher 7875a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 7885a2cc190SJeff Kirsher return err; 7895a2cc190SJeff Kirsher } 790ffe455adSEugenia Emantayev 791cb9ffb76SJoerg Roedel int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 792ffe455adSEugenia Emantayev u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 793ffe455adSEugenia Emantayev { 794ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 795ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *context; 796ffe455adSEugenia Emantayev int err; 797ffe455adSEugenia Emantayev u32 in_mod; 798ffe455adSEugenia Emantayev 799ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 800ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 801ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 802ffe455adSEugenia Emantayev context = mailbox->buf; 803ffe455adSEugenia Emantayev memset(context, 0, sizeof *context); 804ffe455adSEugenia Emantayev 805ffe455adSEugenia Emantayev context->flags = SET_PORT_GEN_ALL_VALID; 806ffe455adSEugenia Emantayev context->mtu = cpu_to_be16(mtu); 807ffe455adSEugenia Emantayev context->pptx = (pptx * (!pfctx)) << 7; 808ffe455adSEugenia Emantayev context->pfctx = pfctx; 809ffe455adSEugenia Emantayev context->pprx = (pprx * (!pfcrx)) << 7; 810ffe455adSEugenia Emantayev context->pfcrx = pfcrx; 811ffe455adSEugenia Emantayev 812ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 813ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 814ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 815ffe455adSEugenia Emantayev 816ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 817ffe455adSEugenia Emantayev return err; 818ffe455adSEugenia Emantayev } 819ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_general); 820ffe455adSEugenia Emantayev 821cb9ffb76SJoerg Roedel int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 822ffe455adSEugenia Emantayev u8 promisc) 823ffe455adSEugenia Emantayev { 824ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 825ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *context; 826ffe455adSEugenia Emantayev int err; 827ffe455adSEugenia Emantayev u32 in_mod; 828ffe455adSEugenia Emantayev u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? 829ffe455adSEugenia Emantayev MCAST_DIRECT : MCAST_DEFAULT; 830ffe455adSEugenia Emantayev 831ffe455adSEugenia Emantayev if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && 832ffe455adSEugenia Emantayev dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) 833ffe455adSEugenia Emantayev return 0; 834ffe455adSEugenia Emantayev 835ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 836ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 837ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 838ffe455adSEugenia Emantayev context = mailbox->buf; 839ffe455adSEugenia Emantayev memset(context, 0, sizeof *context); 840ffe455adSEugenia Emantayev 841ffe455adSEugenia Emantayev context->base_qpn = cpu_to_be32(base_qpn); 842ffe455adSEugenia Emantayev context->n_mac = dev->caps.log_num_macs; 843ffe455adSEugenia Emantayev context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | 844ffe455adSEugenia Emantayev base_qpn); 845ffe455adSEugenia Emantayev context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | 846ffe455adSEugenia Emantayev base_qpn); 847ffe455adSEugenia Emantayev context->intra_no_vlan = 0; 848ffe455adSEugenia Emantayev context->no_vlan = MLX4_NO_VLAN_IDX; 849ffe455adSEugenia Emantayev context->intra_vlan_miss = 0; 850ffe455adSEugenia Emantayev context->vlan_miss = MLX4_VLAN_MISS_IDX; 851ffe455adSEugenia Emantayev 852ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 853ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 854ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 855ffe455adSEugenia Emantayev 856ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 857ffe455adSEugenia Emantayev return err; 858ffe455adSEugenia Emantayev } 859ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); 860ffe455adSEugenia Emantayev 861ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, 862ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 863ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 864ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 865ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 866ffe455adSEugenia Emantayev { 867ffe455adSEugenia Emantayev int err = 0; 868ffe455adSEugenia Emantayev 869ffe455adSEugenia Emantayev return err; 870ffe455adSEugenia Emantayev } 871ffe455adSEugenia Emantayev 872ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 873ffe455adSEugenia Emantayev u64 mac, u64 clear, u8 mode) 874ffe455adSEugenia Emantayev { 875ffe455adSEugenia Emantayev return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 876ffe455adSEugenia Emantayev MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, 877ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 878ffe455adSEugenia Emantayev } 879ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); 880ffe455adSEugenia Emantayev 881ffe455adSEugenia Emantayev int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, 882ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 883ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 884ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 885ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 886ffe455adSEugenia Emantayev { 887ffe455adSEugenia Emantayev int err = 0; 888ffe455adSEugenia Emantayev 889ffe455adSEugenia Emantayev return err; 890ffe455adSEugenia Emantayev } 891ffe455adSEugenia Emantayev 892ffe455adSEugenia Emantayev int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, 893ffe455adSEugenia Emantayev u32 in_mod, struct mlx4_cmd_mailbox *outbox) 894ffe455adSEugenia Emantayev { 895ffe455adSEugenia Emantayev return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, 896ffe455adSEugenia Emantayev MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, 897ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 898ffe455adSEugenia Emantayev } 899ffe455adSEugenia Emantayev 900ffe455adSEugenia Emantayev int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, 901ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 902ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 903ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 904ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 905ffe455adSEugenia Emantayev { 90635fb9afbSEugenia Emantayev if (slave != dev->caps.function) 90735fb9afbSEugenia Emantayev return 0; 908ffe455adSEugenia Emantayev return mlx4_common_dump_eth_stats(dev, slave, 909ffe455adSEugenia Emantayev vhcr->in_modifier, outbox); 910ffe455adSEugenia Emantayev } 91193ece0c1SEugenia Emantayev 91293ece0c1SEugenia Emantayev void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap) 91393ece0c1SEugenia Emantayev { 91493ece0c1SEugenia Emantayev if (!mlx4_is_mfunc(dev)) { 91593ece0c1SEugenia Emantayev *stats_bitmap = 0; 91693ece0c1SEugenia Emantayev return; 91793ece0c1SEugenia Emantayev } 91893ece0c1SEugenia Emantayev 91993ece0c1SEugenia Emantayev *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK | 92093ece0c1SEugenia Emantayev MLX4_STATS_TRAFFIC_DROPS_MASK | 92193ece0c1SEugenia Emantayev MLX4_STATS_PORT_COUNTERS_MASK); 92293ece0c1SEugenia Emantayev 92393ece0c1SEugenia Emantayev if (mlx4_is_master(dev)) 92493ece0c1SEugenia Emantayev *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK; 92593ece0c1SEugenia Emantayev } 92693ece0c1SEugenia Emantayev EXPORT_SYMBOL(mlx4_set_stats_bitmap); 927