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> 35c59fec20SEugenia Emantayev #include <linux/if_vlan.h> 36ee40fa06SPaul Gortmaker #include <linux/export.h> 375a2cc190SJeff Kirsher 385a2cc190SJeff Kirsher #include <linux/mlx4/cmd.h> 395a2cc190SJeff Kirsher 405a2cc190SJeff Kirsher #include "mlx4.h" 415a2cc190SJeff Kirsher 425a2cc190SJeff Kirsher #define MLX4_MAC_VALID (1ull << 63) 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 785a2cc190SJeff Kirsher static int validate_index(struct mlx4_dev *dev, 795a2cc190SJeff Kirsher struct mlx4_mac_table *table, int index) 805a2cc190SJeff Kirsher { 815a2cc190SJeff Kirsher int err = 0; 825a2cc190SJeff Kirsher 835a2cc190SJeff Kirsher if (index < 0 || index >= table->max || !table->entries[index]) { 845a2cc190SJeff Kirsher mlx4_warn(dev, "No valid Mac entry for the given index\n"); 855a2cc190SJeff Kirsher err = -EINVAL; 865a2cc190SJeff Kirsher } 875a2cc190SJeff Kirsher return err; 885a2cc190SJeff Kirsher } 895a2cc190SJeff Kirsher 905a2cc190SJeff Kirsher static int find_index(struct mlx4_dev *dev, 915a2cc190SJeff Kirsher struct mlx4_mac_table *table, u64 mac) 925a2cc190SJeff Kirsher { 935a2cc190SJeff Kirsher int i; 94ffe455adSEugenia Emantayev 955a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 96ffe455adSEugenia Emantayev if ((mac & MLX4_MAC_MASK) == 97ffe455adSEugenia Emantayev (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) 985a2cc190SJeff Kirsher return i; 995a2cc190SJeff Kirsher } 1005a2cc190SJeff Kirsher /* Mac not found */ 1015a2cc190SJeff Kirsher return -EINVAL; 1025a2cc190SJeff Kirsher } 1035a2cc190SJeff Kirsher 104ffe455adSEugenia Emantayev static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, 105ffe455adSEugenia Emantayev __be64 *entries) 106ffe455adSEugenia Emantayev { 107ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 108ffe455adSEugenia Emantayev u32 in_mod; 109ffe455adSEugenia Emantayev int err; 110ffe455adSEugenia Emantayev 111ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 112ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 113ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 114ffe455adSEugenia Emantayev 115ffe455adSEugenia Emantayev memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); 116ffe455adSEugenia Emantayev 117ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; 118ffe455adSEugenia Emantayev 119ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 120ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 121ffe455adSEugenia Emantayev 122ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 123ffe455adSEugenia Emantayev return err; 124ffe455adSEugenia Emantayev } 125ffe455adSEugenia Emantayev 126297e0dadSMoni Shoua int mlx4_find_cached_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *idx) 127297e0dadSMoni Shoua { 128297e0dadSMoni Shoua struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 129297e0dadSMoni Shoua struct mlx4_mac_table *table = &info->mac_table; 130297e0dadSMoni Shoua int i; 131297e0dadSMoni Shoua 132297e0dadSMoni Shoua for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 133297e0dadSMoni Shoua if (!table->refs[i]) 134297e0dadSMoni Shoua continue; 135297e0dadSMoni Shoua 136297e0dadSMoni Shoua if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 137297e0dadSMoni Shoua *idx = i; 138297e0dadSMoni Shoua return 0; 139297e0dadSMoni Shoua } 140297e0dadSMoni Shoua } 141297e0dadSMoni Shoua 142297e0dadSMoni Shoua return -ENOENT; 143297e0dadSMoni Shoua } 144297e0dadSMoni Shoua EXPORT_SYMBOL_GPL(mlx4_find_cached_mac); 145297e0dadSMoni Shoua 146ffe455adSEugenia Emantayev int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 147ffe455adSEugenia Emantayev { 148ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 149ffe455adSEugenia Emantayev struct mlx4_mac_table *table = &info->mac_table; 150ffe455adSEugenia Emantayev int i, err = 0; 151ffe455adSEugenia Emantayev int free = -1; 152ffe455adSEugenia Emantayev 153ffe455adSEugenia Emantayev mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", 154ffe455adSEugenia Emantayev (unsigned long long) mac, port); 155ffe455adSEugenia Emantayev 156ffe455adSEugenia Emantayev mutex_lock(&table->mutex); 157ffe455adSEugenia Emantayev for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 158ffe455adSEugenia Emantayev if (free < 0 && !table->entries[i]) { 159ffe455adSEugenia Emantayev free = i; 160ffe455adSEugenia Emantayev continue; 161ffe455adSEugenia Emantayev } 162ffe455adSEugenia Emantayev 163ffe455adSEugenia Emantayev if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 1646ce71acdSRony Efraim /* MAC already registered, increment ref count */ 1656ce71acdSRony Efraim err = i; 1666ce71acdSRony Efraim ++table->refs[i]; 167ffe455adSEugenia Emantayev goto out; 168ffe455adSEugenia Emantayev } 169ffe455adSEugenia Emantayev } 170ffe455adSEugenia Emantayev 171ffe455adSEugenia Emantayev mlx4_dbg(dev, "Free MAC index is %d\n", free); 172ffe455adSEugenia Emantayev 173ffe455adSEugenia Emantayev if (table->total == table->max) { 174ffe455adSEugenia Emantayev /* No free mac entries */ 175ffe455adSEugenia Emantayev err = -ENOSPC; 176ffe455adSEugenia Emantayev goto out; 177ffe455adSEugenia Emantayev } 178ffe455adSEugenia Emantayev 179ffe455adSEugenia Emantayev /* Register new MAC */ 180ffe455adSEugenia Emantayev table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); 181ffe455adSEugenia Emantayev 182ffe455adSEugenia Emantayev err = mlx4_set_port_mac_table(dev, port, table->entries); 183ffe455adSEugenia Emantayev if (unlikely(err)) { 184ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 185ffe455adSEugenia Emantayev (unsigned long long) mac); 186ffe455adSEugenia Emantayev table->entries[free] = 0; 187ffe455adSEugenia Emantayev goto out; 188ffe455adSEugenia Emantayev } 1896ce71acdSRony Efraim table->refs[free] = 1; 190ffe455adSEugenia Emantayev err = free; 191ffe455adSEugenia Emantayev ++table->total; 192ffe455adSEugenia Emantayev out: 193ffe455adSEugenia Emantayev mutex_unlock(&table->mutex); 194ffe455adSEugenia Emantayev return err; 195ffe455adSEugenia Emantayev } 196ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(__mlx4_register_mac); 197ffe455adSEugenia Emantayev 198ffe455adSEugenia Emantayev int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 199ffe455adSEugenia Emantayev { 200e7dbeba8SJack Morgenstein u64 out_param = 0; 201acddd5ddSJack Morgenstein int err = -EINVAL; 202ffe455adSEugenia Emantayev 203ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 204acddd5ddSJack Morgenstein if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) { 205acddd5ddSJack Morgenstein err = mlx4_cmd_imm(dev, mac, &out_param, 206acddd5ddSJack Morgenstein ((u32) port) << 8 | (u32) RES_MAC, 207acddd5ddSJack Morgenstein RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 208acddd5ddSJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 209acddd5ddSJack Morgenstein } 210acddd5ddSJack Morgenstein if (err && err == -EINVAL && mlx4_is_slave(dev)) { 211acddd5ddSJack Morgenstein /* retry using old REG_MAC format */ 212ffe455adSEugenia Emantayev set_param_l(&out_param, port); 213ffe455adSEugenia Emantayev err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 214ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 215ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 216acddd5ddSJack Morgenstein if (!err) 217acddd5ddSJack Morgenstein dev->flags |= MLX4_FLAG_OLD_REG_MAC; 218acddd5ddSJack Morgenstein } 219ffe455adSEugenia Emantayev if (err) 220ffe455adSEugenia Emantayev return err; 221ffe455adSEugenia Emantayev 222ffe455adSEugenia Emantayev return get_param_l(&out_param); 223ffe455adSEugenia Emantayev } 224ffe455adSEugenia Emantayev return __mlx4_register_mac(dev, port, mac); 225ffe455adSEugenia Emantayev } 226ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(mlx4_register_mac); 227ffe455adSEugenia Emantayev 22816a10ffdSYan Burman int mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port) 22916a10ffdSYan Burman { 23016a10ffdSYan Burman return dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] + 23116a10ffdSYan Burman (port - 1) * (1 << dev->caps.log_num_macs); 23216a10ffdSYan Burman } 23316a10ffdSYan Burman EXPORT_SYMBOL_GPL(mlx4_get_base_qpn); 234ffe455adSEugenia Emantayev 235ffe455adSEugenia Emantayev void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 236ffe455adSEugenia Emantayev { 237ffe455adSEugenia Emantayev struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 238ffe455adSEugenia Emantayev struct mlx4_mac_table *table = &info->mac_table; 239ffe455adSEugenia Emantayev int index; 240ffe455adSEugenia Emantayev 2415a2cc190SJeff Kirsher mutex_lock(&table->mutex); 2426ce71acdSRony Efraim index = find_index(dev, table, mac); 2435a2cc190SJeff Kirsher 2445a2cc190SJeff Kirsher if (validate_index(dev, table, index)) 2455a2cc190SJeff Kirsher goto out; 2466ce71acdSRony Efraim if (--table->refs[index]) { 2476ce71acdSRony Efraim mlx4_dbg(dev, "Have more references for index %d," 2486ce71acdSRony Efraim "no need to modify mac table\n", index); 2496ce71acdSRony Efraim goto out; 2506ce71acdSRony Efraim } 2515a2cc190SJeff Kirsher 2525a2cc190SJeff Kirsher table->entries[index] = 0; 2535a2cc190SJeff Kirsher mlx4_set_port_mac_table(dev, port, table->entries); 2545a2cc190SJeff Kirsher --table->total; 2555a2cc190SJeff Kirsher out: 2565a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 2575a2cc190SJeff Kirsher } 258ffe455adSEugenia Emantayev EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); 259ffe455adSEugenia Emantayev 260ffe455adSEugenia Emantayev void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 261ffe455adSEugenia Emantayev { 262e7dbeba8SJack Morgenstein u64 out_param = 0; 263ffe455adSEugenia Emantayev 264ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 265acddd5ddSJack Morgenstein if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) { 266acddd5ddSJack Morgenstein (void) mlx4_cmd_imm(dev, mac, &out_param, 267acddd5ddSJack Morgenstein ((u32) port) << 8 | (u32) RES_MAC, 268acddd5ddSJack Morgenstein RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, 269acddd5ddSJack Morgenstein MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 270acddd5ddSJack Morgenstein } else { 271acddd5ddSJack Morgenstein /* use old unregister mac format */ 272ffe455adSEugenia Emantayev set_param_l(&out_param, port); 273162344edSOr Gerlitz (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 274ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, 275ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 276acddd5ddSJack Morgenstein } 277ffe455adSEugenia Emantayev return; 278ffe455adSEugenia Emantayev } 279ffe455adSEugenia Emantayev __mlx4_unregister_mac(dev, port, mac); 280ffe455adSEugenia Emantayev return; 281ffe455adSEugenia Emantayev } 2825a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_unregister_mac); 2835a2cc190SJeff Kirsher 28416a10ffdSYan Burman int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) 2855a2cc190SJeff Kirsher { 2865a2cc190SJeff Kirsher struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 2875a2cc190SJeff Kirsher struct mlx4_mac_table *table = &info->mac_table; 288ffe455adSEugenia Emantayev int index = qpn - info->base_qpn; 289ffe455adSEugenia Emantayev int err = 0; 2905a2cc190SJeff Kirsher 291ffe455adSEugenia Emantayev /* CX1 doesn't support multi-functions */ 2925a2cc190SJeff Kirsher mutex_lock(&table->mutex); 2935a2cc190SJeff Kirsher 2945a2cc190SJeff Kirsher err = validate_index(dev, table, index); 2955a2cc190SJeff Kirsher if (err) 2965a2cc190SJeff Kirsher goto out; 2975a2cc190SJeff Kirsher 2985a2cc190SJeff Kirsher table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID); 2995a2cc190SJeff Kirsher 3005a2cc190SJeff Kirsher err = mlx4_set_port_mac_table(dev, port, table->entries); 3015a2cc190SJeff Kirsher if (unlikely(err)) { 302ffe455adSEugenia Emantayev mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 303ffe455adSEugenia Emantayev (unsigned long long) new_mac); 3045a2cc190SJeff Kirsher table->entries[index] = 0; 3055a2cc190SJeff Kirsher } 3065a2cc190SJeff Kirsher out: 3075a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 3085a2cc190SJeff Kirsher return err; 3095a2cc190SJeff Kirsher } 31016a10ffdSYan Burman EXPORT_SYMBOL_GPL(__mlx4_replace_mac); 311ffe455adSEugenia Emantayev 3125a2cc190SJeff Kirsher static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, 3135a2cc190SJeff Kirsher __be32 *entries) 3145a2cc190SJeff Kirsher { 3155a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 3165a2cc190SJeff Kirsher u32 in_mod; 3175a2cc190SJeff Kirsher int err; 3185a2cc190SJeff Kirsher 3195a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 3205a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 3215a2cc190SJeff Kirsher return PTR_ERR(mailbox); 3225a2cc190SJeff Kirsher 3235a2cc190SJeff Kirsher memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); 3245a2cc190SJeff Kirsher in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; 3255a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 326162226a1SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 3275a2cc190SJeff Kirsher 3285a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 3295a2cc190SJeff Kirsher 3305a2cc190SJeff Kirsher return err; 3315a2cc190SJeff Kirsher } 3325a2cc190SJeff Kirsher 3335a2cc190SJeff Kirsher int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) 3345a2cc190SJeff Kirsher { 3355a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 3365a2cc190SJeff Kirsher int i; 3375a2cc190SJeff Kirsher 3385a2cc190SJeff Kirsher for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) { 3395a2cc190SJeff Kirsher if (table->refs[i] && 3405a2cc190SJeff Kirsher (vid == (MLX4_VLAN_MASK & 3415a2cc190SJeff Kirsher be32_to_cpu(table->entries[i])))) { 3425a2cc190SJeff Kirsher /* VLAN already registered, increase reference count */ 3435a2cc190SJeff Kirsher *idx = i; 3445a2cc190SJeff Kirsher return 0; 3455a2cc190SJeff Kirsher } 3465a2cc190SJeff Kirsher } 3475a2cc190SJeff Kirsher 3485a2cc190SJeff Kirsher return -ENOENT; 3495a2cc190SJeff Kirsher } 3505a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); 3515a2cc190SJeff Kirsher 3523f7fb021SRony Efraim int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, 353ffe455adSEugenia Emantayev int *index) 3545a2cc190SJeff Kirsher { 3555a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 3565a2cc190SJeff Kirsher int i, err = 0; 3575a2cc190SJeff Kirsher int free = -1; 3585a2cc190SJeff Kirsher 3595a2cc190SJeff Kirsher mutex_lock(&table->mutex); 360e72ebf5aSYevgeny Petrilin 361e72ebf5aSYevgeny Petrilin if (table->total == table->max) { 362e72ebf5aSYevgeny Petrilin /* No free vlan entries */ 363e72ebf5aSYevgeny Petrilin err = -ENOSPC; 364e72ebf5aSYevgeny Petrilin goto out; 365e72ebf5aSYevgeny Petrilin } 366e72ebf5aSYevgeny Petrilin 3675a2cc190SJeff Kirsher for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { 3685a2cc190SJeff Kirsher if (free < 0 && (table->refs[i] == 0)) { 3695a2cc190SJeff Kirsher free = i; 3705a2cc190SJeff Kirsher continue; 3715a2cc190SJeff Kirsher } 3725a2cc190SJeff Kirsher 3735a2cc190SJeff Kirsher if (table->refs[i] && 3745a2cc190SJeff Kirsher (vlan == (MLX4_VLAN_MASK & 3755a2cc190SJeff Kirsher be32_to_cpu(table->entries[i])))) { 3765a2cc190SJeff Kirsher /* Vlan already registered, increase references count */ 3775a2cc190SJeff Kirsher *index = i; 3785a2cc190SJeff Kirsher ++table->refs[i]; 3795a2cc190SJeff Kirsher goto out; 3805a2cc190SJeff Kirsher } 3815a2cc190SJeff Kirsher } 3825a2cc190SJeff Kirsher 3835a2cc190SJeff Kirsher if (free < 0) { 3845a2cc190SJeff Kirsher err = -ENOMEM; 3855a2cc190SJeff Kirsher goto out; 3865a2cc190SJeff Kirsher } 3875a2cc190SJeff Kirsher 388ffe455adSEugenia Emantayev /* Register new VLAN */ 3895a2cc190SJeff Kirsher table->refs[free] = 1; 3905a2cc190SJeff Kirsher table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); 3915a2cc190SJeff Kirsher 3925a2cc190SJeff Kirsher err = mlx4_set_port_vlan_table(dev, port, table->entries); 3935a2cc190SJeff Kirsher if (unlikely(err)) { 3945a2cc190SJeff Kirsher mlx4_warn(dev, "Failed adding vlan: %u\n", vlan); 3955a2cc190SJeff Kirsher table->refs[free] = 0; 3965a2cc190SJeff Kirsher table->entries[free] = 0; 3975a2cc190SJeff Kirsher goto out; 3985a2cc190SJeff Kirsher } 3995a2cc190SJeff Kirsher 4005a2cc190SJeff Kirsher *index = free; 4015a2cc190SJeff Kirsher ++table->total; 4025a2cc190SJeff Kirsher out: 4035a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 4045a2cc190SJeff Kirsher return err; 4055a2cc190SJeff Kirsher } 406ffe455adSEugenia Emantayev 407ffe455adSEugenia Emantayev int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) 408ffe455adSEugenia Emantayev { 409e7dbeba8SJack Morgenstein u64 out_param = 0; 410ffe455adSEugenia Emantayev int err; 411ffe455adSEugenia Emantayev 412162226a1SJack Morgenstein if (vlan > 4095) 413162226a1SJack Morgenstein return -EINVAL; 414162226a1SJack Morgenstein 415ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 416acddd5ddSJack Morgenstein err = mlx4_cmd_imm(dev, vlan, &out_param, 417acddd5ddSJack Morgenstein ((u32) port) << 8 | (u32) RES_VLAN, 418ffe455adSEugenia Emantayev RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 419ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 420ffe455adSEugenia Emantayev if (!err) 421ffe455adSEugenia Emantayev *index = get_param_l(&out_param); 422ffe455adSEugenia Emantayev 423ffe455adSEugenia Emantayev return err; 424ffe455adSEugenia Emantayev } 425ffe455adSEugenia Emantayev return __mlx4_register_vlan(dev, port, vlan, index); 426ffe455adSEugenia Emantayev } 4275a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_register_vlan); 4285a2cc190SJeff Kirsher 4292009d005SJack Morgenstein void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) 4305a2cc190SJeff Kirsher { 4315a2cc190SJeff Kirsher struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 4322009d005SJack Morgenstein int index; 4332009d005SJack Morgenstein 4342009d005SJack Morgenstein mutex_lock(&table->mutex); 4352009d005SJack Morgenstein if (mlx4_find_cached_vlan(dev, port, vlan, &index)) { 4362009d005SJack Morgenstein mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan); 4372009d005SJack Morgenstein goto out; 4382009d005SJack Morgenstein } 4395a2cc190SJeff Kirsher 4405a2cc190SJeff Kirsher if (index < MLX4_VLAN_REGULAR) { 4415a2cc190SJeff Kirsher mlx4_warn(dev, "Trying to free special vlan index %d\n", index); 4425a2cc190SJeff Kirsher goto out; 4435a2cc190SJeff Kirsher } 4442009d005SJack Morgenstein 4455a2cc190SJeff Kirsher if (--table->refs[index]) { 4462009d005SJack Morgenstein mlx4_dbg(dev, "Have %d more references for index %d," 4472009d005SJack Morgenstein "no need to modify vlan table\n", table->refs[index], 4482009d005SJack Morgenstein index); 4495a2cc190SJeff Kirsher goto out; 4505a2cc190SJeff Kirsher } 4515a2cc190SJeff Kirsher table->entries[index] = 0; 4525a2cc190SJeff Kirsher mlx4_set_port_vlan_table(dev, port, table->entries); 4535a2cc190SJeff Kirsher --table->total; 4545a2cc190SJeff Kirsher out: 4555a2cc190SJeff Kirsher mutex_unlock(&table->mutex); 4565a2cc190SJeff Kirsher } 457ffe455adSEugenia Emantayev 4582009d005SJack Morgenstein void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) 459ffe455adSEugenia Emantayev { 460162226a1SJack Morgenstein u64 out_param = 0; 461ffe455adSEugenia Emantayev 462ffe455adSEugenia Emantayev if (mlx4_is_mfunc(dev)) { 4632009d005SJack Morgenstein (void) mlx4_cmd_imm(dev, vlan, &out_param, 464acddd5ddSJack Morgenstein ((u32) port) << 8 | (u32) RES_VLAN, 465162226a1SJack Morgenstein RES_OP_RESERVE_AND_MAP, 466ffe455adSEugenia Emantayev MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, 467ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 468ffe455adSEugenia Emantayev return; 469ffe455adSEugenia Emantayev } 4702009d005SJack Morgenstein __mlx4_unregister_vlan(dev, port, vlan); 471ffe455adSEugenia Emantayev } 4725a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); 4735a2cc190SJeff Kirsher 4745a2cc190SJeff Kirsher int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) 4755a2cc190SJeff Kirsher { 4765a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 4775a2cc190SJeff Kirsher u8 *inbuf, *outbuf; 4785a2cc190SJeff Kirsher int err; 4795a2cc190SJeff Kirsher 4805a2cc190SJeff Kirsher inmailbox = mlx4_alloc_cmd_mailbox(dev); 4815a2cc190SJeff Kirsher if (IS_ERR(inmailbox)) 4825a2cc190SJeff Kirsher return PTR_ERR(inmailbox); 4835a2cc190SJeff Kirsher 4845a2cc190SJeff Kirsher outmailbox = mlx4_alloc_cmd_mailbox(dev); 4855a2cc190SJeff Kirsher if (IS_ERR(outmailbox)) { 4865a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, inmailbox); 4875a2cc190SJeff Kirsher return PTR_ERR(outmailbox); 4885a2cc190SJeff Kirsher } 4895a2cc190SJeff Kirsher 4905a2cc190SJeff Kirsher inbuf = inmailbox->buf; 4915a2cc190SJeff Kirsher outbuf = outmailbox->buf; 4925a2cc190SJeff Kirsher inbuf[0] = 1; 4935a2cc190SJeff Kirsher inbuf[1] = 1; 4945a2cc190SJeff Kirsher inbuf[2] = 1; 4955a2cc190SJeff Kirsher inbuf[3] = 1; 4965a2cc190SJeff Kirsher *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015); 4975a2cc190SJeff Kirsher *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); 4985a2cc190SJeff Kirsher 4995a2cc190SJeff Kirsher err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, 500f9baff50SJack Morgenstein MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 501f9baff50SJack Morgenstein MLX4_CMD_NATIVE); 5025a2cc190SJeff Kirsher if (!err) 5035a2cc190SJeff Kirsher *caps = *(__be32 *) (outbuf + 84); 5045a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, inmailbox); 5055a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, outmailbox); 5065a2cc190SJeff Kirsher return err; 5075a2cc190SJeff Kirsher } 5089cd59352SJack Morgenstein static struct mlx4_roce_gid_entry zgid_entry; 5095a2cc190SJeff Kirsher 510449fc488SMatan Barak int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port) 511b6ffaeffSJack Morgenstein { 512449fc488SMatan Barak int vfs; 513449fc488SMatan Barak int slave_gid = slave; 514449fc488SMatan Barak unsigned i; 515449fc488SMatan Barak struct mlx4_slaves_pport slaves_pport; 516449fc488SMatan Barak struct mlx4_active_ports actv_ports; 517449fc488SMatan Barak unsigned max_port_p_one; 518449fc488SMatan Barak 519b6ffaeffSJack Morgenstein if (slave == 0) 520b6ffaeffSJack Morgenstein return MLX4_ROCE_PF_GIDS; 521449fc488SMatan Barak 522449fc488SMatan Barak /* Slave is a VF */ 523449fc488SMatan Barak slaves_pport = mlx4_phys_to_slaves_pport(dev, port); 524449fc488SMatan Barak actv_ports = mlx4_get_active_ports(dev, slave); 525449fc488SMatan Barak max_port_p_one = find_first_bit(actv_ports.ports, dev->caps.num_ports) + 526449fc488SMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports) + 1; 527449fc488SMatan Barak 528449fc488SMatan Barak for (i = 1; i < max_port_p_one; i++) { 529449fc488SMatan Barak struct mlx4_active_ports exclusive_ports; 530449fc488SMatan Barak struct mlx4_slaves_pport slaves_pport_actv; 531449fc488SMatan Barak bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); 532449fc488SMatan Barak set_bit(i - 1, exclusive_ports.ports); 533449fc488SMatan Barak if (i == port) 534449fc488SMatan Barak continue; 535449fc488SMatan Barak slaves_pport_actv = mlx4_phys_to_slaves_pport_actv( 536449fc488SMatan Barak dev, &exclusive_ports); 537449fc488SMatan Barak slave_gid -= bitmap_weight(slaves_pport_actv.slaves, 538449fc488SMatan Barak dev->num_vfs + 1); 539449fc488SMatan Barak } 540449fc488SMatan Barak vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; 541449fc488SMatan Barak if (slave_gid <= ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) % vfs)) 542449fc488SMatan Barak return ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / vfs) + 1; 543449fc488SMatan Barak return (MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / vfs; 544b6ffaeffSJack Morgenstein } 545b6ffaeffSJack Morgenstein 546449fc488SMatan Barak int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave, int port) 547b6ffaeffSJack Morgenstein { 548b6ffaeffSJack Morgenstein int gids; 549449fc488SMatan Barak unsigned i; 550449fc488SMatan Barak int slave_gid = slave; 551b6ffaeffSJack Morgenstein int vfs; 552b6ffaeffSJack Morgenstein 553449fc488SMatan Barak struct mlx4_slaves_pport slaves_pport; 554449fc488SMatan Barak struct mlx4_active_ports actv_ports; 555449fc488SMatan Barak unsigned max_port_p_one; 556b6ffaeffSJack Morgenstein 557b6ffaeffSJack Morgenstein if (slave == 0) 558b6ffaeffSJack Morgenstein return 0; 559b6ffaeffSJack Morgenstein 560449fc488SMatan Barak slaves_pport = mlx4_phys_to_slaves_pport(dev, port); 561449fc488SMatan Barak actv_ports = mlx4_get_active_ports(dev, slave); 562449fc488SMatan Barak max_port_p_one = find_first_bit(actv_ports.ports, dev->caps.num_ports) + 563449fc488SMatan Barak bitmap_weight(actv_ports.ports, dev->caps.num_ports) + 1; 564449fc488SMatan Barak 565449fc488SMatan Barak for (i = 1; i < max_port_p_one; i++) { 566449fc488SMatan Barak struct mlx4_active_ports exclusive_ports; 567449fc488SMatan Barak struct mlx4_slaves_pport slaves_pport_actv; 568449fc488SMatan Barak bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); 569449fc488SMatan Barak set_bit(i - 1, exclusive_ports.ports); 570449fc488SMatan Barak if (i == port) 571449fc488SMatan Barak continue; 572449fc488SMatan Barak slaves_pport_actv = mlx4_phys_to_slaves_pport_actv( 573449fc488SMatan Barak dev, &exclusive_ports); 574449fc488SMatan Barak slave_gid -= bitmap_weight(slaves_pport_actv.slaves, 575449fc488SMatan Barak dev->num_vfs + 1); 576b6ffaeffSJack Morgenstein } 577449fc488SMatan Barak gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; 578449fc488SMatan Barak vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; 579449fc488SMatan Barak if (slave_gid <= gids % vfs) 580449fc488SMatan Barak return MLX4_ROCE_PF_GIDS + ((gids / vfs) + 1) * (slave_gid - 1); 581449fc488SMatan Barak 582449fc488SMatan Barak return MLX4_ROCE_PF_GIDS + (gids % vfs) + 583449fc488SMatan Barak ((gids / vfs) * (slave_gid - 1)); 584449fc488SMatan Barak } 585449fc488SMatan Barak EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix); 586b6ffaeffSJack Morgenstein 587ffe455adSEugenia Emantayev static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, 588ffe455adSEugenia Emantayev u8 op_mod, struct mlx4_cmd_mailbox *inbox) 589ffe455adSEugenia Emantayev { 590ffe455adSEugenia Emantayev struct mlx4_priv *priv = mlx4_priv(dev); 591ffe455adSEugenia Emantayev struct mlx4_port_info *port_info; 592ffe455adSEugenia Emantayev struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; 593ffe455adSEugenia Emantayev struct mlx4_slave_state *slave_st = &master->slave_state[slave]; 594ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *qpn_context; 595ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *gen_context; 596b6ffaeffSJack Morgenstein struct mlx4_roce_gid_entry *gid_entry_tbl, *gid_entry_mbox, *gid_entry_mb1; 597ffe455adSEugenia Emantayev int reset_qkey_viols; 598ffe455adSEugenia Emantayev int port; 599ffe455adSEugenia Emantayev int is_eth; 600b6ffaeffSJack Morgenstein int num_gids; 601b6ffaeffSJack Morgenstein int base; 602ffe455adSEugenia Emantayev u32 in_modifier; 603ffe455adSEugenia Emantayev u32 promisc; 604ffe455adSEugenia Emantayev u16 mtu, prev_mtu; 605ffe455adSEugenia Emantayev int err; 606b6ffaeffSJack Morgenstein int i, j; 607b6ffaeffSJack Morgenstein int offset; 608ffe455adSEugenia Emantayev __be32 agg_cap_mask; 609ffe455adSEugenia Emantayev __be32 slave_cap_mask; 610ffe455adSEugenia Emantayev __be32 new_cap_mask; 611ffe455adSEugenia Emantayev 612ffe455adSEugenia Emantayev port = in_mod & 0xff; 613ffe455adSEugenia Emantayev in_modifier = in_mod >> 8; 614ffe455adSEugenia Emantayev is_eth = op_mod; 615ffe455adSEugenia Emantayev port_info = &priv->port[port]; 616ffe455adSEugenia Emantayev 617ffe455adSEugenia Emantayev /* Slaves cannot perform SET_PORT operations except changing MTU */ 618ffe455adSEugenia Emantayev if (is_eth) { 619ffe455adSEugenia Emantayev if (slave != dev->caps.function && 6209cd59352SJack Morgenstein in_modifier != MLX4_SET_PORT_GENERAL && 6219cd59352SJack Morgenstein in_modifier != MLX4_SET_PORT_GID_TABLE) { 622ffe455adSEugenia Emantayev mlx4_warn(dev, "denying SET_PORT for slave:%d\n", 623ffe455adSEugenia Emantayev slave); 624ffe455adSEugenia Emantayev return -EINVAL; 625ffe455adSEugenia Emantayev } 626ffe455adSEugenia Emantayev switch (in_modifier) { 627ffe455adSEugenia Emantayev case MLX4_SET_PORT_RQP_CALC: 628ffe455adSEugenia Emantayev qpn_context = inbox->buf; 629ffe455adSEugenia Emantayev qpn_context->base_qpn = 630ffe455adSEugenia Emantayev cpu_to_be32(port_info->base_qpn); 631ffe455adSEugenia Emantayev qpn_context->n_mac = 0x7; 632ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->promisc) >> 633ffe455adSEugenia Emantayev SET_PORT_PROMISC_SHIFT; 634ffe455adSEugenia Emantayev qpn_context->promisc = cpu_to_be32( 635ffe455adSEugenia Emantayev promisc << SET_PORT_PROMISC_SHIFT | 636ffe455adSEugenia Emantayev port_info->base_qpn); 637ffe455adSEugenia Emantayev promisc = be32_to_cpu(qpn_context->mcast) >> 638ffe455adSEugenia Emantayev SET_PORT_MC_PROMISC_SHIFT; 639ffe455adSEugenia Emantayev qpn_context->mcast = cpu_to_be32( 640ffe455adSEugenia Emantayev promisc << SET_PORT_MC_PROMISC_SHIFT | 641ffe455adSEugenia Emantayev port_info->base_qpn); 642ffe455adSEugenia Emantayev break; 643ffe455adSEugenia Emantayev case MLX4_SET_PORT_GENERAL: 644ffe455adSEugenia Emantayev gen_context = inbox->buf; 645ffe455adSEugenia Emantayev /* Mtu is configured as the max MTU among all the 646ffe455adSEugenia Emantayev * the functions on the port. */ 647ffe455adSEugenia Emantayev mtu = be16_to_cpu(gen_context->mtu); 648c59fec20SEugenia Emantayev mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port] + 649c59fec20SEugenia Emantayev ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); 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; 6679cd59352SJack Morgenstein case MLX4_SET_PORT_GID_TABLE: 668b6ffaeffSJack Morgenstein /* change to MULTIPLE entries: number of guest's gids 669b6ffaeffSJack Morgenstein * need a FOR-loop here over number of gids the guest has. 670b6ffaeffSJack Morgenstein * 1. Check no duplicates in gids passed by slave 671b6ffaeffSJack Morgenstein */ 672449fc488SMatan Barak num_gids = mlx4_get_slave_num_gids(dev, slave, port); 673449fc488SMatan Barak base = mlx4_get_base_gid_ix(dev, slave, port); 674b6ffaeffSJack Morgenstein gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 675b6ffaeffSJack Morgenstein for (i = 0; i < num_gids; gid_entry_mbox++, i++) { 676b6ffaeffSJack Morgenstein if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw, 677b6ffaeffSJack Morgenstein sizeof(zgid_entry))) 678b6ffaeffSJack Morgenstein continue; 679b6ffaeffSJack Morgenstein gid_entry_mb1 = gid_entry_mbox + 1; 680b6ffaeffSJack Morgenstein for (j = i + 1; j < num_gids; gid_entry_mb1++, j++) { 681b6ffaeffSJack Morgenstein if (!memcmp(gid_entry_mb1->raw, 682b6ffaeffSJack Morgenstein zgid_entry.raw, sizeof(zgid_entry))) 683b6ffaeffSJack Morgenstein continue; 684b6ffaeffSJack Morgenstein if (!memcmp(gid_entry_mb1->raw, gid_entry_mbox->raw, 685b6ffaeffSJack Morgenstein sizeof(gid_entry_mbox->raw))) { 686b6ffaeffSJack Morgenstein /* found duplicate */ 687b6ffaeffSJack Morgenstein return -EINVAL; 688b6ffaeffSJack Morgenstein } 689b6ffaeffSJack Morgenstein } 690b6ffaeffSJack Morgenstein } 691b6ffaeffSJack Morgenstein 692b6ffaeffSJack Morgenstein /* 2. Check that do not have duplicates in OTHER 693b6ffaeffSJack Morgenstein * entries in the port GID table 694b6ffaeffSJack Morgenstein */ 6959cd59352SJack Morgenstein for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { 696b6ffaeffSJack Morgenstein if (i >= base && i < base + num_gids) 697b6ffaeffSJack Morgenstein continue; /* don't compare to slave's current gids */ 698b6ffaeffSJack Morgenstein gid_entry_tbl = &priv->roce_gids[port - 1][i]; 699b6ffaeffSJack Morgenstein if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry))) 700b6ffaeffSJack Morgenstein continue; 701b6ffaeffSJack Morgenstein gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 702b6ffaeffSJack Morgenstein for (j = 0; j < num_gids; gid_entry_mbox++, j++) { 703b6ffaeffSJack Morgenstein if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw, 704b6ffaeffSJack Morgenstein sizeof(zgid_entry))) 705b6ffaeffSJack Morgenstein continue; 706b6ffaeffSJack Morgenstein if (!memcmp(gid_entry_mbox->raw, gid_entry_tbl->raw, 707b6ffaeffSJack Morgenstein sizeof(gid_entry_tbl->raw))) { 708b6ffaeffSJack Morgenstein /* found duplicate */ 7099cd59352SJack Morgenstein mlx4_warn(dev, "requested gid entry for slave:%d " 710b6ffaeffSJack Morgenstein "is a duplicate of gid at index %d\n", 7119cd59352SJack Morgenstein slave, i); 712b6ffaeffSJack Morgenstein return -EINVAL; 7139cd59352SJack Morgenstein } 7149cd59352SJack Morgenstein } 7159cd59352SJack Morgenstein } 716b6ffaeffSJack Morgenstein 717b6ffaeffSJack Morgenstein /* insert slave GIDs with memcpy, starting at slave's base index */ 718b6ffaeffSJack Morgenstein gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 719b6ffaeffSJack Morgenstein for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++) 720b6ffaeffSJack Morgenstein memcpy(priv->roce_gids[port - 1][offset].raw, gid_entry_mbox->raw, 16); 721b6ffaeffSJack Morgenstein 722b6ffaeffSJack Morgenstein /* Now, copy roce port gids table to current mailbox for passing to FW */ 723b6ffaeffSJack Morgenstein gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 724b6ffaeffSJack Morgenstein for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++) 725b6ffaeffSJack Morgenstein memcpy(gid_entry_mbox->raw, priv->roce_gids[port - 1][i].raw, 16); 726b6ffaeffSJack Morgenstein 7279cd59352SJack Morgenstein break; 728ffe455adSEugenia Emantayev } 729ffe455adSEugenia Emantayev return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, 730ffe455adSEugenia Emantayev MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 731ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 732ffe455adSEugenia Emantayev } 733ffe455adSEugenia Emantayev 734ffe455adSEugenia Emantayev /* For IB, we only consider: 735ffe455adSEugenia Emantayev * - The capability mask, which is set to the aggregate of all 736ffe455adSEugenia Emantayev * slave function capabilities 737ffe455adSEugenia Emantayev * - The QKey violatin counter - reset according to each request. 738ffe455adSEugenia Emantayev */ 739ffe455adSEugenia Emantayev 740ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 741ffe455adSEugenia Emantayev reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; 742ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[2]; 743ffe455adSEugenia Emantayev } else { 744ffe455adSEugenia Emantayev reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; 745ffe455adSEugenia Emantayev new_cap_mask = ((__be32 *) inbox->buf)[1]; 746ffe455adSEugenia Emantayev } 747ffe455adSEugenia Emantayev 748efcd235dSJack Morgenstein /* slave may not set the IS_SM capability for the port */ 749efcd235dSJack Morgenstein if (slave != mlx4_master_func_num(dev) && 750efcd235dSJack Morgenstein (be32_to_cpu(new_cap_mask) & MLX4_PORT_CAP_IS_SM)) 751efcd235dSJack Morgenstein return -EINVAL; 752efcd235dSJack Morgenstein 753efcd235dSJack Morgenstein /* No DEV_MGMT in multifunc mode */ 754efcd235dSJack Morgenstein if (mlx4_is_mfunc(dev) && 755efcd235dSJack Morgenstein (be32_to_cpu(new_cap_mask) & MLX4_PORT_CAP_DEV_MGMT_SUP)) 756efcd235dSJack Morgenstein return -EINVAL; 757efcd235dSJack Morgenstein 758ffe455adSEugenia Emantayev agg_cap_mask = 0; 759ffe455adSEugenia Emantayev slave_cap_mask = 760ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; 761ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; 762ffe455adSEugenia Emantayev for (i = 0; i < dev->num_slaves; i++) 763ffe455adSEugenia Emantayev agg_cap_mask |= 764ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[i].ib_cap_mask[port]; 765ffe455adSEugenia Emantayev 766ffe455adSEugenia Emantayev /* only clear mailbox for guests. Master may be setting 767ffe455adSEugenia Emantayev * MTU or PKEY table size 768ffe455adSEugenia Emantayev */ 769ffe455adSEugenia Emantayev if (slave != dev->caps.function) 770ffe455adSEugenia Emantayev memset(inbox->buf, 0, 256); 771ffe455adSEugenia Emantayev if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 772edc4a67eSJack Morgenstein *(u8 *) inbox->buf |= !!reset_qkey_viols << 6; 773ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[2] = agg_cap_mask; 774ffe455adSEugenia Emantayev } else { 775edc4a67eSJack Morgenstein ((u8 *) inbox->buf)[3] |= !!reset_qkey_viols; 776ffe455adSEugenia Emantayev ((__be32 *) inbox->buf)[1] = agg_cap_mask; 777ffe455adSEugenia Emantayev } 778ffe455adSEugenia Emantayev 779ffe455adSEugenia Emantayev err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, 780ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 781ffe455adSEugenia Emantayev if (err) 782ffe455adSEugenia Emantayev priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = 783ffe455adSEugenia Emantayev slave_cap_mask; 784ffe455adSEugenia Emantayev return err; 785ffe455adSEugenia Emantayev } 786ffe455adSEugenia Emantayev 787ffe455adSEugenia Emantayev int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, 788ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 789ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 790ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 791ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 792ffe455adSEugenia Emantayev { 793449fc488SMatan Barak int port = mlx4_slave_convert_port( 794449fc488SMatan Barak dev, slave, vhcr->in_modifier & 0xFF); 795449fc488SMatan Barak 796449fc488SMatan Barak if (port < 0) 797449fc488SMatan Barak return -EINVAL; 798449fc488SMatan Barak 799449fc488SMatan Barak vhcr->in_modifier = (vhcr->in_modifier & ~0xFF) | 800449fc488SMatan Barak (port & 0xFF); 801449fc488SMatan Barak 802ffe455adSEugenia Emantayev return mlx4_common_set_port(dev, slave, vhcr->in_modifier, 803ffe455adSEugenia Emantayev vhcr->op_modifier, inbox); 804ffe455adSEugenia Emantayev } 805ffe455adSEugenia Emantayev 806096335b3SOr Gerlitz /* bit locations for set port command with zero op modifier */ 807096335b3SOr Gerlitz enum { 808096335b3SOr Gerlitz MLX4_SET_PORT_VL_CAP = 4, /* bits 7:4 */ 809096335b3SOr Gerlitz MLX4_SET_PORT_MTU_CAP = 12, /* bits 15:12 */ 8106634961cSJack Morgenstein MLX4_CHANGE_PORT_PKEY_TBL_SZ = 20, 811096335b3SOr Gerlitz MLX4_CHANGE_PORT_VL_CAP = 21, 812096335b3SOr Gerlitz MLX4_CHANGE_PORT_MTU_CAP = 22, 813096335b3SOr Gerlitz }; 814096335b3SOr Gerlitz 8156634961cSJack Morgenstein int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz) 8165a2cc190SJeff Kirsher { 8175a2cc190SJeff Kirsher struct mlx4_cmd_mailbox *mailbox; 8186634961cSJack Morgenstein int err, vl_cap, pkey_tbl_flag = 0; 8195a2cc190SJeff Kirsher 8205a2cc190SJeff Kirsher if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) 8215a2cc190SJeff Kirsher return 0; 8225a2cc190SJeff Kirsher 8235a2cc190SJeff Kirsher mailbox = mlx4_alloc_cmd_mailbox(dev); 8245a2cc190SJeff Kirsher if (IS_ERR(mailbox)) 8255a2cc190SJeff Kirsher return PTR_ERR(mailbox); 8265a2cc190SJeff Kirsher 8275a2cc190SJeff Kirsher ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; 828096335b3SOr Gerlitz 8296634961cSJack Morgenstein if (pkey_tbl_sz >= 0 && mlx4_is_master(dev)) { 8306634961cSJack Morgenstein pkey_tbl_flag = 1; 8316634961cSJack Morgenstein ((__be16 *) mailbox->buf)[20] = cpu_to_be16(pkey_tbl_sz); 8326634961cSJack Morgenstein } 8336634961cSJack Morgenstein 834096335b3SOr Gerlitz /* IB VL CAP enum isn't used by the firmware, just numerical values */ 835096335b3SOr Gerlitz for (vl_cap = 8; vl_cap >= 1; vl_cap >>= 1) { 836096335b3SOr Gerlitz ((__be32 *) mailbox->buf)[0] = cpu_to_be32( 837096335b3SOr Gerlitz (1 << MLX4_CHANGE_PORT_MTU_CAP) | 838096335b3SOr Gerlitz (1 << MLX4_CHANGE_PORT_VL_CAP) | 8396634961cSJack Morgenstein (pkey_tbl_flag << MLX4_CHANGE_PORT_PKEY_TBL_SZ) | 840096335b3SOr Gerlitz (dev->caps.port_ib_mtu[port] << MLX4_SET_PORT_MTU_CAP) | 841096335b3SOr Gerlitz (vl_cap << MLX4_SET_PORT_VL_CAP)); 8425a2cc190SJeff Kirsher err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 843f9baff50SJack Morgenstein MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 844096335b3SOr Gerlitz if (err != -ENOMEM) 845096335b3SOr Gerlitz break; 846096335b3SOr Gerlitz } 8475a2cc190SJeff Kirsher 8485a2cc190SJeff Kirsher mlx4_free_cmd_mailbox(dev, mailbox); 8495a2cc190SJeff Kirsher return err; 8505a2cc190SJeff Kirsher } 851ffe455adSEugenia Emantayev 852cb9ffb76SJoerg Roedel int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 853ffe455adSEugenia Emantayev u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 854ffe455adSEugenia Emantayev { 855ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 856ffe455adSEugenia Emantayev struct mlx4_set_port_general_context *context; 857ffe455adSEugenia Emantayev int err; 858ffe455adSEugenia Emantayev u32 in_mod; 859ffe455adSEugenia Emantayev 860ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 861ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 862ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 863ffe455adSEugenia Emantayev context = mailbox->buf; 864ffe455adSEugenia Emantayev context->flags = SET_PORT_GEN_ALL_VALID; 865ffe455adSEugenia Emantayev context->mtu = cpu_to_be16(mtu); 866ffe455adSEugenia Emantayev context->pptx = (pptx * (!pfctx)) << 7; 867ffe455adSEugenia Emantayev context->pfctx = pfctx; 868ffe455adSEugenia Emantayev context->pprx = (pprx * (!pfcrx)) << 7; 869ffe455adSEugenia Emantayev context->pfcrx = pfcrx; 870ffe455adSEugenia Emantayev 871ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 872ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 873ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 874ffe455adSEugenia Emantayev 875ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 876ffe455adSEugenia Emantayev return err; 877ffe455adSEugenia Emantayev } 878ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_general); 879ffe455adSEugenia Emantayev 880cb9ffb76SJoerg Roedel int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 881ffe455adSEugenia Emantayev u8 promisc) 882ffe455adSEugenia Emantayev { 883ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *mailbox; 884ffe455adSEugenia Emantayev struct mlx4_set_port_rqp_calc_context *context; 885ffe455adSEugenia Emantayev int err; 886ffe455adSEugenia Emantayev u32 in_mod; 887ffe455adSEugenia Emantayev u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? 888ffe455adSEugenia Emantayev MCAST_DIRECT : MCAST_DEFAULT; 889ffe455adSEugenia Emantayev 890c96d97f4SHadar Hen Zion if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) 891ffe455adSEugenia Emantayev return 0; 892ffe455adSEugenia Emantayev 893ffe455adSEugenia Emantayev mailbox = mlx4_alloc_cmd_mailbox(dev); 894ffe455adSEugenia Emantayev if (IS_ERR(mailbox)) 895ffe455adSEugenia Emantayev return PTR_ERR(mailbox); 896ffe455adSEugenia Emantayev context = mailbox->buf; 897ffe455adSEugenia Emantayev context->base_qpn = cpu_to_be32(base_qpn); 898ffe455adSEugenia Emantayev context->n_mac = dev->caps.log_num_macs; 899ffe455adSEugenia Emantayev context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | 900ffe455adSEugenia Emantayev base_qpn); 901ffe455adSEugenia Emantayev context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | 902ffe455adSEugenia Emantayev base_qpn); 903ffe455adSEugenia Emantayev context->intra_no_vlan = 0; 904ffe455adSEugenia Emantayev context->no_vlan = MLX4_NO_VLAN_IDX; 905ffe455adSEugenia Emantayev context->intra_vlan_miss = 0; 906ffe455adSEugenia Emantayev context->vlan_miss = MLX4_VLAN_MISS_IDX; 907ffe455adSEugenia Emantayev 908ffe455adSEugenia Emantayev in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 909ffe455adSEugenia Emantayev err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 910ffe455adSEugenia Emantayev MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 911ffe455adSEugenia Emantayev 912ffe455adSEugenia Emantayev mlx4_free_cmd_mailbox(dev, mailbox); 913ffe455adSEugenia Emantayev return err; 914ffe455adSEugenia Emantayev } 915ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); 916ffe455adSEugenia Emantayev 917e5395e92SAmir Vadai int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc) 918e5395e92SAmir Vadai { 919e5395e92SAmir Vadai struct mlx4_cmd_mailbox *mailbox; 920e5395e92SAmir Vadai struct mlx4_set_port_prio2tc_context *context; 921e5395e92SAmir Vadai int err; 922e5395e92SAmir Vadai u32 in_mod; 923e5395e92SAmir Vadai int i; 924e5395e92SAmir Vadai 925e5395e92SAmir Vadai mailbox = mlx4_alloc_cmd_mailbox(dev); 926e5395e92SAmir Vadai if (IS_ERR(mailbox)) 927e5395e92SAmir Vadai return PTR_ERR(mailbox); 928e5395e92SAmir Vadai context = mailbox->buf; 929e5395e92SAmir Vadai for (i = 0; i < MLX4_NUM_UP; i += 2) 930e5395e92SAmir Vadai context->prio2tc[i >> 1] = prio2tc[i] << 4 | prio2tc[i + 1]; 931e5395e92SAmir Vadai 932e5395e92SAmir Vadai in_mod = MLX4_SET_PORT_PRIO2TC << 8 | port; 933e5395e92SAmir Vadai err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 934e5395e92SAmir Vadai MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 935e5395e92SAmir Vadai 936e5395e92SAmir Vadai mlx4_free_cmd_mailbox(dev, mailbox); 937e5395e92SAmir Vadai return err; 938e5395e92SAmir Vadai } 939e5395e92SAmir Vadai EXPORT_SYMBOL(mlx4_SET_PORT_PRIO2TC); 940e5395e92SAmir Vadai 941e5395e92SAmir Vadai int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw, 942e5395e92SAmir Vadai u8 *pg, u16 *ratelimit) 943e5395e92SAmir Vadai { 944e5395e92SAmir Vadai struct mlx4_cmd_mailbox *mailbox; 945e5395e92SAmir Vadai struct mlx4_set_port_scheduler_context *context; 946e5395e92SAmir Vadai int err; 947e5395e92SAmir Vadai u32 in_mod; 948e5395e92SAmir Vadai int i; 949e5395e92SAmir Vadai 950e5395e92SAmir Vadai mailbox = mlx4_alloc_cmd_mailbox(dev); 951e5395e92SAmir Vadai if (IS_ERR(mailbox)) 952e5395e92SAmir Vadai return PTR_ERR(mailbox); 953e5395e92SAmir Vadai context = mailbox->buf; 954e5395e92SAmir Vadai 955e5395e92SAmir Vadai for (i = 0; i < MLX4_NUM_TC; i++) { 956e5395e92SAmir Vadai struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i]; 957e5395e92SAmir Vadai u16 r = ratelimit && ratelimit[i] ? ratelimit[i] : 958e5395e92SAmir Vadai MLX4_RATELIMIT_DEFAULT; 959e5395e92SAmir Vadai 960e5395e92SAmir Vadai tc->pg = htons(pg[i]); 961e5395e92SAmir Vadai tc->bw_precentage = htons(tc_tx_bw[i]); 962e5395e92SAmir Vadai 963e5395e92SAmir Vadai tc->max_bw_units = htons(MLX4_RATELIMIT_UNITS); 964e5395e92SAmir Vadai tc->max_bw_value = htons(r); 965e5395e92SAmir Vadai } 966e5395e92SAmir Vadai 967e5395e92SAmir Vadai in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port; 968e5395e92SAmir Vadai err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 969e5395e92SAmir Vadai MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 970e5395e92SAmir Vadai 971e5395e92SAmir Vadai mlx4_free_cmd_mailbox(dev, mailbox); 972e5395e92SAmir Vadai return err; 973e5395e92SAmir Vadai } 974e5395e92SAmir Vadai EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER); 975e5395e92SAmir Vadai 9767ffdf726SOr Gerlitz enum { 9777ffdf726SOr Gerlitz VXLAN_ENABLE_MODIFY = 1 << 7, 9787ffdf726SOr Gerlitz VXLAN_STEERING_MODIFY = 1 << 6, 9797ffdf726SOr Gerlitz 9807ffdf726SOr Gerlitz VXLAN_ENABLE = 1 << 7, 9817ffdf726SOr Gerlitz }; 9827ffdf726SOr Gerlitz 9837ffdf726SOr Gerlitz struct mlx4_set_port_vxlan_context { 9847ffdf726SOr Gerlitz u32 reserved1; 9857ffdf726SOr Gerlitz u8 modify_flags; 9867ffdf726SOr Gerlitz u8 reserved2; 9877ffdf726SOr Gerlitz u8 enable_flags; 9887ffdf726SOr Gerlitz u8 steering; 9897ffdf726SOr Gerlitz }; 9907ffdf726SOr Gerlitz 9911b136de1SOr Gerlitz int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering, int enable) 9927ffdf726SOr Gerlitz { 9937ffdf726SOr Gerlitz int err; 9947ffdf726SOr Gerlitz u32 in_mod; 9957ffdf726SOr Gerlitz struct mlx4_cmd_mailbox *mailbox; 9967ffdf726SOr Gerlitz struct mlx4_set_port_vxlan_context *context; 9977ffdf726SOr Gerlitz 9987ffdf726SOr Gerlitz mailbox = mlx4_alloc_cmd_mailbox(dev); 9997ffdf726SOr Gerlitz if (IS_ERR(mailbox)) 10007ffdf726SOr Gerlitz return PTR_ERR(mailbox); 10017ffdf726SOr Gerlitz context = mailbox->buf; 10027ffdf726SOr Gerlitz memset(context, 0, sizeof(*context)); 10037ffdf726SOr Gerlitz 10047ffdf726SOr Gerlitz context->modify_flags = VXLAN_ENABLE_MODIFY | VXLAN_STEERING_MODIFY; 10051b136de1SOr Gerlitz if (enable) 10067ffdf726SOr Gerlitz context->enable_flags = VXLAN_ENABLE; 10077ffdf726SOr Gerlitz context->steering = steering; 10087ffdf726SOr Gerlitz 10097ffdf726SOr Gerlitz in_mod = MLX4_SET_PORT_VXLAN << 8 | port; 10107ffdf726SOr Gerlitz err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 10117ffdf726SOr Gerlitz MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 10127ffdf726SOr Gerlitz 10137ffdf726SOr Gerlitz mlx4_free_cmd_mailbox(dev, mailbox); 10147ffdf726SOr Gerlitz return err; 10157ffdf726SOr Gerlitz } 10167ffdf726SOr Gerlitz EXPORT_SYMBOL(mlx4_SET_PORT_VXLAN); 10177ffdf726SOr Gerlitz 1018ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, 1019ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 1020ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 1021ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 1022ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 1023ffe455adSEugenia Emantayev { 1024ffe455adSEugenia Emantayev int err = 0; 1025ffe455adSEugenia Emantayev 1026ffe455adSEugenia Emantayev return err; 1027ffe455adSEugenia Emantayev } 1028ffe455adSEugenia Emantayev 1029ffe455adSEugenia Emantayev int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 1030ffe455adSEugenia Emantayev u64 mac, u64 clear, u8 mode) 1031ffe455adSEugenia Emantayev { 1032ffe455adSEugenia Emantayev return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 1033ffe455adSEugenia Emantayev MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, 1034ffe455adSEugenia Emantayev MLX4_CMD_WRAPPED); 1035ffe455adSEugenia Emantayev } 1036ffe455adSEugenia Emantayev EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); 1037ffe455adSEugenia Emantayev 1038ffe455adSEugenia Emantayev int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, 1039ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 1040ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 1041ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 1042ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 1043ffe455adSEugenia Emantayev { 1044ffe455adSEugenia Emantayev int err = 0; 1045ffe455adSEugenia Emantayev 1046ffe455adSEugenia Emantayev return err; 1047ffe455adSEugenia Emantayev } 1048ffe455adSEugenia Emantayev 1049ffe455adSEugenia Emantayev int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, 1050ffe455adSEugenia Emantayev u32 in_mod, struct mlx4_cmd_mailbox *outbox) 1051ffe455adSEugenia Emantayev { 1052ffe455adSEugenia Emantayev return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, 1053ffe455adSEugenia Emantayev MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, 1054ffe455adSEugenia Emantayev MLX4_CMD_NATIVE); 1055ffe455adSEugenia Emantayev } 1056ffe455adSEugenia Emantayev 1057ffe455adSEugenia Emantayev int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, 1058ffe455adSEugenia Emantayev struct mlx4_vhcr *vhcr, 1059ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *inbox, 1060ffe455adSEugenia Emantayev struct mlx4_cmd_mailbox *outbox, 1061ffe455adSEugenia Emantayev struct mlx4_cmd_info *cmd) 1062ffe455adSEugenia Emantayev { 106335fb9afbSEugenia Emantayev if (slave != dev->caps.function) 106435fb9afbSEugenia Emantayev return 0; 1065ffe455adSEugenia Emantayev return mlx4_common_dump_eth_stats(dev, slave, 1066ffe455adSEugenia Emantayev vhcr->in_modifier, outbox); 1067ffe455adSEugenia Emantayev } 106893ece0c1SEugenia Emantayev 106993ece0c1SEugenia Emantayev void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap) 107093ece0c1SEugenia Emantayev { 107193ece0c1SEugenia Emantayev if (!mlx4_is_mfunc(dev)) { 107293ece0c1SEugenia Emantayev *stats_bitmap = 0; 107393ece0c1SEugenia Emantayev return; 107493ece0c1SEugenia Emantayev } 107593ece0c1SEugenia Emantayev 107693ece0c1SEugenia Emantayev *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK | 107793ece0c1SEugenia Emantayev MLX4_STATS_TRAFFIC_DROPS_MASK | 107893ece0c1SEugenia Emantayev MLX4_STATS_PORT_COUNTERS_MASK); 107993ece0c1SEugenia Emantayev 108093ece0c1SEugenia Emantayev if (mlx4_is_master(dev)) 108193ece0c1SEugenia Emantayev *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK; 108293ece0c1SEugenia Emantayev } 108393ece0c1SEugenia Emantayev EXPORT_SYMBOL(mlx4_set_stats_bitmap); 10846ee51a4eSJack Morgenstein 10859cd59352SJack Morgenstein int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, 10869cd59352SJack Morgenstein int *slave_id) 10876ee51a4eSJack Morgenstein { 10886ee51a4eSJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 10896ee51a4eSJack Morgenstein int i, found_ix = -1; 1090b6ffaeffSJack Morgenstein int vf_gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; 1091449fc488SMatan Barak struct mlx4_slaves_pport slaves_pport; 1092449fc488SMatan Barak unsigned num_vfs; 1093449fc488SMatan Barak int slave_gid; 10946ee51a4eSJack Morgenstein 10956ee51a4eSJack Morgenstein if (!mlx4_is_mfunc(dev)) 10966ee51a4eSJack Morgenstein return -EINVAL; 10976ee51a4eSJack Morgenstein 1098449fc488SMatan Barak slaves_pport = mlx4_phys_to_slaves_pport(dev, port); 1099449fc488SMatan Barak num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; 1100449fc488SMatan Barak 11016ee51a4eSJack Morgenstein for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { 11026ee51a4eSJack Morgenstein if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) { 11036ee51a4eSJack Morgenstein found_ix = i; 11046ee51a4eSJack Morgenstein break; 11056ee51a4eSJack Morgenstein } 11066ee51a4eSJack Morgenstein } 11076ee51a4eSJack Morgenstein 1108b6ffaeffSJack Morgenstein if (found_ix >= 0) { 11090254bc82SMatan Barak /* Calculate a slave_gid which is the slave number in the gid 11100254bc82SMatan Barak * table and not a globally unique slave number. 11110254bc82SMatan Barak */ 1112b6ffaeffSJack Morgenstein if (found_ix < MLX4_ROCE_PF_GIDS) 1113449fc488SMatan Barak slave_gid = 0; 1114449fc488SMatan Barak else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % num_vfs) * 1115449fc488SMatan Barak (vf_gids / num_vfs + 1)) 1116449fc488SMatan Barak slave_gid = ((found_ix - MLX4_ROCE_PF_GIDS) / 1117449fc488SMatan Barak (vf_gids / num_vfs + 1)) + 1; 1118b6ffaeffSJack Morgenstein else 1119449fc488SMatan Barak slave_gid = 1120b6ffaeffSJack Morgenstein ((found_ix - MLX4_ROCE_PF_GIDS - 1121449fc488SMatan Barak ((vf_gids % num_vfs) * ((vf_gids / num_vfs + 1)))) / 1122449fc488SMatan Barak (vf_gids / num_vfs)) + vf_gids % num_vfs + 1; 1123449fc488SMatan Barak 11240254bc82SMatan Barak /* Calculate the globally unique slave id */ 1125449fc488SMatan Barak if (slave_gid) { 1126449fc488SMatan Barak struct mlx4_active_ports exclusive_ports; 1127449fc488SMatan Barak struct mlx4_active_ports actv_ports; 1128449fc488SMatan Barak struct mlx4_slaves_pport slaves_pport_actv; 1129449fc488SMatan Barak unsigned max_port_p_one; 11300254bc82SMatan Barak int num_vfs_before = 0; 11310254bc82SMatan Barak int candidate_slave_gid; 1132449fc488SMatan Barak 11330254bc82SMatan Barak /* Calculate how many VFs are on the previous port, if exists */ 1134449fc488SMatan Barak for (i = 1; i < port; i++) { 1135449fc488SMatan Barak bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); 11360254bc82SMatan Barak set_bit(i - 1, exclusive_ports.ports); 1137449fc488SMatan Barak slaves_pport_actv = 1138449fc488SMatan Barak mlx4_phys_to_slaves_pport_actv( 1139449fc488SMatan Barak dev, &exclusive_ports); 11400254bc82SMatan Barak num_vfs_before += bitmap_weight( 1141449fc488SMatan Barak slaves_pport_actv.slaves, 1142449fc488SMatan Barak dev->num_vfs + 1); 1143449fc488SMatan Barak } 1144449fc488SMatan Barak 11450254bc82SMatan Barak /* candidate_slave_gid isn't necessarily the correct slave, but 11460254bc82SMatan Barak * it has the same number of ports and is assigned to the same 11470254bc82SMatan Barak * ports as the real slave we're looking for. On dual port VF, 11480254bc82SMatan Barak * slave_gid = [single port VFs on port <port>] + 11490254bc82SMatan Barak * [offset of the current slave from the first dual port VF] + 11500254bc82SMatan Barak * 1 (for the PF). 11510254bc82SMatan Barak */ 11520254bc82SMatan Barak candidate_slave_gid = slave_gid + num_vfs_before; 11530254bc82SMatan Barak 11540254bc82SMatan Barak actv_ports = mlx4_get_active_ports(dev, candidate_slave_gid); 1155449fc488SMatan Barak max_port_p_one = find_first_bit( 1156449fc488SMatan Barak actv_ports.ports, dev->caps.num_ports) + 1157449fc488SMatan Barak bitmap_weight(actv_ports.ports, 1158449fc488SMatan Barak dev->caps.num_ports) + 1; 1159449fc488SMatan Barak 11600254bc82SMatan Barak /* Calculate the real slave number */ 1161449fc488SMatan Barak for (i = 1; i < max_port_p_one; i++) { 1162449fc488SMatan Barak if (i == port) 1163449fc488SMatan Barak continue; 1164449fc488SMatan Barak bitmap_zero(exclusive_ports.ports, 1165449fc488SMatan Barak dev->caps.num_ports); 1166449fc488SMatan Barak set_bit(i - 1, exclusive_ports.ports); 1167449fc488SMatan Barak slaves_pport_actv = 1168449fc488SMatan Barak mlx4_phys_to_slaves_pport_actv( 1169449fc488SMatan Barak dev, &exclusive_ports); 1170449fc488SMatan Barak slave_gid += bitmap_weight( 1171449fc488SMatan Barak slaves_pport_actv.slaves, 1172449fc488SMatan Barak dev->num_vfs + 1); 1173449fc488SMatan Barak } 1174449fc488SMatan Barak } 1175449fc488SMatan Barak *slave_id = slave_gid; 1176b6ffaeffSJack Morgenstein } 11776ee51a4eSJack Morgenstein 11786ee51a4eSJack Morgenstein return (found_ix >= 0) ? 0 : -EINVAL; 11796ee51a4eSJack Morgenstein } 11806ee51a4eSJack Morgenstein EXPORT_SYMBOL(mlx4_get_slave_from_roce_gid); 11816ee51a4eSJack Morgenstein 11829cd59352SJack Morgenstein int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id, 11839cd59352SJack Morgenstein u8 *gid) 11846ee51a4eSJack Morgenstein { 11856ee51a4eSJack Morgenstein struct mlx4_priv *priv = mlx4_priv(dev); 11866ee51a4eSJack Morgenstein 11876ee51a4eSJack Morgenstein if (!mlx4_is_master(dev)) 11886ee51a4eSJack Morgenstein return -EINVAL; 11896ee51a4eSJack Morgenstein 11906ee51a4eSJack Morgenstein memcpy(gid, priv->roce_gids[port - 1][slave_id].raw, 16); 11916ee51a4eSJack Morgenstein return 0; 11926ee51a4eSJack Morgenstein } 11936ee51a4eSJack Morgenstein EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); 1194