mlx4_port.c revision 255932
1219820Sjeff/* 2219820Sjeff * Copyright (c) 2007 Mellanox Technologies. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff */ 32219820Sjeff 33219820Sjeff#include <linux/errno.h> 34219820Sjeff#include <linux/if_ether.h> 35219820Sjeff 36219820Sjeff#include <linux/mlx4/cmd.h> 37255932Salfred#include <linux/moduleparam.h> 38219820Sjeff#include "mlx4.h" 39219820Sjeff 40255932Salfredint mlx4_set_4k_mtu = -1; 41255932Salfredmodule_param_named(set_4k_mtu, mlx4_set_4k_mtu, int, 0444); 42255932SalfredMODULE_PARM_DESC(set_4k_mtu, 43255932Salfred "(Obsolete) attempt to set 4K MTU to all ConnectX ports"); 44219820Sjeff 45255932Salfred 46219820Sjeff#define MLX4_MAC_VALID (1ull << 63) 47219820Sjeff 48219820Sjeff#define MLX4_VLAN_VALID (1u << 31) 49219820Sjeff#define MLX4_VLAN_MASK 0xfff 50219820Sjeff 51255932Salfred#define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL 52255932Salfred#define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL 53255932Salfred#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL 54255932Salfred#define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL 55255932Salfred#define MLX4_STATS_IF_RX_ERRORS_COUNTERS_MASK 0x8010ULL 56255932Salfred 57219820Sjeffvoid mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table) 58219820Sjeff{ 59219820Sjeff int i; 60219820Sjeff 61219820Sjeff mutex_init(&table->mutex); 62219820Sjeff for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 63219820Sjeff table->entries[i] = 0; 64219820Sjeff table->refs[i] = 0; 65219820Sjeff } 66219820Sjeff table->max = 1 << dev->caps.log_num_macs; 67219820Sjeff table->total = 0; 68219820Sjeff} 69219820Sjeff 70219820Sjeffvoid mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) 71219820Sjeff{ 72219820Sjeff int i; 73219820Sjeff 74219820Sjeff mutex_init(&table->mutex); 75219820Sjeff for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) { 76219820Sjeff table->entries[i] = 0; 77219820Sjeff table->refs[i] = 0; 78219820Sjeff } 79255932Salfred table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR; 80219820Sjeff table->total = 0; 81219820Sjeff} 82219820Sjeff 83255932Salfredstatic int validate_index(struct mlx4_dev *dev, 84255932Salfred struct mlx4_mac_table *table, int index) 85255932Salfred{ 86255932Salfred int err = 0; 87255932Salfred 88255932Salfred if (index < 0 || index >= table->max || !table->entries[index]) { 89255932Salfred mlx4_warn(dev, "No valid Mac entry for the given index\n"); 90255932Salfred err = -EINVAL; 91255932Salfred } 92255932Salfred return err; 93255932Salfred} 94255932Salfred 95255932Salfredstatic int find_index(struct mlx4_dev *dev, 96255932Salfred struct mlx4_mac_table *table, u64 mac) 97255932Salfred{ 98255932Salfred int i; 99255932Salfred 100255932Salfred for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 101255932Salfred if ((mac & MLX4_MAC_MASK) == 102255932Salfred (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) 103255932Salfred return i; 104255932Salfred } 105255932Salfred /* Mac not found */ 106255932Salfred return -EINVAL; 107255932Salfred} 108255932Salfred 109219820Sjeffstatic int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, 110219820Sjeff __be64 *entries) 111219820Sjeff{ 112219820Sjeff struct mlx4_cmd_mailbox *mailbox; 113219820Sjeff u32 in_mod; 114219820Sjeff int err; 115219820Sjeff 116219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 117219820Sjeff if (IS_ERR(mailbox)) 118219820Sjeff return PTR_ERR(mailbox); 119219820Sjeff 120219820Sjeff memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); 121219820Sjeff 122219820Sjeff in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; 123255932Salfred 124219820Sjeff err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 125255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 126219820Sjeff 127219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 128219820Sjeff return err; 129219820Sjeff} 130219820Sjeff 131255932Salfredint __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 132219820Sjeff{ 133255932Salfred struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 134255932Salfred struct mlx4_mac_table *table = &info->mac_table; 135219820Sjeff int i, err = 0; 136219820Sjeff int free = -1; 137219820Sjeff 138255932Salfred mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", 139255932Salfred (unsigned long long) mac, port); 140255932Salfred 141219820Sjeff mutex_lock(&table->mutex); 142255932Salfred for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 143255932Salfred if (free < 0 && !table->entries[i]) { 144219820Sjeff free = i; 145219820Sjeff continue; 146219820Sjeff } 147219820Sjeff 148219820Sjeff if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 149255932Salfred /* MAC already registered, Must not have duplicates */ 150255932Salfred err = i; 151219820Sjeff ++table->refs[i]; 152219820Sjeff goto out; 153219820Sjeff } 154219820Sjeff } 155219820Sjeff 156219820Sjeff mlx4_dbg(dev, "Free MAC index is %d\n", free); 157219820Sjeff 158219820Sjeff if (table->total == table->max) { 159219820Sjeff /* No free mac entries */ 160219820Sjeff err = -ENOSPC; 161219820Sjeff goto out; 162219820Sjeff } 163219820Sjeff 164219820Sjeff /* Register new MAC */ 165219820Sjeff table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); 166219820Sjeff 167219820Sjeff err = mlx4_set_port_mac_table(dev, port, table->entries); 168219820Sjeff if (unlikely(err)) { 169255932Salfred mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 170255932Salfred (unsigned long long) mac); 171219820Sjeff table->entries[free] = 0; 172219820Sjeff goto out; 173219820Sjeff } 174255932Salfred table->refs[free] = 1; 175219820Sjeff 176255932Salfred err = free; 177219820Sjeff ++table->total; 178219820Sjeffout: 179219820Sjeff mutex_unlock(&table->mutex); 180219820Sjeff return err; 181219820Sjeff} 182255932SalfredEXPORT_SYMBOL_GPL(__mlx4_register_mac); 183255932Salfred 184255932Salfredint mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 185255932Salfred{ 186255932Salfred u64 out_param = 0; 187255932Salfred int err; 188255932Salfred 189255932Salfred if (mlx4_is_mfunc(dev)) { 190255932Salfred err = mlx4_cmd_imm(dev, mac, &out_param, 191255932Salfred ((u32) port) << 8 | (u32) RES_MAC, 192255932Salfred RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 193255932Salfred MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 194255932Salfred if (err) 195255932Salfred return err; 196255932Salfred 197255932Salfred return get_param_l(&out_param); 198255932Salfred } 199255932Salfred return __mlx4_register_mac(dev, port, mac); 200255932Salfred} 201219820SjeffEXPORT_SYMBOL_GPL(mlx4_register_mac); 202219820Sjeff 203255932Salfredint mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port) 204219820Sjeff{ 205255932Salfred return dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] + 206255932Salfred (port - 1) * (1 << dev->caps.log_num_macs); 207255932Salfred} 208255932SalfredEXPORT_SYMBOL_GPL(mlx4_get_base_qpn); 209219820Sjeff 210255932Salfredvoid __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 211255932Salfred{ 212255932Salfred struct mlx4_port_info *info; 213255932Salfred struct mlx4_mac_table *table; 214255932Salfred int index; 215255932Salfred 216255932Salfred if (port < 1 || port > dev->caps.num_ports) { 217255932Salfred mlx4_warn(dev, "invalid port number (%d), aborting...\n", port); 218255932Salfred return; 219255932Salfred } 220255932Salfred info = &mlx4_priv(dev)->port[port]; 221255932Salfred table = &info->mac_table; 222219820Sjeff mutex_lock(&table->mutex); 223255932Salfred 224255932Salfred index = find_index(dev, table, mac); 225255932Salfred 226255932Salfred if (validate_index(dev, table, index)) 227219820Sjeff goto out; 228255932Salfred 229219820Sjeff if (--table->refs[index]) { 230255932Salfred mlx4_dbg(dev, "Have more references for index %d," 231255932Salfred "no need to modify mac table\n", index); 232219820Sjeff goto out; 233219820Sjeff } 234255932Salfred 235219820Sjeff table->entries[index] = 0; 236219820Sjeff mlx4_set_port_mac_table(dev, port, table->entries); 237219820Sjeff --table->total; 238219820Sjeffout: 239219820Sjeff mutex_unlock(&table->mutex); 240219820Sjeff} 241255932SalfredEXPORT_SYMBOL_GPL(__mlx4_unregister_mac); 242255932Salfred 243255932Salfredvoid mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) 244255932Salfred{ 245255932Salfred u64 out_param = 0; 246255932Salfred 247255932Salfred if (mlx4_is_mfunc(dev)) { 248255932Salfred (void) mlx4_cmd_imm(dev, mac, &out_param, 249255932Salfred ((u32) port) << 8 | (u32) RES_MAC, 250255932Salfred RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, 251255932Salfred MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 252255932Salfred return; 253255932Salfred } 254255932Salfred __mlx4_unregister_mac(dev, port, mac); 255255932Salfred return; 256255932Salfred} 257219820SjeffEXPORT_SYMBOL_GPL(mlx4_unregister_mac); 258219820Sjeff 259255932Salfredint __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) 260255932Salfred{ 261255932Salfred struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 262255932Salfred struct mlx4_mac_table *table = &info->mac_table; 263255932Salfred int index = qpn - info->base_qpn; 264255932Salfred int err = 0; 265255932Salfred 266255932Salfred /* CX1 doesn't support multi-functions */ 267255932Salfred mutex_lock(&table->mutex); 268255932Salfred 269255932Salfred err = validate_index(dev, table, index); 270255932Salfred if (err) 271255932Salfred goto out; 272255932Salfred 273255932Salfred table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID); 274255932Salfred 275255932Salfred err = mlx4_set_port_mac_table(dev, port, table->entries); 276255932Salfred if (unlikely(err)) { 277255932Salfred mlx4_err(dev, "Failed adding MAC: 0x%llx\n", 278255932Salfred (unsigned long long) new_mac); 279255932Salfred table->entries[index] = 0; 280255932Salfred } 281255932Salfredout: 282255932Salfred mutex_unlock(&table->mutex); 283255932Salfred return err; 284255932Salfred} 285255932SalfredEXPORT_SYMBOL_GPL(__mlx4_replace_mac); 286255932Salfred 287219820Sjeffstatic int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, 288219820Sjeff __be32 *entries) 289219820Sjeff{ 290219820Sjeff struct mlx4_cmd_mailbox *mailbox; 291219820Sjeff u32 in_mod; 292219820Sjeff int err; 293219820Sjeff 294219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 295219820Sjeff if (IS_ERR(mailbox)) 296219820Sjeff return PTR_ERR(mailbox); 297219820Sjeff 298219820Sjeff memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); 299219820Sjeff in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; 300219820Sjeff err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 301255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 302219820Sjeff 303219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 304219820Sjeff 305219820Sjeff return err; 306219820Sjeff} 307219820Sjeff 308219820Sjeffint mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) 309219820Sjeff{ 310219820Sjeff struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 311219820Sjeff int i; 312219820Sjeff 313219820Sjeff for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) { 314219820Sjeff if (table->refs[i] && 315219820Sjeff (vid == (MLX4_VLAN_MASK & 316219820Sjeff be32_to_cpu(table->entries[i])))) { 317255932Salfred /* VLAN already registered, increase reference count */ 318219820Sjeff *idx = i; 319219820Sjeff return 0; 320219820Sjeff } 321219820Sjeff } 322219820Sjeff 323219820Sjeff return -ENOENT; 324219820Sjeff} 325219820SjeffEXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); 326219820Sjeff 327255932Salfredint __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, 328255932Salfred int *index) 329219820Sjeff{ 330219820Sjeff struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 331219820Sjeff int i, err = 0; 332219820Sjeff int free = -1; 333219820Sjeff 334219820Sjeff mutex_lock(&table->mutex); 335255932Salfred 336255932Salfred if (table->total == table->max) { 337255932Salfred /* No free vlan entries */ 338255932Salfred err = -ENOSPC; 339255932Salfred goto out; 340255932Salfred } 341255932Salfred 342219820Sjeff for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { 343219820Sjeff if (free < 0 && (table->refs[i] == 0)) { 344219820Sjeff free = i; 345219820Sjeff continue; 346219820Sjeff } 347219820Sjeff 348219820Sjeff if (table->refs[i] && 349219820Sjeff (vlan == (MLX4_VLAN_MASK & 350219820Sjeff be32_to_cpu(table->entries[i])))) { 351255932Salfred /* Vlan already registered, increase references count */ 352219820Sjeff *index = i; 353219820Sjeff ++table->refs[i]; 354219820Sjeff goto out; 355219820Sjeff } 356219820Sjeff } 357219820Sjeff 358219820Sjeff if (free < 0) { 359219820Sjeff err = -ENOMEM; 360219820Sjeff goto out; 361219820Sjeff } 362219820Sjeff 363255932Salfred /* Register new VLAN */ 364219820Sjeff table->refs[free] = 1; 365219820Sjeff table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); 366219820Sjeff 367219820Sjeff err = mlx4_set_port_vlan_table(dev, port, table->entries); 368219820Sjeff if (unlikely(err)) { 369219820Sjeff mlx4_warn(dev, "Failed adding vlan: %u\n", vlan); 370219820Sjeff table->refs[free] = 0; 371219820Sjeff table->entries[free] = 0; 372219820Sjeff goto out; 373219820Sjeff } 374219820Sjeff 375219820Sjeff *index = free; 376219820Sjeff ++table->total; 377219820Sjeffout: 378219820Sjeff mutex_unlock(&table->mutex); 379219820Sjeff return err; 380219820Sjeff} 381255932Salfred 382255932Salfredint mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) 383255932Salfred{ 384255932Salfred u64 out_param = 0; 385255932Salfred int err; 386255932Salfred 387255932Salfred if (vlan > 4095) 388255932Salfred return -EINVAL; 389255932Salfred 390255932Salfred if (mlx4_is_mfunc(dev)) { 391255932Salfred err = mlx4_cmd_imm(dev, vlan, &out_param, 392255932Salfred ((u32) port) << 8 | (u32) RES_VLAN, 393255932Salfred RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 394255932Salfred MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 395255932Salfred if (!err) 396255932Salfred *index = get_param_l(&out_param); 397255932Salfred 398255932Salfred return err; 399255932Salfred } 400255932Salfred return __mlx4_register_vlan(dev, port, vlan, index); 401255932Salfred} 402219820SjeffEXPORT_SYMBOL_GPL(mlx4_register_vlan); 403219820Sjeff 404255932Salfredvoid __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) 405219820Sjeff{ 406219820Sjeff struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; 407255932Salfred int index; 408219820Sjeff 409255932Salfred mutex_lock(&table->mutex); 410255932Salfred if (mlx4_find_cached_vlan(dev, port, vlan, &index)) { 411255932Salfred mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan); 412255932Salfred goto out; 413255932Salfred } 414255932Salfred 415219820Sjeff if (index < MLX4_VLAN_REGULAR) { 416219820Sjeff mlx4_warn(dev, "Trying to free special vlan index %d\n", index); 417255932Salfred goto out; 418219820Sjeff } 419219820Sjeff 420219820Sjeff if (--table->refs[index]) { 421255932Salfred mlx4_dbg(dev, "Have %d more references for index %d, " 422255932Salfred "no need to modify vlan table\n", table->refs[index], 423255932Salfred index); 424219820Sjeff goto out; 425219820Sjeff } 426219820Sjeff table->entries[index] = 0; 427219820Sjeff mlx4_set_port_vlan_table(dev, port, table->entries); 428219820Sjeff --table->total; 429219820Sjeffout: 430219820Sjeff mutex_unlock(&table->mutex); 431219820Sjeff} 432255932Salfred 433255932Salfredvoid mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan) 434255932Salfred{ 435255932Salfred u64 out_param = 0; 436255932Salfred 437255932Salfred if (mlx4_is_mfunc(dev)) { 438255932Salfred (void) mlx4_cmd_imm(dev, vlan, &out_param, 439255932Salfred ((u32) port) << 8 | (u32) RES_VLAN, 440255932Salfred RES_OP_RESERVE_AND_MAP, 441255932Salfred MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, 442255932Salfred MLX4_CMD_WRAPPED); 443255932Salfred return; 444255932Salfred } 445255932Salfred __mlx4_unregister_vlan(dev, port, vlan); 446255932Salfred} 447219820SjeffEXPORT_SYMBOL_GPL(mlx4_unregister_vlan); 448219820Sjeff 449219820Sjeffint mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) 450219820Sjeff{ 451219820Sjeff struct mlx4_cmd_mailbox *inmailbox, *outmailbox; 452219820Sjeff u8 *inbuf, *outbuf; 453219820Sjeff int err; 454219820Sjeff 455219820Sjeff inmailbox = mlx4_alloc_cmd_mailbox(dev); 456219820Sjeff if (IS_ERR(inmailbox)) 457219820Sjeff return PTR_ERR(inmailbox); 458219820Sjeff 459219820Sjeff outmailbox = mlx4_alloc_cmd_mailbox(dev); 460219820Sjeff if (IS_ERR(outmailbox)) { 461219820Sjeff mlx4_free_cmd_mailbox(dev, inmailbox); 462219820Sjeff return PTR_ERR(outmailbox); 463219820Sjeff } 464219820Sjeff 465219820Sjeff inbuf = inmailbox->buf; 466219820Sjeff outbuf = outmailbox->buf; 467219820Sjeff memset(inbuf, 0, 256); 468219820Sjeff memset(outbuf, 0, 256); 469219820Sjeff inbuf[0] = 1; 470219820Sjeff inbuf[1] = 1; 471219820Sjeff inbuf[2] = 1; 472219820Sjeff inbuf[3] = 1; 473219820Sjeff *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015); 474219820Sjeff *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); 475219820Sjeff 476219820Sjeff err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, 477255932Salfred MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, 478255932Salfred MLX4_CMD_NATIVE); 479219820Sjeff if (!err) 480219820Sjeff *caps = *(__be32 *) (outbuf + 84); 481219820Sjeff mlx4_free_cmd_mailbox(dev, inmailbox); 482219820Sjeff mlx4_free_cmd_mailbox(dev, outmailbox); 483219820Sjeff return err; 484219820Sjeff} 485255932Salfredstatic struct mlx4_roce_gid_entry zgid_entry; 486219820Sjeff 487255932Salfredint mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave) 488219820Sjeff{ 489255932Salfred if (slave == 0) 490255932Salfred return MLX4_ROCE_PF_GIDS; 491255932Salfred if (slave <= ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) % dev->num_vfs)) 492255932Salfred return ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / dev->num_vfs) + 1; 493255932Salfred return (MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / dev->num_vfs; 494255932Salfred} 495255932Salfred 496255932Salfredint mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave) 497255932Salfred{ 498255932Salfred int gids; 499255932Salfred int vfs; 500255932Salfred 501255932Salfred gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; 502255932Salfred vfs = dev->num_vfs; 503255932Salfred 504255932Salfred if (slave == 0) 505255932Salfred return 0; 506255932Salfred if (slave <= gids % vfs) 507255932Salfred return MLX4_ROCE_PF_GIDS + ((gids / vfs) + 1) * (slave - 1); 508255932Salfred 509255932Salfred return MLX4_ROCE_PF_GIDS + (gids % vfs) + ((gids / vfs) * (slave - 1)); 510255932Salfred} 511255932Salfred 512255932Salfredstatic int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, 513255932Salfred u8 op_mod, struct mlx4_cmd_mailbox *inbox) 514255932Salfred{ 515255932Salfred struct mlx4_priv *priv = mlx4_priv(dev); 516255932Salfred struct mlx4_port_info *port_info; 517255932Salfred struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; 518255932Salfred struct mlx4_slave_state *slave_st = &master->slave_state[slave]; 519255932Salfred struct mlx4_set_port_rqp_calc_context *qpn_context; 520255932Salfred struct mlx4_set_port_general_context *gen_context; 521255932Salfred struct mlx4_roce_gid_entry *gid_entry_tbl, *gid_entry_mbox, *gid_entry_mb1; 522255932Salfred int reset_qkey_viols; 523255932Salfred int port; 524255932Salfred int is_eth; 525255932Salfred int num_gids; 526255932Salfred int base; 527255932Salfred u32 in_modifier; 528255932Salfred u32 promisc; 529255932Salfred u16 mtu, prev_mtu; 530219820Sjeff int err; 531255932Salfred int i, j; 532255932Salfred int offset; 533255932Salfred __be32 agg_cap_mask; 534255932Salfred __be32 slave_cap_mask; 535255932Salfred __be32 new_cap_mask; 536219820Sjeff 537255932Salfred port = in_mod & 0xff; 538255932Salfred in_modifier = in_mod >> 8; 539255932Salfred is_eth = op_mod; 540255932Salfred port_info = &priv->port[port]; 541255932Salfred 542255932Salfred /* Slaves cannot perform SET_PORT operations except changing MTU */ 543255932Salfred if (is_eth) { 544255932Salfred if (slave != dev->caps.function && 545255932Salfred in_modifier != MLX4_SET_PORT_GENERAL && 546255932Salfred in_modifier != MLX4_SET_PORT_GID_TABLE) { 547255932Salfred mlx4_warn(dev, "denying SET_PORT for slave:%d\n", 548255932Salfred slave); 549255932Salfred return -EINVAL; 550255932Salfred } 551255932Salfred switch (in_modifier) { 552255932Salfred case MLX4_SET_PORT_RQP_CALC: 553255932Salfred qpn_context = inbox->buf; 554255932Salfred qpn_context->base_qpn = 555255932Salfred cpu_to_be32(port_info->base_qpn); 556255932Salfred qpn_context->n_mac = 0x7; 557255932Salfred promisc = be32_to_cpu(qpn_context->promisc) >> 558255932Salfred SET_PORT_PROMISC_SHIFT; 559255932Salfred qpn_context->promisc = cpu_to_be32( 560255932Salfred promisc << SET_PORT_PROMISC_SHIFT | 561255932Salfred port_info->base_qpn); 562255932Salfred promisc = be32_to_cpu(qpn_context->mcast) >> 563255932Salfred SET_PORT_MC_PROMISC_SHIFT; 564255932Salfred qpn_context->mcast = cpu_to_be32( 565255932Salfred promisc << SET_PORT_MC_PROMISC_SHIFT | 566255932Salfred port_info->base_qpn); 567255932Salfred break; 568255932Salfred case MLX4_SET_PORT_GENERAL: 569255932Salfred gen_context = inbox->buf; 570255932Salfred /* Mtu is configured as the max MTU among all the 571255932Salfred * the functions on the port. */ 572255932Salfred mtu = be16_to_cpu(gen_context->mtu); 573255932Salfred mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]); 574255932Salfred prev_mtu = slave_st->mtu[port]; 575255932Salfred slave_st->mtu[port] = mtu; 576255932Salfred if (mtu > master->max_mtu[port]) 577255932Salfred master->max_mtu[port] = mtu; 578255932Salfred if (mtu < prev_mtu && prev_mtu == 579255932Salfred master->max_mtu[port]) { 580255932Salfred slave_st->mtu[port] = mtu; 581255932Salfred master->max_mtu[port] = mtu; 582255932Salfred for (i = 0; i < dev->num_slaves; i++) { 583255932Salfred master->max_mtu[port] = 584255932Salfred max(master->max_mtu[port], 585255932Salfred master->slave_state[i].mtu[port]); 586255932Salfred } 587255932Salfred } 588255932Salfred 589255932Salfred gen_context->mtu = cpu_to_be16(master->max_mtu[port]); 590255932Salfred break; 591255932Salfred case MLX4_SET_PORT_GID_TABLE: 592255932Salfred /* change to MULTIPLE entries: number of guest's gids 593255932Salfred * need a FOR-loop here over number of gids the guest has. 594255932Salfred * 1. Check no duplicates in gids passed by slave 595255932Salfred */ 596255932Salfred num_gids = mlx4_get_slave_num_gids(dev, slave); 597255932Salfred base = mlx4_get_base_gid_ix(dev, slave); 598255932Salfred gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf); 599255932Salfred for (i = 0; i < num_gids; gid_entry_mbox++, i++) { 600255932Salfred if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw, 601255932Salfred sizeof(zgid_entry))) 602255932Salfred continue; 603255932Salfred gid_entry_mb1 = gid_entry_mbox + 1; 604255932Salfred for (j = i + 1; j < num_gids; gid_entry_mb1++, j++) { 605255932Salfred if (!memcmp(gid_entry_mb1->raw, 606255932Salfred zgid_entry.raw, sizeof(zgid_entry))) 607255932Salfred continue; 608255932Salfred if (!memcmp(gid_entry_mb1->raw, gid_entry_mbox->raw, 609255932Salfred sizeof(gid_entry_mbox->raw))) { 610255932Salfred /* found duplicate */ 611255932Salfred return -EINVAL; 612255932Salfred } 613255932Salfred } 614255932Salfred } 615255932Salfred 616255932Salfred /* 2. Check that do not have duplicates in OTHER 617255932Salfred * entries in the port GID table 618255932Salfred */ 619255932Salfred for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { 620255932Salfred if (i >= base && i < base + num_gids) 621255932Salfred continue; /* don't compare to slave's current gids */ 622255932Salfred gid_entry_tbl = &priv->roce_gids[port - 1][i]; 623255932Salfred if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry))) 624255932Salfred continue; 625255932Salfred gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf); 626255932Salfred for (j = 0; j < num_gids; gid_entry_mbox++, j++) { 627255932Salfred if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw, 628255932Salfred sizeof(zgid_entry))) 629255932Salfred continue; 630255932Salfred if (!memcmp(gid_entry_mbox->raw, gid_entry_tbl->raw, 631255932Salfred sizeof(gid_entry_tbl->raw))) { 632255932Salfred /* found duplicate */ 633255932Salfred mlx4_warn(dev, "requested gid entry for slave:%d " 634255932Salfred "is a duplicate of gid at index %d\n", 635255932Salfred slave, i); 636255932Salfred return -EINVAL; 637255932Salfred } 638255932Salfred } 639255932Salfred } 640255932Salfred 641255932Salfred /* insert slave GIDs with memcpy, starting at slave's base index */ 642255932Salfred gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf); 643255932Salfred for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++) 644255932Salfred memcpy(priv->roce_gids[port - 1][offset].raw, gid_entry_mbox->raw, 16); 645255932Salfred 646255932Salfred /* Now, copy roce port gids table to current mailbox for passing to FW */ 647255932Salfred gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf); 648255932Salfred for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++) 649255932Salfred memcpy(gid_entry_mbox->raw, priv->roce_gids[port - 1][i].raw, 16); 650255932Salfred 651255932Salfred break; 652255932Salfred } 653255932Salfred return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, 654255932Salfred MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 655255932Salfred MLX4_CMD_NATIVE); 656255932Salfred } 657255932Salfred 658255932Salfred /* For IB, we only consider: 659255932Salfred * - The capability mask, which is set to the aggregate of all 660255932Salfred * slave function capabilities 661255932Salfred * - The QKey violatin counter - reset according to each request. 662255932Salfred */ 663255932Salfred 664255932Salfred if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 665255932Salfred reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; 666255932Salfred new_cap_mask = ((__be32 *) inbox->buf)[2]; 667255932Salfred } else { 668255932Salfred reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; 669255932Salfred new_cap_mask = ((__be32 *) inbox->buf)[1]; 670255932Salfred } 671255932Salfred 672255932Salfred /* slave may not set the IS_SM capability for the port */ 673255932Salfred if (slave != mlx4_master_func_num(dev) && 674255932Salfred (be32_to_cpu(new_cap_mask) & MLX4_PORT_CAP_IS_SM)) 675255932Salfred return -EINVAL; 676255932Salfred 677255932Salfred /* No DEV_MGMT in multifunc mode */ 678255932Salfred if (mlx4_is_mfunc(dev) && 679255932Salfred (be32_to_cpu(new_cap_mask) & MLX4_PORT_CAP_DEV_MGMT_SUP)) 680255932Salfred return -EINVAL; 681255932Salfred 682255932Salfred agg_cap_mask = 0; 683255932Salfred slave_cap_mask = 684255932Salfred priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; 685255932Salfred priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; 686255932Salfred for (i = 0; i < dev->num_slaves; i++) 687255932Salfred agg_cap_mask |= 688255932Salfred priv->mfunc.master.slave_state[i].ib_cap_mask[port]; 689255932Salfred 690255932Salfred /* only clear mailbox for guests. Master may be setting 691255932Salfred * MTU or PKEY table size 692255932Salfred */ 693255932Salfred if (slave != dev->caps.function) 694255932Salfred memset(inbox->buf, 0, 256); 695255932Salfred if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 696255932Salfred *(u8 *) inbox->buf |= !!reset_qkey_viols << 6; 697255932Salfred ((__be32 *) inbox->buf)[2] = agg_cap_mask; 698255932Salfred } else { 699255932Salfred ((u8 *) inbox->buf)[3] |= !!reset_qkey_viols; 700255932Salfred ((__be32 *) inbox->buf)[1] = agg_cap_mask; 701255932Salfred } 702255932Salfred 703255932Salfred err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, 704255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 705255932Salfred if (err) 706255932Salfred priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = 707255932Salfred slave_cap_mask; 708255932Salfred return err; 709255932Salfred} 710255932Salfred 711255932Salfredint mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, 712255932Salfred struct mlx4_vhcr *vhcr, 713255932Salfred struct mlx4_cmd_mailbox *inbox, 714255932Salfred struct mlx4_cmd_mailbox *outbox, 715255932Salfred struct mlx4_cmd_info *cmd) 716255932Salfred{ 717255932Salfred return mlx4_common_set_port(dev, slave, vhcr->in_modifier, 718255932Salfred vhcr->op_modifier, inbox); 719255932Salfred} 720255932Salfred 721255932Salfred/* bit locations for set port command with zero op modifier */ 722255932Salfredenum { 723255932Salfred MLX4_SET_PORT_VL_CAP = 4, /* bits 7:4 */ 724255932Salfred MLX4_SET_PORT_MTU_CAP = 12, /* bits 15:12 */ 725255932Salfred MLX4_CHANGE_PORT_PKEY_TBL_SZ = 20, 726255932Salfred MLX4_CHANGE_PORT_VL_CAP = 21, 727255932Salfred MLX4_CHANGE_PORT_MTU_CAP = 22, 728255932Salfred}; 729255932Salfred 730255932Salfred#define CX3_PPF_DEV_ID 0x1003 731255932Salfredstatic int vl_cap_start(struct mlx4_dev *dev) 732255932Salfred{ 733255932Salfred /* for non CX3 devices, start with 4 VLs to avoid errors in syslog */ 734255932Salfred if (dev->pdev->device != CX3_PPF_DEV_ID) 735255932Salfred return 4; 736255932Salfred return 8; 737255932Salfred} 738255932Salfred 739255932Salfredint mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz) 740255932Salfred{ 741255932Salfred struct mlx4_cmd_mailbox *mailbox; 742255932Salfred int err, vl_cap, pkey_tbl_flag = 0; 743255932Salfred u32 in_mod; 744255932Salfred 745255932Salfred if (dev->caps.port_type[port] == MLX4_PORT_TYPE_NONE) 746219820Sjeff return 0; 747219820Sjeff 748219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 749219820Sjeff if (IS_ERR(mailbox)) 750219820Sjeff return PTR_ERR(mailbox); 751219820Sjeff 752219820Sjeff memset(mailbox->buf, 0, 256); 753219820Sjeff 754255932Salfred if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) { 755255932Salfred in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 756255932Salfred err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, 757255932Salfred MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 758255932Salfred MLX4_CMD_WRAPPED); 759255932Salfred } else { 760255932Salfred ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; 761219820Sjeff 762255932Salfred if (pkey_tbl_sz >= 0 && mlx4_is_master(dev)) { 763255932Salfred pkey_tbl_flag = 1; 764255932Salfred ((__be16 *) mailbox->buf)[20] = cpu_to_be16(pkey_tbl_sz); 765255932Salfred } 766219820Sjeff 767255932Salfred /* IB VL CAP enum isn't used by the firmware, just numerical values */ 768255932Salfred for (vl_cap = vl_cap_start(dev); vl_cap >= 1; vl_cap >>= 1) { 769255932Salfred ((__be32 *) mailbox->buf)[0] = cpu_to_be32( 770255932Salfred (1 << MLX4_CHANGE_PORT_MTU_CAP) | 771255932Salfred (1 << MLX4_CHANGE_PORT_VL_CAP) | 772255932Salfred (pkey_tbl_flag << MLX4_CHANGE_PORT_PKEY_TBL_SZ) | 773255932Salfred (dev->caps.port_ib_mtu[port] << MLX4_SET_PORT_MTU_CAP) | 774255932Salfred (vl_cap << MLX4_SET_PORT_VL_CAP)); 775255932Salfred err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 776255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 777255932Salfred if (err != -ENOMEM) 778255932Salfred break; 779255932Salfred } 780255932Salfred } 781255932Salfred 782219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 783219820Sjeff return err; 784219820Sjeff} 785255932Salfred 786255932Salfredint mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 787255932Salfred u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 788255932Salfred{ 789255932Salfred struct mlx4_cmd_mailbox *mailbox; 790255932Salfred struct mlx4_set_port_general_context *context; 791255932Salfred int err; 792255932Salfred u32 in_mod; 793255932Salfred 794255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 795255932Salfred if (IS_ERR(mailbox)) 796255932Salfred return PTR_ERR(mailbox); 797255932Salfred context = mailbox->buf; 798255932Salfred memset(context, 0, sizeof *context); 799255932Salfred 800255932Salfred context->flags = SET_PORT_GEN_ALL_VALID; 801255932Salfred context->mtu = cpu_to_be16(mtu); 802255932Salfred context->pptx = (pptx * (!pfctx)) << 7; 803255932Salfred context->pfctx = pfctx; 804255932Salfred context->pprx = (pprx * (!pfcrx)) << 7; 805255932Salfred context->pfcrx = pfcrx; 806255932Salfred 807255932Salfred in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 808255932Salfred err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 809255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 810255932Salfred 811255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 812255932Salfred return err; 813255932Salfred} 814255932SalfredEXPORT_SYMBOL(mlx4_SET_PORT_general); 815255932Salfred 816255932Salfredint mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 817255932Salfred u8 promisc) 818255932Salfred{ 819255932Salfred struct mlx4_cmd_mailbox *mailbox; 820255932Salfred struct mlx4_set_port_rqp_calc_context *context; 821255932Salfred int err; 822255932Salfred u32 in_mod; 823255932Salfred u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? 824255932Salfred MCAST_DIRECT : MCAST_DEFAULT; 825255932Salfred/* 826255932Salfred if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) 827255932Salfred return 0; 828255932Salfred*/ 829255932Salfred 830255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 831255932Salfred if (IS_ERR(mailbox)) 832255932Salfred return PTR_ERR(mailbox); 833255932Salfred context = mailbox->buf; 834255932Salfred memset(context, 0, sizeof *context); 835255932Salfred 836255932Salfred context->base_qpn = cpu_to_be32(base_qpn); 837255932Salfred /* 838255932Salfred * This assignment breaks vlan support - I don't know why. Probablya an A0 issue - shahar Klein 839255932Salfred * context->n_mac = dev->caps.log_num_macs; 840255932Salfred */ 841255932Salfred context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | 842255932Salfred base_qpn); 843255932Salfred context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | 844255932Salfred base_qpn); 845255932Salfred context->intra_no_vlan = 0; 846255932Salfred context->no_vlan = MLX4_NO_VLAN_IDX; 847255932Salfred context->intra_vlan_miss = 0; 848255932Salfred context->vlan_miss = MLX4_VLAN_MISS_IDX; 849255932Salfred 850255932Salfred in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 851255932Salfred err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 852255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 853255932Salfred 854255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 855255932Salfred return err; 856255932Salfred} 857255932SalfredEXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); 858255932Salfred 859255932Salfredint mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc) 860255932Salfred{ 861255932Salfred struct mlx4_cmd_mailbox *mailbox; 862255932Salfred struct mlx4_set_port_prio2tc_context *context; 863255932Salfred int err; 864255932Salfred u32 in_mod; 865255932Salfred int i; 866255932Salfred 867255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 868255932Salfred if (IS_ERR(mailbox)) 869255932Salfred return PTR_ERR(mailbox); 870255932Salfred context = mailbox->buf; 871255932Salfred memset(context, 0, sizeof *context); 872255932Salfred 873255932Salfred for (i = 0; i < MLX4_NUM_UP; i += 2) 874255932Salfred context->prio2tc[i >> 1] = prio2tc[i] << 4 | prio2tc[i + 1]; 875255932Salfred 876255932Salfred in_mod = MLX4_SET_PORT_PRIO2TC << 8 | port; 877255932Salfred err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 878255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 879255932Salfred 880255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 881255932Salfred return err; 882255932Salfred} 883255932SalfredEXPORT_SYMBOL(mlx4_SET_PORT_PRIO2TC); 884255932Salfred 885255932Salfredint mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw, 886255932Salfred u8 *pg, u16 *ratelimit) 887255932Salfred{ 888255932Salfred struct mlx4_cmd_mailbox *mailbox; 889255932Salfred struct mlx4_set_port_scheduler_context *context; 890255932Salfred int err; 891255932Salfred u32 in_mod; 892255932Salfred int i; 893255932Salfred 894255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 895255932Salfred if (IS_ERR(mailbox)) 896255932Salfred return PTR_ERR(mailbox); 897255932Salfred context = mailbox->buf; 898255932Salfred memset(context, 0, sizeof *context); 899255932Salfred 900255932Salfred for (i = 0; i < MLX4_NUM_TC; i++) { 901255932Salfred struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i]; 902255932Salfred u16 r; 903255932Salfred if (ratelimit && ratelimit[i]) { 904255932Salfred if (ratelimit[i] <= MLX4_MAX_100M_UNITS_VAL) { 905255932Salfred r = ratelimit[i]; 906255932Salfred tc->max_bw_units = 907255932Salfred htons(MLX4_RATELIMIT_100M_UNITS); 908255932Salfred } else { 909255932Salfred r = ratelimit[i]/10; 910255932Salfred tc->max_bw_units = 911255932Salfred htons(MLX4_RATELIMIT_1G_UNITS); 912255932Salfred } 913255932Salfred tc->max_bw_value = htons(r); 914255932Salfred } else { 915255932Salfred tc->max_bw_value = htons(MLX4_RATELIMIT_DEFAULT); 916255932Salfred tc->max_bw_units = htons(MLX4_RATELIMIT_1G_UNITS); 917255932Salfred } 918255932Salfred 919255932Salfred tc->pg = htons(pg[i]); 920255932Salfred tc->bw_precentage = htons(tc_tx_bw[i]); 921255932Salfred } 922255932Salfred 923255932Salfred in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port; 924255932Salfred err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 925255932Salfred MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 926255932Salfred 927255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 928255932Salfred return err; 929255932Salfred} 930255932SalfredEXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER); 931255932Salfred 932255932Salfredint mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, 933255932Salfred struct mlx4_vhcr *vhcr, 934255932Salfred struct mlx4_cmd_mailbox *inbox, 935255932Salfred struct mlx4_cmd_mailbox *outbox, 936255932Salfred struct mlx4_cmd_info *cmd) 937255932Salfred{ 938255932Salfred int err = 0; 939255932Salfred 940255932Salfred return err; 941255932Salfred} 942255932Salfred 943255932Salfredint mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 944255932Salfred u64 mac, u64 clear, u8 mode) 945255932Salfred{ 946255932Salfred return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 947255932Salfred MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, 948255932Salfred MLX4_CMD_WRAPPED); 949255932Salfred} 950255932SalfredEXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); 951255932Salfred 952255932Salfredint mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, 953255932Salfred struct mlx4_vhcr *vhcr, 954255932Salfred struct mlx4_cmd_mailbox *inbox, 955255932Salfred struct mlx4_cmd_mailbox *outbox, 956255932Salfred struct mlx4_cmd_info *cmd) 957255932Salfred{ 958255932Salfred int err = 0; 959255932Salfred 960255932Salfred return err; 961255932Salfred} 962255932Salfred 963255932Salfredint mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, 964255932Salfred u32 in_mod, struct mlx4_cmd_mailbox *outbox) 965255932Salfred{ 966255932Salfred return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, 967255932Salfred MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, 968255932Salfred MLX4_CMD_NATIVE); 969255932Salfred} 970255932Salfred 971255932Salfredint mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, 972255932Salfred struct mlx4_vhcr *vhcr, 973255932Salfred struct mlx4_cmd_mailbox *inbox, 974255932Salfred struct mlx4_cmd_mailbox *outbox, 975255932Salfred struct mlx4_cmd_info *cmd) 976255932Salfred{ 977255932Salfred if (slave != dev->caps.function) 978255932Salfred return 0; 979255932Salfred return mlx4_common_dump_eth_stats(dev, slave, 980255932Salfred vhcr->in_modifier, outbox); 981255932Salfred} 982255932Salfred 983255932Salfredvoid mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap) 984255932Salfred{ 985255932Salfred if (!mlx4_is_mfunc(dev)) { 986255932Salfred *stats_bitmap = 0; 987255932Salfred return; 988255932Salfred } 989255932Salfred 990255932Salfred *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK | 991255932Salfred MLX4_STATS_TRAFFIC_DROPS_MASK | 992255932Salfred MLX4_STATS_PORT_COUNTERS_MASK | 993255932Salfred MLX4_STATS_IF_RX_ERRORS_COUNTERS_MASK); 994255932Salfred 995255932Salfred if (mlx4_is_master(dev)) 996255932Salfred *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK; 997255932Salfred} 998255932SalfredEXPORT_SYMBOL(mlx4_set_stats_bitmap); 999255932Salfred 1000255932Salfredint mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, int *slave_id) 1001255932Salfred{ 1002255932Salfred struct mlx4_priv *priv = mlx4_priv(dev); 1003255932Salfred int i, found_ix = -1; 1004255932Salfred int vf_gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; 1005255932Salfred 1006255932Salfred if (!mlx4_is_mfunc(dev)) 1007255932Salfred return -EINVAL; 1008255932Salfred 1009255932Salfred for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { 1010255932Salfred if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) { 1011255932Salfred found_ix = i; 1012255932Salfred break; 1013255932Salfred } 1014255932Salfred } 1015255932Salfred 1016255932Salfred if (found_ix >= 0) { 1017255932Salfred if (found_ix < MLX4_ROCE_PF_GIDS) 1018255932Salfred *slave_id = 0; 1019255932Salfred else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % dev->num_vfs) * 1020255932Salfred (vf_gids / dev->num_vfs + 1)) 1021255932Salfred *slave_id = ((found_ix - MLX4_ROCE_PF_GIDS) / 1022255932Salfred (vf_gids / dev->num_vfs + 1)) + 1; 1023255932Salfred else 1024255932Salfred *slave_id = 1025255932Salfred ((found_ix - MLX4_ROCE_PF_GIDS - 1026255932Salfred ((vf_gids % dev->num_vfs) * ((vf_gids / dev->num_vfs + 1)))) / 1027255932Salfred (vf_gids / dev->num_vfs)) + vf_gids % dev->num_vfs + 1; 1028255932Salfred } 1029255932Salfred 1030255932Salfred return (found_ix >= 0) ? 0 : -EINVAL; 1031255932Salfred} 1032255932SalfredEXPORT_SYMBOL(mlx4_get_slave_from_roce_gid); 1033255932Salfred 1034255932Salfredint mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id, u8 *gid) 1035255932Salfred{ 1036255932Salfred struct mlx4_priv *priv = mlx4_priv(dev); 1037255932Salfred 1038255932Salfred if (!mlx4_is_master(dev)) 1039255932Salfred return -EINVAL; 1040255932Salfred 1041255932Salfred memcpy(gid, priv->roce_gids[port - 1][slave_id].raw, 16); 1042255932Salfred return 0; 1043255932Salfred} 1044255932SalfredEXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); 1045255932Salfred 1046