From patchwork Thu Jun 10 19:04:19 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yevgeny Petrilin X-Patchwork-Id: 105438 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o5AJ4WSr016592 for ; Thu, 10 Jun 2010 19:04:32 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759704Ab0FJTEX (ORCPT ); Thu, 10 Jun 2010 15:04:23 -0400 Received: from mail.mellanox.co.il ([194.90.237.43]:41807 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1759690Ab0FJTEX (ORCPT ); Thu, 10 Jun 2010 15:04:23 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from yevgenyp@mellanox.co.il) with SMTP; 10 Jun 2010 22:05:11 +0300 Received: from vnc8.lab.mtl.com ([10.4.45.8]) by mtlexch01.mtl.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 10 Jun 2010 22:04:20 +0300 Message-ID: <4C113733.5030706@mellanox.co.il> Date: Thu, 10 Jun 2010 22:04:19 +0300 From: Yevgeny Petrilin User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 MIME-Version: 1.0 To: Roland Dreier CC: linux-rdma@vger.kernel.org Subject: [PATCH 12/19 V4] mlx4_core: slave multicast support X-OriginalArrivalTime: 10 Jun 2010 19:04:20.0118 (UTC) FILETIME=[BB249360:01CB08CF] X-TM-AS-Product-Ver: SMEX-8.0.0.1181-6.000.1038-17438.001 X-TM-AS-Result: No--13.613900-8.000000-31 X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 10 Jun 2010 19:04:32 +0000 (UTC) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 4e94e36..2c28f98 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -452,13 +452,15 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) return mlx4_multicast_attach(to_mdev(ibqp->device)->dev, &to_mqp(ibqp)->mqp, gid->raw, !!(to_mqp(ibqp)->flags & - MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK)); + MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), + MLX4_PROT_IB_IPV6); } static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) { return mlx4_multicast_detach(to_mdev(ibqp->device)->dev, - &to_mqp(ibqp)->mqp, gid->raw); + &to_mqp(ibqp)->mqp, gid->raw, + MLX4_PROT_IB_IPV6); } static int init_node_data(struct mlx4_ib_dev *dev) diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c index b25e40e..0f45fde 100644 --- a/drivers/net/mlx4/cmd.c +++ b/drivers/net/mlx4/cmd.c @@ -903,6 +903,14 @@ static struct mlx4_cmd_info { /* Native multicast commands are not available for guests */ { + .opcode = MLX4_CMD_MCAST_ATTACH, + .has_inbox = true, + .has_outbox = false, + .out_is_imm = false, + .verify = NULL, + .wrapper = mlx4_MCAST_wrapper + }, + { .opcode = MLX4_CMD_DIAG_RPRT, .has_inbox = false, .has_outbox = true, diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 7389fa2..5ebe135 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -173,6 +173,7 @@ static void mlx4_en_cache_mclist(struct net_device *dev) int mc_addrs_cnt = netdev_mc_count(dev); int i; + mlx4_en_clear_list(dev); mc_addrs = kmalloc(mc_addrs_cnt * ETH_ALEN, GFP_ATOMIC); if (!mc_addrs) { en_err(priv, "failed to allocate multicast list\n"); @@ -203,6 +204,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) struct mlx4_en_dev *mdev = priv->mdev; struct net_device *dev = priv->dev; u64 mcast_addr = 0; + u8 mc_list[16] = {0}; int err; mutex_lock(&mdev->state_lock); @@ -284,6 +286,14 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) if (err) en_err(priv, "Failed disabling multicast filter\n"); + /* Detach our qp from all the multicast addresses */ + for (i = 0; i < priv->mc_addrs_cnt; i++) { + memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, + ETH_ALEN); + mc_list[7] = (priv->port - 1) << 4; + mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, + mc_list, MLX4_PROT_ETH); + } /* Flush mcast filter and init it with broadcast address */ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST, 1, MLX4_MCAST_CONFIG); @@ -294,6 +304,11 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) mlx4_en_cache_mclist(dev); netif_tx_unlock_bh(dev); for (i = 0; i < priv->mc_addrs_cnt; i++) { + memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, + ETH_ALEN); + mc_list[7] = (priv->port - 1) << 4; + mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, + mc_list, 0, MLX4_PROT_ETH); mcast_addr = mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN); mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, @@ -303,8 +318,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) 0, MLX4_MCAST_ENABLE); if (err) en_err(priv, "Failed enabling multicast filter\n"); - - mlx4_en_clear_list(dev); } out: mutex_unlock(&mdev->state_lock); @@ -550,6 +563,7 @@ int mlx4_en_start_port(struct net_device *dev) int err = 0; int i; int j; + u8 mc_list[16] = {0}; if (priv->port_up) { en_dbg(DRV, priv, "start port called while port already up\n"); @@ -662,6 +676,13 @@ int mlx4_en_start_port(struct net_device *dev) goto tx_err; } + /* Attach rx QP to bradcast address */ + memset(&mc_list[10], 0xff, ETH_ALEN); + mc_list[7] = (priv->port - 1) << 4; + if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list, + 0, MLX4_PROT_ETH)) + mlx4_warn(mdev, "Failed Attaching Broadcast\n"); + /* Schedule multicast task to populate multicast list */ queue_work(mdev->workqueue, &priv->mcast_task); @@ -693,6 +714,7 @@ void mlx4_en_stop_port(struct net_device *dev) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; int i; + u8 mc_list[16] = {0}; if (!priv->port_up) { en_dbg(DRV, priv, "stop port called while port already down\n"); @@ -708,6 +730,22 @@ void mlx4_en_stop_port(struct net_device *dev) priv->port_up = false; mlx4_CLOSE_PORT(mdev->dev, priv->port); + /* Detach All multicasts */ + memset(&mc_list[10], 0xff, ETH_ALEN); + mc_list[7] = (priv->port - 1) << 4; + mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list, + MLX4_PROT_ETH); + for (i = 0; i < priv->mc_addrs_cnt; i++) { + memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, + ETH_ALEN); + mc_list[7] = (priv->port - 1) << 4; + mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, + mc_list, MLX4_PROT_ETH); + } + mlx4_en_clear_list(dev); + /* Flush multicast filter */ + mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); + /* Unregister Mac address for the port */ mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn); diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c index c099cb4..32a9943 100644 --- a/drivers/net/mlx4/en_port.c +++ b/drivers/net/mlx4/en_port.c @@ -119,6 +119,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, struct mlx4_set_port_rqp_calc_context *context; int err; u32 in_mod; + u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) @@ -129,7 +130,8 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, context->base_qpn = cpu_to_be32(base_qpn); context->n_mac = 0x7; context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | base_qpn); - context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_SHIFT | base_qpn); + context->mcast = cpu_to_be32((m_promisc << SET_PORT_MC_PROMISC_SHIFT) | + base_qpn); context->intra_no_vlan = 0; context->no_vlan = MLX4_NO_VLAN_IDX; context->intra_vlan_miss = 0; diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h index 80e6269..beaddff 100644 --- a/drivers/net/mlx4/en_port.h +++ b/drivers/net/mlx4/en_port.h @@ -39,6 +39,11 @@ #define SET_PORT_PROMISC_SHIFT 31 #define SET_PORT_MC_PROMISC_SHIFT 30 +enum { + MCAST_DIRECT_ONLY = 0, + MCAST_DIRECT = 1, + MCAST_DEFAULT = 2 +}; struct mlx4_set_port_general_context { u8 reserved[3]; diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index 55377c0..e53a392 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -229,6 +229,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f +#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43 #define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 #define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 #define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 @@ -323,6 +324,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_msg_sz = 1 << (field & 0x1f); MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); dev_cap->stat_rate_support = stat_rate; + MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET); + dev_cap->vep_uc_steering = field & 0x4; + dev_cap->vep_mc_steering = field & 0x8; MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); dev_cap->reserved_uars = field >> 4; diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 9fd15f1..d5c17cf 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -76,6 +76,8 @@ struct mlx4_dev_cap { u16 eth_mtu[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; u32 flags; + int vep_uc_steering; + int vep_mc_steering; int reserved_uars; int uar_size; int min_page_sz; diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index e670aa0..b1eb69e 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -245,6 +245,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.bmme_flags = dev_cap->bmme_flags; dev->caps.reserved_lkey = dev_cap->reserved_lkey; dev->caps.stat_rate_support = dev_cap->stat_rate_support; + dev->caps.vep_uc_steering = dev_cap->vep_uc_steering; + dev->caps.vep_mc_steering = dev_cap->vep_mc_steering; dev->caps.max_gso_sz = dev_cap->max_gso_sz; dev->caps.log_num_macs = log_num_mac; diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c index b8c7a72..e3dc486 100644 --- a/drivers/net/mlx4/mcg.c +++ b/drivers/net/mlx4/mcg.c @@ -65,12 +65,12 @@ static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index, } static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - u16 *hash) + u16 *hash, u8 op_mod) { u64 imm; int err; - err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH, + err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod, MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A); if (!err) @@ -95,13 +95,15 @@ static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox * entry in hash chain and *mgm holds end of hash chain. */ static int find_mgm(struct mlx4_dev *dev, - u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox, + u8 *gid, enum mlx4_protocol prot, + struct mlx4_cmd_mailbox *mgm_mailbox, u16 *hash, int *prev, int *index) { struct mlx4_cmd_mailbox *mailbox; struct mlx4_mgm *mgm = mgm_mailbox->buf; u8 *mgid; int err; + u8 op_mod = (prot == MLX4_PROT_ETH) ? !!(dev->caps.vep_mc_steering) : 0; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) @@ -110,7 +112,7 @@ static int find_mgm(struct mlx4_dev *dev, memcpy(mgid, gid, 16); - err = mlx4_MGID_HASH(dev, mailbox, hash); + err = mlx4_MGID_HASH(dev, mailbox, hash, op_mod); mlx4_free_cmd_mailbox(dev, mailbox); if (err) return err; @@ -134,8 +136,9 @@ static int find_mgm(struct mlx4_dev *dev, return err; } - if (!memcmp(mgm->gid, gid, 16)) - return err; + if (!memcmp(mgm->gid, gid, 16) && + (prot == be32_to_cpu(mgm->members_count) >> 30)) + return err; *prev = *index; *index = be32_to_cpu(mgm->next_gid_index) >> 6; @@ -145,8 +148,10 @@ static int find_mgm(struct mlx4_dev *dev, return err; } -int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - int block_mcast_loopback) +static int mlx4_multicast_attach_common(struct mlx4_dev *dev, + struct mlx4_qp *qp, u8 gid[16], + int block_mcast_loopback, + enum mlx4_protocol prot) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_cmd_mailbox *mailbox; @@ -165,7 +170,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], mutex_lock(&priv->mcg_table.mutex); - err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); + err = find_mgm(dev, gid, prot, mailbox, &hash, &prev, &index); if (err) goto out; @@ -207,7 +212,8 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], else mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK); - mgm->members_count = cpu_to_be32(members_count); + mgm->members_count = cpu_to_be32(members_count | ((u32) prot << 30)); + mgm->next_gid_index = cpu_to_be32(!!(dev->caps.vep_mc_steering) << 4); err = mlx4_WRITE_MCG(dev, index, mailbox); if (err) @@ -220,7 +226,8 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], if (err) goto out; - mgm->next_gid_index = cpu_to_be32(index << 6); + mgm->next_gid_index = cpu_to_be32((index << 6) | + (!!(dev->caps.vep_mc_steering) << 4)); err = mlx4_WRITE_MCG(dev, prev, mailbox); if (err) @@ -240,9 +247,10 @@ out: mlx4_free_cmd_mailbox(dev, mailbox); return err; } -EXPORT_SYMBOL_GPL(mlx4_multicast_attach); -int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) +static int mlx4_multicast_detach_common(struct mlx4_dev *dev, + struct mlx4_qp *qp, u8 gid[16], + enum mlx4_protocol prot) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_cmd_mailbox *mailbox; @@ -252,6 +260,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) int prev, index; int i, loc; int err; + u8 pf_num = gid[7] >> 4; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) @@ -260,7 +269,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) mutex_lock(&priv->mcg_table.mutex); - err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); + err = find_mgm(dev, gid, prot, mailbox, &hash, &prev, &index); if (err) goto out; @@ -282,7 +291,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) } - mgm->members_count = cpu_to_be32(--members_count); + mgm->members_count = cpu_to_be32(--members_count | ((u32) prot << 30)); mgm->qp[loc] = mgm->qp[i - 1]; mgm->qp[i - 1] = 0; @@ -298,8 +307,11 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) err = mlx4_READ_MCG(dev, amgm_index, mailbox); if (err) goto out; - } else + } else { memset(mgm->gid, 0, 16); + if (prot == MLX4_PROT_ETH) + mgm->gid[7] = pf_num << 4; + } err = mlx4_WRITE_MCG(dev, index, mailbox); if (err) @@ -315,12 +327,12 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) } } else { /* Remove entry from AMGM */ - int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; + int cur_next_index = be32_to_cpu(mgm->next_gid_index); err = mlx4_READ_MCG(dev, prev, mailbox); if (err) goto out; - mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); + mgm->next_gid_index = cpu_to_be32(cur_next_index); err = mlx4_WRITE_MCG(dev, prev, mailbox); if (err) @@ -340,6 +352,85 @@ out: mlx4_free_cmd_mailbox(dev, mailbox); return err; } + +int mlx4_MCAST_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox) +{ + struct mlx4_qp qp; /* dummy for calling attach/detach */ + u8 *gid = inbox->buf; + enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7; + + if (prot == MLX4_PROT_ETH) + gid[7] |= slave << 4; + + qp.qpn = vhcr->in_modifier & 0xffffff; + if (vhcr->op_modifier) + return mlx4_multicast_attach_common(dev, &qp, gid, + vhcr->in_modifier >> 31, prot); + else + return mlx4_multicast_detach_common(dev, &qp, gid, prot); +} + +static int mlx4_MCAST(struct mlx4_dev *dev, struct mlx4_qp *qp, + u8 gid[16], u8 attach, u8 block_loopback, + enum mlx4_protocol prot) +{ + struct mlx4_cmd_mailbox *mailbox; + int err; + int qpn; + + if (!mlx4_is_slave(dev)) + return -EBADF; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + memcpy(mailbox->buf, gid, 16); + qpn = qp->qpn; + qpn |= (prot << 28); + if (attach && block_loopback) + qpn |= (1 << 31); + + err = mlx4_cmd(dev, mailbox->dma, qpn, attach, MLX4_CMD_MCAST_ATTACH, + MLX4_CMD_TIME_CLASS_A); + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} + + +int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], + int block_mcast_loopback, enum mlx4_protocol prot) +{ + if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering) + return 0; + + if (mlx4_is_slave(dev)) + return mlx4_MCAST(dev, qp, gid, 1, block_mcast_loopback, prot); + + if (mlx4_is_master(dev) && prot == MLX4_PROT_ETH) + gid[7] |= dev->caps.function << 4; + + return mlx4_multicast_attach_common(dev, qp, gid, + block_mcast_loopback, prot); +} +EXPORT_SYMBOL_GPL(mlx4_multicast_attach); + +int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], + enum mlx4_protocol prot) +{ + if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering) + return 0; + + if (mlx4_is_slave(dev)) + return mlx4_MCAST(dev, qp, gid, 0, 0, prot); + + if (mlx4_is_master(dev) && prot == MLX4_PROT_ETH) + gid[7] |= dev->caps.function << 4; + + return mlx4_multicast_detach_common(dev, qp, gid, prot); +} EXPORT_SYMBOL_GPL(mlx4_multicast_detach); int mlx4_init_mcg_table(struct mlx4_dev *dev) diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 1a37f63..56b23f0 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -550,4 +550,8 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *v struct mlx4_cmd_mailbox *outbox); int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps); +int mlx4_MCAST_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox); + #endif /* MLX4_H */ diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index 902bd94..b67aadd 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c @@ -389,9 +389,9 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc promisc << SET_PORT_PROMISC_SHIFT | port_info->base_qpn); promisc = be32_to_cpu(qpn_context->mcast) >> - SET_PORT_PROMISC_SHIFT; + SET_PORT_MC_PROMISC_SHIFT; qpn_context->mcast = cpu_to_be32( - promisc << SET_PORT_PROMISC_SHIFT | + promisc << SET_PORT_MC_PROMISC_SHIFT | port_info->base_qpn); break; case MLX4_SET_PORT_GENERAL: diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index 01a1873..236e03f 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -131,6 +131,7 @@ enum { MLX4_CMD_REPLACE_RES = 0xf02, MLX4_CMD_GET_EVENT = 0xf03, MLX4_CMD_QUERY_SLAVE_CAP = 0xf04, + MLX4_CMD_MCAST_ATTACH = 0xf05, /* debug commands */ MLX4_CMD_QUERY_DEBUG_MSG = 0x2a, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 0765845..5911dc0 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -148,6 +148,13 @@ enum { MLX4_STAT_RATE_OFFSET = 5 }; +enum mlx4_protocol { + MLX4_PROT_IB_IPV6 = 0, + MLX4_PROT_ETH, + MLX4_PROT_IB_IPV4, + MLX4_PROT_FCOE +}; + enum { MLX4_MTT_FLAG_PRESENT = 1 }; @@ -240,6 +247,8 @@ struct mlx4_caps { u32 bmme_flags; u32 reserved_lkey; u16 stat_rate_support; + int vep_uc_steering; + int vep_mc_steering; u8 port_width_cap[MLX4_MAX_PORTS + 1]; int max_gso_sz; int reserved_qps_cnt[MLX4_NUM_QP_REGION]; @@ -488,8 +497,9 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port); int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port); int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - int block_mcast_loopback); -int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]); + int block_mcast_loopback, enum mlx4_protocol prot); +int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], + enum mlx4_protocol prot); int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn); void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn);