Commit 5a6e55c4 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlx4'

Or Gerlitz says:

====================
Mellanox driver updates

This patch set from Jack Morgenstein does the following:

1. Fix MAC/VLAN SRIOV implementation, and add wrapper functions for VLAN allocation
   and de-allocation (patches 1-6).

2. Implements resource quotas when running under SRIOV (patches 7-10).
   Patch 7 is a small bug fix, and patches 8-10 implement the quotas.

Quotas are implemented per resource type for VFs and the PF, to prevent
any entity from simply grabbing all the resources for itself and leaving
the other entities unable to obtain such resources.

The series is against net-next commit ba486502 "ipv6: remove the unnecessary statement in find_match()"

changes from V0:
 - dropped the 1st patch which needs to go to -stable and hence through net,
   not net-next
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3b4c5cbf 146f3ef4
...@@ -177,18 +177,18 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, ...@@ -177,18 +177,18 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->max_mr_size = ~0ull; props->max_mr_size = ~0ull;
props->page_size_cap = dev->dev->caps.page_size_cap; props->page_size_cap = dev->dev->caps.page_size_cap;
props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; props->max_qp = dev->dev->quotas.qp;
props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE; props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE;
props->max_sge = min(dev->dev->caps.max_sq_sg, props->max_sge = min(dev->dev->caps.max_sq_sg,
dev->dev->caps.max_rq_sg); dev->dev->caps.max_rq_sg);
props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; props->max_cq = dev->dev->quotas.cq;
props->max_cqe = dev->dev->caps.max_cqes; props->max_cqe = dev->dev->caps.max_cqes;
props->max_mr = dev->dev->caps.num_mpts - dev->dev->caps.reserved_mrws; props->max_mr = dev->dev->quotas.mpt;
props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds;
props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma;
props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma;
props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs; props->max_srq = dev->dev->quotas.srq;
props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1; props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1;
props->max_srq_sge = dev->dev->caps.max_srq_sge; props->max_srq_sge = dev->dev->caps.max_srq_sge;
props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES; props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES;
......
...@@ -1687,7 +1687,7 @@ static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave ...@@ -1687,7 +1687,7 @@ static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
if (NO_INDX != vp_oper->vlan_idx) { if (NO_INDX != vp_oper->vlan_idx) {
__mlx4_unregister_vlan(&priv->dev, __mlx4_unregister_vlan(&priv->dev,
port, vp_oper->vlan_idx); port, vp_oper->state.default_vlan);
vp_oper->vlan_idx = NO_INDX; vp_oper->vlan_idx = NO_INDX;
} }
if (NO_INDX != vp_oper->mac_idx) { if (NO_INDX != vp_oper->mac_idx) {
...@@ -1718,6 +1718,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, ...@@ -1718,6 +1718,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
if (cmd == MLX4_COMM_CMD_RESET) { if (cmd == MLX4_COMM_CMD_RESET) {
mlx4_warn(dev, "Received reset from slave:%d\n", slave); mlx4_warn(dev, "Received reset from slave:%d\n", slave);
slave_state[slave].active = false; slave_state[slave].active = false;
slave_state[slave].old_vlan_api = false;
mlx4_master_deactivate_admin_state(priv, slave); mlx4_master_deactivate_admin_state(priv, slave);
for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
slave_state[slave].event_eq[i].eqn = -1; slave_state[slave].event_eq[i].eqn = -1;
......
...@@ -417,7 +417,6 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, ...@@ -417,7 +417,6 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev,
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_dev *mdev = priv->mdev;
int err; int err;
int idx;
en_dbg(HW, priv, "Killing VID:%d\n", vid); en_dbg(HW, priv, "Killing VID:%d\n", vid);
...@@ -425,10 +424,7 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, ...@@ -425,10 +424,7 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev,
/* Remove VID from port VLAN filter */ /* Remove VID from port VLAN filter */
mutex_lock(&mdev->state_lock); mutex_lock(&mdev->state_lock);
if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx)) mlx4_unregister_vlan(mdev->dev, priv->port, vid);
mlx4_unregister_vlan(mdev->dev, priv->port, idx);
else
en_dbg(HW, priv, "could not find vid %d in cache\n", vid);
if (mdev->device_up && priv->port_up) { if (mdev->device_up && priv->port_up) {
err = mlx4_SET_VLAN_FLTR(mdev->dev, priv); err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
......
...@@ -177,6 +177,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, ...@@ -177,6 +177,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd) struct mlx4_cmd_info *cmd)
{ {
struct mlx4_priv *priv = mlx4_priv(dev);
u8 field; u8 field;
u32 size; u32 size;
int err = 0; int err = 0;
...@@ -185,18 +186,26 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, ...@@ -185,18 +186,26 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1
#define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 #define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4
#define QUERY_FUNC_CAP_FMR_OFFSET 0x8 #define QUERY_FUNC_CAP_FMR_OFFSET 0x8
#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10 #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP 0x10
#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14 #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP 0x14
#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x18 #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP 0x18
#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x20 #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP 0x20
#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x24 #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP 0x24
#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x28 #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP 0x28
#define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c #define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c
#define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30 #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30
#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x50
#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x54
#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x58
#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x60
#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64
#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68
#define QUERY_FUNC_CAP_FMR_FLAG 0x80 #define QUERY_FUNC_CAP_FMR_FLAG 0x80
#define QUERY_FUNC_CAP_FLAG_RDMA 0x40 #define QUERY_FUNC_CAP_FLAG_RDMA 0x40
#define QUERY_FUNC_CAP_FLAG_ETH 0x80 #define QUERY_FUNC_CAP_FLAG_ETH 0x80
#define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10
/* when opcode modifier = 1 */ /* when opcode modifier = 1 */
#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3
...@@ -237,8 +246,9 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, ...@@ -237,8 +246,9 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY);
} else if (vhcr->op_modifier == 0) { } else if (vhcr->op_modifier == 0) {
/* enable rdma and ethernet interfaces */ /* enable rdma and ethernet interfaces, and new quota locations */
field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA); field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA |
QUERY_FUNC_CAP_FLAG_QUOTAS);
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
field = dev->caps.num_ports; field = dev->caps.num_ports;
...@@ -250,14 +260,20 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, ...@@ -250,14 +260,20 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
field = 0; /* protected FMR support not available as yet */ field = 0; /* protected FMR support not available as yet */
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET); MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET);
size = dev->caps.num_qps; size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
size = dev->caps.num_qps;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
size = dev->caps.num_srqs; size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
size = dev->caps.num_srqs;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
size = dev->caps.num_cqs; size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
size = dev->caps.num_cqs;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
size = dev->caps.num_eqs; size = dev->caps.num_eqs;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
...@@ -265,14 +281,19 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, ...@@ -265,14 +281,19 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
size = dev->caps.reserved_eqs; size = dev->caps.reserved_eqs;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
size = dev->caps.num_mpts; size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
size = dev->caps.num_mpts;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
size = dev->caps.num_mtts; size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
size = dev->caps.num_mtts;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
size = dev->caps.num_mgms + dev->caps.num_amgms; size = dev->caps.num_mgms + dev->caps.num_amgms;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
} else } else
err = -EINVAL; err = -EINVAL;
...@@ -287,7 +308,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, ...@@ -287,7 +308,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
u32 *outbox; u32 *outbox;
u8 field, op_modifier; u8 field, op_modifier;
u32 size; u32 size;
int err = 0; int err = 0, quotas = 0;
op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
...@@ -311,6 +332,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, ...@@ -311,6 +332,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
goto out; goto out;
} }
func_cap->flags = field; func_cap->flags = field;
quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS);
MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
func_cap->num_ports = field; func_cap->num_ports = field;
...@@ -318,29 +340,50 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, ...@@ -318,29 +340,50 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET); MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
func_cap->pf_context_behaviour = size; func_cap->pf_context_behaviour = size;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); if (quotas) {
func_cap->qp_quota = size & 0xFFFFFF; MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
func_cap->qp_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
func_cap->srq_quota = size & 0xFFFFFF; func_cap->srq_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
func_cap->cq_quota = size & 0xFFFFFF; func_cap->cq_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
func_cap->mpt_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
func_cap->mtt_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
func_cap->mcg_quota = size & 0xFFFFFF;
} else {
MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
func_cap->qp_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
func_cap->srq_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
func_cap->cq_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
func_cap->mpt_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
func_cap->mtt_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
func_cap->mcg_quota = size & 0xFFFFFF;
}
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET); MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
func_cap->max_eq = size & 0xFFFFFF; func_cap->max_eq = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
func_cap->reserved_eq = size & 0xFFFFFF; func_cap->reserved_eq = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
func_cap->mpt_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
func_cap->mtt_quota = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
func_cap->mcg_quota = size & 0xFFFFFF;
goto out; goto out;
} }
......
...@@ -562,13 +562,17 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) ...@@ -562,13 +562,17 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
} }
dev->caps.num_ports = func_cap.num_ports; dev->caps.num_ports = func_cap.num_ports;
dev->caps.num_qps = func_cap.qp_quota; dev->quotas.qp = func_cap.qp_quota;
dev->caps.num_srqs = func_cap.srq_quota; dev->quotas.srq = func_cap.srq_quota;
dev->caps.num_cqs = func_cap.cq_quota; dev->quotas.cq = func_cap.cq_quota;
dev->caps.num_eqs = func_cap.max_eq; dev->quotas.mpt = func_cap.mpt_quota;
dev->caps.reserved_eqs = func_cap.reserved_eq; dev->quotas.mtt = func_cap.mtt_quota;
dev->caps.num_mpts = func_cap.mpt_quota; dev->caps.num_qps = 1 << hca_param.log_num_qps;
dev->caps.num_mtts = func_cap.mtt_quota; dev->caps.num_srqs = 1 << hca_param.log_num_srqs;
dev->caps.num_cqs = 1 << hca_param.log_num_cqs;
dev->caps.num_mpts = 1 << hca_param.log_mpt_sz;
dev->caps.num_eqs = func_cap.max_eq;
dev->caps.reserved_eqs = func_cap.reserved_eq;
dev->caps.num_pds = MLX4_NUM_PDS; dev->caps.num_pds = MLX4_NUM_PDS;
dev->caps.num_mgms = 0; dev->caps.num_mgms = 0;
dev->caps.num_amgms = 0; dev->caps.num_amgms = 0;
...@@ -2102,9 +2106,15 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) ...@@ -2102,9 +2106,15 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
"aborting.\n"); "aborting.\n");
return err; return err;
} }
if (num_vfs > MLX4_MAX_NUM_VF) {
printk(KERN_ERR "There are more VF's (%d) than allowed(%d)\n", /* Due to requirement that all VFs and the PF are *guaranteed* 2 MACS
num_vfs, MLX4_MAX_NUM_VF); * per port, we must limit the number of VFs to 63 (since their are
* 128 MACs)
*/
if (num_vfs >= MLX4_MAX_NUM_VF) {
dev_err(&pdev->dev,
"Requested more VF's (%d) than allowed (%d)\n",
num_vfs, MLX4_MAX_NUM_VF - 1);
return -EINVAL; return -EINVAL;
} }
...@@ -2322,6 +2332,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) ...@@ -2322,6 +2332,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
if (err) if (err)
goto err_steer; goto err_steer;
mlx4_init_quotas(dev);
for (port = 1; port <= dev->caps.num_ports; port++) { for (port = 1; port <= dev->caps.num_ports; port++) {
err = mlx4_init_port_info(dev, port); err = mlx4_init_port_info(dev, port);
if (err) if (err)
......
...@@ -455,6 +455,7 @@ struct mlx4_slave_state { ...@@ -455,6 +455,7 @@ struct mlx4_slave_state {
u8 last_cmd; u8 last_cmd;
u8 init_port_mask; u8 init_port_mask;
bool active; bool active;
bool old_vlan_api;
u8 function; u8 function;
dma_addr_t vhcr_dma; dma_addr_t vhcr_dma;
u16 mtu[MLX4_MAX_PORTS + 1]; u16 mtu[MLX4_MAX_PORTS + 1];
...@@ -503,12 +504,28 @@ struct slave_list { ...@@ -503,12 +504,28 @@ struct slave_list {
struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE]; struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE];
}; };
struct resource_allocator {
spinlock_t alloc_lock; /* protect quotas */
union {
int res_reserved;
int res_port_rsvd[MLX4_MAX_PORTS];
};
union {
int res_free;
int res_port_free[MLX4_MAX_PORTS];
};
int *quota;
int *allocated;
int *guaranteed;
};
struct mlx4_resource_tracker { struct mlx4_resource_tracker {
spinlock_t lock; spinlock_t lock;
/* tree for each resources */ /* tree for each resources */
struct rb_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE]; struct rb_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE];
/* num_of_slave's lists, one per slave */ /* num_of_slave's lists, one per slave */
struct slave_list *slave_list; struct slave_list *slave_list;
struct resource_allocator res_alloc[MLX4_NUM_OF_RESOURCE_TYPE];
}; };
#define SLAVE_EVENT_EQ_SIZE 128 #define SLAVE_EVENT_EQ_SIZE 128
...@@ -1111,7 +1128,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev, ...@@ -1111,7 +1128,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz); int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz);
...@@ -1252,4 +1269,6 @@ static inline spinlock_t *mlx4_tlock(struct mlx4_dev *dev) ...@@ -1252,4 +1269,6 @@ static inline spinlock_t *mlx4_tlock(struct mlx4_dev *dev)
void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work); void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work);
void mlx4_init_quotas(struct mlx4_dev *dev);
#endif /* MLX4_H */ #endif /* MLX4_H */
...@@ -755,14 +755,14 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) ...@@ -755,14 +755,14 @@ int mlx4_init_mr_table(struct mlx4_dev *dev)
struct mlx4_mr_table *mr_table = &priv->mr_table; struct mlx4_mr_table *mr_table = &priv->mr_table;
int err; int err;
if (!is_power_of_2(dev->caps.num_mpts))
return -EINVAL;
/* Nothing to do for slaves - all MR handling is forwarded /* Nothing to do for slaves - all MR handling is forwarded
* to the master */ * to the master */
if (mlx4_is_slave(dev)) if (mlx4_is_slave(dev))
return 0; return 0;
if (!is_power_of_2(dev->caps.num_mpts))
return -EINVAL;
err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts,
~0, dev->caps.reserved_mrws, 0); ~0, dev->caps.reserved_mrws, 0);
if (err) if (err)
......
...@@ -178,13 +178,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac); ...@@ -178,13 +178,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac);
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
{ {
u64 out_param = 0; u64 out_param = 0;
int err; int err = -EINVAL;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, err = mlx4_cmd_imm(dev, mac, &out_param,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, ((u32) port) << 8 | (u32) RES_MAC,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
if (err && err == -EINVAL && mlx4_is_slave(dev)) {
/* retry using old REG_MAC format */
set_param_l(&out_param, port);
err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (!err)
dev->flags |= MLX4_FLAG_OLD_REG_MAC;
}
if (err) if (err)
return err; return err;
...@@ -231,10 +242,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) ...@@ -231,10 +242,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
u64 out_param = 0; u64 out_param = 0;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
(void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, (void) mlx4_cmd_imm(dev, mac, &out_param,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, ((u32) port) << 8 | (u32) RES_MAC,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
} else {
/* use old unregister mac format */
set_param_l(&out_param, port);
(void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
return; return;
} }
__mlx4_unregister_mac(dev, port, mac); __mlx4_unregister_mac(dev, port, mac);
...@@ -284,7 +303,7 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, ...@@ -284,7 +303,7 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE);
in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port;
err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
mlx4_free_cmd_mailbox(dev, mailbox); mlx4_free_cmd_mailbox(dev, mailbox);
...@@ -370,9 +389,12 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) ...@@ -370,9 +389,12 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
u64 out_param = 0; u64 out_param = 0;
int err; int err;
if (vlan > 4095)
return -EINVAL;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); err = mlx4_cmd_imm(dev, vlan, &out_param,
err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, ((u32) port) << 8 | (u32) RES_VLAN,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (!err) if (!err)
...@@ -384,23 +406,26 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) ...@@ -384,23 +406,26 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
} }
EXPORT_SYMBOL_GPL(mlx4_register_vlan); EXPORT_SYMBOL_GPL(mlx4_register_vlan);
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
{ {
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
int index;
if (index < MLX4_VLAN_REGULAR) { mutex_lock(&table->mutex);
mlx4_warn(dev, "Trying to free special vlan index %d\n", index); if (mlx4_find_cached_vlan(dev, port, vlan, &index)) {
return; mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan);
goto out;
} }
mutex_lock(&table->mutex); if (index < MLX4_VLAN_REGULAR) {
if (!table->refs[index]) { mlx4_warn(dev, "Trying to free special vlan index %d\n", index);
mlx4_warn(dev, "No vlan entry for index %d\n", index);
goto out; goto out;
} }
if (--table->refs[index]) { if (--table->refs[index]) {
mlx4_dbg(dev, "Have more references for index %d," mlx4_dbg(dev, "Have %d more references for index %d,"
"no need to modify vlan table\n", index); "no need to modify vlan table\n", table->refs[index],
index);
goto out; goto out;
} }
table->entries[index] = 0; table->entries[index] = 0;
...@@ -410,23 +435,19 @@ void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) ...@@ -410,23 +435,19 @@ void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
mutex_unlock(&table->mutex); mutex_unlock(&table->mutex);
} }
void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
{ {
u64 in_param = 0; u64 out_param = 0;
int err;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&in_param, port); (void) mlx4_cmd_imm(dev, vlan, &out_param,
err = mlx4_cmd(dev, in_param, RES_VLAN, RES_OP_RESERVE_AND_MAP, ((u32) port) << 8 | (u32) RES_VLAN,
MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, RES_OP_RESERVE_AND_MAP,
MLX4_CMD_WRAPPED); MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
if (!err) MLX4_CMD_WRAPPED);
mlx4_warn(dev, "Failed freeing vlan at index:%d\n",
index);
return; return;
} }
__mlx4_unregister_vlan(dev, port, index); __mlx4_unregister_vlan(dev, port, vlan);
} }
EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
......
...@@ -480,8 +480,7 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) ...@@ -480,8 +480,7 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
*/ */
err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
(1 << 23) - 1, dev->phys_caps.base_sqpn + 8 + (1 << 23) - 1, mlx4_num_reserved_sqps(dev),
16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev),
reserved_from_top); reserved_from_top);
if (err) if (err)
return err; return err;
......
...@@ -54,6 +54,7 @@ enum { ...@@ -54,6 +54,7 @@ enum {
MLX4_FLAG_MASTER = 1 << 2, MLX4_FLAG_MASTER = 1 << 2,
MLX4_FLAG_SLAVE = 1 << 3, MLX4_FLAG_SLAVE = 1 << 3,
MLX4_FLAG_SRIOV = 1 << 4, MLX4_FLAG_SRIOV = 1 << 4,
MLX4_FLAG_OLD_REG_MAC = 1 << 6,
}; };
enum { enum {
...@@ -640,12 +641,23 @@ struct mlx4_counter { ...@@ -640,12 +641,23 @@ struct mlx4_counter {
__be64 tx_bytes; __be64 tx_bytes;
}; };
struct mlx4_quotas {
int qp;
int cq;
int srq;
int mpt;
int mtt;
int counter;
int xrcd;
};
struct mlx4_dev { struct mlx4_dev {
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned long flags; unsigned long flags;
unsigned long num_slaves; unsigned long num_slaves;
struct mlx4_caps caps; struct mlx4_caps caps;
struct mlx4_phys_caps phys_caps; struct mlx4_phys_caps phys_caps;
struct mlx4_quotas quotas;
struct radix_tree_root qp_table_tree; struct radix_tree_root qp_table_tree;
u8 rev_id; u8 rev_id;
char board_id[MLX4_BOARD_ID_LEN]; char board_id[MLX4_BOARD_ID_LEN];
...@@ -771,6 +783,12 @@ static inline int mlx4_is_master(struct mlx4_dev *dev) ...@@ -771,6 +783,12 @@ static inline int mlx4_is_master(struct mlx4_dev *dev)
return dev->flags & MLX4_FLAG_MASTER; return dev->flags & MLX4_FLAG_MASTER;
} }
static inline int mlx4_num_reserved_sqps(struct mlx4_dev *dev)
{
return dev->phys_caps.base_sqpn + 8 +
16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev);
}
static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn) static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn)
{ {
return (qpn < dev->phys_caps.base_sqpn + 8 + return (qpn < dev->phys_caps.base_sqpn + 8 +
...@@ -1078,7 +1096,7 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw, ...@@ -1078,7 +1096,7 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
u8 *pg, u16 *ratelimit); u8 *pg, u16 *ratelimit);
int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list, int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list,
int npages, u64 iova, u32 *lkey, u32 *rkey); int npages, u64 iova, u32 *lkey, u32 *rkey);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment