void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; struct mlx4_mac_table *table = &info->mac_table; int index = qpn - info->base_qpn; struct mlx4_mac_entry *entry; if (dev->caps.vep_uc_steering) { entry = radix_tree_lookup(&info->mac_tree, qpn); if (entry) { mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1); radix_tree_delete(&info->mac_tree, qpn); index = find_index(dev, table, entry->mac); kfree(entry); } } mutex_lock(&table->mutex); if (validate_index(dev, table, index)) goto out; table->entries[index] = 0; mlx4_set_port_mac_table(dev, port, table->entries); --table->total; out: mutex_unlock(&table->mutex); }
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; struct mlx4_mac_table *table = &info->mac_table; int index = qpn - info->base_qpn; struct mlx4_mac_entry *entry; if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { entry = radix_tree_lookup(&info->mac_tree, qpn); if (entry) { mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1); radix_tree_delete(&info->mac_tree, qpn); index = find_index(dev, table, entry->mac); kfree(entry); } } mutex_lock(&table->mutex); if (validate_index(dev, table, index)) goto out; /* Check whether this address has reference count */ if (!(--table->refs[index])) { table->entries[index] = 0; mlx4_set_port_mac_table(dev, port, table->entries); --table->total; } out: mutex_unlock(&table->mutex); }
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index) { struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table; int i, err = 0; int free = -1; mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac); mutex_lock(&table->mutex); for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) { if (free < 0 && !table->refs[i]) { free = i; continue; } if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { /* MAC already registered, increase refernce count */ *index = i; ++table->refs[i]; goto out; } } if (free < 0) { err = -ENOMEM; goto out; } mlx4_dbg(dev, "Free MAC index is %d\n", free); if (table->total == table->max) { /* No free mac entries */ err = -ENOSPC; goto out; } /* Register new MAC */ table->refs[free] = 1; table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); err = mlx4_set_port_mac_table(dev, port, table->entries); if (unlikely(err)) { mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac); table->refs[free] = 0; table->entries[free] = 0; goto out; } *index = free; ++table->total; out: mutex_unlock(&table->mutex); return err; }
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index) { struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table; mutex_lock(&table->mutex); if (!table->refs[index]) { mlx4_warn(dev, "No MAC entry for index %d\n", index); goto out; } if (--table->refs[index]) { mlx4_warn(dev, "Have more references for index %d," "no need to modify MAC table\n", index); goto out; } table->entries[index] = 0; mlx4_set_port_mac_table(dev, port, table->entries); --table->total; out: mutex_unlock(&table->mutex); }
int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; struct mlx4_mac_table *table = &info->mac_table; int index = qpn - info->base_qpn; struct mlx4_mac_entry *entry; int err; if (dev->caps.vep_uc_steering) { entry = radix_tree_lookup(&info->mac_tree, qpn); if (!entry) return -EINVAL; index = find_index(dev, table, entry->mac); mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0); entry->mac = new_mac; err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0); if (err || index < 0) return err; } mutex_lock(&table->mutex); err = validate_index(dev, table, index); if (err) goto out; table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID); err = mlx4_set_port_mac_table(dev, port, table->entries); if (unlikely(err)) { mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac); table->entries[index] = 0; } out: mutex_unlock(&table->mutex); return err; }
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; struct mlx4_mac_table *table = &info->mac_table; struct mlx4_mac_entry *entry; int i, err = 0; int free = -1; if (dev->caps.vep_uc_steering) { err = mlx4_uc_steer_add(dev, port, mac, qpn, 1); if (!err) { entry = kmalloc(sizeof *entry, GFP_KERNEL); if (!entry) { mlx4_uc_steer_release(dev, port, mac, *qpn, 1); return -ENOMEM; } entry->mac = mac; err = radix_tree_insert(&info->mac_tree, *qpn, entry); if (err) { mlx4_uc_steer_release(dev, port, mac, *qpn, 1); return err; } } else return err; } mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac); mutex_lock(&table->mutex); for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { if (free < 0 && !table->entries[i]) { free = i; continue; } if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { /* MAC already registered, Must not have duplicates */ err = -EEXIST; goto out; } } mlx4_dbg(dev, "Free MAC index is %d\n", free); if (table->total == table->max) { /* No free mac entries */ err = -ENOSPC; goto out; } /* Register new MAC */ table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); err = mlx4_set_port_mac_table(dev, port, table->entries); if (unlikely(err)) { mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac); table->entries[free] = 0; goto out; } if (!dev->caps.vep_uc_steering) *qpn = info->base_qpn + free; ++table->total; out: mutex_unlock(&table->mutex); return err; }