mlx4_mcg.c revision 255932
1219820Sjeff/* 2219820Sjeff * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff */ 33219820Sjeff 34219820Sjeff#include <linux/string.h> 35219820Sjeff 36219820Sjeff#include <linux/mlx4/cmd.h> 37219820Sjeff 38219820Sjeff#include "mlx4.h" 39219820Sjeff 40219820Sjeff 41219820Sjeffstatic const u8 zero_gid[16]; /* automatically initialized to 0 */ 42219820Sjeff 43255932Salfredint mlx4_get_mgm_entry_size(struct mlx4_dev *dev) 44219820Sjeff{ 45255932Salfred return 1 << dev->oper_log_mgm_entry_size; 46255932Salfred} 47255932Salfred 48255932Salfredint mlx4_get_qp_per_mgm(struct mlx4_dev *dev) 49255932Salfred{ 50255932Salfred return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2); 51255932Salfred} 52255932Salfred 53255932Salfredstatic int mlx4_QP_FLOW_STEERING_ATTACH(struct mlx4_dev *dev, 54255932Salfred struct mlx4_cmd_mailbox *mailbox, 55255932Salfred u32 size, 56255932Salfred u64 *reg_id) 57255932Salfred{ 58255932Salfred u64 imm; 59255932Salfred int err = 0; 60255932Salfred 61255932Salfred err = mlx4_cmd_imm(dev, mailbox->dma, &imm, size, 0, 62255932Salfred MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, 63255932Salfred MLX4_CMD_NATIVE); 64255932Salfred if (err) 65255932Salfred return err; 66255932Salfred *reg_id = imm; 67255932Salfred 68255932Salfred return err; 69255932Salfred} 70255932Salfred 71255932Salfredstatic int mlx4_QP_FLOW_STEERING_DETACH(struct mlx4_dev *dev, u64 regid) 72255932Salfred{ 73255932Salfred int err = 0; 74255932Salfred 75255932Salfred err = mlx4_cmd(dev, regid, 0, 0, 76255932Salfred MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, 77255932Salfred MLX4_CMD_NATIVE); 78255932Salfred 79255932Salfred return err; 80255932Salfred} 81255932Salfred 82255932Salfredstatic int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, 83255932Salfred struct mlx4_cmd_mailbox *mailbox) 84255932Salfred{ 85219820Sjeff return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, 86255932Salfred MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 87219820Sjeff} 88219820Sjeff 89255932Salfredstatic int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index, 90255932Salfred struct mlx4_cmd_mailbox *mailbox) 91219820Sjeff{ 92219820Sjeff return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, 93255932Salfred MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 94219820Sjeff} 95219820Sjeff 96255932Salfredstatic int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer, 97255932Salfred struct mlx4_cmd_mailbox *mailbox) 98219820Sjeff{ 99255932Salfred u32 in_mod; 100255932Salfred 101255932Salfred in_mod = (u32) port << 16 | steer << 1; 102255932Salfred return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1, 103255932Salfred MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A, 104255932Salfred MLX4_CMD_NATIVE); 105255932Salfred} 106255932Salfred 107255932Salfredstatic int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, 108255932Salfred u16 *hash, u8 op_mod) 109255932Salfred{ 110219820Sjeff u64 imm; 111219820Sjeff int err; 112219820Sjeff 113255932Salfred err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod, 114255932Salfred MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A, 115255932Salfred MLX4_CMD_NATIVE); 116219820Sjeff 117219820Sjeff if (!err) 118219820Sjeff *hash = imm; 119219820Sjeff 120219820Sjeff return err; 121219820Sjeff} 122219820Sjeff 123255932Salfredstatic struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port, 124255932Salfred enum mlx4_steer_type steer, 125255932Salfred u32 qpn) 126255932Salfred{ 127255932Salfred struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1]; 128255932Salfred struct mlx4_promisc_qp *pqp; 129255932Salfred 130255932Salfred list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { 131255932Salfred if (pqp->qpn == qpn) 132255932Salfred return pqp; 133255932Salfred } 134255932Salfred /* not found */ 135255932Salfred return NULL; 136255932Salfred} 137255932Salfred 138219820Sjeff/* 139255932Salfred * Add new entry to steering data structure. 140255932Salfred * All promisc QPs should be added as well 141255932Salfred */ 142255932Salfredstatic int new_steering_entry(struct mlx4_dev *dev, u8 port, 143255932Salfred enum mlx4_steer_type steer, 144255932Salfred unsigned int index, u32 qpn) 145255932Salfred{ 146255932Salfred struct mlx4_steer *s_steer; 147255932Salfred struct mlx4_cmd_mailbox *mailbox; 148255932Salfred struct mlx4_mgm *mgm; 149255932Salfred u32 members_count; 150255932Salfred struct mlx4_steer_index *new_entry; 151255932Salfred struct mlx4_promisc_qp *pqp; 152255932Salfred struct mlx4_promisc_qp *dqp = NULL; 153255932Salfred u32 prot; 154255932Salfred int err; 155255932Salfred 156255932Salfred s_steer = &mlx4_priv(dev)->steer[port - 1]; 157255932Salfred new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL); 158255932Salfred if (!new_entry) 159255932Salfred return -ENOMEM; 160255932Salfred 161255932Salfred INIT_LIST_HEAD(&new_entry->duplicates); 162255932Salfred new_entry->index = index; 163255932Salfred list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]); 164255932Salfred 165255932Salfred /* If the given qpn is also a promisc qp, 166255932Salfred * it should be inserted to duplicates list 167255932Salfred */ 168255932Salfred pqp = get_promisc_qp(dev, port, steer, qpn); 169255932Salfred if (pqp) { 170255932Salfred dqp = kmalloc(sizeof *dqp, GFP_KERNEL); 171255932Salfred if (!dqp) { 172255932Salfred err = -ENOMEM; 173255932Salfred goto out_alloc; 174255932Salfred } 175255932Salfred dqp->qpn = qpn; 176255932Salfred list_add_tail(&dqp->list, &new_entry->duplicates); 177255932Salfred } 178255932Salfred 179255932Salfred /* if no promisc qps for this vep, we are done */ 180255932Salfred if (list_empty(&s_steer->promisc_qps[steer])) 181255932Salfred return 0; 182255932Salfred 183255932Salfred /* now need to add all the promisc qps to the new 184255932Salfred * steering entry, as they should also receive the packets 185255932Salfred * destined to this address */ 186255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 187255932Salfred if (IS_ERR(mailbox)) { 188255932Salfred err = -ENOMEM; 189255932Salfred goto out_alloc; 190255932Salfred } 191255932Salfred mgm = mailbox->buf; 192255932Salfred 193255932Salfred err = mlx4_READ_ENTRY(dev, index, mailbox); 194255932Salfred if (err) 195255932Salfred goto out_mailbox; 196255932Salfred 197255932Salfred members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 198255932Salfred prot = be32_to_cpu(mgm->members_count) >> 30; 199255932Salfred list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { 200255932Salfred /* don't add already existing qpn */ 201255932Salfred if (pqp->qpn == qpn) 202255932Salfred continue; 203255932Salfred if (members_count == dev->caps.num_qp_per_mgm) { 204255932Salfred /* out of space */ 205255932Salfred err = -ENOMEM; 206255932Salfred goto out_mailbox; 207255932Salfred } 208255932Salfred 209255932Salfred /* add the qpn */ 210255932Salfred mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK); 211255932Salfred } 212255932Salfred /* update the qps count and update the entry with all the promisc qps*/ 213255932Salfred mgm->members_count = cpu_to_be32(members_count | (prot << 30)); 214255932Salfred err = mlx4_WRITE_ENTRY(dev, index, mailbox); 215255932Salfred 216255932Salfredout_mailbox: 217255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 218255932Salfred if (!err) 219255932Salfred return 0; 220255932Salfredout_alloc: 221255932Salfred if (dqp) { 222255932Salfred list_del(&dqp->list); 223255932Salfred kfree(dqp); 224255932Salfred } 225255932Salfred list_del(&new_entry->list); 226255932Salfred kfree(new_entry); 227255932Salfred return err; 228255932Salfred} 229255932Salfred 230255932Salfred/* update the data structures with existing steering entry */ 231255932Salfredstatic int existing_steering_entry(struct mlx4_dev *dev, u8 port, 232255932Salfred enum mlx4_steer_type steer, 233255932Salfred unsigned int index, u32 qpn) 234255932Salfred{ 235255932Salfred struct mlx4_steer *s_steer; 236255932Salfred struct mlx4_steer_index *tmp_entry, *entry = NULL; 237255932Salfred struct mlx4_promisc_qp *pqp; 238255932Salfred struct mlx4_promisc_qp *dqp; 239255932Salfred 240255932Salfred s_steer = &mlx4_priv(dev)->steer[port - 1]; 241255932Salfred 242255932Salfred pqp = get_promisc_qp(dev, port, steer, qpn); 243255932Salfred if (!pqp) 244255932Salfred return 0; /* nothing to do */ 245255932Salfred 246255932Salfred list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) { 247255932Salfred if (tmp_entry->index == index) { 248255932Salfred entry = tmp_entry; 249255932Salfred break; 250255932Salfred } 251255932Salfred } 252255932Salfred if (unlikely(!entry)) { 253255932Salfred mlx4_warn(dev, "Steering entry at index %x is not registered\n", index); 254255932Salfred return -EINVAL; 255255932Salfred } 256255932Salfred 257255932Salfred /* the given qpn is listed as a promisc qpn 258255932Salfred * we need to add it as a duplicate to this entry 259255932Salfred * for future references */ 260255932Salfred list_for_each_entry(dqp, &entry->duplicates, list) { 261255932Salfred if (qpn == pqp->qpn) 262255932Salfred return 0; /* qp is already duplicated */ 263255932Salfred } 264255932Salfred 265255932Salfred /* add the qp as a duplicate on this index */ 266255932Salfred dqp = kmalloc(sizeof *dqp, GFP_KERNEL); 267255932Salfred if (!dqp) 268255932Salfred return -ENOMEM; 269255932Salfred dqp->qpn = qpn; 270255932Salfred list_add_tail(&dqp->list, &entry->duplicates); 271255932Salfred 272255932Salfred return 0; 273255932Salfred} 274255932Salfred 275255932Salfred/* Check whether a qpn is a duplicate on steering entry 276255932Salfred * If so, it should not be removed from mgm */ 277255932Salfredstatic bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, 278255932Salfred enum mlx4_steer_type steer, 279255932Salfred unsigned int index, u32 qpn) 280255932Salfred{ 281255932Salfred struct mlx4_steer *s_steer; 282255932Salfred struct mlx4_steer_index *tmp_entry, *entry = NULL; 283255932Salfred struct mlx4_promisc_qp *dqp, *tmp_dqp; 284255932Salfred 285255932Salfred s_steer = &mlx4_priv(dev)->steer[port - 1]; 286255932Salfred 287255932Salfred /* if qp is not promisc, it cannot be duplicated */ 288255932Salfred if (!get_promisc_qp(dev, port, steer, qpn)) 289255932Salfred return false; 290255932Salfred 291255932Salfred /* The qp is promisc qp so it is a duplicate on this index 292255932Salfred * Find the index entry, and remove the duplicate */ 293255932Salfred list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) { 294255932Salfred if (tmp_entry->index == index) { 295255932Salfred entry = tmp_entry; 296255932Salfred break; 297255932Salfred } 298255932Salfred } 299255932Salfred if (unlikely(!entry)) { 300255932Salfred mlx4_warn(dev, "Steering entry for index %x is not registered\n", index); 301255932Salfred return false; 302255932Salfred } 303255932Salfred list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) { 304255932Salfred if (dqp->qpn == qpn) { 305255932Salfred list_del(&dqp->list); 306255932Salfred kfree(dqp); 307255932Salfred } 308255932Salfred } 309255932Salfred return true; 310255932Salfred} 311255932Salfred 312255932Salfred/* I a steering entry contains only promisc QPs, it can be removed. */ 313255932Salfredstatic bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, 314255932Salfred enum mlx4_steer_type steer, 315255932Salfred unsigned int index, u32 tqpn) 316255932Salfred{ 317255932Salfred struct mlx4_steer *s_steer; 318255932Salfred struct mlx4_cmd_mailbox *mailbox; 319255932Salfred struct mlx4_mgm *mgm; 320255932Salfred struct mlx4_steer_index *entry = NULL, *tmp_entry; 321255932Salfred u32 qpn; 322255932Salfred u32 members_count; 323255932Salfred bool ret = false; 324255932Salfred int i; 325255932Salfred 326255932Salfred s_steer = &mlx4_priv(dev)->steer[port - 1]; 327255932Salfred 328255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 329255932Salfred if (IS_ERR(mailbox)) 330255932Salfred return false; 331255932Salfred mgm = mailbox->buf; 332255932Salfred 333255932Salfred if (mlx4_READ_ENTRY(dev, index, mailbox)) 334255932Salfred goto out; 335255932Salfred members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 336255932Salfred for (i = 0; i < members_count; i++) { 337255932Salfred qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; 338255932Salfred if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) { 339255932Salfred /* the qp is not promisc, the entry can't be removed */ 340255932Salfred goto out; 341255932Salfred } 342255932Salfred } 343255932Salfred /* All the qps currently registered for this entry are promiscuous, 344255932Salfred * Checking for duplicates */ 345255932Salfred ret = true; 346255932Salfred list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) { 347255932Salfred if (entry->index == index) { 348255932Salfred if (list_empty(&entry->duplicates) || members_count == 1) { 349255932Salfred struct mlx4_promisc_qp *pqp, *tmp_pqp; 350255932Salfred /* 351255932Salfred * If there is only 1 entry in duplicates than 352255932Salfred * this is the QP we want to delete, going over 353255932Salfred * the list and deleting the entry. 354255932Salfred */ 355255932Salfred list_del(&entry->list); 356255932Salfred list_for_each_entry_safe(pqp, tmp_pqp, 357255932Salfred &entry->duplicates, 358255932Salfred list) { 359255932Salfred list_del(&pqp->list); 360255932Salfred kfree(pqp); 361255932Salfred } 362255932Salfred kfree(entry); 363255932Salfred } else { 364255932Salfred /* This entry contains duplicates so it shouldn't be removed */ 365255932Salfred ret = false; 366255932Salfred goto out; 367255932Salfred } 368255932Salfred } 369255932Salfred } 370255932Salfred 371255932Salfredout: 372255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 373255932Salfred return ret; 374255932Salfred} 375255932Salfred 376255932Salfredstatic int add_promisc_qp(struct mlx4_dev *dev, u8 port, 377255932Salfred enum mlx4_steer_type steer, u32 qpn) 378255932Salfred{ 379255932Salfred struct mlx4_steer *s_steer; 380255932Salfred struct mlx4_cmd_mailbox *mailbox; 381255932Salfred struct mlx4_mgm *mgm; 382255932Salfred struct mlx4_steer_index *entry; 383255932Salfred struct mlx4_promisc_qp *pqp; 384255932Salfred struct mlx4_promisc_qp *dqp; 385255932Salfred u32 members_count; 386255932Salfred u32 prot; 387255932Salfred int i; 388255932Salfred bool found; 389255932Salfred int err; 390255932Salfred struct mlx4_priv *priv = mlx4_priv(dev); 391255932Salfred 392255932Salfred s_steer = &mlx4_priv(dev)->steer[port - 1]; 393255932Salfred 394255932Salfred mutex_lock(&priv->mcg_table.mutex); 395255932Salfred 396255932Salfred if (get_promisc_qp(dev, port, steer, qpn)) { 397255932Salfred err = 0; /* Noting to do, already exists */ 398255932Salfred goto out_mutex; 399255932Salfred } 400255932Salfred 401255932Salfred pqp = kmalloc(sizeof *pqp, GFP_KERNEL); 402255932Salfred if (!pqp) { 403255932Salfred err = -ENOMEM; 404255932Salfred goto out_mutex; 405255932Salfred } 406255932Salfred pqp->qpn = qpn; 407255932Salfred 408255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 409255932Salfred if (IS_ERR(mailbox)) { 410255932Salfred err = -ENOMEM; 411255932Salfred goto out_alloc; 412255932Salfred } 413255932Salfred mgm = mailbox->buf; 414255932Salfred 415255932Salfred /* the promisc qp needs to be added for each one of the steering 416255932Salfred * entries, if it already exists, needs to be added as a duplicate 417255932Salfred * for this entry */ 418255932Salfred list_for_each_entry(entry, &s_steer->steer_entries[steer], list) { 419255932Salfred err = mlx4_READ_ENTRY(dev, entry->index, mailbox); 420255932Salfred if (err) 421255932Salfred goto out_mailbox; 422255932Salfred 423255932Salfred members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 424255932Salfred prot = be32_to_cpu(mgm->members_count) >> 30; 425255932Salfred found = false; 426255932Salfred for (i = 0; i < members_count; i++) { 427255932Salfred if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { 428255932Salfred /* Entry already exists, add to duplicates */ 429255932Salfred dqp = kmalloc(sizeof *dqp, GFP_KERNEL); 430255932Salfred if (!dqp) { 431255932Salfred err = -ENOMEM; 432255932Salfred goto out_mailbox; 433255932Salfred } 434255932Salfred dqp->qpn = qpn; 435255932Salfred list_add_tail(&dqp->list, &entry->duplicates); 436255932Salfred found = true; 437255932Salfred } 438255932Salfred } 439255932Salfred if (!found) { 440255932Salfred /* Need to add the qpn to mgm */ 441255932Salfred if (members_count == dev->caps.num_qp_per_mgm) { 442255932Salfred /* entry is full */ 443255932Salfred err = -ENOMEM; 444255932Salfred goto out_mailbox; 445255932Salfred } 446255932Salfred mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK); 447255932Salfred mgm->members_count = cpu_to_be32(members_count | (prot << 30)); 448255932Salfred err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox); 449255932Salfred if (err) 450255932Salfred goto out_mailbox; 451255932Salfred } 452255932Salfred } 453255932Salfred 454255932Salfred /* add the new qpn to list of promisc qps */ 455255932Salfred list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]); 456255932Salfred /* now need to add all the promisc qps to default entry */ 457255932Salfred memset(mgm, 0, sizeof *mgm); 458255932Salfred members_count = 0; 459255932Salfred list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) { 460255932Salfred if (members_count == dev->caps.num_qp_per_mgm) { 461255932Salfred /* entry is full */ 462255932Salfred err = -ENOMEM; 463255932Salfred goto out_list; 464255932Salfred } 465255932Salfred mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); 466255932Salfred } 467255932Salfred mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); 468255932Salfred 469255932Salfred err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); 470255932Salfred if (err) 471255932Salfred goto out_list; 472255932Salfred 473255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 474255932Salfred mutex_unlock(&priv->mcg_table.mutex); 475255932Salfred return 0; 476255932Salfred 477255932Salfredout_list: 478255932Salfred list_del(&pqp->list); 479255932Salfredout_mailbox: 480255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 481255932Salfredout_alloc: 482255932Salfred kfree(pqp); 483255932Salfredout_mutex: 484255932Salfred mutex_unlock(&priv->mcg_table.mutex); 485255932Salfred return err; 486255932Salfred} 487255932Salfred 488255932Salfredstatic int remove_promisc_qp(struct mlx4_dev *dev, u8 port, 489255932Salfred enum mlx4_steer_type steer, u32 qpn) 490255932Salfred{ 491255932Salfred struct mlx4_priv *priv = mlx4_priv(dev); 492255932Salfred struct mlx4_steer *s_steer; 493255932Salfred struct mlx4_cmd_mailbox *mailbox; 494255932Salfred struct mlx4_mgm *mgm; 495255932Salfred struct mlx4_steer_index *entry; 496255932Salfred struct mlx4_promisc_qp *pqp; 497255932Salfred struct mlx4_promisc_qp *dqp; 498255932Salfred u32 members_count; 499255932Salfred bool found; 500255932Salfred bool back_to_list = false; 501255932Salfred int i, loc = -1; 502255932Salfred int err; 503255932Salfred 504255932Salfred s_steer = &mlx4_priv(dev)->steer[port - 1]; 505255932Salfred mutex_lock(&priv->mcg_table.mutex); 506255932Salfred 507255932Salfred pqp = get_promisc_qp(dev, port, steer, qpn); 508255932Salfred if (unlikely(!pqp)) { 509255932Salfred mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); 510255932Salfred /* nothing to do */ 511255932Salfred err = 0; 512255932Salfred goto out_mutex; 513255932Salfred } 514255932Salfred 515255932Salfred /*remove from list of promisc qps */ 516255932Salfred list_del(&pqp->list); 517255932Salfred 518255932Salfred /* set the default entry not to include the removed one */ 519255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 520255932Salfred if (IS_ERR(mailbox)) { 521255932Salfred err = -ENOMEM; 522255932Salfred back_to_list = true; 523255932Salfred goto out_list; 524255932Salfred } 525255932Salfred mgm = mailbox->buf; 526255932Salfred memset(mgm, 0, sizeof *mgm); 527255932Salfred members_count = 0; 528255932Salfred list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) 529255932Salfred mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); 530255932Salfred mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); 531255932Salfred 532255932Salfred err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); 533255932Salfred if (err) 534255932Salfred goto out_mailbox; 535255932Salfred 536255932Salfred /* remove the qp from all the steering entries*/ 537255932Salfred list_for_each_entry(entry, &s_steer->steer_entries[steer], list) { 538255932Salfred found = false; 539255932Salfred list_for_each_entry(dqp, &entry->duplicates, list) { 540255932Salfred if (dqp->qpn == qpn) { 541255932Salfred found = true; 542255932Salfred break; 543255932Salfred } 544255932Salfred } 545255932Salfred if (found) { 546255932Salfred /* a duplicate, no need to change the mgm, 547255932Salfred * only update the duplicates list */ 548255932Salfred list_del(&dqp->list); 549255932Salfred kfree(dqp); 550255932Salfred } else { 551255932Salfred err = mlx4_READ_ENTRY(dev, entry->index, mailbox); 552255932Salfred if (err) 553255932Salfred goto out_mailbox; 554255932Salfred members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 555255932Salfred for (i = 0; i < members_count; ++i) 556255932Salfred if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { 557255932Salfred loc = i; 558255932Salfred break; 559255932Salfred } 560255932Salfred 561255932Salfred if (loc < 0) { 562255932Salfred mlx4_err(dev, "QP %06x wasn't found in entry %d\n", 563255932Salfred qpn, entry->index); 564255932Salfred err = -EINVAL; 565255932Salfred goto out_mailbox; 566255932Salfred } 567255932Salfred 568255932Salfred /* copy the last QP in this MGM over removed QP */ 569255932Salfred mgm->qp[loc] = mgm->qp[members_count - 1]; 570255932Salfred mgm->qp[members_count - 1] = 0; 571255932Salfred mgm->members_count = cpu_to_be32(--members_count | 572255932Salfred (MLX4_PROT_ETH << 30)); 573255932Salfred 574255932Salfred err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox); 575255932Salfred if (err) 576255932Salfred goto out_mailbox; 577255932Salfred } 578255932Salfred 579255932Salfred } 580255932Salfred 581255932Salfredout_mailbox: 582255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 583255932Salfredout_list: 584255932Salfred if (back_to_list) 585255932Salfred list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]); 586255932Salfred else 587255932Salfred kfree(pqp); 588255932Salfredout_mutex: 589255932Salfred mutex_unlock(&priv->mcg_table.mutex); 590255932Salfred return err; 591255932Salfred} 592255932Salfred 593255932Salfred/* 594219820Sjeff * Caller must hold MCG table semaphore. gid and mgm parameters must 595219820Sjeff * be properly aligned for command interface. 596219820Sjeff * 597219820Sjeff * Returns 0 unless a firmware command error occurs. 598219820Sjeff * 599219820Sjeff * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1 600219820Sjeff * and *mgm holds MGM entry. 601219820Sjeff * 602219820Sjeff * if GID is found in AMGM, *index = index in AMGM, *prev = index of 603219820Sjeff * previous entry in hash chain and *mgm holds AMGM entry. 604219820Sjeff * 605219820Sjeff * If no AMGM exists for given gid, *index = -1, *prev = index of last 606219820Sjeff * entry in hash chain and *mgm holds end of hash chain. 607219820Sjeff */ 608255932Salfredstatic int find_entry(struct mlx4_dev *dev, u8 port, 609255932Salfred u8 *gid, enum mlx4_protocol prot, 610255932Salfred struct mlx4_cmd_mailbox *mgm_mailbox, 611255932Salfred int *prev, int *index) 612219820Sjeff{ 613219820Sjeff struct mlx4_cmd_mailbox *mailbox; 614219820Sjeff struct mlx4_mgm *mgm = mgm_mailbox->buf; 615219820Sjeff u8 *mgid; 616219820Sjeff int err; 617255932Salfred u16 hash; 618255932Salfred u8 op_mod = (prot == MLX4_PROT_ETH) ? 619255932Salfred !!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0; 620219820Sjeff 621219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 622219820Sjeff if (IS_ERR(mailbox)) 623219820Sjeff return -ENOMEM; 624219820Sjeff mgid = mailbox->buf; 625219820Sjeff 626219820Sjeff memcpy(mgid, gid, 16); 627219820Sjeff 628255932Salfred err = mlx4_GID_HASH(dev, mailbox, &hash, op_mod); 629219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 630219820Sjeff if (err) 631219820Sjeff return err; 632219820Sjeff 633219820Sjeff if (0) 634255932Salfred mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, hash); 635219820Sjeff 636255932Salfred *index = hash; 637219820Sjeff *prev = -1; 638219820Sjeff 639219820Sjeff do { 640255932Salfred err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox); 641219820Sjeff if (err) 642219820Sjeff return err; 643219820Sjeff 644255932Salfred if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) { 645255932Salfred if (*index != hash) { 646219820Sjeff mlx4_err(dev, "Found zero MGID in AMGM.\n"); 647219820Sjeff err = -EINVAL; 648219820Sjeff } 649219820Sjeff return err; 650219820Sjeff } 651219820Sjeff 652219820Sjeff if (!memcmp(mgm->gid, gid, 16) && 653255932Salfred be32_to_cpu(mgm->members_count) >> 30 == prot) 654219820Sjeff return err; 655219820Sjeff 656219820Sjeff *prev = *index; 657219820Sjeff *index = be32_to_cpu(mgm->next_gid_index) >> 6; 658219820Sjeff } while (*index); 659219820Sjeff 660219820Sjeff *index = -1; 661219820Sjeff return err; 662219820Sjeff} 663219820Sjeff 664255932Salfredstatic void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, 665255932Salfred struct mlx4_net_trans_rule_hw_ctrl *hw) 666219820Sjeff{ 667255932Salfred static const u8 __promisc_mode[] = { 668255932Salfred [MLX4_FS_REGULAR] = 0x0, 669255932Salfred [MLX4_FS_ALL_DEFAULT] = 0x1, 670255932Salfred [MLX4_FS_MC_DEFAULT] = 0x3, 671255932Salfred [MLX4_FS_UC_SNIFFER] = 0x4, 672255932Salfred [MLX4_FS_MC_SNIFFER] = 0x5, 673255932Salfred }; 674255932Salfred 675255932Salfred u32 dw = 0; 676255932Salfred 677255932Salfred dw = ctrl->queue_mode == MLX4_NET_TRANS_Q_LIFO ? 1 : 0; 678255932Salfred dw |= ctrl->exclusive ? (1 << 2) : 0; 679255932Salfred dw |= ctrl->allow_loopback ? (1 << 3) : 0; 680255932Salfred dw |= __promisc_mode[ctrl->promisc_mode] << 8; 681255932Salfred dw |= ctrl->priority << 16; 682255932Salfred 683255932Salfred hw->ctrl = cpu_to_be32(dw); 684255932Salfred hw->port = ctrl->port; 685255932Salfred hw->qpn = cpu_to_be32(ctrl->qpn); 686255932Salfred} 687255932Salfred 688255932Salfredconst u16 __sw_id_hw[] = { 689255932Salfred [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, 690255932Salfred [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, 691255932Salfred [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, 692255932Salfred [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, 693255932Salfred [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, 694255932Salfred [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 695255932Salfred}; 696255932Salfred 697255932Salfredstatic int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, 698255932Salfred struct _rule_hw *rule_hw) 699255932Salfred{ 700255932Salfred static const size_t __rule_hw_sz[] = { 701255932Salfred [MLX4_NET_TRANS_RULE_ID_ETH] = 702255932Salfred sizeof(struct mlx4_net_trans_rule_hw_eth), 703255932Salfred [MLX4_NET_TRANS_RULE_ID_IB] = 704255932Salfred sizeof(struct mlx4_net_trans_rule_hw_ib), 705255932Salfred [MLX4_NET_TRANS_RULE_ID_IPV6] = 0, 706255932Salfred [MLX4_NET_TRANS_RULE_ID_IPV4] = 707255932Salfred sizeof(struct mlx4_net_trans_rule_hw_ipv4), 708255932Salfred [MLX4_NET_TRANS_RULE_ID_TCP] = 709255932Salfred sizeof(struct mlx4_net_trans_rule_hw_tcp_udp), 710255932Salfred [MLX4_NET_TRANS_RULE_ID_UDP] = 711255932Salfred sizeof(struct mlx4_net_trans_rule_hw_tcp_udp) 712255932Salfred }; 713255932Salfred if (spec->id >= MLX4_NET_TRANS_RULE_NUM) { 714255932Salfred mlx4_err(dev, "Invalid network rule id. id = %d\n", spec->id); 715255932Salfred return -EINVAL; 716255932Salfred } 717255932Salfred memset(rule_hw, 0, __rule_hw_sz[spec->id]); 718255932Salfred rule_hw->id = cpu_to_be16(__sw_id_hw[spec->id]); 719255932Salfred rule_hw->size = __rule_hw_sz[spec->id] >> 2; 720255932Salfred 721255932Salfred switch (spec->id) { 722255932Salfred case MLX4_NET_TRANS_RULE_ID_ETH: 723255932Salfred memcpy(rule_hw->eth.dst_mac, spec->eth.dst_mac, ETH_ALEN); 724255932Salfred memcpy(rule_hw->eth.dst_mac_msk, spec->eth.dst_mac_msk, 725255932Salfred ETH_ALEN); 726255932Salfred memcpy(rule_hw->eth.src_mac, spec->eth.src_mac, ETH_ALEN); 727255932Salfred memcpy(rule_hw->eth.src_mac_msk, spec->eth.src_mac_msk, 728255932Salfred ETH_ALEN); 729255932Salfred if (spec->eth.ether_type_enable) { 730255932Salfred rule_hw->eth.ether_type_enable = 1; 731255932Salfred rule_hw->eth.ether_type = spec->eth.ether_type; 732255932Salfred } 733255932Salfred rule_hw->eth.vlan_id = spec->eth.vlan_id; 734255932Salfred rule_hw->eth.vlan_id_msk = spec->eth.vlan_id_msk; 735255932Salfred break; 736255932Salfred 737255932Salfred case MLX4_NET_TRANS_RULE_ID_IB: 738255932Salfred rule_hw->ib.r_u_qpn = spec->ib.r_u_qpn; 739255932Salfred rule_hw->ib.qpn_mask = spec->ib.qpn_msk; 740255932Salfred memcpy(&rule_hw->ib.dst_gid, &spec->ib.dst_gid, 16); 741255932Salfred memcpy(&rule_hw->ib.dst_gid_msk, &spec->ib.dst_gid_msk, 16); 742255932Salfred break; 743255932Salfred 744255932Salfred case MLX4_NET_TRANS_RULE_ID_IPV6: 745255932Salfred return -EOPNOTSUPP; 746255932Salfred 747255932Salfred case MLX4_NET_TRANS_RULE_ID_IPV4: 748255932Salfred rule_hw->ipv4.src_ip = spec->ipv4.src_ip; 749255932Salfred rule_hw->ipv4.src_ip_msk = spec->ipv4.src_ip_msk; 750255932Salfred rule_hw->ipv4.dst_ip = spec->ipv4.dst_ip; 751255932Salfred rule_hw->ipv4.dst_ip_msk = spec->ipv4.dst_ip_msk; 752255932Salfred break; 753255932Salfred 754255932Salfred case MLX4_NET_TRANS_RULE_ID_TCP: 755255932Salfred case MLX4_NET_TRANS_RULE_ID_UDP: 756255932Salfred rule_hw->tcp_udp.dst_port = spec->tcp_udp.dst_port; 757255932Salfred rule_hw->tcp_udp.dst_port_msk = spec->tcp_udp.dst_port_msk; 758255932Salfred rule_hw->tcp_udp.src_port = spec->tcp_udp.src_port; 759255932Salfred rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk; 760255932Salfred break; 761255932Salfred 762255932Salfred default: 763255932Salfred return -EINVAL; 764255932Salfred } 765255932Salfred 766255932Salfred return __rule_hw_sz[spec->id]; 767255932Salfred} 768255932Salfred 769255932Salfredstatic void mlx4_err_rule(struct mlx4_dev *dev, char *str, 770255932Salfred struct mlx4_net_trans_rule *rule) 771255932Salfred{ 772255932Salfred#define BUF_SIZE 256 773255932Salfred struct mlx4_spec_list *cur; 774255932Salfred char buf[BUF_SIZE]; 775255932Salfred int len = 0; 776255932Salfred 777255932Salfred mlx4_err(dev, "%s", str); 778255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 779255932Salfred "port = %d prio = 0x%x qp = 0x%x ", 780255932Salfred rule->port, rule->priority, rule->qpn); 781255932Salfred 782255932Salfred list_for_each_entry(cur, &rule->list, list) { 783255932Salfred switch (cur->id) { 784255932Salfred case MLX4_NET_TRANS_RULE_ID_ETH: 785255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 786255932Salfred "dmac = %pM ", &cur->eth.dst_mac); 787255932Salfred if (cur->eth.ether_type) 788255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 789255932Salfred "ethertype = 0x%x ", 790255932Salfred be16_to_cpu(cur->eth.ether_type)); 791255932Salfred if (cur->eth.vlan_id) 792255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 793255932Salfred "vlan-id = %d ", 794255932Salfred be16_to_cpu(cur->eth.vlan_id)); 795255932Salfred break; 796255932Salfred 797255932Salfred case MLX4_NET_TRANS_RULE_ID_IPV4: 798255932Salfred if (cur->ipv4.src_ip) 799255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 800255932Salfred "src-ip = %pI4 ", 801255932Salfred &cur->ipv4.src_ip); 802255932Salfred if (cur->ipv4.dst_ip) 803255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 804255932Salfred "dst-ip = %pI4 ", 805255932Salfred &cur->ipv4.dst_ip); 806255932Salfred break; 807255932Salfred 808255932Salfred case MLX4_NET_TRANS_RULE_ID_TCP: 809255932Salfred case MLX4_NET_TRANS_RULE_ID_UDP: 810255932Salfred if (cur->tcp_udp.src_port) 811255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 812255932Salfred "src-port = %d ", 813255932Salfred be16_to_cpu(cur->tcp_udp.src_port)); 814255932Salfred if (cur->tcp_udp.dst_port) 815255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 816255932Salfred "dst-port = %d ", 817255932Salfred be16_to_cpu(cur->tcp_udp.dst_port)); 818255932Salfred break; 819255932Salfred 820255932Salfred case MLX4_NET_TRANS_RULE_ID_IB: 821255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 822255932Salfred "dst-gid = %pI6\n", cur->ib.dst_gid); 823255932Salfred len += snprintf(buf + len, BUF_SIZE - len, 824255932Salfred "dst-gid-mask = %pI6\n", 825255932Salfred cur->ib.dst_gid_msk); 826255932Salfred break; 827255932Salfred 828255932Salfred case MLX4_NET_TRANS_RULE_ID_IPV6: 829255932Salfred break; 830255932Salfred 831255932Salfred default: 832255932Salfred break; 833255932Salfred } 834255932Salfred } 835255932Salfred len += snprintf(buf + len, BUF_SIZE - len, "\n"); 836255932Salfred mlx4_err(dev, "%s", buf); 837255932Salfred 838255932Salfred if (len >= BUF_SIZE) 839255932Salfred mlx4_err(dev, "Network rule error message was truncated, print buffer is too small.\n"); 840255932Salfred} 841255932Salfred 842255932Salfredint mlx4_flow_attach(struct mlx4_dev *dev, 843255932Salfred struct mlx4_net_trans_rule *rule, u64 *reg_id) 844255932Salfred{ 845255932Salfred struct mlx4_cmd_mailbox *mailbox; 846255932Salfred struct mlx4_spec_list *cur; 847255932Salfred u32 size = 0; 848255932Salfred int ret; 849255932Salfred 850255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 851255932Salfred if (IS_ERR(mailbox)) 852255932Salfred return PTR_ERR(mailbox); 853255932Salfred 854255932Salfred memset(mailbox->buf, 0, sizeof(struct mlx4_net_trans_rule_hw_ctrl)); 855255932Salfred trans_rule_ctrl_to_hw(rule, mailbox->buf); 856255932Salfred 857255932Salfred size += sizeof(struct mlx4_net_trans_rule_hw_ctrl); 858255932Salfred 859255932Salfred list_for_each_entry(cur, &rule->list, list) { 860255932Salfred ret = parse_trans_rule(dev, cur, mailbox->buf + size); 861255932Salfred if (ret < 0) { 862255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 863255932Salfred return -EINVAL; 864255932Salfred } 865255932Salfred size += ret; 866255932Salfred } 867255932Salfred 868255932Salfred ret = mlx4_QP_FLOW_STEERING_ATTACH(dev, mailbox, size >> 2, reg_id); 869255932Salfred if (ret == -ENOMEM) 870255932Salfred mlx4_err_rule(dev, 871255932Salfred "mcg table is full. Fail to register network rule.\n", 872255932Salfred rule); 873255932Salfred else if (ret) 874255932Salfred mlx4_err_rule(dev, "Fail to register network rule.\n", rule); 875255932Salfred 876255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 877255932Salfred 878255932Salfred return ret; 879255932Salfred} 880255932SalfredEXPORT_SYMBOL_GPL(mlx4_flow_attach); 881255932Salfred 882255932Salfredint mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id) 883255932Salfred{ 884255932Salfred int err; 885255932Salfred 886255932Salfred err = mlx4_QP_FLOW_STEERING_DETACH(dev, reg_id); 887255932Salfred if (err) 888255932Salfred mlx4_err(dev, "Fail to detach network rule. registration id = 0x%llx\n", 889255932Salfred reg_id); 890255932Salfred return err; 891255932Salfred} 892255932SalfredEXPORT_SYMBOL_GPL(mlx4_flow_detach); 893255932Salfred 894255932Salfredint mlx4_FLOW_STEERING_IB_UC_QP_RANGE(struct mlx4_dev *dev, u32 min_range_qpn, u32 max_range_qpn) 895255932Salfred{ 896255932Salfred int err; 897255932Salfred u64 in_param; 898255932Salfred 899255932Salfred in_param = ((u64) min_range_qpn) << 32; 900255932Salfred in_param |= ((u64) max_range_qpn) & 0xFFFFFFFF; 901255932Salfred 902255932Salfred err = mlx4_cmd(dev, in_param, 0, 0, 903255932Salfred MLX4_FLOW_STEERING_IB_UC_QP_RANGE, 904255932Salfred MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 905255932Salfred 906255932Salfred return err; 907255932Salfred} 908255932SalfredEXPORT_SYMBOL_GPL(mlx4_FLOW_STEERING_IB_UC_QP_RANGE); 909255932Salfred 910255932Salfredint mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 911255932Salfred int block_mcast_loopback, enum mlx4_protocol prot, 912255932Salfred enum mlx4_steer_type steer) 913255932Salfred{ 914219820Sjeff struct mlx4_priv *priv = mlx4_priv(dev); 915219820Sjeff struct mlx4_cmd_mailbox *mailbox; 916219820Sjeff struct mlx4_mgm *mgm; 917219820Sjeff u32 members_count; 918219820Sjeff int index, prev; 919219820Sjeff int link = 0; 920219820Sjeff int i; 921219820Sjeff int err; 922255932Salfred u8 port = gid[5]; 923255932Salfred u8 new_entry = 0; 924219820Sjeff 925219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 926219820Sjeff if (IS_ERR(mailbox)) 927219820Sjeff return PTR_ERR(mailbox); 928219820Sjeff mgm = mailbox->buf; 929219820Sjeff 930219820Sjeff mutex_lock(&priv->mcg_table.mutex); 931255932Salfred err = find_entry(dev, port, gid, prot, 932255932Salfred mailbox, &prev, &index); 933219820Sjeff if (err) 934219820Sjeff goto out; 935219820Sjeff 936219820Sjeff if (index != -1) { 937255932Salfred if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) { 938255932Salfred new_entry = 1; 939219820Sjeff memcpy(mgm->gid, gid, 16); 940255932Salfred } 941219820Sjeff } else { 942219820Sjeff link = 1; 943219820Sjeff 944219820Sjeff index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap); 945219820Sjeff if (index == -1) { 946219820Sjeff mlx4_err(dev, "No AMGM entries left\n"); 947219820Sjeff err = -ENOMEM; 948219820Sjeff goto out; 949219820Sjeff } 950219820Sjeff index += dev->caps.num_mgms; 951219820Sjeff 952255932Salfred new_entry = 1; 953219820Sjeff memset(mgm, 0, sizeof *mgm); 954219820Sjeff memcpy(mgm->gid, gid, 16); 955219820Sjeff } 956219820Sjeff 957219820Sjeff members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 958255932Salfred if (members_count == dev->caps.num_qp_per_mgm) { 959219820Sjeff mlx4_err(dev, "MGM at index %x is full.\n", index); 960219820Sjeff err = -ENOMEM; 961219820Sjeff goto out; 962219820Sjeff } 963219820Sjeff 964219820Sjeff for (i = 0; i < members_count; ++i) 965219820Sjeff if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) { 966219820Sjeff mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn); 967219820Sjeff err = 0; 968219820Sjeff goto out; 969219820Sjeff } 970219820Sjeff 971219820Sjeff mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) | 972219820Sjeff (!!mlx4_blck_lb << MGM_BLCK_LB_BIT)); 973219820Sjeff 974255932Salfred mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30); 975219820Sjeff 976255932Salfred err = mlx4_WRITE_ENTRY(dev, index, mailbox); 977219820Sjeff if (err) 978219820Sjeff goto out; 979219820Sjeff 980219820Sjeff if (!link) 981219820Sjeff goto out; 982219820Sjeff 983255932Salfred err = mlx4_READ_ENTRY(dev, prev, mailbox); 984219820Sjeff if (err) 985219820Sjeff goto out; 986219820Sjeff 987219820Sjeff mgm->next_gid_index = cpu_to_be32(index << 6); 988219820Sjeff 989255932Salfred err = mlx4_WRITE_ENTRY(dev, prev, mailbox); 990219820Sjeff if (err) 991219820Sjeff goto out; 992219820Sjeff 993255932Salfred if (prot == MLX4_PROT_ETH) { 994255932Salfred /* manage the steering entry for promisc mode */ 995255932Salfred if (new_entry) 996255932Salfred new_steering_entry(dev, port, steer, index, qp->qpn); 997255932Salfred else 998255932Salfred existing_steering_entry(dev, port, steer, 999255932Salfred index, qp->qpn); 1000255932Salfred } 1001255932Salfred 1002219820Sjeffout: 1003219820Sjeff if (err && link && index != -1) { 1004219820Sjeff if (index < dev->caps.num_mgms) 1005219820Sjeff mlx4_warn(dev, "Got AMGM index %d < %d", 1006219820Sjeff index, dev->caps.num_mgms); 1007219820Sjeff else 1008219820Sjeff mlx4_bitmap_free(&priv->mcg_table.bitmap, 1009219820Sjeff index - dev->caps.num_mgms); 1010219820Sjeff } 1011219820Sjeff mutex_unlock(&priv->mcg_table.mutex); 1012219820Sjeff 1013219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 1014219820Sjeff return err; 1015219820Sjeff} 1016219820Sjeff 1017255932Salfredint mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 1018255932Salfred enum mlx4_protocol prot, enum mlx4_steer_type steer) 1019219820Sjeff{ 1020219820Sjeff struct mlx4_priv *priv = mlx4_priv(dev); 1021219820Sjeff struct mlx4_cmd_mailbox *mailbox; 1022219820Sjeff struct mlx4_mgm *mgm; 1023219820Sjeff u32 members_count; 1024219820Sjeff int prev, index; 1025255932Salfred int i, loc = -1; 1026219820Sjeff int err; 1027255932Salfred u8 port = gid[5]; 1028255932Salfred bool removed_entry = false; 1029219820Sjeff 1030219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 1031219820Sjeff if (IS_ERR(mailbox)) 1032219820Sjeff return PTR_ERR(mailbox); 1033219820Sjeff mgm = mailbox->buf; 1034219820Sjeff 1035219820Sjeff mutex_lock(&priv->mcg_table.mutex); 1036219820Sjeff 1037255932Salfred err = find_entry(dev, port, gid, prot, 1038255932Salfred mailbox, &prev, &index); 1039219820Sjeff if (err) 1040219820Sjeff goto out; 1041219820Sjeff 1042219820Sjeff if (index == -1) { 1043219820Sjeff mlx4_err(dev, "MGID %pI6 not found\n", gid); 1044219820Sjeff err = -EINVAL; 1045219820Sjeff goto out; 1046219820Sjeff } 1047219820Sjeff 1048255932Salfred /* if this pq is also a promisc qp, it shouldn't be removed */ 1049255932Salfred if (prot == MLX4_PROT_ETH && 1050255932Salfred check_duplicate_entry(dev, port, steer, index, qp->qpn)) 1051255932Salfred goto out; 1052255932Salfred 1053219820Sjeff members_count = be32_to_cpu(mgm->members_count) & 0xffffff; 1054255932Salfred for (i = 0; i < members_count; ++i) 1055255932Salfred if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) { 1056219820Sjeff loc = i; 1057255932Salfred break; 1058255932Salfred } 1059219820Sjeff 1060219820Sjeff if (loc == -1) { 1061219820Sjeff mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn); 1062219820Sjeff err = -EINVAL; 1063219820Sjeff goto out; 1064219820Sjeff } 1065219820Sjeff 1066255932Salfred /* copy the last QP in this MGM over removed QP */ 1067255932Salfred mgm->qp[loc] = mgm->qp[members_count - 1]; 1068255932Salfred mgm->qp[members_count - 1] = 0; 1069255932Salfred mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30); 1070219820Sjeff 1071255932Salfred if (prot == MLX4_PROT_ETH) 1072255932Salfred removed_entry = can_remove_steering_entry(dev, port, steer, 1073255932Salfred index, qp->qpn); 1074255932Salfred if (members_count && (prot != MLX4_PROT_ETH || !removed_entry)) { 1075255932Salfred err = mlx4_WRITE_ENTRY(dev, index, mailbox); 1076219820Sjeff goto out; 1077219820Sjeff } 1078219820Sjeff 1079255932Salfred /* We are going to delete the entry, members count should be 0 */ 1080255932Salfred mgm->members_count = cpu_to_be32((u32) prot << 30); 1081255932Salfred 1082219820Sjeff if (prev == -1) { 1083219820Sjeff /* Remove entry from MGM */ 1084219820Sjeff int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; 1085219820Sjeff if (amgm_index) { 1086255932Salfred err = mlx4_READ_ENTRY(dev, amgm_index, mailbox); 1087219820Sjeff if (err) 1088219820Sjeff goto out; 1089219820Sjeff } else 1090219820Sjeff memset(mgm->gid, 0, 16); 1091219820Sjeff 1092255932Salfred err = mlx4_WRITE_ENTRY(dev, index, mailbox); 1093219820Sjeff if (err) 1094219820Sjeff goto out; 1095219820Sjeff 1096219820Sjeff if (amgm_index) { 1097219820Sjeff if (amgm_index < dev->caps.num_mgms) 1098219820Sjeff mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d", 1099219820Sjeff index, amgm_index, dev->caps.num_mgms); 1100219820Sjeff else 1101219820Sjeff mlx4_bitmap_free(&priv->mcg_table.bitmap, 1102219820Sjeff amgm_index - dev->caps.num_mgms); 1103219820Sjeff } 1104219820Sjeff } else { 1105219820Sjeff /* Remove entry from AMGM */ 1106219820Sjeff int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 1107255932Salfred err = mlx4_READ_ENTRY(dev, prev, mailbox); 1108219820Sjeff if (err) 1109219820Sjeff goto out; 1110219820Sjeff 1111219820Sjeff mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); 1112219820Sjeff 1113255932Salfred err = mlx4_WRITE_ENTRY(dev, prev, mailbox); 1114219820Sjeff if (err) 1115219820Sjeff goto out; 1116219820Sjeff 1117219820Sjeff if (index < dev->caps.num_mgms) 1118219820Sjeff mlx4_warn(dev, "entry %d had next AMGM index %d < %d", 1119219820Sjeff prev, index, dev->caps.num_mgms); 1120219820Sjeff else 1121219820Sjeff mlx4_bitmap_free(&priv->mcg_table.bitmap, 1122219820Sjeff index - dev->caps.num_mgms); 1123219820Sjeff } 1124219820Sjeff 1125219820Sjeffout: 1126219820Sjeff mutex_unlock(&priv->mcg_table.mutex); 1127219820Sjeff 1128219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 1129219820Sjeff return err; 1130219820Sjeff} 1131255932Salfred 1132255932Salfredstatic int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp, 1133255932Salfred u8 gid[16], u8 attach, u8 block_loopback, 1134255932Salfred enum mlx4_protocol prot) 1135255932Salfred{ 1136255932Salfred struct mlx4_cmd_mailbox *mailbox; 1137255932Salfred int err = 0; 1138255932Salfred int qpn; 1139255932Salfred 1140255932Salfred if (!mlx4_is_mfunc(dev)) 1141255932Salfred return -EBADF; 1142255932Salfred 1143255932Salfred mailbox = mlx4_alloc_cmd_mailbox(dev); 1144255932Salfred if (IS_ERR(mailbox)) 1145255932Salfred return PTR_ERR(mailbox); 1146255932Salfred 1147255932Salfred memcpy(mailbox->buf, gid, 16); 1148255932Salfred qpn = qp->qpn; 1149255932Salfred qpn |= (prot << 28); 1150255932Salfred if (attach && block_loopback) 1151255932Salfred qpn |= (1 << 31); 1152255932Salfred 1153255932Salfred err = mlx4_cmd(dev, mailbox->dma, qpn, attach, 1154255932Salfred MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A, 1155255932Salfred MLX4_CMD_WRAPPED); 1156255932Salfred 1157255932Salfred mlx4_free_cmd_mailbox(dev, mailbox); 1158255932Salfred return err; 1159255932Salfred} 1160255932Salfred 1161255932Salfredint mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 1162255932Salfred u8 port, int block_mcast_loopback, 1163255932Salfred enum mlx4_protocol prot, u64 *reg_id) 1164255932Salfred{ 1165255932Salfred 1166255932Salfred switch (dev->caps.steering_mode) { 1167255932Salfred case MLX4_STEERING_MODE_A0: 1168255932Salfred if (prot == MLX4_PROT_ETH) 1169255932Salfred return 0; 1170255932Salfred 1171255932Salfred case MLX4_STEERING_MODE_B0: 1172255932Salfred if (prot == MLX4_PROT_ETH) 1173255932Salfred gid[7] |= (MLX4_MC_STEER << 1); 1174255932Salfred 1175255932Salfred if (mlx4_is_mfunc(dev)) 1176255932Salfred return mlx4_QP_ATTACH(dev, qp, gid, 1, 1177255932Salfred block_mcast_loopback, prot); 1178255932Salfred return mlx4_qp_attach_common(dev, qp, gid, 1179255932Salfred block_mcast_loopback, prot, 1180255932Salfred MLX4_MC_STEER); 1181255932Salfred 1182255932Salfred case MLX4_STEERING_MODE_DEVICE_MANAGED: { 1183255932Salfred struct mlx4_spec_list spec = { {NULL} }; 1184255932Salfred __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16); 1185255932Salfred 1186255932Salfred struct mlx4_net_trans_rule rule = { 1187255932Salfred .queue_mode = MLX4_NET_TRANS_Q_FIFO, 1188255932Salfred .exclusive = 0, 1189255932Salfred .promisc_mode = MLX4_FS_REGULAR, 1190255932Salfred .priority = MLX4_DOMAIN_NIC, 1191255932Salfred }; 1192255932Salfred 1193255932Salfred rule.allow_loopback = !block_mcast_loopback; 1194255932Salfred rule.port = port; 1195255932Salfred rule.qpn = qp->qpn; 1196255932Salfred INIT_LIST_HEAD(&rule.list); 1197255932Salfred 1198255932Salfred switch (prot) { 1199255932Salfred case MLX4_PROT_ETH: 1200255932Salfred spec.id = MLX4_NET_TRANS_RULE_ID_ETH; 1201255932Salfred memcpy(spec.eth.dst_mac, &gid[10], ETH_ALEN); 1202255932Salfred memcpy(spec.eth.dst_mac_msk, &mac_mask, ETH_ALEN); 1203255932Salfred break; 1204255932Salfred 1205255932Salfred case MLX4_PROT_IB_IPV6: 1206255932Salfred spec.id = MLX4_NET_TRANS_RULE_ID_IB; 1207255932Salfred memcpy(spec.ib.dst_gid, gid, 16); 1208255932Salfred memset(&spec.ib.dst_gid_msk, 0xff, 16); 1209255932Salfred break; 1210255932Salfred default: 1211255932Salfred return -EINVAL; 1212255932Salfred } 1213255932Salfred list_add_tail(&spec.list, &rule.list); 1214255932Salfred 1215255932Salfred return mlx4_flow_attach(dev, &rule, reg_id); 1216255932Salfred } 1217255932Salfred 1218255932Salfred default: 1219255932Salfred return -EINVAL; 1220255932Salfred } 1221255932Salfred} 1222255932SalfredEXPORT_SYMBOL_GPL(mlx4_multicast_attach); 1223255932Salfred 1224255932Salfredint mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 1225255932Salfred enum mlx4_protocol prot, u64 reg_id) 1226255932Salfred{ 1227255932Salfred switch (dev->caps.steering_mode) { 1228255932Salfred case MLX4_STEERING_MODE_A0: 1229255932Salfred if (prot == MLX4_PROT_ETH) 1230255932Salfred return 0; 1231255932Salfred 1232255932Salfred case MLX4_STEERING_MODE_B0: 1233255932Salfred if (prot == MLX4_PROT_ETH) 1234255932Salfred gid[7] |= (MLX4_MC_STEER << 1); 1235255932Salfred 1236255932Salfred if (mlx4_is_mfunc(dev)) 1237255932Salfred return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); 1238255932Salfred 1239255932Salfred return mlx4_qp_detach_common(dev, qp, gid, prot, 1240255932Salfred MLX4_MC_STEER); 1241255932Salfred 1242255932Salfred case MLX4_STEERING_MODE_DEVICE_MANAGED: 1243255932Salfred return mlx4_flow_detach(dev, reg_id); 1244255932Salfred 1245255932Salfred default: 1246255932Salfred return -EINVAL; 1247255932Salfred } 1248255932Salfred} 1249219820SjeffEXPORT_SYMBOL_GPL(mlx4_multicast_detach); 1250219820Sjeff 1251255932Salfredint mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, 1252255932Salfred u32 qpn, enum mlx4_net_trans_promisc_mode mode) 1253255932Salfred{ 1254255932Salfred struct mlx4_net_trans_rule rule; 1255255932Salfred u64 *regid_p; 1256255932Salfred 1257255932Salfred switch (mode) { 1258255932Salfred case MLX4_FS_ALL_DEFAULT: 1259255932Salfred regid_p = &dev->regid_promisc_array[port]; 1260255932Salfred break; 1261255932Salfred case MLX4_FS_MC_DEFAULT: 1262255932Salfred regid_p = &dev->regid_allmulti_array[port]; 1263255932Salfred break; 1264255932Salfred default: 1265255932Salfred return -1; 1266255932Salfred } 1267255932Salfred 1268255932Salfred if (*regid_p != 0) 1269255932Salfred return -1; 1270255932Salfred 1271255932Salfred rule.promisc_mode = mode; 1272255932Salfred rule.port = port; 1273255932Salfred rule.qpn = qpn; 1274255932Salfred INIT_LIST_HEAD(&rule.list); 1275255932Salfred mlx4_err(dev, "going promisc on %x\n", port); 1276255932Salfred 1277255932Salfred return mlx4_flow_attach(dev, &rule, regid_p); 1278255932Salfred} 1279255932SalfredEXPORT_SYMBOL_GPL(mlx4_flow_steer_promisc_add); 1280255932Salfred 1281255932Salfredint mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port, 1282255932Salfred enum mlx4_net_trans_promisc_mode mode) 1283255932Salfred{ 1284255932Salfred int ret; 1285255932Salfred u64 *regid_p; 1286255932Salfred 1287255932Salfred switch (mode) { 1288255932Salfred case MLX4_FS_ALL_DEFAULT: 1289255932Salfred regid_p = &dev->regid_promisc_array[port]; 1290255932Salfred break; 1291255932Salfred case MLX4_FS_MC_DEFAULT: 1292255932Salfred regid_p = &dev->regid_allmulti_array[port]; 1293255932Salfred break; 1294255932Salfred default: 1295255932Salfred return -1; 1296255932Salfred } 1297255932Salfred 1298255932Salfred if (*regid_p == 0) 1299255932Salfred return -1; 1300255932Salfred 1301255932Salfred ret = mlx4_flow_detach(dev, *regid_p); 1302255932Salfred if (ret == 0) 1303255932Salfred *regid_p = 0; 1304255932Salfred 1305255932Salfred return ret; 1306255932Salfred} 1307255932SalfredEXPORT_SYMBOL_GPL(mlx4_flow_steer_promisc_remove); 1308255932Salfred 1309255932Salfredint mlx4_unicast_attach(struct mlx4_dev *dev, 1310255932Salfred struct mlx4_qp *qp, u8 gid[16], 1311255932Salfred int block_mcast_loopback, enum mlx4_protocol prot) 1312255932Salfred{ 1313255932Salfred if (prot == MLX4_PROT_ETH) 1314255932Salfred gid[7] |= (MLX4_UC_STEER << 1); 1315255932Salfred 1316255932Salfred if (mlx4_is_mfunc(dev)) 1317255932Salfred return mlx4_QP_ATTACH(dev, qp, gid, 1, 1318255932Salfred block_mcast_loopback, prot); 1319255932Salfred 1320255932Salfred return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, 1321255932Salfred prot, MLX4_UC_STEER); 1322255932Salfred} 1323255932SalfredEXPORT_SYMBOL_GPL(mlx4_unicast_attach); 1324255932Salfred 1325255932Salfredint mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, 1326255932Salfred u8 gid[16], enum mlx4_protocol prot) 1327255932Salfred{ 1328255932Salfred if (prot == MLX4_PROT_ETH) 1329255932Salfred gid[7] |= (MLX4_UC_STEER << 1); 1330255932Salfred 1331255932Salfred if (mlx4_is_mfunc(dev)) 1332255932Salfred return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); 1333255932Salfred 1334255932Salfred return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER); 1335255932Salfred} 1336255932SalfredEXPORT_SYMBOL_GPL(mlx4_unicast_detach); 1337255932Salfred 1338255932Salfredint mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave, 1339255932Salfred struct mlx4_vhcr *vhcr, 1340255932Salfred struct mlx4_cmd_mailbox *inbox, 1341255932Salfred struct mlx4_cmd_mailbox *outbox, 1342255932Salfred struct mlx4_cmd_info *cmd) 1343255932Salfred{ 1344255932Salfred u32 qpn = (u32) vhcr->in_param & 0xffffffff; 1345255932Salfred u8 port = vhcr->in_param >> 62; 1346255932Salfred enum mlx4_steer_type steer = vhcr->in_modifier; 1347255932Salfred 1348255932Salfred /* Promiscuous unicast is not allowed in mfunc */ 1349255932Salfred if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER) 1350255932Salfred return 0; 1351255932Salfred 1352255932Salfred if (vhcr->op_modifier) 1353255932Salfred return add_promisc_qp(dev, port, steer, qpn); 1354255932Salfred else 1355255932Salfred return remove_promisc_qp(dev, port, steer, qpn); 1356255932Salfred} 1357255932Salfred 1358255932Salfredstatic int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn, 1359255932Salfred enum mlx4_steer_type steer, u8 add, u8 port) 1360255932Salfred{ 1361255932Salfred return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add, 1362255932Salfred MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A, 1363255932Salfred MLX4_CMD_WRAPPED); 1364255932Salfred} 1365255932Salfred 1366255932Salfredint mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) 1367255932Salfred{ 1368255932Salfred if (mlx4_is_mfunc(dev)) 1369255932Salfred return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port); 1370255932Salfred 1371255932Salfred return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn); 1372255932Salfred} 1373255932SalfredEXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); 1374255932Salfred 1375255932Salfredint mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) 1376255932Salfred{ 1377255932Salfred if (mlx4_is_mfunc(dev)) 1378255932Salfred return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port); 1379255932Salfred 1380255932Salfred return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn); 1381255932Salfred} 1382255932SalfredEXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); 1383255932Salfred 1384255932Salfredint mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) 1385255932Salfred{ 1386255932Salfred if (mlx4_is_mfunc(dev)) 1387255932Salfred return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port); 1388255932Salfred 1389255932Salfred return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn); 1390255932Salfred} 1391255932SalfredEXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); 1392255932Salfred 1393255932Salfredint mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) 1394255932Salfred{ 1395255932Salfred if (mlx4_is_mfunc(dev)) 1396255932Salfred return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port); 1397255932Salfred 1398255932Salfred return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn); 1399255932Salfred} 1400255932SalfredEXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove); 1401255932Salfred 1402219820Sjeffint mlx4_init_mcg_table(struct mlx4_dev *dev) 1403219820Sjeff{ 1404219820Sjeff struct mlx4_priv *priv = mlx4_priv(dev); 1405219820Sjeff int err; 1406219820Sjeff 1407255932Salfred /* No need for mcg_table when fw managed the mcg table*/ 1408255932Salfred if (dev->caps.steering_mode == 1409255932Salfred MLX4_STEERING_MODE_DEVICE_MANAGED) 1410255932Salfred return 0; 1411219820Sjeff err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms, 1412219820Sjeff dev->caps.num_amgms - 1, 0, 0); 1413219820Sjeff if (err) 1414219820Sjeff return err; 1415219820Sjeff 1416219820Sjeff mutex_init(&priv->mcg_table.mutex); 1417219820Sjeff 1418219820Sjeff return 0; 1419219820Sjeff} 1420219820Sjeff 1421219820Sjeffvoid mlx4_cleanup_mcg_table(struct mlx4_dev *dev) 1422219820Sjeff{ 1423255932Salfred if (dev->caps.steering_mode != 1424255932Salfred MLX4_STEERING_MODE_DEVICE_MANAGED) 1425255932Salfred mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); 1426219820Sjeff} 1427