* [PATCH 00/23 v3] mlx4: multi-function framework and Ethernet SRIOV
[not found] <49BFC313.1030901@mellanox.co.il>
@ 2010-02-04 15:54 ` Yevgeny Petrilin
2010-02-04 15:54 ` [PATCH 01/23 v3] mlx4_core: identify function as pf or vf Yevgeny Petrilin
` (22 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:54 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Hello Roland,
This is the third version of these patches, the main changes from previous time:
1. ConnectX-2 HW support.
2. The master function raises interfaces as well.
3. Using HCR completion interrupts for the master function.
4. Multicast fixes.
5. Removed bitmap allocation wrapper.
Thanks,
Yevgeny
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 01/23 v3] mlx4_core: identify function as pf or vf
[not found] <49BFC313.1030901@mellanox.co.il>
2010-02-04 15:54 ` [PATCH 00/23 v3] mlx4: multi-function framework and Ethernet SRIOV Yevgeny Petrilin
@ 2010-02-04 15:54 ` Yevgeny Petrilin
2010-02-09 13:41 ` Ben Hutchings
2010-02-04 15:54 ` [PATCH 02/23 v3] mlx4_core: add multi-function communication channel Yevgeny Petrilin
` (21 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:54 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
include/linux/mlx4/device.h | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index e92d1bf..f7f0508 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -42,6 +42,9 @@
enum {
MLX4_FLAG_MSI_X = 1 << 0,
MLX4_FLAG_OLD_PORT_CMDS = 1 << 1,
+ MLX4_FLAG_MASTER = 1 << 2,
+ MLX4_FLAG_SLAVE = 1 << 3,
+ MLX4_FLAG_SRIOV = 1 << 4,
};
enum {
@@ -376,6 +379,7 @@ struct mlx4_av {
struct mlx4_dev {
struct pci_dev *pdev;
unsigned long flags;
+ unsigned long num_slaves;
struct mlx4_caps caps;
struct radix_tree_root qp_table_tree;
u32 rev_id;
@@ -401,6 +405,21 @@ struct mlx4_init_port_param {
if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \
~(dev)->caps.port_mask) & 1 << ((port) - 1))
+static inline int mlx4_is_slave(struct mlx4_dev *dev)
+{
+ return dev->flags & MLX4_FLAG_SLAVE;
+}
+
+static inline int mlx4_is_master(struct mlx4_dev *dev)
+{
+ return dev->flags & MLX4_FLAG_MASTER;
+}
+
+static inline int mlx4_is_mfunc(struct mlx4_dev *dev)
+{
+ return dev->flags & (MLX4_FLAG_MASTER | MLX4_FLAG_SLAVE);
+}
+
int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
struct mlx4_buf *buf);
void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 02/23 v3] mlx4_core: add multi-function communication channel
[not found] <49BFC313.1030901@mellanox.co.il>
2010-02-04 15:54 ` [PATCH 00/23 v3] mlx4: multi-function framework and Ethernet SRIOV Yevgeny Petrilin
2010-02-04 15:54 ` [PATCH 01/23 v3] mlx4_core: identify function as pf or vf Yevgeny Petrilin
@ 2010-02-04 15:54 ` Yevgeny Petrilin
2010-02-09 14:37 ` Ben Hutchings
2010-02-04 15:54 ` [PATCH 03/23 v3] mlx4_core: add WRITE_MTT support Yevgeny Petrilin
` (20 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:54 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
The communication channel consists of 2 registers per vf (a slave function)
that are shared with the pf (the master function), as well as a new command for
inter-function memory copying (only exposed to the master).
The communication channel is used to establish a Virtual HCA Command Register
(vHCR) in each slave function, which allows it to pass FW commands to the master
function for execution.
The slave also uses the vHCR to pull slave-specific events from the master.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 746 ++++++++++++++++++++++++++++++++++++++++++-
drivers/net/mlx4/en_port.h | 5 -
drivers/net/mlx4/eq.c | 67 ++++
drivers/net/mlx4/fw.c | 8 +
drivers/net/mlx4/mlx4.h | 72 ++++-
include/linux/mlx4/cmd.h | 12 +-
include/linux/mlx4/device.h | 3 +-
7 files changed, 895 insertions(+), 18 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 65ec77d..6c3d25c 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -140,6 +140,46 @@ static int mlx4_status_to_errno(u8 status)
return trans_table[status];
}
+static int comm_pending(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ u32 status = readl(&priv->mfunc.comm->slave_read);
+
+ return (swab32(status) >> 30) != priv->cmd.comm_toggle;
+}
+
+int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, unsigned long timeout)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ unsigned long end;
+ u32 val;
+
+ /* First, verify that the master reports correct status */
+ if (comm_pending(dev)) {
+ mlx4_warn(dev, "Communication channel is not idle\n");
+ return -EAGAIN;
+ }
+
+ /* Write command */
+ if (cmd == MLX4_COMM_CMD_RESET)
+ priv->cmd.comm_toggle = 0;
+ else if (++priv->cmd.comm_toggle > 2)
+ priv->cmd.comm_toggle = 1;
+ val = param | (cmd << 16) | (priv->cmd.comm_toggle << 30);
+ __raw_writel((__force u32) cpu_to_be32(val), &priv->mfunc.comm->slave_write);
+ wmb();
+
+ end = msecs_to_jiffies(timeout) + jiffies;
+ while (comm_pending(dev) && time_before(jiffies, end))
+ cond_resched();
+
+ if (comm_pending(dev)) {
+ mlx4_warn(dev, "Communication channel timed out\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
static int cmd_pending(struct mlx4_dev *dev)
{
u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
@@ -207,6 +247,33 @@ out:
return ret;
}
+static int mlx4_slave_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
+ int out_is_imm, u32 in_modifier, u8 op_modifier,
+ u16 op, unsigned long timeout)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_vhcr *vhcr = priv->mfunc.vhcr;
+ int ret;
+
+ down(&priv->cmd.poll_sem);
+ vhcr->in_param = in_param;
+ vhcr->out_param = out_param ? *out_param : 0;
+ vhcr->in_modifier = in_modifier;
+ vhcr->timeout = timeout;
+ vhcr->op = op;
+ vhcr->token = CMD_POLL_TOKEN;
+ vhcr->op_modifier = op_modifier;
+ vhcr->errno = 0;
+ ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0, MLX4_COMM_TIME + timeout);
+ if (!ret) {
+ if (out_is_imm)
+ *out_param = vhcr->out_param;
+ ret = vhcr->errno;
+ }
+ up(&priv->cmd.poll_sem);
+ return ret;
+}
+
static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
int out_is_imm, u32 in_modifier, u8 op_modifier,
u16 op, unsigned long timeout)
@@ -314,12 +381,646 @@ int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
if (mlx4_priv(dev)->cmd.use_events)
return mlx4_cmd_wait(dev, in_param, out_param, out_is_imm,
in_modifier, op_modifier, op, timeout);
+
+ if (mlx4_is_slave(dev))
+ return mlx4_slave_cmd_poll(dev, in_param, out_param, out_is_imm,
+ in_modifier, op_modifier, op, timeout);
else
return mlx4_cmd_poll(dev, in_param, out_param, out_is_imm,
in_modifier, op_modifier, op, timeout);
}
EXPORT_SYMBOL_GPL(__mlx4_cmd);
+static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
+ int slave, u64 slave_addr,
+ int size, int is_read)
+{
+ u64 in_param;
+ u64 out_param;
+
+ if ((slave_addr & 0xfff) | (master_addr & 0xfff) |
+ (slave & ~0x7f) | (size & 0xff)) {
+ mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx "
+ "master_addr:0x%llx slave_id:%d size:%d\n",
+ slave_addr, master_addr, slave, size);
+ return -EINVAL;
+ }
+
+ if (is_read) {
+ in_param = (u64) slave | slave_addr;
+ out_param = master_addr;
+ } else {
+ in_param = master_addr;
+ out_param = (u64) slave | slave_addr;
+ }
+
+ return mlx4_cmd_imm(dev, in_param, &out_param, size, 0,
+ MLX4_CMD_ACCESS_MEM,
+ MLX4_CMD_TIME_CLASS_A);
+}
+
+static struct mlx4_cmd_info {
+ u16 opcode;
+ bool has_inbox;
+ bool has_outbox;
+ bool out_is_imm;
+ int (*verify)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox);
+ int (*wrapper)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+} cmd_info[] = {
+ {
+ .opcode = MLX4_CMD_QUERY_FW,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_ADAPTER,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL
+ },
+
+ {
+ .opcode = MLX4_CMD_SW2HW_EQ,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /*need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_NOP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL
+ },
+
+ {
+ .opcode = MLX4_CMD_SW2HW_MPT,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_MPT,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_HW2SW_MPT,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_READ_MTT,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SYNC_TPT,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+
+ {
+ .opcode = MLX4_CMD_HW2SW_EQ,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_EQ,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SW2HW_CQ,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_HW2SW_CQ,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_CQ,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_MODIFY_CQ,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = true,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SW2HW_SRQ,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_HW2SW_SRQ,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_SRQ,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_ARM_SRQ,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_RST2INIT_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_INIT2RTR_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_RTR2RTS_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_RTS2RTS_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SQERR2RTS_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_2ERR_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_RTS2SQD_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SQD2SQD_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SQD2RTS_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_2RST_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_QP,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_INIT2INIT_QP,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_SUSPEND_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_UNSUSPEND_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+ {
+ .opcode = MLX4_CMD_MAD_IFC,
+ .has_inbox = true,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+
+ /* Native multicast commands are not available for guests */
+ {
+ .opcode = MLX4_CMD_DIAG_RPRT,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = NULL
+ },
+
+ /* Ethernet specific commands */
+ {
+ .opcode = MLX4_CMD_SET_VLAN_FLTR,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL /* need wrapper*/
+ },
+ {
+ .opcode = MLX4_CMD_SET_MCAST_FLTR,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL /* need wrapper*/
+ },
+ {
+ .opcode = MLX4_CMD_DUMP_ETH_STATS,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = NULL /* need wrapper*/
+ },
+};
+
+static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_cmd_info *cmd = NULL;
+ struct mlx4_vhcr *vhcr = priv->mfunc.vhcr;
+ struct mlx4_cmd_mailbox *inbox = NULL;
+ struct mlx4_cmd_mailbox *outbox = NULL;
+ u64 in_param;
+ u64 out_param;
+ int ret;
+ int i;
+
+ /* DMA in the vHCR */
+ ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave,
+ priv->mfunc.master.slave_state[slave].vhcr_dma,
+ ALIGN(sizeof(struct mlx4_vhcr),
+ MLX4_ACCESS_MEM_ALIGN), 1);
+ if (ret) {
+ mlx4_err(dev, "Failed reading vhcr\n");
+ return ret;
+ }
+
+ /* Lookup command */
+ for (i = 0; i < ARRAY_SIZE(cmd_info); ++i) {
+ if (vhcr->op == cmd_info[i].opcode) {
+ cmd = &cmd_info[i];
+ break;
+ }
+ }
+ if (!cmd) {
+ mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n",
+ vhcr->op, slave);
+ vhcr->errno = -EINVAL;
+ goto out_status;
+ }
+
+ /* Read inbox */
+ if (cmd->has_inbox) {
+ inbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(inbox)) {
+ ret = PTR_ERR(inbox);
+ inbox = NULL;
+ goto out;
+ }
+
+ /* FIXME: add mailbox size per-command */
+ ret = mlx4_ACCESS_MEM(dev, inbox->dma, slave,
+ vhcr->in_param,
+ MLX4_MAILBOX_SIZE, 1);
+ if (ret) {
+ mlx4_err(dev, "Failed reading inbox\n");
+ goto out;
+ }
+ }
+
+ /* Apply permission and bound checks if applicable */
+ if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) {
+ mlx4_warn(dev, "Command:0x%x failed protection checks\n", vhcr->op);
+ vhcr->errno = -EPERM;
+ goto out_status;
+ }
+
+ /* Allocate outbox */
+ if (cmd->has_outbox) {
+ outbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(outbox)) {
+ ret = PTR_ERR(outbox);
+ outbox = NULL;
+ goto out;
+ }
+ }
+
+ /* Execute the command! */
+ if (cmd->wrapper)
+ vhcr->errno = cmd->wrapper(dev, slave, vhcr, inbox, outbox);
+ else {
+ in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param;
+ out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param;
+ vhcr->errno = __mlx4_cmd(dev, in_param, &out_param,
+ cmd->out_is_imm,
+ vhcr->in_modifier,
+ vhcr->op_modifier,
+ vhcr->op,
+ vhcr->timeout);
+ if (cmd->out_is_imm)
+ vhcr->out_param = out_param;
+ }
+
+ /* Write outbox if command completed successfully */
+ if (cmd->has_outbox && !vhcr->errno) {
+ ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave,
+ vhcr->out_param,
+ MLX4_MAILBOX_SIZE, 0);
+ if (ret) {
+ mlx4_err(dev, "Failed writing outbox\n");
+ goto out;
+ }
+ }
+
+out_status:
+ /* DMA back vhcr result */
+ ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave,
+ priv->mfunc.master.slave_state[slave].vhcr_dma,
+ ALIGN(sizeof(struct mlx4_vhcr),
+ MLX4_ACCESS_MEM_ALIGN), 0);
+ if (ret)
+ mlx4_err(dev, "Failed writing vhcr result\n");
+
+ if (vhcr->errno)
+ mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with error:%d\n",
+ vhcr->op, slave, vhcr->errno);
+ /* Fall through... */
+
+out:
+ mlx4_free_cmd_mailbox(dev, inbox);
+ mlx4_free_cmd_mailbox(dev, outbox);
+ return ret;
+}
+
+static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u16 param, u8 toggle)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
+ u8 toggle_next;
+ u32 reply;
+
+ if (cmd == MLX4_COMM_CMD_RESET) {
+ mlx4_warn(dev, "Received reset from slave:%d\n", slave);
+ goto reset_slave;
+ }
+
+ /* Increment next toggle token */
+ toggle_next = slave_state[slave].comm_toggle + 1;
+ if (toggle_next > 2)
+ toggle_next = 1;
+ if (toggle != toggle_next) {
+ mlx4_warn(dev, "Incorrect token:%d from slave:%d expected:%d\n",
+ toggle, toggle_next, slave);
+ goto reset_slave;
+ }
+
+ switch (cmd) {
+ case MLX4_COMM_CMD_VHCR0:
+ if (slave_state[slave].last_cmd != MLX4_COMM_CMD_RESET)
+ goto reset_slave;
+ slave_state[slave].vhcr_dma = ((u64) param) << 48;
+ break;
+ case MLX4_COMM_CMD_VHCR1:
+ if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0)
+ goto reset_slave;
+ slave_state[slave].vhcr_dma |= ((u64) param) << 32;
+ break;
+ case MLX4_COMM_CMD_VHCR2:
+ if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR1)
+ goto reset_slave;
+ slave_state[slave].vhcr_dma |= ((u64) param) << 16;
+ break;
+ case MLX4_COMM_CMD_VHCR_EN:
+ if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
+ goto reset_slave;
+ slave_state[slave].vhcr_dma |= param;
+ break;
+ case MLX4_COMM_CMD_VHCR_POST:
+ if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&
+ (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_POST))
+ goto reset_slave;
+ if (mlx4_master_process_vhcr(dev, slave)) {
+ mlx4_err(dev, "Failed processing vhcr for slave:%d, reseting slave.\n", slave);
+ goto reset_slave;
+ }
+ break;
+ default:
+ mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave);
+ goto reset_slave;
+ }
+
+ slave_state[slave].last_cmd = cmd;
+ slave_state[slave].comm_toggle = toggle_next;
+ reply = (u32) toggle_next << 30;
+ __raw_writel((__force u32) cpu_to_be32(reply),
+ &priv->mfunc.comm[slave].slave_read);
+ wmb();
+ return;
+
+reset_slave:
+ /* FIXME: cleanup any slave resources */
+ slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET;
+ slave_state[slave].comm_toggle = 0;
+ __raw_writel((__force u32) 0, &priv->mfunc.comm[slave].slave_write);
+ __raw_writel((__force u32) 0, &priv->mfunc.comm[slave].slave_read);
+ wmb();
+}
+
+/* master command processing */
+static void mlx4_master_poll_comm(struct work_struct *work)
+{
+ struct delayed_work *delay = container_of(work, struct delayed_work, work);
+ struct mlx4_mfunc *mfunc = container_of(delay, struct mlx4_mfunc, comm_work);
+ struct mlx4_priv *priv = container_of(mfunc, struct mlx4_priv, mfunc);
+ struct mlx4_dev *dev = &priv->dev;
+ u32 comm_cmd;
+ int polled = 0;
+ int i;
+
+ /* Give each slave a chance for one command */
+ for (i = 0; i < dev->num_slaves; i++) {
+ comm_cmd = swab32(readl(&priv->mfunc.comm[i].slave_write));
+ if (comm_cmd >> 30 != priv->mfunc.master.slave_state[i].comm_toggle) {
+ mlx4_master_do_cmd(dev, i, comm_cmd >> 16, comm_cmd, comm_cmd >> 30);
+ polled = 1;
+ }
+ }
+ queue_delayed_work(priv->mfunc.comm_wq, &priv->mfunc.comm_work,
+ polled ? 0 : HZ / 10);
+}
+
+int mlx4_multi_func_init(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int i;
+
+ priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
+ &priv->mfunc.vhcr_dma,
+ GFP_KERNEL);
+ if (!priv->mfunc.vhcr) {
+ mlx4_err(dev, "Couldn't allocate vhcr.\n");
+ return -ENOMEM;
+ }
+
+ if (mlx4_is_master(dev))
+ priv->mfunc.comm = ioremap(pci_resource_start(dev->pdev,
+ priv->fw.comm_bar) +
+ priv->fw.comm_base,
+ MLX4_COMM_PAGESIZE);
+ else
+ priv->mfunc.comm = ioremap(pci_resource_start(dev->pdev, 2) +
+ MLX4_SLAVE_COMM_BASE,
+ MLX4_COMM_PAGESIZE);
+ if (!priv->mfunc.comm) {
+ mlx4_err(dev, "Couldn't map communication vector.");
+ goto err_vhcr;
+ }
+
+ if (mlx4_is_master(dev)) {
+ priv->mfunc.master.slave_state = kzalloc(dev->num_slaves *
+ sizeof(struct mlx4_slave_state),
+ GFP_KERNEL);
+ if (!priv->mfunc.master.slave_state)
+ goto err_comm;
+
+ for (i = 0; i < dev->num_slaves; ++i)
+ priv->mfunc.master.slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
+
+ INIT_DELAYED_WORK(&priv->mfunc.comm_work, mlx4_master_poll_comm);
+ priv->mfunc.comm_wq = create_singlethread_workqueue("mlx4_comm");
+ if (!priv->mfunc.comm_wq) {
+ kfree(priv->mfunc.master.slave_state);
+ goto err_comm;
+ }
+ } else {
+ priv->cmd.comm_toggle = 0;
+ INIT_DELAYED_WORK(&priv->mfunc.comm_work, mlx4_slave_async_eq_poll);
+ priv->mfunc.comm_wq = create_singlethread_workqueue("mlx4_event");
+ if (!priv->mfunc.comm_wq)
+ goto err_comm;
+ }
+ return 0;
+
+err_comm:
+ iounmap(priv->mfunc.comm);
+err_vhcr:
+ dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
+ priv->mfunc.vhcr,
+ priv->mfunc.vhcr_dma);
+ priv->mfunc.vhcr = NULL;
+ return -ENOMEM;
+}
+
int mlx4_cmd_init(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -329,22 +1030,45 @@ int mlx4_cmd_init(struct mlx4_dev *dev)
priv->cmd.use_events = 0;
priv->cmd.toggle = 1;
- priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_HCR_BASE,
- MLX4_HCR_SIZE);
- if (!priv->cmd.hcr) {
- mlx4_err(dev, "Couldn't map command register.");
- return -ENOMEM;
+ priv->cmd.hcr = NULL;
+ priv->mfunc.vhcr = NULL;
+
+ if (!mlx4_is_slave(dev)) {
+ priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) +
+ MLX4_HCR_BASE, MLX4_HCR_SIZE);
+ if (!priv->cmd.hcr) {
+ mlx4_err(dev, "Couldn't map command register.");
+ return -ENOMEM;
+ }
}
priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev,
MLX4_MAILBOX_SIZE,
MLX4_MAILBOX_SIZE, 0);
- if (!priv->cmd.pool) {
- iounmap(priv->cmd.hcr);
- return -ENOMEM;
- }
+ if (!priv->cmd.pool)
+ goto err_hcr;
return 0;
+
+err_hcr:
+ if (!mlx4_is_slave(dev))
+ iounmap(priv->cmd.hcr);
+ return -ENOMEM;
+}
+
+void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ if (priv->mfunc.vhcr) {
+ destroy_workqueue(priv->mfunc.comm_wq);
+ kfree(priv->mfunc.master.slave_state);
+ iounmap(priv->mfunc.comm);
+ dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
+ priv->mfunc.vhcr,
+ priv->mfunc.vhcr_dma);
+ priv->mfunc.vhcr = NULL;
+ }
}
void mlx4_cmd_cleanup(struct mlx4_dev *dev)
@@ -352,7 +1076,9 @@ void mlx4_cmd_cleanup(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
pci_pool_destroy(priv->cmd.pool);
- iounmap(priv->cmd.hcr);
+
+ if (!mlx4_is_slave(dev))
+ iounmap(priv->cmd.hcr);
}
/*
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index e6477f1..3892896 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -38,11 +38,6 @@
#define SET_PORT_GEN_ALL_VALID 0x7
#define SET_PORT_PROMISC_SHIFT 31
-enum {
- MLX4_CMD_SET_VLAN_FLTR = 0x47,
- MLX4_CMD_SET_MCAST_FLTR = 0x48,
- MLX4_CMD_DUMP_ETH_STATS = 0x49,
-};
struct mlx4_set_port_general_context {
u8 reserved[3];
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index bffb799..70c16d4 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -160,6 +160,22 @@ static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq)
return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe;
}
+static int mlx4_GET_EVENT(struct mlx4_dev *dev, struct mlx4_slave_eqe *eqe)
+{
+ int ret;
+ u64 out_param;
+
+ ret = mlx4_cmd_imm(dev, 0, &out_param, 0, 0, MLX4_CMD_GET_EVENT,
+ MLX4_CMD_TIME_CLASS_A);
+ if (!ret) {
+ eqe->type = out_param & 0xff;
+ eqe->port = (out_param >> 8) & 0xff;
+ eqe->param = out_param >> 32;
+ } else
+ mlx4_err(dev, "Failed retrieving event\n");
+ return ret;
+}
+
static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
{
struct mlx4_eqe *eqe;
@@ -262,6 +278,57 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
return eqes_found;
}
+void mlx4_slave_async_eq_poll(struct work_struct *work)
+{
+ struct delayed_work *delay = container_of(work, struct delayed_work, work);
+ struct mlx4_mfunc *mfunc = container_of(delay, struct mlx4_mfunc, comm_work);
+ struct mlx4_priv *priv = container_of(mfunc, struct mlx4_priv, mfunc);
+ struct mlx4_dev *dev = &priv->dev;
+ struct mlx4_slave_eqe eqe;
+ int ret;
+ int i;
+
+ for (i = 0; i < MLX4_MFUNC_MAX_EQES; i++) {
+ ret = mlx4_GET_EVENT(dev, &eqe);
+ if (ret || eqe.type == MLX4_EVENT_TYPE_NONE)
+ break;
+
+ switch (eqe.type) {
+ case MLX4_EVENT_TYPE_PATH_MIG:
+ case MLX4_EVENT_TYPE_COMM_EST:
+ case MLX4_EVENT_TYPE_SQ_DRAINED:
+ case MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE:
+ case MLX4_EVENT_TYPE_WQ_CATAS_ERROR:
+ case MLX4_EVENT_TYPE_PATH_MIG_FAILED:
+ case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
+ case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR:
+ mlx4_qp_event(dev, eqe.param, eqe.type);
+ break;
+
+ case MLX4_EVENT_TYPE_SRQ_LIMIT:
+ case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
+ mlx4_srq_event(dev, eqe.param, eqe.type);
+ break;
+
+ case MLX4_EVENT_TYPE_PORT_CHANGE:
+ mlx4_dispatch_event(dev, eqe.param, eqe.port);
+ break;
+
+ case MLX4_EVENT_TYPE_CQ_ERROR:
+ mlx4_cq_event(dev, eqe.param, eqe.type);
+ break;
+
+ case MLX4_EVENT_TYPE_EQ_OVERFLOW:
+ mlx4_warn(dev, "slave async EQ overrun\n");
+ break;
+
+ default:
+ mlx4_warn(dev, "Unhandled event:%02x\n", eqe.type);
+ }
+ }
+ queue_delayed_work(priv->mfunc.comm_wq, &priv->mfunc.comm_work, HZ);
+}
+
static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr)
{
struct mlx4_dev *dev = dev_ptr;
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 04f42ae..eccac2a 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -555,6 +555,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
#define QUERY_FW_CLR_INT_BASE_OFFSET 0x20
#define QUERY_FW_CLR_INT_BAR_OFFSET 0x28
+#define QUERY_FW_COMM_BASE_OFFSET 0x40
+#define QUERY_FW_COMM_BAR_OFFSET 0x48
+
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -615,6 +618,11 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET);
fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2;
+ MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET);
+ MLX4_GET(fw->comm_bar, outbox, QUERY_FW_COMM_BAR_OFFSET);
+ fw->comm_bar = (fw->comm_bar >> 6) * 2;
+ mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n", fw->comm_bar,
+ fw->comm_base);
mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
/*
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index bc72d6e..92d0682 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -53,8 +53,11 @@
enum {
MLX4_HCR_BASE = 0x80680,
+ MLX4_HCR_SRIOV_BASE = 0x4080680, /* good for SRIOV FW ony */
MLX4_HCR_SIZE = 0x0001c,
- MLX4_CLR_INT_SIZE = 0x00008
+ MLX4_CLR_INT_SIZE = 0x00008,
+ MLX4_SLAVE_COMM_BASE = 0x0,
+ MLX4_COMM_PAGESIZE = 0x1000
};
enum {
@@ -80,6 +83,21 @@ enum {
MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT
};
+#define MLX4_COMM_TIME 10000
+enum {
+ MLX4_COMM_CMD_RESET,
+ MLX4_COMM_CMD_VHCR0,
+ MLX4_COMM_CMD_VHCR1,
+ MLX4_COMM_CMD_VHCR2,
+ MLX4_COMM_CMD_VHCR_EN,
+ MLX4_COMM_CMD_VHCR_POST
+};
+
+enum {
+ MLX4_MFUNC_MAX_EQES = 8,
+ MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
+};
+
#ifdef CONFIG_MLX4_DEBUG
extern int mlx4_debug_level;
#else /* CONFIG_MLX4_DEBUG */
@@ -154,12 +172,56 @@ struct mlx4_profile {
struct mlx4_fw {
u64 clr_int_base;
u64 catas_offset;
+ u64 comm_base;
struct mlx4_icm *fw_icm;
struct mlx4_icm *aux_icm;
u32 catas_size;
u16 fw_pages;
u8 clr_int_bar;
u8 catas_bar;
+ u8 comm_bar;
+};
+
+struct mlx4_comm {
+ u32 slave_write;
+ u32 slave_read;
+};
+
+struct mlx4_slave_eqe {
+ u8 type;
+ u8 port;
+ u32 param;
+};
+
+struct mlx4_slave_state {
+ u8 comm_toggle;
+ u8 last_cmd;
+ dma_addr_t vhcr_dma;
+};
+
+struct mlx4_mfunc_master_ctx {
+ struct mlx4_slave_state *slave_state;
+};
+
+struct mlx4_vhcr {
+ u64 in_param;
+ u64 out_param;
+ u32 in_modifier;
+ u32 timeout;
+ u16 op;
+ u16 token;
+ u8 op_modifier;
+ int errno;
+};
+
+struct mlx4_mfunc {
+ struct mlx4_comm __iomem *comm;
+ struct workqueue_struct *comm_wq;
+ struct delayed_work comm_work;
+ struct mlx4_vhcr *vhcr;
+ dma_addr_t vhcr_dma;
+
+ struct mlx4_mfunc_master_ctx master;
};
struct mlx4_cmd {
@@ -175,6 +237,7 @@ struct mlx4_cmd {
u16 token_mask;
u8 use_events;
u8 toggle;
+ u8 comm_toggle;
};
struct mlx4_uar_table {
@@ -294,6 +357,7 @@ struct mlx4_priv {
struct mlx4_fw fw;
struct mlx4_cmd cmd;
+ struct mlx4_mfunc mfunc;
struct mlx4_bitmap pd_bitmap;
struct mlx4_uar_table uar_table;
@@ -370,13 +434,19 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
struct mlx4_profile *request,
struct mlx4_dev_cap *dev_cap,
struct mlx4_init_hca_param *init_hca);
+void mlx4_slave_async_eq_poll(struct work_struct *work);
int mlx4_cmd_init(struct mlx4_dev *dev);
void mlx4_cmd_cleanup(struct mlx4_dev *dev);
+int mlx4_multi_func_init(struct mlx4_dev *dev);
+void mlx4_multi_func_cleanup(struct mlx4_dev *dev);
void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param);
int mlx4_cmd_use_events(struct mlx4_dev *dev);
void mlx4_cmd_use_polling(struct mlx4_dev *dev);
+int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, unsigned long timeout);
+
+
void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn);
void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type);
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 0f82293..b567e63 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -117,6 +117,15 @@ enum {
/* miscellaneous commands */
MLX4_CMD_DIAG_RPRT = 0x30,
MLX4_CMD_NOP = 0x31,
+ MLX4_CMD_ACCESS_MEM = 0x2e,
+
+ /* Ethernet specific commands */
+ MLX4_CMD_SET_VLAN_FLTR = 0x47,
+ MLX4_CMD_SET_MCAST_FLTR = 0x48,
+ MLX4_CMD_DUMP_ETH_STATS = 0x49,
+
+ /* virtual commands */
+ MLX4_CMD_GET_EVENT = 0xf03,
/* debug commands */
MLX4_CMD_QUERY_DEBUG_MSG = 0x2a,
@@ -130,7 +139,8 @@ enum {
};
enum {
- MLX4_MAILBOX_SIZE = 4096
+ MLX4_MAILBOX_SIZE = 4096,
+ MLX4_ACCESS_MEM_ALIGN = 256,
};
enum {
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index f7f0508..f80b899 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -99,7 +99,8 @@ enum mlx4_event {
MLX4_EVENT_TYPE_PORT_CHANGE = 0x09,
MLX4_EVENT_TYPE_EQ_OVERFLOW = 0x0f,
MLX4_EVENT_TYPE_ECC_DETECT = 0x0e,
- MLX4_EVENT_TYPE_CMD = 0x0a
+ MLX4_EVENT_TYPE_CMD = 0x0a,
+ MLX4_EVENT_TYPE_NONE = 0xff,
};
enum {
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 03/23 v3] mlx4_core: add WRITE_MTT support
[not found] <49BFC313.1030901@mellanox.co.il>
` (2 preceding siblings ...)
2010-02-04 15:54 ` [PATCH 02/23 v3] mlx4_core: add multi-function communication channel Yevgeny Petrilin
@ 2010-02-04 15:54 ` Yevgeny Petrilin
2010-02-04 15:54 ` [PATCH 04/23 v3] mlx4_core: add slave resource allocation Yevgeny Petrilin
` (19 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:54 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Used by vfs to modify mtts, since they cannot access in-memory mtts directly.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 10 +++++-
drivers/net/mlx4/mlx4.h | 5 +++
drivers/net/mlx4/mr.c | 67 ++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 6c3d25c..9e85330 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -36,8 +36,6 @@
#include <linux/pci.h>
#include <linux/errno.h>
-#include <linux/mlx4/cmd.h>
-
#include <asm/io.h>
#include "mlx4.h"
@@ -497,6 +495,14 @@ static struct mlx4_cmd_info {
.wrapper = NULL
},
{
+ .opcode = MLX4_CMD_WRITE_MTT,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL, /* need verifier */
+ .wrapper = mlx4_WRITE_MTT_wrapper
+ },
+ {
.opcode = MLX4_CMD_SYNC_TPT,
.has_inbox = true,
.has_outbox = false,
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 92d0682..18ac62d 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -45,6 +45,7 @@
#include <linux/mlx4/device.h>
#include <linux/mlx4/driver.h>
#include <linux/mlx4/doorbell.h>
+#include <linux/mlx4/cmd.h>
#define DRV_NAME "mlx4_core"
#define PFX DRV_NAME ": "
@@ -419,6 +420,10 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev);
void mlx4_cleanup_srq_table(struct mlx4_dev *dev);
void mlx4_cleanup_mcg_table(struct mlx4_dev *dev);
+int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+
void mlx4_start_catas_poll(struct mlx4_dev *dev);
void mlx4_stop_catas_poll(struct mlx4_dev *dev);
void mlx4_catas_init(void);
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index ca7ab8e..9e4ab0f 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -262,6 +262,35 @@ static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
!mailbox, MLX4_CMD_HW2SW_MPT, MLX4_CMD_TIME_CLASS_B);
}
+int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ struct mlx4_mtt mtt;
+ u64 *page_list = inbox->buf;
+ int i;
+
+ /* Call the SW implementation of write_mtt:
+ * - Prepare a dummy mtt struct
+ * - Translate inbox contents to simple addresses in host endianess */
+ mtt.first_seg = 0;
+ mtt.order = 0;
+ mtt.page_shift = 0;
+ for (i = 0; i < vhcr->in_modifier; ++i)
+ page_list[i + 2] = be64_to_cpu(page_list[i + 2]) & ~1ULL;
+ vhcr->errno = mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]),
+ vhcr->in_modifier,
+ page_list + 2);
+ return 0;
+}
+
+static int mlx4_WRITE_MTT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ int num_entries)
+{
+ return mlx4_cmd(dev, mailbox->dma, num_entries, 0, MLX4_CMD_WRITE_MTT,
+ MLX4_CMD_TIME_CLASS_A);
+}
+
int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
int npages, int page_shift, struct mlx4_mr *mr)
{
@@ -413,24 +442,50 @@ static int mlx4_write_mtt_chunk(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
int start_index, int npages, u64 *page_list)
{
+ struct mlx4_cmd_mailbox *mailbox = NULL;
int chunk;
- int err;
+ int err = 0;
+ __be64 *inbox = NULL;
+ int i;
if (mtt->order < 0)
return -EINVAL;
+ if (mlx4_is_slave(dev)) {
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ inbox = mailbox->buf;
+ }
+
while (npages > 0) {
- chunk = min_t(int, PAGE_SIZE / sizeof(u64), npages);
- err = mlx4_write_mtt_chunk(dev, mtt, start_index, chunk, page_list);
+ if (mlx4_is_slave(dev)) {
+ int s = mtt->first_seg * dev->caps.mtts_per_seg + start_index;
+ chunk = min_t(int, MLX4_MAILBOX_SIZE / sizeof(u64) - dev->caps.mtts_per_seg, npages);
+ if (s / (PAGE_SIZE / sizeof (u64)) !=
+ (s + chunk - 1) / (PAGE_SIZE / sizeof (u64)))
+ chunk = PAGE_SIZE / sizeof (u64) - (s % (PAGE_SIZE / sizeof (u64)));
+
+ inbox[0] = cpu_to_be64(mtt->first_seg * dev->caps.mtts_per_seg + start_index);
+ inbox[1] = 0;
+ for (i = 0; i < chunk; ++i)
+ inbox[i + 2] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT);
+ err = mlx4_WRITE_MTT(dev, mailbox, chunk);
+ } else {
+ chunk = min_t(int, PAGE_SIZE / sizeof(u64), npages);
+ err = mlx4_write_mtt_chunk(dev, mtt, start_index, chunk, page_list);
+ }
if (err)
- return err;
+ goto out;
npages -= chunk;
start_index += chunk;
page_list += chunk;
}
-
- return 0;
+out:
+ if (mlx4_is_slave(dev))
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
}
EXPORT_SYMBOL_GPL(mlx4_write_mtt);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 04/23 v3] mlx4_core: add slave resource allocation
[not found] <49BFC313.1030901@mellanox.co.il>
` (3 preceding siblings ...)
2010-02-04 15:54 ` [PATCH 03/23 v3] mlx4_core: add WRITE_MTT support Yevgeny Petrilin
@ 2010-02-04 15:54 ` Yevgeny Petrilin
2010-02-09 14:44 ` Ben Hutchings
2010-02-04 15:55 ` [PATCH 05/23 v3] mlx4_core: slave multicast support Yevgeny Petrilin
` (18 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:54 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
All QPs/CQs/SRQs/MPTs/MTTs are allocated from shared pools, which are owned by
the master. In addition, all backing ICM memory for these objects is managed by
the master.
To allow slaves to allocate resources, ICM allocation is separated from the rest
of the object state, which is held at the slave.
Slaves can then reserve resource ranges and allocate ICM over the comm channel.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 110 +++++++++++++++++++++++++++++++++
drivers/net/mlx4/cq.c | 91 +++++++++++++++++++++-------
drivers/net/mlx4/mlx4.h | 27 ++++++++
drivers/net/mlx4/mr.c | 125 ++++++++++++++++++++++++++++++++++----
drivers/net/mlx4/qp.c | 151 +++++++++++++++++++++++++++++++++-------------
drivers/net/mlx4/srq.c | 88 ++++++++++++++++++++-------
include/linux/mlx4/cmd.h | 2 +
7 files changed, 496 insertions(+), 98 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 9e85330..533ce77 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -417,6 +417,100 @@ static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
MLX4_CMD_TIME_CLASS_A);
}
+static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ u32 param1 = *((u32 *) &vhcr->in_param);
+ u32 param2 = *(((u32 *) &vhcr->in_param) + 1);
+ int ret;
+
+#if 0
+ char *res[] = {"QP", "CQ", "SRQ", "MPT", "MTT"};
+ mlx4_warn(dev, "resource wrapper - %s (mode: %s) type:%s param1:%d param2:%d\n",
+ vhcr->op == MLX4_CMD_ALLOC_RES ? "allocate" : "free",
+ vhcr->op_modifier == ICM_RESERVE ? "reserve" :
+ (vhcr->op_modifier == ICM_ALLOC ? "alloc" : "reserve+alloc"),
+ res[vhcr->in_modifier], param1, param2);
+#endif
+
+ vhcr->errno = 0;
+ switch (vhcr->in_modifier) {
+ case RES_QP:
+ switch (vhcr->op_modifier) {
+ case ICM_RESERVE:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES) {
+ vhcr->errno = mlx4_qp_reserve_range(dev, param1, param2, &ret);
+ if (!vhcr->errno)
+ vhcr->out_param = ret;
+ } else {
+ mlx4_qp_release_range(dev, param1, param2);
+ }
+ break;
+ case ICM_ALLOC:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES)
+ vhcr->errno = mlx4_qp_alloc_icm(dev, param1);
+ else
+ mlx4_qp_free_icm(dev, param1);
+ break;
+ default:
+ vhcr->errno = -EINVAL;
+ }
+ break;
+ case RES_CQ:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES) {
+ vhcr->errno = mlx4_cq_alloc_icm(dev, &ret);
+ if (!vhcr->errno)
+ vhcr->out_param = ret;
+ } else
+ mlx4_cq_free_icm(dev, param1);
+ break;
+ case RES_SRQ:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES) {
+ vhcr->errno = mlx4_srq_alloc_icm(dev, &ret);
+ if (!vhcr->errno)
+ vhcr->out_param = ret;
+ } else
+ mlx4_srq_free_icm(dev, param1);
+ break;
+ case RES_MPT:
+ switch (vhcr->op_modifier) {
+ case ICM_RESERVE:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES) {
+ ret = mlx4_mr_reserve(dev);
+ if (ret == -1)
+ vhcr->errno = -ENOMEM;
+ else
+ vhcr->out_param = ret;
+ } else
+ mlx4_mr_release(dev, param1);
+ break;
+ case ICM_ALLOC:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES)
+ vhcr->errno = mlx4_mr_alloc_icm(dev, param1);
+ else
+ mlx4_mr_free_icm(dev, param1);
+ break;
+ default:
+ vhcr->errno = -EINVAL;
+ }
+ break;
+ case RES_MTT:
+ if (vhcr->op == MLX4_CMD_ALLOC_RES) {
+ ret = mlx4_alloc_mtt_range(dev, param1 /* order */);
+ if (ret == -1)
+ vhcr->errno = -ENOMEM;
+ else
+ vhcr->out_param = ret;
+ } else
+ mlx4_free_mtt_range(dev, param1 /* first */, param2 /* order */);
+ break;
+ default:
+ vhcr->errno = -EINVAL;
+ }
+ return 0;
+}
+
static struct mlx4_cmd_info {
u16 opcode;
bool has_inbox;
@@ -461,6 +555,22 @@ static struct mlx4_cmd_info {
.verify = NULL,
.wrapper = NULL
},
+ {
+ .opcode = MLX4_CMD_ALLOC_RES,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = true,
+ .verify = NULL,
+ .wrapper = mlx4_RESOURCE_wrapper
+ },
+ {
+ .opcode = MLX4_CMD_FREE_RES,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_RESOURCE_wrapper
+ },
{
.opcode = MLX4_CMD_SW2HW_MPT,
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index ccfe276..3fb9f7f 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -186,6 +186,70 @@ int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
}
EXPORT_SYMBOL_GPL(mlx4_cq_resize);
+int mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_cq_table *cq_table = &priv->cq_table;
+ u64 out_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ err = mlx4_cmd_imm(dev, 0, &out_param, RES_CQ,
+ ICM_RESERVE_AND_ALLOC,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err) {
+ *cqn = -1;
+ return err;
+ } else {
+ *cqn = out_param;
+ return 0;
+ }
+ }
+
+ *cqn = mlx4_bitmap_alloc(&cq_table->bitmap);
+ if (*cqn == -1)
+ return -ENOMEM;
+
+ err = mlx4_table_get(dev, &cq_table->table, *cqn);
+ if (err)
+ goto err_out;
+
+ err = mlx4_table_get(dev, &cq_table->cmpt_table, *cqn);
+ if (err)
+ goto err_put;
+ return 0;
+
+err_put:
+ mlx4_table_put(dev, &cq_table->table, *cqn);
+
+err_out:
+ mlx4_bitmap_free(&cq_table->bitmap, *cqn);
+ return err;
+}
+
+void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_cq_table *cq_table = &priv->cq_table;
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = cqn;
+ *(((u32 *) &in_param) + 1) = 0;
+ err = mlx4_cmd(dev, in_param, RES_CQ, ICM_RESERVE_AND_ALLOC,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ mlx4_warn(dev, "Failed freeing cq:%d\n", cqn);
+ } else {
+ mlx4_table_put(dev, &cq_table->cmpt_table, cqn);
+ mlx4_table_put(dev, &cq_table->table, cqn);
+ mlx4_bitmap_free(&cq_table->bitmap, cqn);
+ }
+}
+
int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
unsigned vector, int collapsed)
@@ -202,23 +266,15 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
cq->vector = vector;
- cq->cqn = mlx4_bitmap_alloc(&cq_table->bitmap);
- if (cq->cqn == -1)
- return -ENOMEM;
-
- err = mlx4_table_get(dev, &cq_table->table, cq->cqn);
+ err = mlx4_cq_alloc_icm(dev, &cq->cqn);
if (err)
- goto err_out;
-
- err = mlx4_table_get(dev, &cq_table->cmpt_table, cq->cqn);
- if (err)
- goto err_put;
+ return err;
spin_lock_irq(&cq_table->lock);
err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
spin_unlock_irq(&cq_table->lock);
if (err)
- goto err_cmpt_put;
+ goto err_icm;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) {
@@ -257,14 +313,8 @@ err_radix:
radix_tree_delete(&cq_table->tree, cq->cqn);
spin_unlock_irq(&cq_table->lock);
-err_cmpt_put:
- mlx4_table_put(dev, &cq_table->cmpt_table, cq->cqn);
-
-err_put:
- mlx4_table_put(dev, &cq_table->table, cq->cqn);
-
-err_out:
- mlx4_bitmap_free(&cq_table->bitmap, cq->cqn);
+err_icm:
+ mlx4_cq_free_icm(dev, cq->cqn);
return err;
}
@@ -290,8 +340,7 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
complete(&cq->free);
wait_for_completion(&cq->free);
- mlx4_table_put(dev, &cq_table->table, cq->cqn);
- mlx4_bitmap_free(&cq_table->bitmap, cq->cqn);
+ mlx4_cq_free_icm(dev, cq->cqn);
}
EXPORT_SYMBOL_GPL(mlx4_cq_free);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 18ac62d..d62427f 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -94,6 +94,21 @@ enum {
MLX4_COMM_CMD_VHCR_POST
};
+enum mlx4_resource {
+ RES_QP,
+ RES_CQ,
+ RES_SRQ,
+ RES_MPT,
+ RES_MTT
+};
+
+enum mlx4_alloc_mode {
+ ICM_RESERVE_AND_ALLOC,
+ ICM_RESERVE,
+ ICM_ALLOC,
+ ICM_MAC_VLAN,
+};
+
enum {
MLX4_MFUNC_MAX_EQES = 8,
MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
@@ -420,6 +435,18 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev);
void mlx4_cleanup_srq_table(struct mlx4_dev *dev);
void mlx4_cleanup_mcg_table(struct mlx4_dev *dev);
+int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn);
+void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn);
+int mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn);
+void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn);
+int mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn);
+void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn);
+int mlx4_mr_reserve(struct mlx4_dev *dev);
+void mlx4_mr_release(struct mlx4_dev *dev, u32 index);
+int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index);
+void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index);
+u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order);
+void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order);
int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox);
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 9e4ab0f..0db7f88 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -178,10 +178,26 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
kfree(buddy->num_free);
}
-static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
+u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
{
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
+ u64 in_param;
+ u64 out_param;
u32 seg;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = order;
+ *(((u32 *) &in_param) + 1) = 0;
+ err = mlx4_cmd_imm(dev, in_param, &out_param, RES_MTT,
+ ICM_RESERVE_AND_ALLOC,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ return -1;
+ else
+ return out_param;
+ }
seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, order);
if (seg == -1)
@@ -219,16 +235,33 @@ int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift,
}
EXPORT_SYMBOL_GPL(mlx4_mtt_init);
-void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt)
+void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order)
{
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = first_seg;
+ *(((u32 *) &in_param) + 1) = order;
+ err = mlx4_cmd(dev, in_param, RES_MTT, ICM_RESERVE_AND_ALLOC,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ mlx4_warn(dev, "Failed to free mtt range at:%d order:%d\n", first_seg, order);
+ } else {
+ mlx4_buddy_free(&mr_table->mtt_buddy, first_seg, order);
+ mlx4_table_put_range(dev, &mr_table->mtt_table, first_seg,
+ first_seg + (1 << order) - 1);
+ }
+}
+void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt)
+{
if (mtt->order < 0)
return;
- mlx4_buddy_free(&mr_table->mtt_buddy, mtt->first_seg, mtt->order);
- mlx4_table_put_range(dev, &mr_table->mtt_table, mtt->first_seg,
- mtt->first_seg + (1 << mtt->order) - 1);
+ mlx4_free_mtt_range(dev, mtt->first_seg, mtt->order);
}
EXPORT_SYMBOL_GPL(mlx4_mtt_cleanup);
@@ -291,14 +324,81 @@ static int mlx4_WRITE_MTT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
MLX4_CMD_TIME_CLASS_A);
}
+int mlx4_mr_reserve(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ u64 out_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ err = mlx4_cmd_imm(dev, 0, &out_param, RES_MPT, ICM_RESERVE,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ return -1;
+ return out_param;
+ }
+ return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap);
+}
+
+void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = index;
+ *(((u32 *) &in_param) + 1) = 0;
+ err = mlx4_cmd(dev, in_param, RES_MPT, ICM_RESERVE,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ mlx4_warn(dev, "Failed to release mr index:%d\n", index);
+ } else
+ mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index);
+}
+
+int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
+{
+ struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
+ u64 param;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) ¶m) = index;
+ *(((u32 *) ¶m) + 1) = 0;
+ return mlx4_cmd_imm(dev, param, ¶m, RES_MPT, ICM_ALLOC,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ } else
+ return mlx4_table_get(dev, &mr_table->dmpt_table, index);
+}
+
+void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
+{
+ struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = index;
+ *(((u32 *) &in_param) + 1) = 0;
+ err = mlx4_cmd(dev, in_param, RES_MPT, ICM_ALLOC,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ mlx4_warn(dev, "Failed to free icm of mr index:%d\n", index);
+ } else
+ mlx4_table_put(dev, &mr_table->dmpt_table, index);
+}
+
int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
int npages, int page_shift, struct mlx4_mr *mr)
{
- struct mlx4_priv *priv = mlx4_priv(dev);
u32 index;
int err;
- index = mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap);
+ index = mlx4_mr_reserve(dev);
if (index == -1)
return -ENOMEM;
@@ -311,7 +411,7 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
if (err)
- mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index);
+ mlx4_mr_release(dev, index);
return err;
}
@@ -319,7 +419,6 @@ EXPORT_SYMBOL_GPL(mlx4_mr_alloc);
void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
{
- struct mlx4_priv *priv = mlx4_priv(dev);
int err;
if (mr->enabled) {
@@ -331,18 +430,18 @@ void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
}
mlx4_mtt_cleanup(dev, &mr->mtt);
- mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, key_to_hw_index(mr->key));
+ mlx4_mr_release(dev, key_to_hw_index(mr->key));
+ mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
}
EXPORT_SYMBOL_GPL(mlx4_mr_free);
int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
{
- struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mpt_entry *mpt_entry;
int err;
- err = mlx4_table_get(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key));
+ err = mlx4_mr_alloc_icm(dev, key_to_hw_index(mr->key));
if (err)
return err;
@@ -400,7 +499,7 @@ err_cmd:
mlx4_free_cmd_mailbox(dev, mailbox);
err_table:
- mlx4_table_put(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key));
+ mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
return err;
}
EXPORT_SYMBOL_GPL(mlx4_mr_enable);
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 42ab9fc..065c7fc 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -149,13 +149,24 @@ int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_qp_table *qp_table = &priv->qp_table;
- int qpn;
-
- qpn = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align);
- if (qpn == -1)
- return -ENOMEM;
+ u64 in_param;
+ u64 out_param;
+ int err;
- *base = qpn;
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = cnt;
+ *(((u32 *) &in_param) + 1) = align;
+ err = mlx4_cmd_imm(dev, in_param, &out_param, RES_QP, ICM_RESERVE,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ return err;
+ *base = out_param;
+ } else {
+ *base = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align);
+ if (*base == -1)
+ return -ENOMEM;
+ }
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
@@ -164,73 +175,133 @@ void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_qp_table *qp_table = &priv->qp_table;
- if (base_qpn < dev->caps.sqp_start + 8)
- return;
+ u64 in_param;
+ int err;
- mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = base_qpn;
+ *(((u32 *) &in_param) + 1) = cnt;
+ err = mlx4_cmd(dev, in_param, RES_QP, ICM_RESERVE,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err) {
+ mlx4_warn(dev, "Failed to release qp range base:%d cnt:%d\n",
+ base_qpn, cnt);
+ }
+ } else {
+ if (base_qpn < dev->caps.sqp_start + 8)
+ return;
+ mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
+ }
}
EXPORT_SYMBOL_GPL(mlx4_qp_release_range);
-int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
+int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_qp_table *qp_table = &priv->qp_table;
+ u64 param;
int err;
- if (!qpn)
- return -EINVAL;
-
- qp->qpn = qpn;
-
- err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn);
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) ¶m) = qpn;
+ *(((u32 *) ¶m) + 1) = 0;
+ return mlx4_cmd_imm(dev, param, ¶m, RES_QP, ICM_ALLOC,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ }
+ err = mlx4_table_get(dev, &qp_table->qp_table, qpn);
if (err)
goto err_out;
- err = mlx4_table_get(dev, &qp_table->auxc_table, qp->qpn);
+ err = mlx4_table_get(dev, &qp_table->auxc_table, qpn);
if (err)
goto err_put_qp;
- err = mlx4_table_get(dev, &qp_table->altc_table, qp->qpn);
+ err = mlx4_table_get(dev, &qp_table->altc_table, qpn);
if (err)
goto err_put_auxc;
- err = mlx4_table_get(dev, &qp_table->rdmarc_table, qp->qpn);
+ err = mlx4_table_get(dev, &qp_table->rdmarc_table, qpn);
if (err)
goto err_put_altc;
- err = mlx4_table_get(dev, &qp_table->cmpt_table, qp->qpn);
+ err = mlx4_table_get(dev, &qp_table->cmpt_table, qpn);
if (err)
goto err_put_rdmarc;
- spin_lock_irq(&qp_table->lock);
- err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1), qp);
- spin_unlock_irq(&qp_table->lock);
- if (err)
- goto err_put_cmpt;
-
- atomic_set(&qp->refcount, 1);
- init_completion(&qp->free);
-
return 0;
-err_put_cmpt:
- mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn);
-
err_put_rdmarc:
- mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn);
+ mlx4_table_put(dev, &qp_table->rdmarc_table, qpn);
err_put_altc:
- mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
+ mlx4_table_put(dev, &qp_table->altc_table, qpn);
err_put_auxc:
- mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
+ mlx4_table_put(dev, &qp_table->auxc_table, qpn);
err_put_qp:
- mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
+ mlx4_table_put(dev, &qp_table->qp_table, qpn);
err_out:
return err;
}
+
+void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_qp_table *qp_table = &priv->qp_table;
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = qpn;
+ *(((u32 *) &in_param) + 1) = 0;
+ err = mlx4_cmd(dev, in_param, RES_QP, ICM_ALLOC,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ mlx4_warn(dev, "Failed to free icm of qp:%d\n", qpn);
+ } else {
+ mlx4_table_put(dev, &qp_table->cmpt_table, qpn);
+ mlx4_table_put(dev, &qp_table->rdmarc_table, qpn);
+ mlx4_table_put(dev, &qp_table->altc_table, qpn);
+ mlx4_table_put(dev, &qp_table->auxc_table, qpn);
+ mlx4_table_put(dev, &qp_table->qp_table, qpn);
+ }
+}
+
+int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_qp_table *qp_table = &priv->qp_table;
+ int err;
+
+ if (!qpn)
+ return -EINVAL;
+
+ qp->qpn = qpn;
+
+ err = mlx4_qp_alloc_icm(dev, qpn);
+ if (err)
+ return err;
+
+ spin_lock_irq(&qp_table->lock);
+ err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1), qp);
+ spin_unlock_irq(&qp_table->lock);
+ if (err)
+ goto err_icm;
+
+ atomic_set(&qp->refcount, 1);
+ init_completion(&qp->free);
+
+ return 0;
+
+err_icm:
+ mlx4_qp_free_icm(dev, qpn);
+ return err;
+}
EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp)
@@ -246,17 +317,11 @@ EXPORT_SYMBOL_GPL(mlx4_qp_remove);
void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
{
- struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
-
if (atomic_dec_and_test(&qp->refcount))
complete(&qp->free);
wait_for_completion(&qp->free);
- mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn);
- mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn);
- mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
- mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
- mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
+ mlx4_qp_free_icm(dev, qp->qpn);
}
EXPORT_SYMBOL_GPL(mlx4_qp_free);
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c
index 1377d0d..ed11f18 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/mlx4/srq.c
@@ -108,32 +108,86 @@ static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
MLX4_CMD_TIME_CLASS_A);
}
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
- u64 db_rec, struct mlx4_srq *srq)
+int mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn)
{
struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_srq_context *srq_context;
- u64 mtt_addr;
+ u64 out_param;
int err;
- srq->srqn = mlx4_bitmap_alloc(&srq_table->bitmap);
- if (srq->srqn == -1)
+ if (mlx4_is_slave(dev)) {
+ err = mlx4_cmd_imm(dev, 0, &out_param, RES_SRQ,
+ ICM_RESERVE_AND_ALLOC,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err) {
+ *srqn = -1;
+ return err;
+ } else {
+ *srqn = out_param;
+ return 0;
+ }
+ }
+
+ *srqn = mlx4_bitmap_alloc(&srq_table->bitmap);
+ if (*srqn == -1)
return -ENOMEM;
- err = mlx4_table_get(dev, &srq_table->table, srq->srqn);
+ err = mlx4_table_get(dev, &srq_table->table, *srqn);
if (err)
goto err_out;
- err = mlx4_table_get(dev, &srq_table->cmpt_table, srq->srqn);
+ err = mlx4_table_get(dev, &srq_table->cmpt_table, *srqn);
if (err)
goto err_put;
+ return 0;
+
+err_put:
+ mlx4_table_put(dev, &srq_table->table, *srqn);
+
+err_out:
+ mlx4_bitmap_free(&srq_table->bitmap, *srqn);
+ return err;
+}
+
+void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
+{
+ struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ *((u32 *) &in_param) = srqn;
+ *(((u32 *) &in_param) + 1) = 0;
+ err = mlx4_cmd(dev, in_param, RES_SRQ, ICM_RESERVE_AND_ALLOC,
+ MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ mlx4_warn(dev, "Failed freeing cq:%d\n", srqn);
+ } else {
+ mlx4_table_put(dev, &srq_table->cmpt_table, srqn);
+ mlx4_table_put(dev, &srq_table->table, srqn);
+ mlx4_bitmap_free(&srq_table->bitmap, srqn);
+ }
+}
+
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
+ u64 db_rec, struct mlx4_srq *srq)
+{
+ struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_srq_context *srq_context;
+ u64 mtt_addr;
+ int err;
+
+ err = mlx4_srq_alloc_icm(dev, &srq->srqn);
+ if (err)
+ return err;
spin_lock_irq(&srq_table->lock);
err = radix_tree_insert(&srq_table->tree, srq->srqn, srq);
spin_unlock_irq(&srq_table->lock);
if (err)
- goto err_cmpt_put;
+ goto err_icm;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) {
@@ -170,15 +224,8 @@ err_radix:
radix_tree_delete(&srq_table->tree, srq->srqn);
spin_unlock_irq(&srq_table->lock);
-err_cmpt_put:
- mlx4_table_put(dev, &srq_table->cmpt_table, srq->srqn);
-
-err_put:
- mlx4_table_put(dev, &srq_table->table, srq->srqn);
-
-err_out:
- mlx4_bitmap_free(&srq_table->bitmap, srq->srqn);
-
+err_icm:
+ mlx4_srq_free_icm(dev, srq->srqn);
return err;
}
EXPORT_SYMBOL_GPL(mlx4_srq_alloc);
@@ -200,8 +247,7 @@ void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
complete(&srq->free);
wait_for_completion(&srq->free);
- mlx4_table_put(dev, &srq_table->table, srq->srqn);
- mlx4_bitmap_free(&srq_table->bitmap, srq->srqn);
+ mlx4_srq_free_icm(dev, srq->srqn);
}
EXPORT_SYMBOL_GPL(mlx4_srq_free);
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index b567e63..5450781 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -125,6 +125,8 @@ enum {
MLX4_CMD_DUMP_ETH_STATS = 0x49,
/* virtual commands */
+ MLX4_CMD_ALLOC_RES = 0xf00,
+ MLX4_CMD_FREE_RES = 0xf01,
MLX4_CMD_GET_EVENT = 0xf03,
/* debug commands */
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 05/23 v3] mlx4_core: slave multicast support
[not found] <49BFC313.1030901@mellanox.co.il>
` (4 preceding siblings ...)
2010-02-04 15:54 ` [PATCH 04/23 v3] mlx4_core: add slave resource allocation Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 06/23 v3] mlx4_core: add port para-virtualization Yevgeny Petrilin
` (17 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Multicast table processing requires multiple related commands.
To keep things simple, low-level multicast handling is done only by the master;
a new virtual command is added to allow slaves to attach/detach QPs to mulitcast
groups at a higher abstraction level.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 8 ++++++++
drivers/net/mlx4/mcg.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
drivers/net/mlx4/mlx4.h | 4 ++++
include/linux/mlx4/cmd.h | 1 +
4 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 533ce77..5433f3b 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -824,6 +824,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/mcg.c b/drivers/net/mlx4/mcg.c
index 5ccbce9..96f09ed 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -146,6 +146,45 @@ static int find_mgm(struct mlx4_dev *dev,
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 */
+
+ qp.qpn = vhcr->in_modifier & 0xffffff;
+ if (vhcr->op_modifier)
+ return mlx4_multicast_attach(dev, &qp, inbox->buf, vhcr->in_modifier >> 31);
+ else
+ return mlx4_multicast_detach(dev, &qp, inbox->buf);
+}
+
+static int mlx4_MCAST(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ u8 gid[16], u8 attach,
+ u8 block_loopback)
+{
+ 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;
+ 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)
{
@@ -159,6 +198,9 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int i;
int err;
+ if (mlx4_is_slave(dev))
+ return mlx4_MCAST(dev, qp, gid, 1, block_mcast_loopback);
+
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -254,6 +296,9 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
int i, loc;
int err;
+ if (mlx4_is_slave(dev))
+ return mlx4_MCAST(dev, qp, gid, 0, 0);
+
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index d62427f..a7dcad6 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -505,4 +505,8 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
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/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 5450781..27327f7 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -128,6 +128,7 @@ enum {
MLX4_CMD_ALLOC_RES = 0xf00,
MLX4_CMD_FREE_RES = 0xf01,
MLX4_CMD_GET_EVENT = 0xf03,
+ MLX4_CMD_MCAST_ATTACH = 0xf05,
/* debug commands */
MLX4_CMD_QUERY_DEBUG_MSG = 0x2a,
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 06/23 v3] mlx4_core: add port para-virtualization
[not found] <49BFC313.1030901@mellanox.co.il>
` (5 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 05/23 v3] mlx4_core: slave multicast support Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 07/23 v3] mlx4_core: dispatch slave asynch events Yevgeny Petrilin
` (16 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Ports are a shared resource among functions, so special behavior is needed here:
- Bring up ports if at least one function has done so.
- Bring down ports if all functions have done so.
- Aggregate IB port capabilities
- Set max mtu among for Eth port
- Ensure steering is not broken for Eth ports.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 58 +++++++++++
drivers/net/mlx4/en_netdev.c | 32 +++---
drivers/net/mlx4/en_port.c | 1 +
drivers/net/mlx4/en_port.h | 9 +-
drivers/net/mlx4/en_rx.c | 11 +--
drivers/net/mlx4/fw.c | 79 ++++++++++++++-
drivers/net/mlx4/main.c | 22 +++--
drivers/net/mlx4/mlx4.h | 25 +++++-
drivers/net/mlx4/port.c | 220 +++++++++++++++++++++++++++++++++++++----
include/linux/mlx4/cmd.h | 2 +
include/linux/mlx4/device.h | 5 +-
11 files changed, 397 insertions(+), 67 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 5433f3b..c1f2905 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -505,6 +505,24 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
} else
mlx4_free_mtt_range(dev, param1 /* first */, param2 /* order */);
break;
+ case RES_MAC:
+ switch (vhcr->op) {
+ case MLX4_CMD_ALLOC_RES:
+ ret = mlx4_register_mac(dev, vhcr->op_modifier,
+ vhcr->in_param, (int *) &vhcr->out_param);
+ vhcr->errno = ret;
+ break;
+ case MLX4_CMD_FREE_RES:
+ mlx4_unregister_mac(dev, vhcr->op_modifier, vhcr->in_param);
+ break;
+ case MLX4_CMD_REPLACE_RES:
+ ret = mlx4_replace_mac(dev, vhcr->op_modifier,
+ vhcr->out_param, vhcr->in_param);
+ vhcr->errno = ret;
+ break;
+ default:
+ vhcr->errno = -EINVAL;
+ }
default:
vhcr->errno = -EINVAL;
}
@@ -540,6 +558,38 @@ static struct mlx4_cmd_info {
},
{
+ .opcode = MLX4_CMD_INIT_PORT,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_INIT_PORT_wrapper},
+ {
+ .opcode = MLX4_CMD_CLOSE_PORT,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_CLOSE_PORT_wrapper
+ },
+ {
+ .opcode = MLX4_CMD_QUERY_PORT,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_QUERY_PORT_wrapper
+ },
+ {
+ .opcode = MLX4_CMD_SET_PORT,
+ .has_inbox = true,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_SET_PORT_wrapper
+ },
+
+ {
.opcode = MLX4_CMD_SW2HW_EQ,
.has_inbox = true,
.has_outbox = false,
@@ -573,6 +623,14 @@ static struct mlx4_cmd_info {
},
{
+ .opcode = MLX4_CMD_REPLACE_RES,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = true,
+ .verify = NULL,
+ .wrapper = mlx4_RESOURCE_wrapper
+ },
+ {
.opcode = MLX4_CMD_SW2HW_MPT,
.has_inbox = true,
.has_outbox = false,
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index c48b0f4..fd96078 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -145,9 +145,8 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
mutex_lock(&mdev->state_lock);
if (priv->port_up) {
/* Remove old MAC and insert the new one */
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
- err = mlx4_register_mac(mdev->dev, priv->port,
- priv->mac, &priv->mac_index);
+ err = mlx4_replace_mac(mdev->dev, priv->port,
+ priv->base_qpn, priv->mac);
if (err)
en_err(priv, "Failed changing HW MAC address\n");
} else
@@ -596,10 +595,19 @@ int mlx4_en_start_port(struct net_device *dev)
++rx_index;
}
+ /* Set port mac number */
+ en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
+ err = mlx4_register_mac(mdev->dev, priv->port,
+ priv->mac, &priv->base_qpn);
+ if (err) {
+ en_err(priv, "Failed setting port mac\n");
+ goto cq_err;
+ }
+
err = mlx4_en_config_rss_steer(priv);
if (err) {
en_err(priv, "Failed configuring rss steering\n");
- goto cq_err;
+ goto mac_err;
}
/* Configure tx cq's and rings */
@@ -652,21 +660,13 @@ int mlx4_en_start_port(struct net_device *dev)
en_err(priv, "Failed setting default qp numbers\n");
goto tx_err;
}
- /* Set port mac number */
- en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
- err = mlx4_register_mac(mdev->dev, priv->port,
- priv->mac, &priv->mac_index);
- if (err) {
- en_err(priv, "Failed setting port mac\n");
- goto tx_err;
- }
/* Init port */
en_dbg(HW, priv, "Initializing port\n");
err = mlx4_INIT_PORT(mdev->dev, priv->port);
if (err) {
en_err(priv, "Failed Initializing port\n");
- goto mac_err;
+ goto tx_err;
}
/* Schedule multicast task to populate multicast list */
@@ -676,8 +676,6 @@ int mlx4_en_start_port(struct net_device *dev)
netif_tx_start_all_queues(dev);
return 0;
-mac_err:
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
tx_err:
while (tx_index--) {
mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
@@ -685,6 +683,8 @@ tx_err:
}
mlx4_en_release_rss_steer(priv);
+mac_err:
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
cq_err:
while (rx_index--)
mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
@@ -716,7 +716,7 @@ void mlx4_en_stop_port(struct net_device *dev)
mlx4_CLOSE_PORT(mdev->dev, priv->port);
/* Unregister Mac address for the port */
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
/* Free TX Rings */
for (i = 0; i < priv->tx_ring_num; i++) {
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index a29abe8..c099cb4 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -127,6 +127,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
memset(context, 0, sizeof *context);
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->intra_no_vlan = 0;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index 3892896..fc49733 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -54,14 +54,17 @@ struct mlx4_set_port_general_context {
struct mlx4_set_port_rqp_calc_context {
__be32 base_qpn;
- __be32 flags;
- u8 reserved[3];
+ u8 rererved;
+ u8 n_mac;
+ u8 n_vlan;
+ u8 n_prio;
+ u8 reserved2[3];
u8 mac_miss;
u8 intra_no_vlan;
u8 no_vlan;
u8 intra_vlan_miss;
u8 vlan_miss;
- u8 reserved2[3];
+ u8 reserved3[3];
u8 no_vlan_prio;
__be32 promisc;
__be32 mcast;
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 829b9ec..cd0dc14 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -865,16 +865,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
}
/* Configure RSS indirection qp */
- err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
- if (err) {
- en_err(priv, "Failed to reserve range for RSS "
- "indirection qp\n");
- goto rss_err;
- }
err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
if (err) {
en_err(priv, "Failed to allocate RSS indirection QP\n");
- goto reserve_err;
+ goto rss_err;
}
rss_map->indir_qp.event = mlx4_en_sqp_event;
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
@@ -900,8 +894,6 @@ indir_err:
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
-reserve_err:
- mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
rss_err:
for (i = 0; i < good_qps; i++) {
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -923,7 +915,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
- mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
for (i = 0; i < priv->rx_ring_num; i++) {
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index eccac2a..09596c6 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -136,6 +136,14 @@ int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
return err;
}
+int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ return mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, MLX4_CMD_QUERY_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+}
+
int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
struct mlx4_cmd_mailbox *mailbox;
@@ -810,6 +818,35 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
return err;
}
+static int mlx4_common_init_port(struct mlx4_dev *dev, int function, int port)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int err;
+
+ if (priv->mfunc.master.slave_state[function].init_port_mask & (1 << port))
+ return 0;
+
+ /* Enable port only if it was previously disabled */
+ if (!priv->mfunc.master.init_port_ref[port]) {
+ err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
+ MLX4_CMD_TIME_CLASS_A);
+ if (err)
+ return err;
+ }
+ ++priv->mfunc.master.init_port_ref[port];
+ priv->mfunc.master.slave_state[function].init_port_mask |= (1 << port);
+ return 0;
+}
+
+int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ int port = vhcr->in_modifier;
+
+ return mlx4_common_init_port(dev, slave, port);
+}
+
int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
{
struct mlx4_cmd_mailbox *mailbox;
@@ -856,17 +893,51 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
MLX4_CMD_TIME_CLASS_A);
mlx4_free_cmd_mailbox(dev, mailbox);
- } else
- err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
- MLX4_CMD_TIME_CLASS_A);
+ } else {
+ if (mlx4_is_master(dev))
+ err = mlx4_common_init_port(dev, 0, port);
+ else
+ err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
+ MLX4_CMD_TIME_CLASS_A);
+ }
return err;
}
EXPORT_SYMBOL_GPL(mlx4_INIT_PORT);
+static int mlx4_common_close_port(struct mlx4_dev *dev, int function, int port)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int err;
+
+ if (!(priv->mfunc.master.slave_state[function].init_port_mask & (1 << port)))
+ return 0;
+
+ if (priv->mfunc.master.init_port_ref[port] == 1) {
+ err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000);
+ if (err)
+ return err;
+ }
+ --priv->mfunc.master.init_port_ref[port];
+ priv->mfunc.master.slave_state[function].init_port_mask &= ~(1 << port);
+ return 0;
+}
+
+int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ int port = vhcr->in_modifier;
+
+ return mlx4_common_close_port(dev, slave, port);
+}
+
int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port)
{
- return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000);
+ if (mlx4_is_master(dev))
+ return mlx4_common_close_port(dev, 0, port);
+ else
+ return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000);
}
EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 3cf56d9..bb41450 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -87,7 +87,7 @@ static struct mlx4_profile default_profile = {
.num_mtt = 1 << 20,
};
-static int log_num_mac = 2;
+static int log_num_mac = 7;
module_param_named(log_num_mac, log_num_mac, int, 0444);
MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
@@ -436,6 +436,7 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
{
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
+ int num_eqs;
err = mlx4_init_icm_table(dev, &priv->qp_table.cmpt_table,
cmpt_base +
@@ -465,12 +466,12 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
if (err)
goto err_srq;
+ num_eqs = mlx4_is_master(dev) ? 512 : dev->caps.num_eqs;
err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table,
cmpt_base +
((u64) (MLX4_CMPT_TYPE_EQ *
cmpt_entry_sz) << MLX4_CMPT_SHIFT),
- cmpt_entry_sz,
- dev->caps.num_eqs, dev->caps.num_eqs, 0, 0);
+ cmpt_entry_sz, num_eqs, num_eqs, 0, 0);
if (err)
goto err_cq;
@@ -494,6 +495,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
{
struct mlx4_priv *priv = mlx4_priv(dev);
u64 aux_pages;
+ int num_eqs;
int err;
err = mlx4_SET_ICM_SIZE(dev, icm_size, &aux_pages);
@@ -525,10 +527,11 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
goto err_unmap_aux;
}
+
+ num_eqs = mlx4_is_master(dev) ? 512 : dev->caps.num_eqs;
err = mlx4_init_icm_table(dev, &priv->eq_table.table,
init_hca->eqc_base, dev_cap->eqc_entry_sz,
- dev->caps.num_eqs, dev->caps.num_eqs,
- 0, 0);
+ num_eqs, num_eqs, 0, 0);
if (err) {
mlx4_err(dev, "Failed to map EQ context memory, aborting.\n");
goto err_unmap_cmpt;
@@ -1015,9 +1018,12 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
info->dev = dev;
info->port = port;
- mlx4_init_mac_table(dev, &info->mac_table);
- mlx4_init_vlan_table(dev, &info->vlan_table);
-
+ if (!mlx4_is_slave(dev)) {
+ mlx4_init_mac_table(dev, &info->mac_table);
+ mlx4_init_vlan_table(dev, &info->vlan_table);
+ info->base_qpn = dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] +
+ (port - 1) * (1 << log_num_mac);
+ }
sprintf(info->dev_name, "mlx4_port%d", port);
info->port_attr.attr.name = info->dev_name;
info->port_attr.attr.mode = S_IRUGO | S_IWUSR;
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index a7dcad6..cffa31c 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -46,6 +46,7 @@
#include <linux/mlx4/driver.h>
#include <linux/mlx4/doorbell.h>
#include <linux/mlx4/cmd.h>
+#include <rdma/ib_verbs.h>
#define DRV_NAME "mlx4_core"
#define PFX DRV_NAME ": "
@@ -99,7 +100,10 @@ enum mlx4_resource {
RES_CQ,
RES_SRQ,
RES_MPT,
- RES_MTT
+ RES_MTT,
+ RES_MAC,
+ RES_VLAN,
+ RES_MCAST
};
enum mlx4_alloc_mode {
@@ -212,11 +216,16 @@ struct mlx4_slave_eqe {
struct mlx4_slave_state {
u8 comm_toggle;
u8 last_cmd;
+ u8 init_port_mask;
dma_addr_t vhcr_dma;
+ u16 mtu[MLX4_MAX_PORTS + 1];
+ __be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
};
struct mlx4_mfunc_master_ctx {
struct mlx4_slave_state *slave_state;
+ int init_port_ref[MLX4_MAX_PORTS + 1];
+ u16 max_mtu[MLX4_MAX_PORTS + 1];
};
struct mlx4_vhcr {
@@ -327,7 +336,6 @@ struct mlx4_catas_err {
struct mlx4_mac_table {
__be64 entries[MLX4_MAX_MAC_NUM];
- int refs[MLX4_MAX_MAC_NUM];
struct mutex mutex;
int total;
int max;
@@ -352,6 +360,7 @@ struct mlx4_port_info {
enum mlx4_port_type tmp_type;
struct mlx4_mac_table mac_table;
struct mlx4_vlan_table vlan_table;
+ int base_qpn;
};
struct mlx4_sense {
@@ -503,6 +512,18 @@ 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);
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
+int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ 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,
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 606aa58..dcbfd72 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -36,6 +36,7 @@
#include <linux/mlx4/cmd.h>
#include "mlx4.h"
+#include "en_port.h"
#define MLX4_MAC_VALID (1ull << 63)
#define MLX4_MAC_MASK 0xffffffffffffULL
@@ -48,10 +49,8 @@ void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
int i;
mutex_init(&table->mutex);
- for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
+ for (i = 0; i < MLX4_MAX_MAC_NUM; i++)
table->entries[i] = 0;
- table->refs[i] = 0;
- }
table->max = 1 << dev->caps.log_num_macs;
table->total = 0;
}
@@ -90,24 +89,33 @@ static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
return err;
}
-int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
+int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
{
- struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
+ struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+ struct mlx4_mac_table *table = &info->mac_table;
+ u64 out_param;
int i, err = 0;
int free = -1;
+ if (mlx4_is_slave(dev)) {
+ err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, port,
+ MLX4_CMD_ALLOC_RES, MLX4_CMD_TIME_CLASS_A);
+ if (!err)
+ *qpn = out_param;
+ 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 - 1; i++) {
- if (free < 0 && !table->refs[i]) {
+ if (free < 0 && !table->entries[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];
+ /* MAC already registered, Must not have duplicates */
+ err = -EEXIST;
goto out;
}
}
@@ -120,18 +128,16 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
}
/* 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;
+ *qpn = info->base_qpn + free;
++table->total;
out:
mutex_unlock(&table->mutex);
@@ -139,20 +145,35 @@ out:
}
EXPORT_SYMBOL_GPL(mlx4_register_mac);
-void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index)
+static int validate_index(struct mlx4_dev *dev,
+ struct mlx4_mac_table *table, int index)
{
- struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
+ int err = 0;
- mutex_lock(&table->mutex);
- if (!table->refs[index]) {
- mlx4_warn(dev, "No MAC entry for index %d\n", index);
- goto out;
+ if (index < 0 || index >= table->max || !table->entries[index]) {
+ mlx4_warn(dev, "No valid Mac entry for the given index\n");
+ err = -EINVAL;
}
- if (--table->refs[index]) {
- mlx4_warn(dev, "Have more references for index %d,"
- "no need to modify MAC table\n", index);
- goto out;
+ return err;
+}
+
+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;
+
+ if (mlx4_is_slave(dev)) {
+ mlx4_cmd(dev, qpn, RES_MAC, port,
+ MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A);
+ return;
}
+
+ 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;
@@ -161,6 +182,38 @@ out:
}
EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
+int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
+{
+ struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+ struct mlx4_mac_table *table = &info->mac_table;
+ int index = qpn - info->base_qpn;
+ int err;
+
+ if (mlx4_is_slave(dev)) {
+ err = mlx4_cmd_imm(dev, new_mac, (u64 *) &qpn, RES_MAC, port,
+ MLX4_CMD_REPLACE_RES, MLX4_CMD_TIME_CLASS_A);
+ 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;
+}
+EXPORT_SYMBOL_GPL(mlx4_replace_mac);
+
static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
__be32 *entries)
{
@@ -294,6 +347,129 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
return err;
}
+int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_port_info *port_info;
+ struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master;
+ struct mlx4_slave_state *slave_st = &master->slave_state[slave];
+ struct mlx4_set_port_rqp_calc_context *qpn_context;
+ struct mlx4_set_port_general_context *gen_context;
+ int reset_qkey_viols;
+ int port;
+ int is_eth;
+ u32 in_modifier;
+ u32 promisc;
+ u16 mtu, prev_mtu;
+ int err;
+ int i;
+ __be32 agg_cap_mask;
+ __be32 slave_cap_mask;
+ __be32 new_cap_mask;
+
+ port = vhcr->in_modifier & 0xff;
+ in_modifier = vhcr->in_modifier >> 8;
+ is_eth = vhcr->op_modifier;
+ port_info = &priv->port[port];
+
+ /* All slaves can perform SET_PORT operations, just need to verify
+ * we keep the mutual resources unchanged */
+ if (is_eth) {
+ switch (in_modifier) {
+ case MLX4_SET_PORT_RQP_CALC:
+ qpn_context = inbox->buf;
+ qpn_context->base_qpn = cpu_to_be32(port_info->base_qpn);
+ qpn_context->n_mac = 0x7;
+ promisc = be32_to_cpu(qpn_context->promisc) >>
+ SET_PORT_PROMISC_SHIFT;
+ qpn_context->promisc = cpu_to_be32(
+ promisc << SET_PORT_PROMISC_SHIFT |
+ port_info->base_qpn);
+ promisc = be32_to_cpu(qpn_context->mcast) >>
+ SET_PORT_PROMISC_SHIFT;
+ qpn_context->mcast = cpu_to_be32(
+ promisc << SET_PORT_PROMISC_SHIFT |
+ port_info->base_qpn);
+ break;
+ case MLX4_SET_PORT_GENERAL:
+ gen_context = inbox->buf;
+ /* Mtu is configured as the max MTU among all the
+ * the functions on the port. */
+ mtu = be16_to_cpu(gen_context->mtu);
+ mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]);
+ prev_mtu = slave_st->mtu[port];
+ slave_st->mtu[port] = mtu;
+ if (mtu > master->max_mtu[port])
+ master->max_mtu[port] = mtu;
+ if (mtu < prev_mtu && prev_mtu == master->max_mtu[port]) {
+ slave_st->mtu[port] = mtu;
+ master->max_mtu[port] = mtu;
+ for (i = 0; i < dev->num_slaves; i++) {
+ master->max_mtu[port] =
+ max(master->max_mtu[port],
+ master->slave_state[i].mtu[port]);
+ }
+ }
+
+ gen_context->mtu = cpu_to_be16(master->max_mtu[port]);
+ break;
+ }
+ return mlx4_cmd(dev, inbox->dma, vhcr->in_modifier,
+ vhcr->op_modifier,
+ MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+ }
+
+ /* For IB, we only consider:
+ * - The capability mask, which is set to the aggregate of all slave frunction
+ * capabilities
+ * - The QKey violatin counter - reset according to each request.
+ */
+
+ if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+ reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40;
+ new_cap_mask = ((__be32 *) inbox->buf)[2];
+ } else {
+ reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1;
+ new_cap_mask = ((__be32 *) inbox->buf)[1];
+ }
+
+ /* only master has access to qp0 */
+ if (new_cap_mask & cpu_to_be32(IB_PORT_SM)) {
+ mlx4_warn(dev, "denying sm port capability for slave:%d\n", slave);
+ return -EINVAL;
+ }
+
+ agg_cap_mask = 0;
+ slave_cap_mask = priv->mfunc.master.slave_state[slave].ib_cap_mask[port];
+ priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask;
+ for (i = 0; i < dev->num_slaves; i++)
+ agg_cap_mask |= priv->mfunc.master.slave_state[slave].ib_cap_mask[port];
+
+#if 0
+ mlx4_warn(dev, "old_slave_cap:0x%x slave_cap:0x%x cap:0x%x qkey_reset:%d\n",
+ slave_cap_mask, priv->mfunc.master.slave_state[slave].ib_cap_mask[port],
+ agg_cap_mask, reset_qkey_viols);
+#endif
+
+ memset(inbox->buf, 0, 256);
+ if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+ *(u8 *) inbox->buf = !!reset_qkey_viols << 6;
+ ((__be32 *) inbox->buf)[2] = agg_cap_mask;
+ } else {
+ ((u8 *) inbox->buf)[3] = !!reset_qkey_viols;
+ ((__be32 *) inbox->buf)[1] = agg_cap_mask;
+ }
+
+ err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = slave_cap_mask;
+ return err;
+}
+
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
{
struct mlx4_cmd_mailbox *mailbox;
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 27327f7..26390ab 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -127,6 +127,7 @@ enum {
/* virtual commands */
MLX4_CMD_ALLOC_RES = 0xf00,
MLX4_CMD_FREE_RES = 0xf01,
+ MLX4_CMD_REPLACE_RES = 0xf02,
MLX4_CMD_GET_EVENT = 0xf03,
MLX4_CMD_MCAST_ATTACH = 0xf05,
@@ -153,6 +154,7 @@ enum {
MLX4_SET_PORT_MAC_TABLE = 0x2,
MLX4_SET_PORT_VLAN_TABLE = 0x3,
MLX4_SET_PORT_PRIO_MAP = 0x4,
+ MLX4_SET_PORT_MODIFIERS
};
struct mlx4_dev;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index f80b899..b557793 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -485,8 +485,9 @@ 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 mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
-void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
+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);
+int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
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);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 07/23 v3] mlx4_core: dispatch slave asynch events
[not found] <49BFC313.1030901@mellanox.co.il>
` (6 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 06/23 v3] mlx4_core: add port para-virtualization Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 08/23 v3] mlx4_core: track slave special qps Yevgeny Petrilin
` (15 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Affiliated and unaffiliated asynch events are handled by a single EQ owned by
the master. A per-slave SW event queue is added to log and dispatch both slave-specific
events and events that apply to all slaves.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 12 ++++++-
drivers/net/mlx4/eq.c | 92 +++++++++++++++++++++++++++++++++++++++++++---
drivers/net/mlx4/mlx4.h | 8 ++++
3 files changed, 105 insertions(+), 7 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index c1f2905..6a75528 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -621,6 +621,14 @@ static struct mlx4_cmd_info {
.verify = NULL,
.wrapper = mlx4_RESOURCE_wrapper
},
+ {
+ .opcode = MLX4_CMD_GET_EVENT,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = true,
+ .verify = NULL,
+ .wrapper = mlx4_GET_EVENT_wrapper
+ },
{
.opcode = MLX4_CMD_REPLACE_RES,
@@ -1175,8 +1183,10 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
if (!priv->mfunc.master.slave_state)
goto err_comm;
- for (i = 0; i < dev->num_slaves; ++i)
+ for (i = 0; i < dev->num_slaves; ++i) {
priv->mfunc.master.slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
+ spin_lock_init(&priv->mfunc.master.slave_state[i].lock);
+ }
INIT_DELAYED_WORK(&priv->mfunc.comm_work, mlx4_master_poll_comm);
priv->mfunc.comm_wq = create_singlethread_workqueue("mlx4_comm");
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 70c16d4..1e8b62d 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -160,6 +160,61 @@ static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq)
return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe;
}
+void mlx4_slave_event(struct mlx4_dev *dev, int slave, u8 type, u8 port, u32 param)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_slave_state *ctx = &priv->mfunc.master.slave_state[slave];
+ unsigned long flags;
+
+ if (ctx->last_cmd != MLX4_COMM_CMD_VHCR_POST) {
+ mlx4_warn(dev, "received event for inactive slave:%d\n", slave);
+ return;
+ }
+
+ /* Unconditionally add the new event - during overflows, we drop the
+ * oldest events */
+ spin_lock_irqsave(&ctx->lock, flags);
+ ctx->eq[ctx->eq_pi & MLX4_MFUNC_EQE_MASK].type = type;
+ ctx->eq[ctx->eq_pi & MLX4_MFUNC_EQE_MASK].port = port;
+ ctx->eq[ctx->eq_pi & MLX4_MFUNC_EQE_MASK].param = param;
+ ++ctx->eq_pi;
+ spin_unlock_irqrestore(&ctx->lock, flags);
+}
+
+static void mlx4_slave_event_all(struct mlx4_dev *dev, u8 type, u8 port, u32 param)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int i;
+
+ for (i = 0; i < dev->num_slaves; ++i)
+ if (priv->mfunc.master.slave_state[i].last_cmd == MLX4_COMM_CMD_VHCR_POST)
+ mlx4_slave_event(dev, i, type, port, param);
+}
+
+int mlx4_GET_EVENT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_slave_state *ctx = &priv->mfunc.master.slave_state[slave];
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctx->lock, flags);
+ if (ctx->eq_ci == ctx->eq_pi) {
+ vhcr->out_param = MLX4_EVENT_TYPE_NONE;
+ } else if ((u16) (ctx->eq_pi - ctx->eq_ci) > MLX4_MFUNC_MAX_EQES) {
+ ctx->eq_ci = ctx->eq_pi - MLX4_MFUNC_MAX_EQES;
+ vhcr->out_param = MLX4_EVENT_TYPE_EQ_OVERFLOW;
+ } else {
+ vhcr->out_param = ctx->eq[ctx->eq_ci & MLX4_MFUNC_EQE_MASK].type |
+ ((u64) ctx->eq[ctx->eq_ci & MLX4_MFUNC_EQE_MASK].port << 8) |
+ ((u64) ctx->eq[ctx->eq_ci & MLX4_MFUNC_EQE_MASK].param << 32);
+ ++ctx->eq_ci;
+ }
+ spin_unlock_irqrestore(&ctx->lock, flags);
+ return 0;
+}
+
static int mlx4_GET_EVENT(struct mlx4_dev *dev, struct mlx4_slave_eqe *eqe)
{
int ret;
@@ -205,14 +260,26 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
case MLX4_EVENT_TYPE_PATH_MIG_FAILED:
case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR:
- mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
- eqe->type);
+ if (mlx4_is_master(dev)) {
+ /* TODO: forward only to slave owning the QP */
+ mlx4_slave_event(dev, 0, eqe->type, 0,
+ be32_to_cpu(eqe->event.qp.qpn) &
+ 0xffffff);
+ } else
+ mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) &
+ 0xffffff, eqe->type);
break;
case MLX4_EVENT_TYPE_SRQ_LIMIT:
case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
- mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff,
- eqe->type);
+ if (mlx4_is_master(dev)) {
+ /* TODO: forward only to slave owning the SRQ */
+ mlx4_slave_event(dev, 0, eqe->type, 0,
+ be32_to_cpu(eqe->event.srq.srqn) &
+ 0xffffff);
+ } else
+ mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) &
+ 0xffffff, eqe->type);
break;
case MLX4_EVENT_TYPE_CMD:
@@ -227,10 +294,18 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) {
mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN,
port);
+ if (mlx4_is_master(dev)) {
+ mlx4_slave_event_all(dev, MLX4_EVENT_TYPE_PORT_CHANGE,
+ port, MLX4_DEV_EVENT_PORT_DOWN);
+ }
mlx4_priv(dev)->sense.do_sense_port[port] = 1;
} else {
mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP,
port);
+ if (mlx4_is_master(dev)) {
+ mlx4_slave_event_all(dev, MLX4_EVENT_TYPE_PORT_CHANGE,
+ port, MLX4_DEV_EVENT_PORT_UP);
+ }
mlx4_priv(dev)->sense.do_sense_port[port] = 0;
}
break;
@@ -240,8 +315,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
eqe->event.cq_err.syndrome == 1 ?
"overrun" : "access violation",
be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff);
- mlx4_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn),
- eqe->type);
+ if (mlx4_is_master(dev)) {
+ /* TODO: forward only to slave owning the CQ */
+ mlx4_slave_event(dev, 0, eqe->type, 0,
+ be32_to_cpu(eqe->event.cq_err.cqn));
+ } else
+ mlx4_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn),
+ eqe->type);
break;
case MLX4_EVENT_TYPE_EQ_OVERFLOW:
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index cffa31c..e7c0f42 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -220,6 +220,10 @@ struct mlx4_slave_state {
dma_addr_t vhcr_dma;
u16 mtu[MLX4_MAX_PORTS + 1];
__be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
+ struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
+ u16 eq_pi;
+ u16 eq_ci;
+ spinlock_t lock;
};
struct mlx4_mfunc_master_ctx {
@@ -425,6 +429,10 @@ int mlx4_reset(struct mlx4_dev *dev);
int mlx4_alloc_eq_table(struct mlx4_dev *dev);
void mlx4_free_eq_table(struct mlx4_dev *dev);
+void mlx4_slave_event(struct mlx4_dev *dev, int slave, u8 type, u8 port, u32 param);
+int mlx4_GET_EVENT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
int mlx4_init_pd_table(struct mlx4_dev *dev);
int mlx4_init_uar_table(struct mlx4_dev *dev);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 08/23 v3] mlx4_core: track slave special qps
[not found] <49BFC313.1030901@mellanox.co.il>
` (7 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 07/23 v3] mlx4_core: dispatch slave asynch events Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 09/23 v3] mlx4_core: per-function capabilities Yevgeny Petrilin
` (14 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
A single function can own the actual Infiniband hw special qps.
This function demuxes inbound mads and protects outbound mads from spoofing.
To achieve this, it needs to know the special qps used by other functions.
This patch tracks special qp registration and notifies the owning function
on any changes.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 16 +++++++++++++
drivers/net/mlx4/eq.c | 15 ++++++++++++
drivers/net/mlx4/mlx4.h | 11 +++++++++
drivers/net/mlx4/qp.c | 53 +++++++++++++++++++++++++++++++++++++++++++
include/linux/mlx4/cmd.h | 1 +
include/linux/mlx4/device.h | 3 ++
6 files changed, 99 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 6a75528..882b454 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -556,6 +556,14 @@ static struct mlx4_cmd_info {
.verify = NULL,
.wrapper = NULL
},
+ {
+ .opcode = MLX4_CMD_GET_SLAVE_SQP,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_GET_SLAVE_SQP_wrapper
+ },
{
.opcode = MLX4_CMD_INIT_PORT,
@@ -880,6 +888,14 @@ static struct mlx4_cmd_info {
.wrapper = NULL
},
{
+ .opcode = MLX4_CMD_CONF_SPECIAL_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_CONF_SPECIAL_QP_wrapper
+ },
+ {
.opcode = MLX4_CMD_MAD_IFC,
.has_inbox = true,
.has_outbox = true,
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 1e8b62d..a27e1c4 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -358,6 +358,17 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
return eqes_found;
}
+static void mlx4_update_sqp(struct mlx4_dev *dev)
+{
+ if (!dev->caps.sqp_demux) {
+ mlx4_warn(dev, "unexpected update_sqp event\n");
+ return;
+ }
+ if (mlx4_GET_SLAVE_SQP(dev, mlx4_priv(dev)->mfunc.demux_sqp,
+ dev->caps.sqp_demux))
+ mlx4_warn(dev, "couldn't update sqp\n");
+}
+
void mlx4_slave_async_eq_poll(struct work_struct *work)
{
struct delayed_work *delay = container_of(work, struct delayed_work, work);
@@ -402,6 +413,10 @@ void mlx4_slave_async_eq_poll(struct work_struct *work)
mlx4_warn(dev, "slave async EQ overrun\n");
break;
+ case MLX4_EVENT_TYPE_SQP_UPDATE:
+ mlx4_update_sqp(dev);
+ break;
+
default:
mlx4_warn(dev, "Unhandled event:%02x\n", eqe.type);
}
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index e7c0f42..800afe4 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -114,6 +114,7 @@ enum mlx4_alloc_mode {
};
enum {
+ MLX4_MFUNC_MAX = 64,
MLX4_MFUNC_MAX_EQES = 8,
MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
};
@@ -223,6 +224,7 @@ struct mlx4_slave_state {
struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
u16 eq_pi;
u16 eq_ci;
+ int sqp_start;
spinlock_t lock;
};
@@ -251,6 +253,7 @@ struct mlx4_mfunc {
dma_addr_t vhcr_dma;
struct mlx4_mfunc_master_ctx master;
+ u32 demux_sqp[MLX4_MFUNC_MAX];
};
struct mlx4_cmd {
@@ -534,6 +537,14 @@ 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_CONF_SPECIAL_QP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+int mlx4_GET_SLAVE_SQP(struct mlx4_dev *dev, u32 *sqp, int num);
+int mlx4_GET_SLAVE_SQP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+
int mlx4_MCAST_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox);
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 065c7fc..7ec59f0 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -145,6 +145,49 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
}
EXPORT_SYMBOL_GPL(mlx4_qp_modify);
+u32 mlx4_get_slave_sqp(struct mlx4_dev *dev, int slave)
+{
+ if (mlx4_is_master(dev) && slave < dev->num_slaves) {
+ return mlx4_priv(dev)->mfunc.master.slave_state[slave].sqp_start;
+ }
+ if (mlx4_is_slave(dev) && slave < dev->caps.sqp_demux) {
+ return mlx4_priv(dev)->mfunc.demux_sqp[slave];
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_slave_sqp);
+
+int mlx4_GET_SLAVE_SQP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ u32 *slave_sqp = outbox->buf;
+ int i;
+
+ for (i = 0; i < 64; i++)
+ slave_sqp[i] = mlx4_get_slave_sqp(dev, i);
+ return 0;
+}
+
+int mlx4_GET_SLAVE_SQP(struct mlx4_dev *dev, u32 *sqp, int num)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_GET_SLAVE_SQP,
+ MLX4_CMD_TIME_CLASS_A);
+ if (!err)
+ memcpy(sqp, mailbox->buf, sizeof (u32) * num);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_GET_SLAVE_SQP);
+
int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -331,6 +374,16 @@ static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn)
MLX4_CMD_TIME_CLASS_B);
}
+int mlx4_CONF_SPECIAL_QP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ priv->mfunc.master.slave_state[slave].sqp_start = vhcr->in_modifier & 0xffffff;
+ return 0;
+}
+
int mlx4_init_qp_table(struct mlx4_dev *dev)
{
struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 26390ab..9e6395f 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -130,6 +130,7 @@ enum {
MLX4_CMD_REPLACE_RES = 0xf02,
MLX4_CMD_GET_EVENT = 0xf03,
MLX4_CMD_MCAST_ATTACH = 0xf05,
+ MLX4_CMD_GET_SLAVE_SQP = 0xf06,
/* debug commands */
MLX4_CMD_QUERY_DEBUG_MSG = 0x2a,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index b557793..86e715c 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -100,6 +100,7 @@ enum mlx4_event {
MLX4_EVENT_TYPE_EQ_OVERFLOW = 0x0f,
MLX4_EVENT_TYPE_ECC_DETECT = 0x0e,
MLX4_EVENT_TYPE_CMD = 0x0a,
+ MLX4_EVENT_TYPE_SQP_UPDATE = 0xfe,
MLX4_EVENT_TYPE_NONE = 0xff,
};
@@ -243,6 +244,7 @@ struct mlx4_caps {
int log_num_prios;
enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1];
u8 supported_type[MLX4_MAX_PORTS + 1];
+ u8 sqp_demux;
u32 port_mask;
enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1];
};
@@ -471,6 +473,7 @@ void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp);
void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp);
+u32 mlx4_get_slave_sqp(struct mlx4_dev *dev, int vf);
int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
u64 db_rec, struct mlx4_srq *srq);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 09/23 v3] mlx4_core: per-function capabilities
[not found] <49BFC313.1030901@mellanox.co.il>
` (8 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 08/23 v3] mlx4_core: track slave special qps Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 10/23 v3] mlx4_core: associate resources with specific functions Yevgeny Petrilin
` (13 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
The master function builds a HW profile, and manages all resources.
Other functions query the master for function-specific capabilities.
EQs, MSI-X vectors, and UARs are statically divided among all functions,
while other resources are dynamically assigned later upon request.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 9 +++++
drivers/net/mlx4/fw.c | 42 +++++++++++++++++++++++++
drivers/net/mlx4/fw.h | 4 ++
drivers/net/mlx4/main.c | 70 ++++++++++++++++++++++++++++++++++++++++++-
drivers/net/mlx4/mlx4.h | 8 ++++-
drivers/net/mlx4/profile.c | 26 +++++++++++++--
include/linux/mlx4/cmd.h | 1 +
include/linux/mlx4/device.h | 3 ++
8 files changed, 157 insertions(+), 6 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 882b454..f9e8164 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -39,6 +39,7 @@
#include <asm/io.h>
#include "mlx4.h"
+#include "fw.h"
#define CMD_POLL_TOKEN 0xffff
@@ -549,6 +550,14 @@ static struct mlx4_cmd_info {
.wrapper = NULL
},
{
+ .opcode = MLX4_CMD_QUERY_SLAVE_CAP,
+ .has_inbox = false,
+ .has_outbox = true,
+ .out_is_imm = false,
+ .verify = NULL,
+ .wrapper = mlx4_QUERY_SLAVE_CAP_wrapper
+ },
+ {
.opcode = MLX4_CMD_QUERY_ADAPTER,
.has_inbox = false,
.has_outbox = true,
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 09596c6..2e60033 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -144,6 +144,48 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *v
MLX4_CMD_TIME_CLASS_B);
}
+int mlx4_QUERY_SLAVE_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ struct mlx4_caps *caps = outbox->buf;
+
+ memcpy(caps, &dev->caps, sizeof *caps);
+
+ /* The Master function is in charge for qp1 of al slaves */
+ caps->sqp_demux = 0;
+
+ /* PDs have the same range in every guest; the distinction is in the msbs,
+ * which contains the guest ID (vf + 1) */
+ caps->pd_base = slave + 1;
+
+ /* All other resources are allocated by the master, but we still report
+ * 'num' and 'reserved' capabilities as follows:
+ * - num remains the maximum resource index
+ * - 'num - reserved' is the total available objects of a resource, but
+ * resource indices may be less than 'reserved'
+ * TODO: set per-resource quotas */
+ return 0;
+}
+
+int mlx4_QUERY_SLAVE_CAP(struct mlx4_dev *dev, struct mlx4_caps *caps)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_SLAVE_CAP,
+ MLX4_CMD_TIME_CLASS_A);
+ if (!err)
+ memcpy(caps, mailbox->buf, sizeof *caps);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
struct mlx4_cmd_mailbox *mailbox;
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 526d7f3..d066c69 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -160,6 +160,10 @@ struct mlx4_set_ib_param {
};
int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap);
+int mlx4_QUERY_SLAVE_CAP(struct mlx4_dev *dev, struct mlx4_caps *caps);
+int mlx4_QUERY_SLAVE_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm);
int mlx4_UNMAP_FA(struct mlx4_dev *dev);
int mlx4_RUN_FW(struct mlx4_dev *dev);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index bb41450..3349ed5 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -141,6 +141,7 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev)
if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
dev->caps.port_mask |= 1 << (i - 1);
}
+
static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
int err;
@@ -185,6 +186,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.supported_type[i] = dev_cap->supported_port_types[i];
}
+ dev->caps.uar_page_size = PAGE_SIZE;
dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE;
dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay;
dev->caps.bf_reg_size = dev_cap->bf_reg_size;
@@ -211,7 +213,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.reserved_mtts = DIV_ROUND_UP(dev_cap->reserved_mtts,
dev->caps.mtts_per_seg);
dev->caps.reserved_mrws = dev_cap->reserved_mrws;
- dev->caps.reserved_uars = dev_cap->reserved_uars;
+
+ /* The first 128 UARs are used for EQ doorbells */
+ dev->caps.reserved_uars = max_t(int, 128, dev_cap->reserved_uars);
dev->caps.reserved_pds = dev_cap->reserved_pds;
dev->caps.mtt_entry_sz = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz;
dev->caps.max_msg_sz = dev_cap->max_msg_sz;
@@ -265,6 +269,70 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] +
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH];
+ /* Master function demultiplexes mads */
+ dev->caps.sqp_demux = MLX4_MAX_NUM_SLAVES;
+ return 0;
+}
+
+int mlx4_slave_cap(struct mlx4_dev *dev)
+{
+ int err;
+ u32 page_size;
+
+ err = mlx4_QUERY_SLAVE_CAP(dev, &dev->caps);
+ if (err)
+ return err;
+
+ page_size = ~dev->caps.page_size_cap + 1;
+ mlx4_warn(dev, "HCA minimum page size:%d\n", page_size);
+ if (page_size > PAGE_SIZE) {
+ mlx4_err(dev, "HCA minimum page size of %d bigger than "
+ "kernel PAGE_SIZE of %ld, aborting.\n",
+ page_size, PAGE_SIZE);
+ return -ENODEV;
+ }
+
+ /* TODO: relax this assumption */
+ if (dev->caps.uar_page_size != PAGE_SIZE) {
+ mlx4_err(dev, "UAR size:%d != kernel PAGE_SIZE of %ld\n",
+ dev->caps.uar_page_size, PAGE_SIZE);
+ return -ENODEV;
+ }
+
+ if (dev->caps.num_ports > MLX4_MAX_PORTS) {
+ mlx4_err(dev, "HCA has %d ports, but we only support %d, "
+ "aborting.\n", dev->caps.num_ports, MLX4_MAX_PORTS);
+ return -ENODEV;
+ }
+
+ if (dev->caps.uar_page_size * (dev->caps.num_uars -
+ dev->caps.reserved_uars) >
+ pci_resource_len(dev->pdev, 2)) {
+ mlx4_err(dev, "HCA reported UAR region size of 0x%x bigger than "
+ "PCI resource 2 size of 0x%llx, aborting.\n",
+ dev->caps.uar_page_size * dev->caps.num_uars,
+ (unsigned long long) pci_resource_len(dev->pdev, 2));
+ return -ENODEV;
+ }
+
+ /* Adjust eq number */
+ if (dev->caps.num_eqs - dev->caps.reserved_eqs > num_possible_cpus() + 1)
+ dev->caps.num_eqs = dev->caps.reserved_eqs + num_possible_cpus() + 1;
+
+#if 0
+ mlx4_warn(dev, "sqp_demux:%d\n", dev->caps.sqp_demux);
+ mlx4_warn(dev, "num_uars:%d reserved_uars:%d uar region:0x%x bar2:0x%llx\n",
+ dev->caps.num_uars, dev->caps.reserved_uars,
+ dev->caps.uar_page_size * dev->caps.num_uars,
+ pci_resource_len(dev->pdev, 2));
+ mlx4_warn(dev, "num_eqs:%d reserved_eqs:%d\n", dev->caps.num_eqs,
+ dev->caps.reserved_eqs);
+ mlx4_warn(dev, "num_pds:%d reserved_pds:%d slave_pd_shift:%d pd_base:%d\n",
+ dev->caps.num_pds,
+ dev->caps.reserved_pds,
+ dev->caps.slave_pd_shift,
+ dev->caps.pd_base);
+#endif
return 0;
}
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 800afe4..a243ac7 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -69,7 +69,8 @@ enum {
};
enum {
- MLX4_NUM_PDS = 1 << 15
+ MLX4_NUM_PDS = 1 << 15,
+ MLX4_SLAVE_PD_SHIFT = 17, /* the 7 msbs encode the slave id */
};
enum {
@@ -115,6 +116,7 @@ enum mlx4_alloc_mode {
enum {
MLX4_MFUNC_MAX = 64,
+ MLX4_MFUNC_EQ_NUM = 4,
MLX4_MFUNC_MAX_EQES = 8,
MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
};
@@ -138,6 +140,10 @@ extern int mlx4_debug_level;
#define mlx4_warn(mdev, format, arg...) \
dev_warn(&mdev->pdev->dev, format, ## arg)
+#define MLX4_MAX_NUM_PF 16
+#define MLX4_MAX_NUM_VF 64
+#define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF)
+
struct mlx4_bitmap {
u32 last;
u32 top;
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c
index ca25b9d..f6197e9 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/mlx4/profile.c
@@ -105,9 +105,19 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
profile[MLX4_RES_AUXC].num = request->num_qp;
profile[MLX4_RES_SRQ].num = request->num_srq;
profile[MLX4_RES_CQ].num = request->num_cq;
- profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs,
- dev_cap->reserved_eqs +
- num_possible_cpus() + 1);
+ if (mlx4_is_master(dev)) {
+ profile[MLX4_RES_EQ].num = dev_cap->reserved_eqs +
+ MLX4_MFUNC_EQ_NUM *
+ (dev->num_slaves + 1);
+ if (profile[MLX4_RES_EQ].num > dev_cap->max_eqs) {
+ mlx4_warn(dev, "Not enough eqs for:%ld slave functions\n", dev->num_slaves);
+ kfree(profile);
+ return -ENOMEM;
+ }
+ } else
+ profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs,
+ dev_cap->reserved_eqs +
+ num_possible_cpus() + 1);
profile[MLX4_RES_DMPT].num = request->num_mpt;
profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
profile[MLX4_RES_MTT].num = request->num_mtt;
@@ -196,7 +206,13 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
init_hca->log_num_cqs = profile[i].log_num;
break;
case MLX4_RES_EQ:
- dev->caps.num_eqs = profile[i].num;
+ if (mlx4_is_master(dev)) {
+ dev->caps.num_eqs = dev_cap->reserved_eqs +
+ min_t(unsigned,
+ MLX4_MFUNC_EQ_NUM,
+ num_possible_cpus() + 1);
+ } else
+ dev->caps.num_eqs = profile[i].num;
init_hca->eqc_base = profile[i].start;
init_hca->log_num_eqs = profile[i].log_num;
break;
@@ -232,6 +248,8 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
* of the HCA profile anyway.
*/
dev->caps.num_pds = MLX4_NUM_PDS;
+ dev->caps.slave_pd_shift = MLX4_SLAVE_PD_SHIFT;
+ dev->caps.pd_base = 0;
kfree(profile);
return total_size;
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 9e6395f..9526dfd 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -129,6 +129,7 @@ enum {
MLX4_CMD_FREE_RES = 0xf01,
MLX4_CMD_REPLACE_RES = 0xf02,
MLX4_CMD_GET_EVENT = 0xf03,
+ MLX4_CMD_QUERY_SLAVE_CAP = 0xf04,
MLX4_CMD_MCAST_ATTACH = 0xf05,
MLX4_CMD_GET_SLAVE_SQP = 0xf06,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 86e715c..62fd67e 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -193,6 +193,7 @@ struct mlx4_caps {
int pkey_table_len[MLX4_MAX_PORTS + 1];
int local_ca_ack_delay;
int num_uars;
+ int uar_page_size;
int bf_reg_size;
int bf_regs_per_page;
int max_sq_sg;
@@ -227,6 +228,8 @@ struct mlx4_caps {
int num_qp_per_mgm;
int num_pds;
int reserved_pds;
+ int slave_pd_shift;
+ int pd_base;
int mtt_entry_sz;
u32 max_msg_sz;
u32 page_size_cap;
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 10/23 v3] mlx4_core: associate resources with specific functions
[not found] <49BFC313.1030901@mellanox.co.il>
` (9 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 09/23 v3] mlx4_core: per-function capabilities Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 11/23 v3] mlx4_core: multi-function resource setup Yevgeny Petrilin
` (12 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Resources are associated with functions by means of pds - the upper 7 msbs
specify the function id. Since cqs do not refer to a specific pd, the function
id is passed explicitly to hw in the cq context.
For uars, which are statically partitioned between slaves, we only need to adjust
their offsets with respect to the associated function bar.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cq.c | 4 +++-
drivers/net/mlx4/pd.c | 12 +++++++++---
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index 3fb9f7f..9f9f246 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -59,7 +59,8 @@ struct mlx4_cq_context {
__be32 solicit_producer_index;
__be32 consumer_index;
__be32 producer_index;
- u32 reserved4[2];
+ __be32 pd; /* for sriov guest id */
+ u32 reserved4;
__be64 db_rec_addr;
};
@@ -293,6 +294,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
mtt_addr = mlx4_mtt_addr(dev, mtt);
cq_context->mtt_base_addr_h = mtt_addr >> 32;
cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
+ cq_context->pd = cpu_to_be32(dev->caps.pd_base << dev->caps.slave_pd_shift);
cq_context->db_rec_addr = cpu_to_be64(db_rec);
err = mlx4_SW2HW_CQ(dev, mailbox, cq->cqn);
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c
index c4988d6..08eaf08 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/mlx4/pd.c
@@ -45,7 +45,7 @@ int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn)
*pdn = mlx4_bitmap_alloc(&priv->pd_bitmap);
if (*pdn == -1)
return -ENOMEM;
-
+ *pdn |= dev->caps.pd_base << dev->caps.slave_pd_shift;
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
@@ -72,12 +72,18 @@ void mlx4_cleanup_pd_table(struct mlx4_dev *dev)
int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar)
{
+ int offset;
+
uar->index = mlx4_bitmap_alloc(&mlx4_priv(dev)->uar_table.bitmap);
if (uar->index == -1)
return -ENOMEM;
- uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index;
-
+ if (mlx4_is_slave(dev))
+ offset = uar->index % ((int) pci_resource_len(dev->pdev, 2) /
+ dev->caps.uar_page_size);
+ else
+ offset = uar->index;
+ uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + offset;
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_uar_alloc);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 11/23 v3] mlx4_core: multi-function resource setup
[not found] <49BFC313.1030901@mellanox.co.il>
` (10 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 10/23 v3] mlx4_core: associate resources with specific functions Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 12/23 v3] mlx4_core: boot sriov Yevgeny Petrilin
` (11 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Only master function needs to configure eq for asynch events, and initialize resource
allocators.
Only the master function polls for fatal events.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cq.c | 4 +++
drivers/net/mlx4/eq.c | 62 +++++++++++++++++++++++++------------------
drivers/net/mlx4/intf.c | 6 +++-
drivers/net/mlx4/main.c | 44 ++++++++++++++++--------------
drivers/net/mlx4/mcg.c | 6 ++++
drivers/net/mlx4/mr.c | 6 ++++
drivers/net/mlx4/pd.c | 9 +++++-
drivers/net/mlx4/qp.c | 28 ++++++++++++++++++-
drivers/net/mlx4/srq.c | 4 +++
include/linux/mlx4/device.h | 1 +
10 files changed, 118 insertions(+), 52 deletions(-)
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index 9f9f246..b605041 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -353,6 +353,8 @@ int mlx4_init_cq_table(struct mlx4_dev *dev)
spin_lock_init(&cq_table->lock);
INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC);
+ if (mlx4_is_slave(dev))
+ return 0;
err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs,
dev->caps.num_cqs - 1, dev->caps.reserved_cqs, 0);
@@ -364,6 +366,8 @@ int mlx4_init_cq_table(struct mlx4_dev *dev)
void mlx4_cleanup_cq_table(struct mlx4_dev *dev)
{
+ if (mlx4_is_slave(dev))
+ return;
/* Nothing to do to clean up radix_tree */
mlx4_bitmap_cleanup(&mlx4_priv(dev)->cq_table.bitmap);
}
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index a27e1c4..08af60c 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -713,6 +713,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
int i;
+ u32 round_eqs = roundup_pow_of_two(dev->caps.num_eqs);
priv->eq_table.uar_map = kcalloc(sizeof *priv->eq_table.uar_map,
mlx4_num_eq_uar(dev), GFP_KERNEL);
@@ -721,39 +722,42 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
goto err_out_free;
}
- err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs,
- dev->caps.num_eqs - 1, dev->caps.reserved_eqs, 0);
+ err = mlx4_bitmap_init(&priv->eq_table.bitmap, round_eqs, round_eqs - 1,
+ dev->caps.reserved_eqs, round_eqs - dev->caps.num_eqs);
if (err)
goto err_out_free;
for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
priv->eq_table.uar_map[i] = NULL;
- err = mlx4_map_clr_int(dev);
- if (err)
- goto err_out_bitmap;
+ if (!mlx4_is_slave(dev)) {
+ err = mlx4_map_clr_int(dev);
+ if (err)
+ goto err_out_bitmap;
- priv->eq_table.clr_mask =
- swab32(1 << (priv->eq_table.inta_pin & 31));
- priv->eq_table.clr_int = priv->clr_base +
- (priv->eq_table.inta_pin < 32 ? 4 : 0);
+ priv->eq_table.clr_mask =
+ swab32(1 << (priv->eq_table.inta_pin & 31));
+ priv->eq_table.clr_int = priv->clr_base +
+ (priv->eq_table.inta_pin < 32 ? 4 : 0);
+ }
priv->eq_table.irq_names =
kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1),
GFP_KERNEL);
if (!priv->eq_table.irq_names) {
err = -ENOMEM;
- goto err_out_bitmap;
+ i = 0;
+ goto err_out_unmap;
}
for (i = 0; i < dev->caps.num_comp_vectors; ++i) {
- err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE,
+ err = mlx4_create_eq(dev, dev->caps.num_cqs -
+ dev->caps.reserved_cqs +
+ MLX4_NUM_SPARE_EQE,
(dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
&priv->eq_table.eq[i]);
- if (err) {
- --i;
+ if (err)
goto err_out_unmap;
- }
}
err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE,
@@ -803,11 +807,13 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
priv->eq_table.have_irq = 1;
}
- err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
- if (err)
- mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn, err);
+ if (!mlx4_is_slave(dev)) { /* hw async events cannot be shared */
+ err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
+ if (err)
+ mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn, err);
+ }
for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
eq_set_ci(&priv->eq_table.eq[i], 1);
@@ -818,14 +824,15 @@ err_out_async:
mlx4_free_eq(dev, &priv->eq_table.eq[dev->caps.num_comp_vectors]);
err_out_comp:
- i = dev->caps.num_comp_vectors - 1;
+ i = dev->caps.num_comp_vectors;
err_out_unmap:
- while (i >= 0) {
- mlx4_free_eq(dev, &priv->eq_table.eq[i]);
+ while (i > 0) {
--i;
+ mlx4_free_eq(dev, &priv->eq_table.eq[i]);
}
- mlx4_unmap_clr_int(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_unmap_clr_int(dev);
mlx4_free_irqs(dev);
err_out_bitmap:
@@ -842,15 +849,18 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
int i;
- mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1,
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
+ if (!mlx4_is_slave(dev)) {
+ mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1,
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
+ }
mlx4_free_irqs(dev);
for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
mlx4_free_eq(dev, &priv->eq_table.eq[i]);
- mlx4_unmap_clr_int(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_unmap_clr_int(dev);
for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
if (priv->eq_table.uar_map[i])
diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
index 0e7eb10..84c00d0 100644
--- a/drivers/net/mlx4/intf.c
+++ b/drivers/net/mlx4/intf.c
@@ -139,7 +139,8 @@ int mlx4_register_device(struct mlx4_dev *dev)
mlx4_add_device(intf, priv);
mutex_unlock(&intf_mutex);
- mlx4_start_catas_poll(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_start_catas_poll(dev);
return 0;
}
@@ -149,7 +150,8 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_interface *intf;
- mlx4_stop_catas_poll(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_stop_catas_poll(dev);
mutex_lock(&intf_mutex);
list_for_each_entry(intf, &intf_list, list)
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 3349ed5..23dae5b 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -922,11 +922,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_mr_table_free;
}
- err = mlx4_cmd_use_events(dev);
- if (err) {
- mlx4_err(dev, "Failed to switch to event-driven "
- "firmware commands, aborting.\n");
- goto err_eq_table_free;
+ if (!mlx4_is_slave(dev)) {
+ err = mlx4_cmd_use_events(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to switch to event-driven "
+ "firmware commands, aborting.\n");
+ goto err_eq_table_free;
+ }
}
err = mlx4_NOP(dev);
@@ -976,22 +978,23 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_qp_table_free;
}
- for (port = 1; port <= dev->caps.num_ports; port++) {
- ib_port_default_caps = 0;
- err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps);
- if (err)
- mlx4_warn(dev, "failed to get port %d default "
- "ib capabilities (%d). Continuing with "
- "caps = 0\n", port, err);
- dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
- err = mlx4_SET_PORT(dev, port);
- if (err) {
- mlx4_err(dev, "Failed to set port %d, aborting\n",
- port);
- goto err_mcg_table_free;
+ if (!mlx4_is_slave(dev)) {
+ for (port = 1; port <= dev->caps.num_ports; port++) {
+ ib_port_default_caps = 0;
+ err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps);
+ if (err)
+ mlx4_warn(dev, "failed to get port %d default "
+ "ib capabilities (%d). Continuing with "
+ "caps = 0\n", port, err);
+ dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
+ err = mlx4_SET_PORT(dev, port);
+ if (err) {
+ mlx4_err(dev, "Failed to set port %d, aborting\n",
+ port);
+ goto err_mcg_table_free;
+ }
}
}
-
return 0;
err_mcg_table_free:
@@ -1007,7 +1010,8 @@ err_cq_table_free:
mlx4_cleanup_cq_table(dev);
err_cmd_poll:
- mlx4_cmd_use_polling(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_cmd_use_polling(dev);
err_eq_table_free:
mlx4_cleanup_eq_table(dev);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 96f09ed..daa08f1 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -393,6 +393,10 @@ int mlx4_init_mcg_table(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
+ /* Nothing to do for slaves - mcg handling is para-virtualized */
+ if (mlx4_is_slave(dev))
+ return 0;
+
err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms,
dev->caps.num_amgms - 1, 0, 0);
if (err)
@@ -405,5 +409,7 @@ int mlx4_init_mcg_table(struct mlx4_dev *dev)
void mlx4_cleanup_mcg_table(struct mlx4_dev *dev)
{
+ if (mlx4_is_slave(dev))
+ return;
mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap);
}
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 0db7f88..8430d90 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -617,6 +617,10 @@ int mlx4_init_mr_table(struct mlx4_dev *dev)
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
int err;
+ /* Nothing to do for slaves - all MR handling is forwarded to the master */
+ if (mlx4_is_slave(dev))
+ return 0;
+
err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts,
~0, dev->caps.reserved_mrws, 0);
if (err)
@@ -651,6 +655,8 @@ void mlx4_cleanup_mr_table(struct mlx4_dev *dev)
{
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
+ if (mlx4_is_slave(dev))
+ return;
mlx4_buddy_cleanup(&mr_table->mtt_buddy);
mlx4_bitmap_cleanup(&mr_table->mpt_bitmap);
}
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c
index 08eaf08..17127f8 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/mlx4/pd.c
@@ -96,6 +96,8 @@ EXPORT_SYMBOL_GPL(mlx4_uar_free);
int mlx4_init_uar_table(struct mlx4_dev *dev)
{
+ u32 round_uars = roundup_pow_of_two(dev->caps.num_uars);
+
if (dev->caps.num_uars <= 128) {
mlx4_err(dev, "Only %d UAR pages (need more than 128)\n",
dev->caps.num_uars);
@@ -104,11 +106,14 @@ int mlx4_init_uar_table(struct mlx4_dev *dev)
}
return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap,
- dev->caps.num_uars, dev->caps.num_uars - 1,
- max(128, dev->caps.reserved_uars), 0);
+ round_uars, round_uars - 1,
+ dev->caps.reserved_uars,
+ round_uars - dev->caps.num_uars);
}
void mlx4_cleanup_uar_table(struct mlx4_dev *dev)
{
+ if (mlx4_is_master(dev))
+ return;
mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap);
}
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 7ec59f0..f0864c3 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -392,6 +392,23 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
spin_lock_init(&qp_table->lock);
INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC);
+ if (mlx4_is_slave(dev)) {
+ /* For each slave, just allocate a normal 8-byte alligned special-QP
+ * range intead of mlx4_init_qp_table() reservation */
+ err = mlx4_qp_reserve_range(dev, 8, 8, &dev->caps.sqp_start);
+ if (err) {
+ mlx4_err(dev, "Failed to allocate special QP range\n");
+ return err;
+ }
+
+ err = mlx4_CONF_SPECIAL_QP(dev, dev->caps.sqp_start);
+ if (err) {
+ mlx4_err(dev, "Failed to configure special QP range\n");
+ mlx4_qp_release_range(dev, dev->caps.sqp_start, 8);
+ return err;
+ }
+ return 0;
+ }
/*
* We reserve 2 extra QPs per port for the special QPs. The
@@ -401,6 +418,9 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
dev->caps.sqp_start =
ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
+ /* If multi-function is enabled, we reserve an additional QP for qp0/1 tunneling. */
+ dev->caps.tunnel_qpn = mlx4_is_master(dev) ? dev->caps.sqp_start + 8 : 0;
+
{
int sort[MLX4_NUM_QP_REGION];
int i, j, tmp;
@@ -430,8 +450,8 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
}
err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
- (1 << 23) - 1, dev->caps.sqp_start + 8,
- reserved_from_top);
+ (1 << 23) - 1, dev->caps.sqp_start + 8 +
+ 2 * !!dev->caps.tunnel_qpn, reserved_from_top);
if (err)
return err;
@@ -441,6 +461,10 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
void mlx4_cleanup_qp_table(struct mlx4_dev *dev)
{
mlx4_CONF_SPECIAL_QP(dev, 0);
+ if (mlx4_is_slave(dev)) {
+ mlx4_qp_release_range(dev, dev->caps.sqp_start, 8);
+ return;
+ }
mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap);
}
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c
index ed11f18..3050318 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/mlx4/srq.c
@@ -287,6 +287,8 @@ int mlx4_init_srq_table(struct mlx4_dev *dev)
spin_lock_init(&srq_table->lock);
INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC);
+ if (mlx4_is_slave(dev))
+ return 0;
err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs,
dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0);
@@ -298,5 +300,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev)
void mlx4_cleanup_srq_table(struct mlx4_dev *dev)
{
+ if (mlx4_is_slave(dev))
+ return;
mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap);
}
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 62fd67e..1da8c35 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -205,6 +205,7 @@ struct mlx4_caps {
int max_qp_init_rdma;
int max_qp_dest_rdma;
int sqp_start;
+ int tunnel_qpn;
int num_srqs;
int max_srq_wqes;
int max_srq_sge;
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 12/23 v3] mlx4_core: boot sriov
[not found] <49BFC313.1030901@mellanox.co.il>
` (11 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 11/23 v3] mlx4_core: multi-function resource setup Yevgeny Petrilin
@ 2010-02-04 15:55 ` Yevgeny Petrilin
2010-02-04 15:56 ` [PATCH 13/23 v3] mlx4: Unicast Loopback support Yevgeny Petrilin
` (10 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:55 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Add virtual function device ids. Setting VF flag to device private data
Establish comm channel when sriov is enabled, and boot vfs through it.
Each slave gets one msi-X for completions, the master also gets one for
async events.
Signed-off-by: Liran Liss <liranl@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/eq.c | 22 ++--
drivers/net/mlx4/main.c | 326 +++++++++++++++++++++++++++++++++++-----------
drivers/net/mlx4/mlx4.h | 4 +
3 files changed, 265 insertions(+), 87 deletions(-)
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 08af60c..b4726ae 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -760,16 +760,19 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
goto err_out_unmap;
}
- err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE,
- (dev->flags & MLX4_FLAG_MSI_X) ? dev->caps.num_comp_vectors : 0,
- &priv->eq_table.eq[dev->caps.num_comp_vectors]);
- if (err)
- goto err_out_comp;
+ if (!mlx4_is_slave(dev)) {
+ err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE,
+ (dev->flags & MLX4_FLAG_MSI_X) ?
+ dev->caps.num_comp_vectors : 0,
+ &priv->eq_table.eq[dev->caps.num_comp_vectors]);
+ if (err)
+ goto err_out_comp;
+ }
if (dev->flags & MLX4_FLAG_MSI_X) {
const char *eq_name;
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) {
+ for (i = 0; i < dev->caps.num_comp_vectors + !(mlx4_is_slave(dev)); ++i) {
if (i < dev->caps.num_comp_vectors) {
snprintf(priv->eq_table.irq_names +
i * MLX4_IRQNAME_SIZE,
@@ -815,13 +818,14 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
priv->eq_table.eq[dev->caps.num_comp_vectors].eqn, err);
}
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
+ for (i = 0; i < dev->caps.num_comp_vectors + !(mlx4_is_slave(dev)); ++i)
eq_set_ci(&priv->eq_table.eq[i], 1);
return 0;
err_out_async:
- mlx4_free_eq(dev, &priv->eq_table.eq[dev->caps.num_comp_vectors]);
+ if (!mlx4_is_slave(dev))
+ mlx4_free_eq(dev, &priv->eq_table.eq[dev->caps.num_comp_vectors]);
err_out_comp:
i = dev->caps.num_comp_vectors;
@@ -856,7 +860,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
mlx4_free_irqs(dev);
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
+ for (i = 0; i < dev->caps.num_comp_vectors + !mlx4_is_slave(dev); ++i)
mlx4_free_eq(dev, &priv->eq_table.eq[i]);
if (!mlx4_is_slave(dev))
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 23dae5b..6d5a8de 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -73,6 +73,23 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
#endif /* CONFIG_PCI_MSI */
+#ifdef CONFIG_PCI_IOV
+
+static int sr_iov;
+module_param(sr_iov, int, 0444);
+MODULE_PARM_DESC(sr_iov, "enable #sr_iov functions if sr_iov > 0");
+
+static int probe_vf;
+module_param(probe_vf, int, 0444);
+MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (sr_iov > 0)");
+
+#else /* CONFIG_PCI_IOV */
+
+#define sr_iov 0
+#define probe_vf 0
+
+#endif /* CONFIG_PCI_IOV */
+
static char mlx4_version[] __devinitdata =
DRV_NAME ": Mellanox ConnectX core driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -782,12 +799,56 @@ static void mlx4_free_icms(struct mlx4_dev *dev)
mlx4_free_icm(dev, priv->fw.aux_icm, 0);
}
+static void mlx4_slave_exit(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ down(&priv->cmd.poll_sem);
+ if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, MLX4_COMM_TIME))
+ mlx4_warn(dev, "Failed to close slave function.\n");
+ up(&priv->cmd.poll_sem);
+}
+
static void mlx4_close_hca(struct mlx4_dev *dev)
{
- mlx4_CLOSE_HCA(dev, 0);
- mlx4_free_icms(dev);
- mlx4_UNMAP_FA(dev);
- mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0);
+ if (mlx4_is_slave(dev))
+ mlx4_slave_exit(dev);
+ else {
+ mlx4_CLOSE_HCA(dev, 0);
+ mlx4_free_icms(dev);
+ mlx4_UNMAP_FA(dev);
+ mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0);
+ }
+}
+
+static int mlx4_init_slave(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ u64 dma = (u64) priv->mfunc.vhcr_dma;
+
+ down(&priv->cmd.poll_sem);
+ mlx4_warn(dev, "Sending reset\n");
+ if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, MLX4_COMM_TIME))
+ goto err;
+ mlx4_warn(dev, "Sending vhcr0\n");
+ if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR0, dma >> 48,
+ MLX4_COMM_TIME))
+ goto err;
+ if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR1, dma >> 32,
+ MLX4_COMM_TIME))
+ goto err;
+ if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR2, dma >> 16,
+ MLX4_COMM_TIME))
+ goto err;
+ if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_EN, dma, MLX4_COMM_TIME))
+ goto err;
+ up(&priv->cmd.poll_sem);
+ return 0;
+
+err:
+ mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, 0);
+ up(&priv->cmd.poll_sem);
+ return -EIO;
}
static int mlx4_init_hca(struct mlx4_dev *dev)
@@ -801,51 +862,67 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
u64 icm_size;
int err;
- err = mlx4_QUERY_FW(dev);
- if (err) {
- if (err == -EACCES)
- mlx4_info(dev, "non-primary physical function, skipping.\n");
- else
- mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
- return err;
- }
+ if (!mlx4_is_slave(dev)) {
+ err = mlx4_QUERY_FW(dev); /* TODO: verify FW version in slaves as well */
+ if (err) {
+ if (err == -EACCES)
+ mlx4_info(dev, "non-primary physical function, skipping.\n");
+ else {
+ mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
+ if (mlx4_is_master(dev))
+ mlx4_err(dev, "Are you using SRIOV-enabled firmware?\n");
+ }
+ return err;
+ }
- err = mlx4_load_fw(dev);
- if (err) {
- mlx4_err(dev, "Failed to start FW, aborting.\n");
- return err;
- }
+ err = mlx4_load_fw(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to start FW, aborting.\n");
+ return err;
+ }
- mlx4_cfg.log_pg_sz_m = 1;
- mlx4_cfg.log_pg_sz = 0;
- err = mlx4_MOD_STAT_CFG(dev, &mlx4_cfg);
- if (err)
- mlx4_warn(dev, "Failed to override log_pg_sz parameter\n");
+ mlx4_cfg.log_pg_sz_m = 1;
+ mlx4_cfg.log_pg_sz = 0;
+ err = mlx4_MOD_STAT_CFG(dev, &mlx4_cfg);
+ if (err)
+ mlx4_warn(dev, "Failed to override log_pg_sz parameter\n");
- err = mlx4_dev_cap(dev, &dev_cap);
- if (err) {
- mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n");
- goto err_stop_fw;
- }
+ err = mlx4_dev_cap(dev, &dev_cap);
+ if (err) {
+ mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n");
+ goto err_stop_fw;
+ }
- profile = default_profile;
+ profile = default_profile;
+ icm_size = mlx4_make_profile(dev, &profile, &dev_cap, &init_hca);
+ if ((long long) icm_size < 0) {
+ err = icm_size;
+ goto err_stop_fw;
+ }
- icm_size = mlx4_make_profile(dev, &profile, &dev_cap, &init_hca);
- if ((long long) icm_size < 0) {
- err = icm_size;
- goto err_stop_fw;
- }
+ init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
- init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
+ err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);
+ if (err)
+ goto err_stop_fw;
- err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);
- if (err)
- goto err_stop_fw;
+ err = mlx4_INIT_HCA(dev, &init_hca);
+ if (err) {
+ mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
+ goto err_free_icm;
+ }
+ } else {
+ err = mlx4_init_slave(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to initialize slave\n");
+ return err;
+ }
- err = mlx4_INIT_HCA(dev, &init_hca);
- if (err) {
- mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
- goto err_free_icm;
+ err = mlx4_slave_cap(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to obtain slave caps\n");
+ goto err_close;
+ }
}
err = mlx4_QUERY_ADAPTER(dev, &adapter);
@@ -860,15 +937,17 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
return 0;
err_close:
- mlx4_CLOSE_HCA(dev, 0);
+ mlx4_close_hca(dev);
err_free_icm:
- mlx4_free_icms(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_free_icms(dev);
err_stop_fw:
- mlx4_UNMAP_FA(dev);
- mlx4_free_icm(dev, priv->fw.fw_icm, 0);
-
+ if (!mlx4_is_slave(dev)) {
+ mlx4_UNMAP_FA(dev);
+ mlx4_free_icm(dev, priv->fw.fw_icm, 0);
+ }
return err;
}
@@ -1042,8 +1121,13 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
int i;
if (msi_x) {
- nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
- num_possible_cpus() + 1);
+ /* The master only uses en event EQ,
+ * Each one of the slaves have 1 completion eq */
+ if (mlx4_is_mfunc(dev))
+ nreq = 1 + !!mlx4_is_master(dev);
+ else
+ nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
+ num_possible_cpus() + 1);
entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
if (!entries)
goto no_msi;
@@ -1066,7 +1150,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
goto no_msi;
}
- dev->caps.num_comp_vectors = nreq - 1;
+ dev->caps.num_comp_vectors = nreq - !mlx4_is_slave(dev);
for (i = 0; i < nreq; ++i)
priv->eq_table.eq[i].irq = entries[i].vector;
@@ -1137,10 +1221,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
/*
- * Check for BARs. We expect 0: 1MB
+ * Check for BARs.
*/
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
- pci_resource_len(pdev, 0) != 1 << 20) {
+ if (((id == NULL) || !(id->driver_data & MLX4_VF)) &&
+ !(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "Missing DCS, aborting.\n");
err = -ENODEV;
goto err_disable_pdev;
@@ -1198,34 +1282,83 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&priv->pgdir_list);
mutex_init(&priv->pgdir_mutex);
- /*
- * Now reset the HCA before we touch the PCI capabilities or
- * attempt a firmware command, since a boot ROM may have left
- * the HCA in an undefined state.
- */
- err = mlx4_reset(dev);
- if (err) {
- mlx4_err(dev, "Failed to reset HCA, aborting.\n");
- goto err_free_dev;
+ /* Detect if this device is a virtual function */
+ if (id && id->driver_data & MLX4_VF) {
+ /* When acting as pf, we normally skip vfs unless explicitly
+ * requested to probe them. */
+ if (sr_iov && PCI_FUNC(pdev->devfn) > probe_vf) {
+ mlx4_warn(dev, "Skipping virtual function:%d\n",
+ PCI_FUNC(pdev->devfn));
+ err = -ENODEV;
+ goto err_free_dev;
+ }
+ mlx4_warn(dev, "Detected virtual function - running in slave mode\n");
+ dev->flags |= MLX4_FLAG_SLAVE;
+ }
+
+ /* We reset the device and enable SRIOV only for physical devices */
+ if (!mlx4_is_slave(dev)) {
+ /*
+ * Now reset the HCA before we touch the PCI capabilities or
+ * attempt a firmware command, since a boot ROM may have left
+ * the HCA in an undefined state.
+ */
+ err = mlx4_reset(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to reset HCA, aborting.\n");
+ goto err_free_dev;
+ }
+ if (sr_iov) {
+ mlx4_warn(dev, "Enabling sriov with:%d vfs\n", sr_iov);
+ if (pci_enable_sriov(pdev, sr_iov)) {
+ mlx4_err(dev, "Failed to enable sriov, aborting.\n");
+ goto err_free_dev;
+ }
+ mlx4_warn(dev, "Running in master mode\n");
+ dev->flags |= MLX4_FLAG_SRIOV | MLX4_FLAG_MASTER;
+ }
}
if (mlx4_cmd_init(dev)) {
mlx4_err(dev, "Failed to init command interface, aborting.\n");
- goto err_free_dev;
+ goto err_sriov;
+ }
+
+ /* In slave functions, the communication channel must be initialized before
+ * posting commands */
+ if (mlx4_is_slave(dev)) {
+ if (mlx4_multi_func_init(dev)) {
+ mlx4_err(dev, "Failed to init slave mfunc interface, aborting.\n");
+ goto err_cmd;
+ }
}
err = mlx4_init_hca(dev);
if (err)
goto err_cmd;
+ /* In master functions, the communication channel must be initialized after obtaining
+ * its address from fw */
+ if (mlx4_is_master(dev)) {
+ dev->num_slaves = MLX4_MAX_NUM_SLAVES;
+ if (mlx4_multi_func_init(dev)) {
+ mlx4_err(dev, "Failed to init master mfunc interface, aborting.\n");
+ goto err_close;
+ }
+ }
+
err = mlx4_alloc_eq_table(dev);
if (err)
goto err_close;
mlx4_enable_msi_x(dev);
+ if (mlx4_is_slave(dev) && !(dev->flags & MLX4_FLAG_MSI_X)) {
+ mlx4_err(dev, "INTx is not supported in slave mode, aborting.\n");
+ goto err_free_eq;
+ }
err = mlx4_setup_hca(dev);
- if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X)) {
+ if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X) && !mlx4_is_slave(dev)) {
dev->flags &= ~MLX4_FLAG_MSI_X;
pci_disable_msix(pdev);
err = mlx4_setup_hca(dev);
@@ -1249,6 +1382,12 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, dev);
+ /* Start serving comm channel:
+ * - In master function: poll for commands
+ * - in slave functions: poll for events
+ * TODO - enable comm channel interrupts */
+ if (mlx4_is_mfunc(dev))
+ queue_delayed_work(priv->mfunc.comm_wq, &priv->mfunc.comm_work, 0);
return 0;
err_port:
@@ -1259,7 +1398,8 @@ err_port:
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
mlx4_cleanup_cq_table(dev);
- mlx4_cmd_use_polling(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
mlx4_cleanup_mr_table(dev);
mlx4_cleanup_pd_table(dev);
@@ -1277,6 +1417,12 @@ err_close:
err_cmd:
mlx4_cmd_cleanup(dev);
+err_sriov:
+ if (mlx4_is_mfunc(dev))
+ mlx4_multi_func_cleanup(dev);
+ if (sr_iov && (dev->flags & MLX4_FLAG_SRIOV))
+ pci_disable_sriov(pdev);
+
err_free_dev:
kfree(priv);
@@ -1309,19 +1455,24 @@ static void mlx4_remove_one(struct pci_dev *pdev)
int p;
if (dev) {
+ /* Stop serving commands and events over comm channel */
+ if (mlx4_is_mfunc(dev))
+ cancel_delayed_work_sync(&priv->mfunc.comm_work);
mlx4_stop_sense(dev);
mlx4_unregister_device(dev);
for (p = 1; p <= dev->caps.num_ports; p++) {
mlx4_cleanup_port_info(&priv->port[p]);
- mlx4_CLOSE_PORT(dev, p);
+ if (!mlx4_is_slave(dev))
+ mlx4_CLOSE_PORT(dev, p);
}
mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
mlx4_cleanup_cq_table(dev);
- mlx4_cmd_use_polling(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
mlx4_cleanup_mr_table(dev);
mlx4_cleanup_pd_table(dev);
@@ -1331,10 +1482,16 @@ static void mlx4_remove_one(struct pci_dev *pdev)
mlx4_cleanup_uar_table(dev);
mlx4_free_eq_table(dev);
mlx4_close_hca(dev);
+ if (mlx4_is_mfunc(dev))
+ mlx4_multi_func_cleanup(dev);
mlx4_cmd_cleanup(dev);
if (dev->flags & MLX4_FLAG_MSI_X)
pci_disable_msix(pdev);
+ if (sr_iov && (dev->flags & MLX4_FLAG_SRIOV)) {
+ mlx4_warn(dev, "Disabling sriov\n");
+ pci_disable_sriov(pdev);
+ }
kfree(priv);
pci_release_regions(pdev);
@@ -1350,18 +1507,31 @@ int mlx4_restart_one(struct pci_dev *pdev)
}
static struct pci_device_id mlx4_pci_table[] = {
- { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */
- { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */
- { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */
- { PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
- { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
- { PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */
+ { MLX4_VDEVICE(MELLANOX, 0x6340, 0) }, /* MT25408 "Hermon" SDR */
+ { MLX4_VDEVICE(MELLANOX, 0x6341, MLX4_VF) }, /* MT25408 "Hermon" SDR VF */
+ { MLX4_VDEVICE(MELLANOX, 0x634a, 0) }, /* MT25408 "Hermon" DDR */
+ { MLX4_VDEVICE(MELLANOX, 0x634b, MLX4_VF) }, /* MT25408 "Hermon" DDR VF */
+ { MLX4_VDEVICE(MELLANOX, 0x6354, 0) }, /* MT25408 "Hermon" QDR */
+ { MLX4_VDEVICE(MELLANOX, 0x6732, 0) }, /* MT25408 "Hermon" DDR PCIe gen2 */
+ { MLX4_VDEVICE(MELLANOX, 0x6733, MLX4_VF) }, /* MT25408 "Hermon" DDR PCIe gen2 VF */
+ { MLX4_VDEVICE(MELLANOX, 0x673c, 0) }, /* MT25408 "Hermon" QDR PCIe gen2 */
+ { MLX4_VDEVICE(MELLANOX, 0x673d, MLX4_VF) }, /* MT25408 "Hermon" QDR PCIe gen2 VF */
+ { MLX4_VDEVICE(MELLANOX, 0x6368, 0) }, /* MT25408 "Hermon" EN 10GigE */
+ { MLX4_VDEVICE(MELLANOX, 0x6369, MLX4_VF) }, /* MT25408 "Hermon" EN 10GigE VF */
+ { MLX4_VDEVICE(MELLANOX, 0x6750, 0) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
+ { MLX4_VDEVICE(MELLANOX, 0x6751, MLX4_VF) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 VF */
+ { MLX4_VDEVICE(MELLANOX, 0x6372, 0) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
+ { MLX4_VDEVICE(MELLANOX, 0x6373, MLX4_VF) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
+ { MLX4_VDEVICE(MELLANOX, 0x675a, 0) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
+ { MLX4_VDEVICE(MELLANOX, 0x675b, MLX4_VF) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
+ { MLX4_VDEVICE(MELLANOX, 0x6764, 0) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
+ { MLX4_VDEVICE(MELLANOX, 0x6765, MLX4_VF) }, /* MT26468 ConnectX EN 10GigE PCIe gen2 VF*/
+ { MLX4_VDEVICE(MELLANOX, 0x6746, 0) }, /* MT26438 ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virt+ */
+ { MLX4_VDEVICE(MELLANOX, 0x6747, MLX4_VF) }, /* MT26438 ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virt+ VF*/
+ { MLX4_VDEVICE(MELLANOX, 0x676e, 0) }, /* MT26478 ConnectX EN 40GigE PCIe 2.0 5GT/s */
+ { MLX4_VDEVICE(MELLANOX, 0x676f, MLX4_VF) }, /* MT26478 ConnectX EN 40GigE PCIe 2.0 5GT/s VF*/
+ { MLX4_VDEVICE(MELLANOX, 0x6778, 0) }, /* MT26488 ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virt+ */
+ { MLX4_VDEVICE(MELLANOX, 0x6779, MLX4_VF) }, /* MT26488 ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virt+ VF*/
{ 0, }
};
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index a243ac7..6421932 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -144,6 +144,10 @@ extern int mlx4_debug_level;
#define MLX4_MAX_NUM_VF 64
#define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF)
+#define MLX4_VF (1 << 0)
+#define MLX4_VDEVICE(vendor, device, flags) \
+ PCI_VDEVICE(vendor, device), (flags)
+
struct mlx4_bitmap {
u32 last;
u32 top;
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 13/23 v3] mlx4: Unicast Loopback support
[not found] <49BFC313.1030901@mellanox.co.il>
` (12 preceding siblings ...)
2010-02-04 15:55 ` [PATCH 12/23 v3] mlx4_core: boot sriov Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
2010-02-10 8:22 ` Or Gerlitz
2010-02-04 15:56 ` [PATCH 14/23 v3] mlx4_core: Determine primary physical function Yevgeny Petrilin
` (9 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
All packets are subject to loopback.
To enable ethernet loopback we write the dest mac to the wqe.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_netdev.c | 2 +-
drivers/net/mlx4/en_tx.c | 14 ++++++++++++++
drivers/net/mlx4/fw.c | 3 +++
drivers/net/mlx4/fw.h | 1 +
drivers/net/mlx4/main.c | 1 +
drivers/net/mlx4/mlx4_en.h | 1 +
include/linux/mlx4/device.h | 1 +
7 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index fd96078..2987ada 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -108,7 +108,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
mutex_unlock(&mdev->state_lock);
}
-static u64 mlx4_en_mac_to_u64(u8 *addr)
+u64 mlx4_en_mac_to_u64(u8 *addr)
{
u64 mac = 0;
int i;
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 3d1396a..d4af0fe 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -599,6 +599,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
struct mlx4_wqe_data_seg *data;
struct skb_frag_struct *frag;
struct mlx4_en_tx_info *tx_info;
+ struct ethhdr *ethh;
int tx_ind = 0;
int nr_txbb;
int desc_size;
@@ -610,6 +611,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
int i;
int lso_header_size;
void *fragptr;
+ u64 mac;
+ u32 mac_l, mac_h;
real_size = get_real_size(skb, dev, &lso_header_size);
if (unlikely(!real_size))
@@ -675,6 +678,17 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
priv->port_stats.tx_chksum_offload++;
}
+ /* Copy dst mac address to wqe */
+ skb_reset_mac_header(skb);
+ ethh = eth_hdr(skb);
+ if (ethh && ethh->h_dest) {
+ mac = mlx4_en_mac_to_u64(ethh->h_dest);
+ mac_h = (u32) ((mac & 0xffff00000000) >> 16);
+ mac_l = (u32) (mac & 0xffffffff);
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
+ tx_desc->ctrl.imm = cpu_to_be32(mac_l);
+ }
+
/* Handle LSO (TSO) packets */
if (lso_header_size) {
/* Mark opcode as LSO */
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 2e60033..066db0e 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -228,6 +228,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
@@ -318,6 +319,8 @@ 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->loopback_support = field & 0x1;
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 d066c69..f0d4f1c 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -74,6 +74,7 @@ struct mlx4_dev_cap {
u64 def_mac[MLX4_MAX_PORTS + 1];
u16 eth_mtu[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
+ int loopback_support;
u32 flags;
int reserved_uars;
int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 6d5a8de..37293ca 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -241,6 +241,7 @@ 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.loopback_support = dev_cap->loopback_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
dev->caps.log_num_macs = log_num_mac;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 82c3ebc..5ea438e 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -563,6 +563,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+u64 mlx4_en_mac_to_u64(u8 *addr);
/*
* Globals
*/
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 1da8c35..73a1856 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -238,6 +238,7 @@ struct mlx4_caps {
u32 bmme_flags;
u32 reserved_lkey;
u16 stat_rate_support;
+ int loopback_support;
u8 port_width_cap[MLX4_MAX_PORTS + 1];
int max_gso_sz;
int reserved_qps_cnt[MLX4_NUM_QP_REGION];
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 14/23 v3] mlx4_core: Determine primary physical function
[not found] <49BFC313.1030901@mellanox.co.il>
` (13 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 13/23 v3] mlx4: Unicast Loopback support Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
2010-02-04 22:30 ` Roland Dreier
2010-02-04 15:56 ` [PATCH 15/23 v3] mlx4_core: Activating ports according to function number Yevgeny Petrilin
` (8 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In multifunctional devices, only the primary function would succeed
to execute QUERY_FW command, all other would fail with _EACCES error.
A physical function that is not primary would behave as slave.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/fw.c | 4 ++++
drivers/net/mlx4/fw.h | 1 +
drivers/net/mlx4/main.c | 18 +++++++++++++++---
include/linux/mlx4/device.h | 2 ++
4 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 066db0e..3c6601a 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -313,6 +313,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_rdma_global = 1 << (field & 0x3f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
dev_cap->local_ca_ack_delay = field & 0x1f;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
+ dev_cap->pf_num = field;
+ if (dev_cap->pf_num > 1)
+ dev->flags |= MLX4_FLAG_MASTER;
MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
dev_cap->num_ports = field & 0xf;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index f0d4f1c..59acfd0 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -64,6 +64,7 @@ struct mlx4_dev_cap {
int max_responder_per_qp;
int max_rdma_global;
int local_ca_ack_delay;
+ int pf_num;
int num_ports;
u32 max_msg_sz;
int ib_mtu[MLX4_MAX_PORTS + 1];
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 37293ca..9f9292a 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -191,6 +191,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
return -ENODEV;
}
+ dev->caps.pf_num = dev_cap->pf_num;
dev->caps.num_ports = dev_cap->num_ports;
for (i = 1; i <= dev->caps.num_ports; ++i) {
dev->caps.vl_cap[i] = dev_cap->max_vl[i];
@@ -867,7 +868,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
err = mlx4_QUERY_FW(dev); /* TODO: verify FW version in slaves as well */
if (err) {
if (err == -EACCES)
- mlx4_info(dev, "non-primary physical function, skipping.\n");
+ mlx4_info(dev, "Non-primary physical function, "
+ "Running in slave mode.\n");
else {
mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
if (mlx4_is_master(dev))
@@ -1320,6 +1322,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
}
+slave_start:
if (mlx4_cmd_init(dev)) {
mlx4_err(dev, "Failed to init command interface, aborting.\n");
goto err_sriov;
@@ -1335,8 +1338,17 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
err = mlx4_init_hca(dev);
- if (err)
- goto err_cmd;
+ if (err) {
+ if (err == -EACCES) {
+ /* Not primary Physical function
+ * Running in slave mode */
+ mlx4_cmd_cleanup(dev);
+ dev->flags |= MLX4_FLAG_SLAVE;
+ dev->flags &= ~MLX4_FLAG_MASTER;
+ goto slave_start;
+ } else
+ goto err_cmd;
+ }
/* In master functions, the communication channel must be initialized after obtaining
* its address from fw */
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 73a1856..38de006 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -45,6 +45,7 @@ enum {
MLX4_FLAG_MASTER = 1 << 2,
MLX4_FLAG_SLAVE = 1 << 3,
MLX4_FLAG_SRIOV = 1 << 4,
+ MLX4_FLAG_PF = 1 << 5,
};
enum {
@@ -183,6 +184,7 @@ static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
struct mlx4_caps {
u64 fw_ver;
+ int pf_num;
int num_ports;
int vl_cap[MLX4_MAX_PORTS + 1];
int ib_mtu_cap[MLX4_MAX_PORTS + 1];
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 15/23 v3] mlx4_core: Activating ports according to function number
[not found] <49BFC313.1030901@mellanox.co.il>
` (14 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 14/23 v3] mlx4_core: Determine primary physical function Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
2010-02-04 15:56 ` [PATCH 16/23 v3] mlx4_core: Multi-Function MCG support Yevgeny Petrilin
` (7 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In devices with multiple physical functions, each function activates
only one port, according to the function number.
Even functions activate port 1, odd functions activate port2.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/fw.c | 13 +++++++++++--
drivers/net/mlx4/main.c | 16 +++++++++-------
drivers/net/mlx4/mlx4.h | 1 +
include/linux/mlx4/device.h | 7 ++++---
4 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 3c6601a..f797a43 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -155,9 +155,13 @@ int mlx4_QUERY_SLAVE_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
/* The Master function is in charge for qp1 of al slaves */
caps->sqp_demux = 0;
+ /* Ports are activated according to physical function number */
+ mlx4_set_port_mask(dev, caps, slave);
+
/* PDs have the same range in every guest; the distinction is in the msbs,
* which contains the guest ID (vf + 1) */
caps->pd_base = slave + 1;
+ caps->function = slave;
/* All other resources are allocated by the master, but we still report
* 'num' and 'reserved' capabilities as follows:
@@ -602,6 +606,7 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
#define QUERY_FW_OUT_SIZE 0x100
#define QUERY_FW_VER_OFFSET 0x00
+#define QUERY_FW_PPF_ID 0x09
#define QUERY_FW_CMD_IF_REV_OFFSET 0x0a
#define QUERY_FW_MAX_CMD_OFFSET 0x0f
#define QUERY_FW_ERR_START_OFFSET 0x30
@@ -634,6 +639,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
((fw_ver & 0xffff0000ull) >> 16) |
((fw_ver & 0x0000ffffull) << 16);
+ MLX4_GET(lg, outbox, QUERY_FW_PPF_ID);
+ dev->caps.function = lg;
+
MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
@@ -944,7 +952,8 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
mlx4_free_cmd_mailbox(dev, mailbox);
} else {
if (mlx4_is_master(dev))
- err = mlx4_common_init_port(dev, 0, port);
+ err = mlx4_common_init_port(dev, dev->caps.function,
+ port);
else
err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
MLX4_CMD_TIME_CLASS_A);
@@ -984,7 +993,7 @@ int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *v
int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port)
{
if (mlx4_is_master(dev))
- return mlx4_common_close_port(dev, 0, port);
+ return mlx4_common_close_port(dev, dev->caps.function, port);
else
return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000);
}
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 9f9292a..41e622e 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -149,14 +149,16 @@ int mlx4_check_port_params(struct mlx4_dev *dev,
return 0;
}
-static void mlx4_set_port_mask(struct mlx4_dev *dev)
+void mlx4_set_port_mask(struct mlx4_dev *dev, struct mlx4_caps *caps, int function)
{
int i;
+ int active = (function & 1) + 1;
- dev->caps.port_mask = 0;
- for (i = 1; i <= dev->caps.num_ports; ++i)
- if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
- dev->caps.port_mask |= 1 << (i - 1);
+ for (i = 1; i <= caps->num_ports; ++i) {
+ caps->port_mask[i] = caps->port_type[i];
+ if (dev->caps.pf_num > 1 && i != active)
+ caps->port_mask[i] = 0;
+ }
}
static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
@@ -272,7 +274,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
}
}
- mlx4_set_port_mask(dev);
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.pf_num);
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
@@ -385,7 +387,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
goto out;
}
}
- mlx4_set_port_mask(dev);
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.pf_num);
err = mlx4_register_device(dev);
}
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 6421932..3417888 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -528,6 +528,7 @@ int mlx4_check_port_params(struct mlx4_dev *dev,
enum mlx4_port_type *port_type);
int mlx4_change_port_types(struct mlx4_dev *dev,
enum mlx4_port_type *port_types);
+void mlx4_set_port_mask(struct mlx4_dev *dev, struct mlx4_caps *caps, int function);
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);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 38de006..563679b 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -162,6 +162,7 @@ enum mlx4_qp_region {
};
enum mlx4_port_type {
+ MLX4_PORT_TYPE_NONE = 0,
MLX4_PORT_TYPE_IB = 1,
MLX4_PORT_TYPE_ETH = 2,
MLX4_PORT_TYPE_AUTO = 3
@@ -184,6 +185,7 @@ static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
struct mlx4_caps {
u64 fw_ver;
+ int function;
int pf_num;
int num_ports;
int vl_cap[MLX4_MAX_PORTS + 1];
@@ -252,7 +254,7 @@ struct mlx4_caps {
enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1];
u8 supported_type[MLX4_MAX_PORTS + 1];
u8 sqp_demux;
- u32 port_mask;
+ u8 port_mask[MLX4_MAX_PORTS + 1];
enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1];
};
@@ -412,8 +414,7 @@ struct mlx4_init_port_param {
#define mlx4_foreach_port(port, dev, type) \
for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \
- if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \
- ~(dev)->caps.port_mask) & 1 << ((port) - 1))
+ if ((type) == (dev)->caps.port_mask[port])
static inline int mlx4_is_slave(struct mlx4_dev *dev)
{
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 16/23 v3] mlx4_core: Multi-Function MCG support
[not found] <49BFC313.1030901@mellanox.co.il>
` (15 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 15/23 v3] mlx4_core: Activating ports according to function number Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
[not found] ` <4B6AEE30.30202-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org>
2010-02-04 15:56 ` [PATCH 17/23 v3] mlx4_core: Randomize Mac addresses for slaves Yevgeny Petrilin
` (6 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
The multicast attachment mechanism is used both by IB and Ethernet,
so we need to specify for each multicast address (whether it is gid or mac)
its protocol.
For Ethernet addresses, their VEP number should be specified. This field is
set according device capabilities. Search and hash calculation is also done
according to this field.
A Ethernet ports now need to register to the multicast groups, we can not longer
use the default multicast queue per port because of the multiple "clients" per port.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/infiniband/hw/mlx4/main.c | 6 +-
drivers/net/mlx4/en_netdev.c | 33 +++++++-
drivers/net/mlx4/en_port.c | 7 +-
drivers/net/mlx4/en_port.h | 11 ++-
drivers/net/mlx4/fw.c | 2 +
drivers/net/mlx4/fw.h | 2 +
drivers/net/mlx4/main.c | 2 +
drivers/net/mlx4/mcg.c | 176 +++++++++++++++++++++++--------------
drivers/net/mlx4/port.c | 4 +-
include/linux/mlx4/device.h | 14 +++-
10 files changed, 180 insertions(+), 77 deletions(-)
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index e596537..9fa8e1b 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -450,13 +450,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/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 2987ada..751c79d 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -177,6 +177,7 @@ static void mlx4_en_cache_mclist(struct net_device *dev)
struct dev_mc_list *tmp;
struct dev_mc_list *plist = NULL;
+ mlx4_en_clear_list(dev);
for (mclist = dev->mc_list; mclist; mclist = mclist->next) {
tmp = kmalloc(sizeof(struct dev_mc_list), GFP_ATOMIC);
if (!tmp) {
@@ -213,6 +214,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
struct net_device *dev = priv->dev;
struct dev_mc_list *mclist;
u64 mcast_addr = 0;
+ u8 mc_list[16] = {0};
int err;
mutex_lock(&mdev->state_lock);
@@ -292,6 +294,12 @@ 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 (mclist = priv->mc_list; mclist; mclist = mclist->next) {
+ memcpy(&mc_list[10], mclist->dmi_addr, ETH_ALEN);
+ 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);
@@ -302,6 +310,9 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
mlx4_en_cache_mclist(dev);
netif_tx_unlock_bh(dev);
for (mclist = priv->mc_list; mclist; mclist = mclist->next) {
+ memcpy(&mc_list[10], mclist->dmi_addr, ETH_ALEN);
+ mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp,
+ mc_list, 0, MLX4_PROT_ETH);
mcast_addr = mlx4_en_mac_to_u64(mclist->dmi_addr);
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
mcast_addr, 0, MLX4_MCAST_CONFIG);
@@ -310,8 +321,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);
@@ -557,6 +566,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");
@@ -669,6 +679,12 @@ 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);
+ 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);
@@ -699,7 +715,9 @@ void mlx4_en_stop_port(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
+ struct dev_mc_list *mclist;
int i;
+ u8 mc_list[16] = {0};
if (!priv->port_up) {
en_dbg(DRV, priv, "stop port called while port already down\n");
@@ -715,6 +733,17 @@ 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);
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
+ MLX4_PROT_ETH);
+ for (mclist = priv->mc_list; mclist; mclist = mclist->next) {
+ memcpy(&mc_list[10], mclist->dmi_addr, ETH_ALEN);
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
+ mc_list, MLX4_PROT_ETH);
+ }
+ mlx4_en_clear_list(dev);
+
/* 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..2d55c1a 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))
@@ -128,8 +129,10 @@ 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->promisc = cpu_to_be32(promisc << 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 fc49733..f7a367b 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -35,8 +35,15 @@
#define _MLX4_EN_PORT_H_
-#define SET_PORT_GEN_ALL_VALID 0x7
-#define SET_PORT_PROMISC_SHIFT 31
+#define SET_PORT_GEN_ALL_VALID 0x7
+#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 {
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index f797a43..6e3e1d1 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -329,6 +329,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->stat_rate_support = stat_rate;
MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
dev_cap->loopback_support = field & 0x1;
+ 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 59acfd0..e033d26 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;
int loopback_support;
+ int vep_uc_steering;
+ int vep_mc_steering;
u32 flags;
int reserved_uars;
int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 41e622e..d825cc1 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.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
dev->caps.loopback_support = dev_cap->loopback_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 daa08f1..9a678d2 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -66,12 +66,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)
@@ -96,13 +96,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))
@@ -111,7 +113,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;
@@ -135,8 +137,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;
@@ -146,47 +149,10 @@ static int find_mgm(struct mlx4_dev *dev,
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 */
-
- qp.qpn = vhcr->in_modifier & 0xffffff;
- if (vhcr->op_modifier)
- return mlx4_multicast_attach(dev, &qp, inbox->buf, vhcr->in_modifier >> 31);
- else
- return mlx4_multicast_detach(dev, &qp, inbox->buf);
-}
-
-static int mlx4_MCAST(struct mlx4_dev *dev, struct mlx4_qp *qp,
- u8 gid[16], u8 attach,
- u8 block_loopback)
-{
- 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;
- 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)
+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;
@@ -198,9 +164,6 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int i;
int err;
- if (mlx4_is_slave(dev))
- return mlx4_MCAST(dev, qp, gid, 1, block_mcast_loopback);
-
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -208,7 +171,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;
@@ -230,7 +193,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
memcpy(mgm->gid, gid, 16);
}
- members_count = be32_to_cpu(mgm->members_count);
+ members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
if (members_count == MLX4_QP_PER_MGM) {
mlx4_err(dev, "MGM at index %x is full.\n", index);
err = -ENOMEM;
@@ -250,7 +213,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)
@@ -263,7 +227,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)
@@ -283,9 +248,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;
@@ -295,9 +261,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
int prev, index;
int i, loc;
int err;
-
- if (mlx4_is_slave(dev))
- return mlx4_MCAST(dev, qp, gid, 0, 0);
+ u8 pf_num = gid[7] >> 4;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
@@ -306,7 +270,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;
@@ -316,7 +280,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
goto out;
}
- members_count = be32_to_cpu(mgm->members_count);
+ members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
for (loc = -1, i = 0; i < members_count; ++i)
if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
loc = i;
@@ -328,7 +292,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;
@@ -344,8 +308,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)
@@ -361,12 +328,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)
@@ -386,6 +353,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/port.c b/drivers/net/mlx4/port.c
index dcbfd72..5654fff 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -388,9 +388,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/device.h b/include/linux/mlx4/device.h
index 563679b..9bdfbab 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -174,6 +174,13 @@ enum mlx4_special_vlan_idx {
MLX4_VLAN_REGULAR
};
+enum mlx4_protocol {
+ MLX4_PROT_IB_IPV6 = 0,
+ MLX4_PROT_ETH,
+ MLX4_PROT_IB_IPV4,
+ MLX4_PROT_FCOE
+};
+
enum {
MLX4_NUM_FEXCH = 64 * 1024,
};
@@ -243,6 +250,8 @@ struct mlx4_caps {
u32 reserved_lkey;
u16 stat_rate_support;
int loopback_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];
@@ -493,8 +502,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);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 17/23 v3] mlx4_core: Randomize Mac addresses for slaves
[not found] <49BFC313.1030901@mellanox.co.il>
` (16 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 16/23 v3] mlx4_core: Multi-Function MCG support Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
2010-02-09 17:22 ` Ben Hutchings
2010-02-04 15:56 ` [PATCH 18/23 v3] mlx4_core: Managing common port filters by master function Yevgeny Petrilin
` (5 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/fw.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 6e3e1d1..202a256 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -32,6 +32,7 @@
* SOFTWARE.
*/
+#include <linux/etherdevice.h>
#include <linux/mlx4/cmd.h>
#include <linux/cache.h>
@@ -149,11 +150,19 @@ int mlx4_QUERY_SLAVE_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
struct mlx4_cmd_mailbox *outbox)
{
struct mlx4_caps *caps = outbox->buf;
+ u8 rand_mac[6];
+ int i, j;
memcpy(caps, &dev->caps, sizeof *caps);
/* The Master function is in charge for qp1 of al slaves */
caps->sqp_demux = 0;
+ for (i = 1; i <= dev->caps.num_ports; ++i) {
+ random_ether_addr(rand_mac);
+ caps->def_mac[i] = 0;
+ for (j = 0; j < ETH_ALEN - 1; j++)
+ caps->def_mac[i] |= ((u64)(rand_mac[j]) << 8 * j);
+ }
/* Ports are activated according to physical function number */
mlx4_set_port_mask(dev, caps, slave);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 18/23 v3] mlx4_core: Managing common port filters by master function
[not found] <49BFC313.1030901@mellanox.co.il>
` (17 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 17/23 v3] mlx4_core: Randomize Mac addresses for slaves Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
2010-02-10 8:47 ` Or Gerlitz
2010-02-04 15:56 ` [PATCH 19/23 v3] mlx4: SET port for Ethernet moved to mlx4_core Yevgeny Petrilin
` (4 subsequent siblings)
23 siblings, 1 reply; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
The Multicast filter configuration is done by the master,
that manages the filter which is common for all the functions.
The master holds a list of multicast addresses for all the
slaves, and adds them to the filter.
In case some slave wishes to flush the filter, only his addresses
are removed.
The VLAN filter is a bitwise OR of all the VLAN filters for all functions,
the result is a false-positive filter.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 41 ++++++--
drivers/net/mlx4/en_port.c | 42 --------
drivers/net/mlx4/en_port.h | 5 -
drivers/net/mlx4/mlx4.h | 19 ++++
drivers/net/mlx4/mlx4_en.h | 1 -
drivers/net/mlx4/port.c | 221 +++++++++++++++++++++++++++++++++++++++++++
include/linux/mlx4/device.h | 1 +
7 files changed, 273 insertions(+), 57 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index f9e8164..e437d74 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -938,7 +938,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL,
- .wrapper = NULL /* need wrapper*/
+ .wrapper = mlx4_SET_VLAN_FLTR_wrapper
},
{
.opcode = MLX4_CMD_SET_MCAST_FLTR,
@@ -946,7 +946,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL,
- .wrapper = NULL /* need wrapper*/
+ .wrapper = mlx4_SET_MCAST_FLTR_wrapper
},
{
.opcode = MLX4_CMD_DUMP_ETH_STATS,
@@ -1177,7 +1177,8 @@ static void mlx4_master_poll_comm(struct work_struct *work)
int mlx4_multi_func_init(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
+ struct mlx4_slave_state *s_state;
+ int i, port;
priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
&priv->mfunc.vhcr_dma,
@@ -1209,16 +1210,27 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
goto err_comm;
for (i = 0; i < dev->num_slaves; ++i) {
- priv->mfunc.master.slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
- spin_lock_init(&priv->mfunc.master.slave_state[i].lock);
+ s_state = &priv->mfunc.master.slave_state[i];
+ s_state->last_cmd = MLX4_COMM_CMD_RESET;
+ for (port = 1; port <= MLX4_MAX_PORTS; port++) {
+ s_state->vlan_filter[port] =
+ kzalloc(sizeof(struct mlx4_vlan_fltr),
+ GFP_KERNEL);
+ if (!s_state->vlan_filter[port]) {
+ if (--port)
+ kfree(s_state->vlan_filter[port]);
+ goto err_slaves;
+ }
+ INIT_LIST_HEAD(&s_state->mcast_filters[port]);
+ }
+ spin_lock_init(&s_state->lock);
}
INIT_DELAYED_WORK(&priv->mfunc.comm_work, mlx4_master_poll_comm);
priv->mfunc.comm_wq = create_singlethread_workqueue("mlx4_comm");
- if (!priv->mfunc.comm_wq) {
- kfree(priv->mfunc.master.slave_state);
- goto err_comm;
- }
+ if (!priv->mfunc.comm_wq)
+ goto err_slaves;
+
} else {
priv->cmd.comm_toggle = 0;
INIT_DELAYED_WORK(&priv->mfunc.comm_work, mlx4_slave_async_eq_poll);
@@ -1228,6 +1240,12 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
}
return 0;
+err_slaves:
+ while (--i) {
+ for (port = 1; port <= MLX4_MAX_PORTS; port++)
+ kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
+ }
+ kfree(priv->mfunc.master.slave_state);
err_comm:
iounmap(priv->mfunc.comm);
err_vhcr:
@@ -1276,9 +1294,14 @@ err_hcr:
void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
+ int i, port;
if (priv->mfunc.vhcr) {
destroy_workqueue(priv->mfunc.comm_wq);
+ for (i = 0; i < dev->num_slaves; i++) {
+ for (port = 1; port <= MLX4_MAX_PORTS; port++)
+ kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
+ }
kfree(priv->mfunc.master.slave_state);
iounmap(priv->mfunc.comm);
dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index 2d55c1a..b099f81 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -41,48 +41,6 @@
#include "mlx4_en.h"
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
- u64 mac, u64 clear, u8 mode)
-{
- return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
- MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B);
-}
-
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_vlan_fltr_mbox *filter;
- int i;
- int j;
- int index = 0;
- u32 entry;
- int err = 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- filter = mailbox->buf;
- if (grp) {
- memset(filter, 0, sizeof *filter);
- for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
- entry = 0;
- for (j = 0; j < 32; j++)
- if (vlan_group_get_device(grp, index++))
- entry |= 1 << j;
- filter->entry[i] = cpu_to_be32(entry);
- }
- } else {
- /* When no vlans are configured we block all vlans */
- memset(filter, 0, sizeof(*filter));
- }
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
- MLX4_CMD_TIME_CLASS_B);
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-
int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
{
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index f7a367b..8b221d6 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -77,11 +77,6 @@ struct mlx4_set_port_rqp_calc_context {
__be32 mcast;
};
-#define VLAN_FLTR_SIZE 128
-struct mlx4_set_vlan_fltr_mbox {
- __be32 entry[VLAN_FLTR_SIZE];
-};
-
enum {
MLX4_MCAST_CONFIG = 0,
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 3417888..74543d7 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -224,6 +224,16 @@ struct mlx4_slave_eqe {
u32 param;
};
+struct mlx4_mcast_entry {
+ struct list_head list;
+ u64 addr;
+};
+
+#define VLAN_FLTR_SIZE 128
+struct mlx4_vlan_fltr {
+ __be32 entry[VLAN_FLTR_SIZE];
+};
+
struct mlx4_slave_state {
u8 comm_toggle;
u8 last_cmd;
@@ -232,6 +242,8 @@ struct mlx4_slave_state {
u16 mtu[MLX4_MAX_PORTS + 1];
__be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
+ struct list_head mcast_filters[MLX4_MAX_PORTS + 1];
+ struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1];
u16 eq_pi;
u16 eq_ci;
int sqp_start;
@@ -242,6 +254,7 @@ struct mlx4_mfunc_master_ctx {
struct mlx4_slave_state *slave_state;
int init_port_ref[MLX4_MAX_PORTS + 1];
u16 max_mtu[MLX4_MAX_PORTS + 1];
+ int disable_mcast_ref[MLX4_MAX_PORTS + 1];
};
struct mlx4_vhcr {
@@ -559,5 +572,11 @@ int mlx4_GET_SLAVE_SQP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr
int mlx4_MCAST_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox);
+int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox);
+int mlx4_SET_VLAN_FLTR_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/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 5ea438e..809c45d 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -554,7 +554,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
void mlx4_en_rx_irq(struct mlx4_cq *mcq);
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp);
int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 5654fff..1bec155 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -32,6 +32,7 @@
#include <linux/errno.h>
#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
#include <linux/mlx4/cmd.h>
@@ -491,3 +492,223 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
+
+static int mlx4_common_set_mcast_fltr(struct mlx4_dev *dev, int function,
+ int port, u64 addr, u64 clear, u8 mode)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int err = 0;
+ struct mlx4_mcast_entry *entry, *tmp;
+ struct mlx4_slave_state *s_state = &priv->mfunc.master.slave_state[function];
+ int i;
+
+ switch (mode) {
+ case MLX4_MCAST_DISABLE:
+ /* The multicast filter is disabled only once,
+ * If some other function already done it, operation
+ * is ignored */
+ if (!(priv->mfunc.master.disable_mcast_ref[port]++))
+ err = mlx4_cmd(dev, 0, port, MLX4_MCAST_DISABLE,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ break;
+ case MLX4_MCAST_ENABLE:
+ /* We enable the muticast filter only if all functions
+ * have the filter enabled */
+ if (!(--priv->mfunc.master.disable_mcast_ref[port]))
+ err = mlx4_cmd(dev, 0, port, MLX4_MCAST_ENABLE,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ break;
+ case MLX4_MCAST_CONFIG:
+ if (clear) {
+ /* Disable the muticast filter while updating it */
+ if (!priv->mfunc.master.disable_mcast_ref[port]) {
+ err = mlx4_cmd(dev, 0, port, MLX4_MCAST_DISABLE,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ if (err) {
+ mlx4_warn(dev, "Failed to disable multicast "
+ "filter\n");
+ goto out;
+ }
+ }
+ /* Clear the multicast filter */
+ err = mlx4_cmd(dev, clear << 63, port,
+ MLX4_MCAST_CONFIG,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ if (err) {
+ mlx4_warn(dev, "Failed clearing the multicast filter\n");
+ goto out;
+ }
+
+ /* Clear the multicast addresses for the given slave */
+ list_for_each_entry_safe(entry, tmp,
+ &s_state->mcast_filters[port],
+ list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+
+ /* Assign all the multicast addresses that still exist */
+ for (i = 0; i < dev->num_slaves; i++) {
+ list_for_each_entry(entry,
+ &priv->mfunc.master.slave_state[function].mcast_filters[port],
+ list) {
+ if (mlx4_cmd(dev, entry->addr, port,
+ MLX4_MCAST_CONFIG,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B))
+ mlx4_warn(dev, "Failed to reconfigure "
+ "multicast address: 0x%llx\n",
+ entry->addr);
+ }
+ }
+ /* Enable the filter */
+ if (!priv->mfunc.master.disable_mcast_ref[port]) {
+ err = mlx4_cmd(dev, 0, port, MLX4_MCAST_ENABLE,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ if (err) {
+ mlx4_warn(dev, "Failed to enable multicast "
+ "filter\n");
+ goto out;
+ }
+ }
+ }
+ /* Add the new address if exists */
+ if (addr) {
+ entry = kzalloc(sizeof (struct mlx4_mcast_entry),
+ GFP_KERNEL);
+ if (!entry) {
+ mlx4_warn(dev, "Failed to allocate entry for "
+ "muticast address\n");
+ err = -ENOMEM;
+ goto out;
+ }
+ INIT_LIST_HEAD(&entry->list);
+ entry->addr = addr;
+ list_add_tail(&entry->list, &s_state->mcast_filters[port]);
+ err = mlx4_cmd(dev, addr, port, MLX4_MCAST_CONFIG,
+ MLX4_CMD_SET_MCAST_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ mlx4_warn(dev, "Failed to add the new address:"
+ "0x%llx\n", addr);
+ }
+ break;
+ default:
+ mlx4_warn(dev, "SET_MCAST_FILTER called with illegal modifier\n");
+ err = -EINVAL;
+ }
+out:
+ return err;
+}
+
+int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ int port = vhcr->in_modifier;
+ u64 addr = vhcr->in_param & 0xffffffffffffULL;
+ u64 clear = vhcr->in_param >> 63;
+ u8 mode = vhcr->op_modifier;
+
+ return mlx4_common_set_mcast_fltr(dev, slave, port, addr, clear, mode);
+}
+
+int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
+ u64 mac, u64 clear, u8 mode)
+{
+ if (mlx4_is_master(dev))
+ return mlx4_common_set_mcast_fltr(dev, dev->caps.function,
+ port, mac, clear, mode);
+ else
+ return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
+ MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B);
+}
+EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR);
+
+
+static int mlx4_common_set_vlan_fltr(struct mlx4_dev *dev, int function,
+ int port, void *buf)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_vlan_fltr *filter;
+ struct mlx4_slave_state *s_state = &priv->mfunc.master.slave_state[function];
+ int i, j, err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ /* Update slave's Vlan filter */
+ memcpy(s_state->vlan_filter[port]->entry, buf,
+ sizeof(struct mlx4_vlan_fltr));
+
+ /* We configure the Vlan filter to allow the vlans of
+ * all slaves */
+ filter = mailbox->buf;
+ memset(filter, 0, sizeof(*filter));
+ for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
+ for (j = 0; j < dev->num_slaves; j++) {
+ s_state = &priv->mfunc.master.slave_state[j];
+ filter->entry[i] |= s_state->vlan_filter[port]->entry[i];
+ }
+ }
+ err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
+int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ return mlx4_common_set_vlan_fltr(dev, slave, vhcr->in_modifier,
+ inbox->buf);
+}
+
+
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_vlan_fltr *filter;
+ int i;
+ int j;
+ int index = 0;
+ u32 entry;
+ int err = 0;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ filter = mailbox->buf;
+ if (grp) {
+ memset(filter, 0, sizeof *filter);
+ for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
+ entry = 0;
+ for (j = 0; j < 32; j++)
+ if (vlan_group_get_device(grp, index++))
+ entry |= 1 << j;
+ filter->entry[i] = cpu_to_be32(entry);
+ }
+ } else {
+ /* When no vlans are configured we block all vlans */
+ memset(filter, 0, sizeof(*filter));
+ }
+ if (mlx4_is_master(dev))
+ err = mlx4_common_set_vlan_fltr(dev, dev->caps.function,
+ port, mailbox->buf);
+ else
+ err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_SET_VLAN_FLTR);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 9bdfbab..8e51af5 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -505,6 +505,7 @@ int mlx4_multicast_attach(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_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
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);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 19/23 v3] mlx4: SET port for Ethernet moved to mlx4_core
[not found] <49BFC313.1030901@mellanox.co.il>
` (18 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 18/23 v3] mlx4_core: Managing common port filters by master function Yevgeny Petrilin
@ 2010-02-04 15:56 ` Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 20/23 v3] mlx4_core: binding virtual function to physical function Yevgeny Petrilin
` (3 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
The physical port is common resource for all the functions.
Its management should go through the multifunction mechanism.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_port.c | 64 -------------------------
drivers/net/mlx4/en_port.h | 43 -----------------
drivers/net/mlx4/mlx4.h | 44 ++++++++++++++++++
drivers/net/mlx4/port.c | 107 ++++++++++++++++++++++++++++++++++++++-----
include/linux/mlx4/device.h | 5 ++
5 files changed, 144 insertions(+), 119 deletions(-)
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index b099f81..2863a30 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -41,70 +41,6 @@
#include "mlx4_en.h"
-int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
- u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_general_context *context;
- int err;
- u32 in_mod;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- context->flags = SET_PORT_GEN_ALL_VALID;
- context->mtu = cpu_to_be16(mtu);
- context->pptx = (pptx * (!pfctx)) << 7;
- context->pfctx = pfctx;
- context->pprx = (pprx * (!pfcrx)) << 7;
- context->pfcrx = pfcrx;
-
- in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
- u8 promisc)
-{
- struct mlx4_cmd_mailbox *mailbox;
- 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))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- 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(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;
- context->vlan_miss = MLX4_VLAN_MISS_IDX;
-
- in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
{
struct mlx4_en_stat_out_mbox *mlx4_en_stats;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index 8b221d6..40918ab 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -35,49 +35,6 @@
#define _MLX4_EN_PORT_H_
-#define SET_PORT_GEN_ALL_VALID 0x7
-#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];
- u8 flags;
- u16 reserved2;
- __be16 mtu;
- u8 pptx;
- u8 pfctx;
- u16 reserved3;
- u8 pprx;
- u8 pfcrx;
- u16 reserved4;
-};
-
-struct mlx4_set_port_rqp_calc_context {
- __be32 base_qpn;
- u8 rererved;
- u8 n_mac;
- u8 n_vlan;
- u8 n_prio;
- u8 reserved2[3];
- u8 mac_miss;
- u8 intra_no_vlan;
- u8 no_vlan;
- u8 intra_vlan_miss;
- u8 vlan_miss;
- u8 reserved3[3];
- u8 no_vlan_prio;
- __be32 promisc;
- __be32 mcast;
-};
-
-
enum {
MLX4_MCAST_CONFIG = 0,
MLX4_MCAST_DISABLE = 1,
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 74543d7..1cc4c13 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -382,6 +382,50 @@ struct mlx4_vlan_table {
int max;
};
+
+#define SET_PORT_GEN_ALL_VALID 0x7
+#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];
+ u8 flags;
+ u16 reserved2;
+ __be16 mtu;
+ u8 pptx;
+ u8 pfctx;
+ u16 reserved3;
+ u8 pprx;
+ u8 pfcrx;
+ u16 reserved4;
+};
+
+struct mlx4_set_port_rqp_calc_context {
+ __be32 base_qpn;
+ u8 rererved;
+ u8 n_mac;
+ u8 n_vlan;
+ u8 n_prio;
+ u8 reserved2[3];
+ u8 mac_miss;
+ u8 intra_no_vlan;
+ u8 no_vlan;
+ u8 intra_vlan_miss;
+ u8 vlan_miss;
+ u8 reserved3[3];
+ u8 no_vlan_prio;
+ __be32 promisc;
+ __be32 mcast;
+};
+
+
struct mlx4_port_info {
struct mlx4_dev *dev;
int port;
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 1bec155..e94a373 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -348,9 +348,8 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
return err;
}
-int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox)
+static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
+ u8 op_mod, struct mlx4_cmd_mailbox *inbox)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_port_info *port_info;
@@ -370,9 +369,9 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc
__be32 slave_cap_mask;
__be32 new_cap_mask;
- port = vhcr->in_modifier & 0xff;
- in_modifier = vhcr->in_modifier >> 8;
- is_eth = vhcr->op_modifier;
+ port = in_mod & 0xff;
+ in_modifier = in_mod >> 8;
+ is_eth = op_mod;
port_info = &priv->port[port];
/* All slaves can perform SET_PORT operations, just need to verify
@@ -417,10 +416,8 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc
gen_context->mtu = cpu_to_be16(master->max_mtu[port]);
break;
}
- return mlx4_cmd(dev, inbox->dma, vhcr->in_modifier,
- vhcr->op_modifier,
- MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B);
+ return mlx4_cmd(dev, inbox->dma, in_mod, op_mod,
+ MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B);
}
/* For IB, we only consider:
@@ -471,6 +468,16 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc
return err;
}
+int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ return mlx4_common_set_port(dev, slave, vhcr->in_modifier,
+ vhcr->op_modifier, inbox);
+}
+
+
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
{
struct mlx4_cmd_mailbox *mailbox;
@@ -486,12 +493,88 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
memset(mailbox->buf, 0, 256);
((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B);
+
+ if (mlx4_is_master(dev))
+ err = mlx4_common_set_port(dev, dev->caps.function, port, 0, mailbox);
+ else
+ err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+
+
+int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
+ u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_set_port_general_context *context;
+ int err;
+ u32 in_mod;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ context = mailbox->buf;
+ memset(context, 0, sizeof *context);
+
+ context->flags = SET_PORT_GEN_ALL_VALID;
+ context->mtu = cpu_to_be16(mtu);
+ context->pptx = (pptx * (!pfctx)) << 7;
+ context->pfctx = pfctx;
+ context->pprx = (pprx * (!pfcrx)) << 7;
+ context->pfcrx = pfcrx;
+
+ in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
+ if (mlx4_is_master(dev))
+ err = mlx4_common_set_port(dev, dev->caps.function, in_mod, 1, mailbox);
+ else
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_SET_PORT_general);
+
+int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
+ u8 promisc)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ 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))
+ return PTR_ERR(mailbox);
+ context = mailbox->buf;
+ memset(context, 0, sizeof *context);
+
+ 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(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;
+ context->vlan_miss = MLX4_VLAN_MISS_IDX;
+
+ in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
+ if (mlx4_is_master(dev))
+ err = mlx4_common_set_port(dev, dev->caps.function, in_mod, 1, mailbox);
+ else
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
+EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc);
static int mlx4_common_set_mcast_fltr(struct mlx4_dev *dev, int function,
int port, u64 addr, u64 clear, u8 mode)
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 8e51af5..a52caf6 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -498,6 +498,11 @@ void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
+int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
+ u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
+int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
+ u8 promisc);
+
int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 20/23 v3] mlx4_core: binding virtual function to physical function
[not found] <49BFC313.1030901@mellanox.co.il>
` (19 preceding siblings ...)
2010-02-04 15:56 ` [PATCH 19/23 v3] mlx4: SET port for Ethernet moved to mlx4_core Yevgeny Petrilin
@ 2010-02-04 15:57 ` Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 21/23 v3] mlx4_core: Adding VEP number in resource allocation Yevgeny Petrilin
` (2 subsequent siblings)
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 8 ++++++++
drivers/net/mlx4/fw.c | 23 +++++++++++++++++++++++
drivers/net/mlx4/fw.h | 1 +
drivers/net/mlx4/main.c | 4 ++--
drivers/net/mlx4/mcg.c | 3 ++-
drivers/net/mlx4/mlx4.h | 2 ++
drivers/net/mlx4/port.c | 5 +++--
include/linux/mlx4/cmd.h | 1 +
8 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index e437d74..2605344 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -422,9 +422,11 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox)
{
+ struct mlx4_priv *priv = mlx4_priv(dev);
u32 param1 = *((u32 *) &vhcr->in_param);
u32 param2 = *(((u32 *) &vhcr->in_param) + 1);
int ret;
+ u8 pf_num = priv->mfunc.master.slave_state[slave].pf_num;
#if 0
char *res[] = {"QP", "CQ", "SRQ", "MPT", "MTT"};
@@ -507,6 +509,7 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
mlx4_free_mtt_range(dev, param1 /* first */, param2 /* order */);
break;
case RES_MAC:
+ vhcr->in_param |= (u64) (pf_num) << 48;
switch (vhcr->op) {
case MLX4_CMD_ALLOC_RES:
ret = mlx4_register_mac(dev, vhcr->op_modifier,
@@ -1119,6 +1122,11 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u16 para
if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
goto reset_slave;
slave_state[slave].vhcr_dma |= param;
+ if (mlx4_QUERY_FUNC(dev, slave, &slave_state[slave].pf_num)) {
+ mlx4_err(dev, "Failed to determine physical function "
+ "number for slave %d\n", slave);
+ goto reset_slave;
+ }
break;
case MLX4_COMM_CMD_VHCR_POST:
if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 202a256..18294c3 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -1038,3 +1038,26 @@ int mlx4_NOP(struct mlx4_dev *dev)
/* Input modifier of 0x1f means "finish as soon as possible." */
return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
}
+
+int mlx4_QUERY_FUNC(struct mlx4_dev *dev, int func, u8 *pf_num)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ u8 *outbox;
+ int ret;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ outbox = mailbox->buf;
+
+ ret = mlx4_cmd_box(dev, 0, mailbox->dma, func & 0xff, 0,
+ MLX4_CMD_QUERY_FUNC, MLX4_CMD_TIME_CLASS_A);
+ if (ret)
+ goto out;
+
+ *pf_num = outbox[3];
+
+out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return ret;
+}
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index e033d26..4ec92f4 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -181,5 +181,6 @@ int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
int mlx4_NOP(struct mlx4_dev *dev);
int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg);
+int mlx4_QUERY_FUNC(struct mlx4_dev *dev, int func, u8 *pf_num);
#endif /* MLX4_FW_H */
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index d825cc1..b57bac2 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -276,7 +276,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
}
}
- mlx4_set_port_mask(dev, &dev->caps, dev->caps.pf_num);
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
@@ -389,7 +389,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
goto out;
}
}
- mlx4_set_port_mask(dev, &dev->caps, dev->caps.pf_num);
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
err = mlx4_register_device(dev);
}
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 9a678d2..4e2b422 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -361,9 +361,10 @@ int mlx4_MCAST_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
struct mlx4_qp qp; /* dummy for calling attach/detach */
u8 *gid = inbox->buf;
enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;
+ u8 pf_num = mlx4_priv(dev)->mfunc.master.slave_state[slave].pf_num;
if (prot == MLX4_PROT_ETH)
- gid[7] = slave << 4;
+ gid[7] = pf_num << 4;
qp.qpn = vhcr->in_modifier & 0xffffff;
if (vhcr->op_modifier)
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 1cc4c13..cdf6aff 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -238,6 +238,8 @@ struct mlx4_slave_state {
u8 comm_toggle;
u8 last_cmd;
u8 init_port_mask;
+ u8 pf_num;
+ u8 function;
dma_addr_t vhcr_dma;
u16 mtu[MLX4_MAX_PORTS + 1];
__be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index e94a373..22a224e 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -104,7 +104,8 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
if (!err)
*qpn = out_param;
return err;
- }
+ } else
+ mac |= (u64) (dev->caps.function) << 48;
mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
mutex_lock(&table->mutex);
@@ -115,7 +116,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
}
if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
- /* MAC already registered, Must not have duplicates */
+ /* MAC + PF already registered, Must not have duplicates */
err = -EEXIST;
goto out;
}
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 9526dfd..0b68447 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -57,6 +57,7 @@ enum {
MLX4_CMD_QUERY_PORT = 0x43,
MLX4_CMD_SENSE_PORT = 0x4d,
MLX4_CMD_SET_PORT = 0xc,
+ MLX4_CMD_QUERY_FUNC = 0x56,
MLX4_CMD_ACCESS_DDR = 0x2e,
MLX4_CMD_MAP_ICM = 0xffa,
MLX4_CMD_UNMAP_ICM = 0xff9,
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 21/23 v3] mlx4_core: Adding VEP number in resource allocation
[not found] <49BFC313.1030901@mellanox.co.il>
` (20 preceding siblings ...)
2010-02-04 15:57 ` [PATCH 20/23 v3] mlx4_core: binding virtual function to physical function Yevgeny Petrilin
@ 2010-02-04 15:57 ` Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 22/23 v3] mlx4_en: Use reasonable resources for slaves Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 23/23 v3] mlx4_en: querying link state Yevgeny Petrilin
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
Each slave would have its relative range of resources.
Specifying the function number at resource allocation allows the firmware
to calculate the absolute resource number
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/cmd.c | 58 ++++++++++++++++++++++++++++++++++-------------
drivers/net/mlx4/fw.c | 2 +-
2 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 2605344..7eab34d 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -533,6 +533,32 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
return 0;
}
+static int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ u64 in_param = inbox ? inbox->dma : vhcr->in_param;
+
+ in_param |= (u64) slave;
+ return mlx4_cmd(dev, in_param, vhcr->in_modifier,
+ vhcr->op_modifier, vhcr->op, MLX4_CMD_TIME_CLASS_C);
+}
+
+static int mlx4_DMA_outbox_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox)
+{
+ u64 in_param = inbox ? inbox->dma : vhcr->in_param;
+ u64 out_param = outbox ? outbox->dma : vhcr->out_param;
+
+ in_param |= (u64) slave;
+ return mlx4_cmd_box(dev, in_param, out_param,
+ vhcr->in_modifier, vhcr->op_modifier, vhcr->op,
+ MLX4_CMD_TIME_CLASS_C);
+}
+
static struct mlx4_cmd_info {
u16 opcode;
bool has_inbox;
@@ -615,7 +641,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /*need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_NOP,
@@ -664,7 +690,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL,
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_QUERY_MPT,
@@ -710,10 +736,10 @@ static struct mlx4_cmd_info {
{
.opcode = MLX4_CMD_HW2SW_EQ,
.has_inbox = false,
- .has_outbox = false,
+ .has_outbox = true,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_outbox_wrapper
},
{
.opcode = MLX4_CMD_QUERY_EQ,
@@ -729,7 +755,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_HW2SW_CQ,
@@ -737,7 +763,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_QUERY_CQ,
@@ -761,7 +787,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_HW2SW_SRQ,
@@ -793,7 +819,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_INIT2RTR_QP,
@@ -801,7 +827,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_RTR2RTS_QP,
@@ -809,7 +835,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_RTS2RTS_QP,
@@ -817,7 +843,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_SQERR2RTS_QP,
@@ -825,7 +851,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_2ERR_QP,
@@ -833,7 +859,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_RTS2SQD_QP,
@@ -841,7 +867,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_SQD2SQD_QP,
@@ -849,7 +875,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_SQD2RTS_QP,
@@ -857,7 +883,7 @@ static struct mlx4_cmd_info {
.has_outbox = false,
.out_is_imm = false,
.verify = NULL, /* need verifier */
- .wrapper = NULL
+ .wrapper = mlx4_DMA_wrapper
},
{
.opcode = MLX4_CMD_2RST_QP,
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 18294c3..18a35af 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -300,7 +300,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET);
dev_cap->max_mpts = 1 << (field & 0x3f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET);
- dev_cap->reserved_eqs = field & 0xf;
+ dev_cap->reserved_eqs = field & 0xff;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET);
dev_cap->max_eqs = 1 << (field & 0xf);
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 22/23 v3] mlx4_en: Use reasonable resources for slaves
[not found] <49BFC313.1030901@mellanox.co.il>
` (21 preceding siblings ...)
2010-02-04 15:57 ` [PATCH 21/23 v3] mlx4_core: Adding VEP number in resource allocation Yevgeny Petrilin
@ 2010-02-04 15:57 ` Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 23/23 v3] mlx4_en: querying link state Yevgeny Petrilin
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
>From d42a1ac0bbfeb2522e11d2aca2f41396b070d6eb Mon Sep 17 00:00:00 2001
From: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Date: Fri, 6 Nov 2009 01:10:28 +0200
Subject: [PATCH 22/23] mlx4_en: Use reasonable resources for slaves.
Each slave gets a single MSI-X vector when in multi function mode.
In this case each slave would allocate less resources (which
normally depend on number of completion vectors).
We set a minimum number of RX and TX queues to achieve an
acceptable performance in multi function mode.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_main.c | 12 +++++++-----
drivers/net/mlx4/en_netdev.c | 3 ++-
drivers/net/mlx4/en_tx.c | 2 +-
drivers/net/mlx4/mlx4_en.h | 8 +++++---
4 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 507e11f..3883071 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -93,8 +93,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->prof[i].tx_ppp = pfctx;
params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
- params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
- (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
}
return 0;
@@ -216,11 +214,15 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
/* If we did not receive an explicit number of Rx rings, default to
* the number of completion vectors populated by the mlx4_core */
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+ mdev->profile.prof[i].tx_ring_num = max_t(int,
+ min_t(int, roundup_pow_of_two(dev->caps.num_comp_vectors),
+ NUM_TX_RINGS), MIN_TX_RINGS) +
+ (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
mlx4_info(mdev, "Using %d tx rings for port:%d\n",
mdev->profile.prof[i].tx_ring_num, i);
- mdev->profile.prof[i].rx_ring_num = min_t(int,
- roundup_pow_of_two(dev->caps.num_comp_vectors),
- MAX_RX_RINGS);
+ mdev->profile.prof[i].rx_ring_num = max_t(int,
+ min_t(int, roundup_pow_of_two(dev->caps.num_comp_vectors),
+ MAX_RX_RINGS), MIN_RX_RINGS);
mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
mdev->profile.prof[i].rx_ring_num, i);
}
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 751c79d..947fb2f 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1053,7 +1053,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
*/
dev->netdev_ops = &mlx4_netdev_ops;
dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
- dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS;
+ dev->real_num_tx_queues = priv->tx_ring_num -
+ !!(priv->prof->rx_ppp) * MLX4_EN_NUM_PPP_RINGS;
SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index d4af0fe..b8e994d 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -583,7 +583,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
*/
if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) {
vlan_tag = vlan_tx_tag_get(skb);
- return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
+ return priv->tx_ring_num - MLX4_EN_NUM_PPP_RINGS + (vlan_tag >> 13);
}
return skb_tx_hash(dev, skb);
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 809c45d..834fd24 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -93,8 +93,11 @@
#define MLX4_EN_PAGE_SHIFT 12
#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_TX_RINGS 16
-#define MAX_RX_RINGS 16
+#define MAX_TX_RINGS 12
+#define MAX_RX_RINGS 8
+#define MIN_RX_RINGS 4
+#define NUM_TX_RINGS 4
+#define MIN_TX_RINGS 4
#define TXBB_SIZE 64
#define HEADROOM (2048 / TXBB_SIZE + 1)
#define STAMP_STRIDE 64
@@ -137,7 +140,6 @@ enum {
#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
#define MLX4_EN_SMALL_PKT_SIZE 64
-#define MLX4_EN_NUM_TX_RINGS 8
#define MLX4_EN_NUM_PPP_RINGS 8
#define MLX4_EN_DEF_TX_RING_SIZE 512
#define MLX4_EN_DEF_RX_RING_SIZE 1024
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 23/23 v3] mlx4_en: querying link state
[not found] <49BFC313.1030901@mellanox.co.il>
` (22 preceding siblings ...)
2010-02-04 15:57 ` [PATCH 22/23 v3] mlx4_en: Use reasonable resources for slaves Yevgeny Petrilin
@ 2010-02-04 15:57 ` Yevgeny Petrilin
23 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In multifunction device, a certain function can initialize its port after some
other function already done that. In that case link event would not be generated.
Need to query the port to retrieve the port state.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_netdev.c | 10 ++++++++++
drivers/net/mlx4/en_port.c | 31 +++++++++++++++++++++++++++++++
drivers/net/mlx4/en_port.h | 15 +++++++++++++++
drivers/net/mlx4/mlx4_en.h | 8 ++++++++
4 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 947fb2f..22511ec 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -229,6 +229,16 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
goto out;
}
+ if (!netif_carrier_ok(dev)) {
+ if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
+ if (priv->port_state.link_state) {
+ priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
+ netif_carrier_on(dev);
+ en_dbg(LINK, priv, "Link Up\n");
+ }
+ }
+ }
+
/*
* Promsicuous mode: disable all filters
*/
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index 2863a30..8b3c537 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -41,6 +41,37 @@
#include "mlx4_en.h"
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
+{
+ struct mlx4_en_query_port_context *qport_context;
+ struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+ struct mlx4_en_port_state *state = &priv->port_state;
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ memset(mailbox->buf, 0, sizeof(*qport_context));
+ err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
+ MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ goto out;
+ qport_context = mailbox->buf;
+
+ state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
+ if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
+ MLX4_EN_1G_SPEED)
+ state->link_speed = 1000;
+ else
+ state->link_speed = 10000;
+ state->transciver = qport_context->transceiver;
+
+out:
+ mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+ return err;
+}
+
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
{
struct mlx4_en_stat_out_mbox *mlx4_en_stats;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index 40918ab..8c387a0 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -42,6 +42,21 @@ enum {
};
+struct mlx4_en_query_port_context {
+ u8 link_up;
+#define MLX4_EN_LINK_UP_MASK 0x80
+ u8 reserved;
+ __be16 mtu;
+ u8 reserved2;
+ u8 link_speed;
+#define MLX4_EN_SPEED_MASK 0x3
+#define MLX4_EN_1G_SPEED 0x2
+ u16 reserved3[5];
+ __be64 mac;
+ u8 transceiver;
+};
+
+
struct mlx4_en_stat_out_mbox {
/* Received frames with a length of 64 octets */
__be64 R64_prio_0;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 834fd24..5f6c080 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -391,6 +391,12 @@ struct mlx4_en_rss_context {
__be32 rss_key[10];
};
+struct mlx4_en_port_state {
+ int link_state;
+ int link_speed;
+ int transciver;
+};
+
struct mlx4_en_pkt_stats {
unsigned long broadcast;
unsigned long rx_prio[8];
@@ -439,6 +445,7 @@ struct mlx4_en_priv {
struct vlan_group *vlgrp;
struct net_device_stats stats;
struct net_device_stats ret_stats;
+ struct mlx4_en_port_state port_state;
spinlock_t stats_lock;
unsigned long last_moder_packets;
@@ -563,6 +570,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
u8 promisc);
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
u64 mlx4_en_mac_to_u64(u8 *addr);
/*
--
1.6.1.3
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 14/23 v3] mlx4_core: Determine primary physical function
2010-02-04 15:56 ` [PATCH 14/23 v3] mlx4_core: Determine primary physical function Yevgeny Petrilin
@ 2010-02-04 22:30 ` Roland Dreier
2010-02-06 6:26 ` Yevgeny Petrilin
0 siblings, 1 reply; 34+ messages in thread
From: Roland Dreier @ 2010-02-04 22:30 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: general, netdev, liranl, tziporet
> + MLX4_FLAG_PF = 1 << 5,
Am I mistaken, or is this the only place this flag appears anywhere in
the patch set? In other words it is never set and never tested -- so
probably we don't need it?
> + dev_cap->pf_num = field;
> + if (dev_cap->pf_num > 1)
> + dev->flags |= MLX4_FLAG_MASTER;
Is this correct? All PFs > 1 are masters? Or should the test be "== 1"
rather than "> 1" instead?
--
Roland Dreier <rolandd@cisco.com>
Cisco.com - http://www.cisco.com
For corporate legal information go to:
http://www.cisco.com/web/about/doing_business/legal/cri/index.html
^ permalink raw reply [flat|nested] 34+ messages in thread
* RE: [PATCH 14/23 v3] mlx4_core: Determine primary physical function
2010-02-04 22:30 ` Roland Dreier
@ 2010-02-06 6:26 ` Yevgeny Petrilin
0 siblings, 0 replies; 34+ messages in thread
From: Yevgeny Petrilin @ 2010-02-06 6:26 UTC (permalink / raw)
To: Roland Dreier
Cc: general@lists.openfabrics.org, netdev@vger.kernel.org, Liran Liss,
Tziporet Koren
>> + MLX4_FLAG_PF = 1 << 5,
>
> Am I mistaken, or is this the only place this flag appears anywhere in the patch set? In other words it is never set and never tested -- so probably we > don't need it?
That is correct
>> + dev_cap->pf_num = field;
>> + if (dev_cap->pf_num > 1)
>> + dev->flags |= MLX4_FLAG_MASTER;
>
> Is this correct? All PFs > 1 are masters? Or should the test be "== 1"
> rather than "> 1" instead?
No, It means that if some function get notified that there are more then 1 physical functions on the device, it should act as master.
Thanks,
Yevgeny
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 01/23 v3] mlx4_core: identify function as pf or vf
2010-02-04 15:54 ` [PATCH 01/23 v3] mlx4_core: identify function as pf or vf Yevgeny Petrilin
@ 2010-02-09 13:41 ` Ben Hutchings
0 siblings, 0 replies; 34+ messages in thread
From: Ben Hutchings @ 2010-02-09 13:41 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, general, netdev, liranl, tziporet
The summary 'mlx4_core: identify function as pf or vf' doesn't match the
implementation. Patch 14 'mlx4_core: Determine primary physical
function' makes it clear that a PF can also be a 'slave'.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 02/23 v3] mlx4_core: add multi-function communication channel
2010-02-04 15:54 ` [PATCH 02/23 v3] mlx4_core: add multi-function communication channel Yevgeny Petrilin
@ 2010-02-09 14:37 ` Ben Hutchings
0 siblings, 0 replies; 34+ messages in thread
From: Ben Hutchings @ 2010-02-09 14:37 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, general, netdev, liranl, tziporet
On Thu, 2010-02-04 at 17:54 +0200, Yevgeny Petrilin wrote:
> The communication channel consists of 2 registers per vf (a slave function)
> that are shared with the pf (the master function), as well as a new command for
> inter-function memory copying (only exposed to the master).
>
> The communication channel is used to establish a Virtual HCA Command Register
> (vHCR) in each slave function, which allows it to pass FW commands to the master
> function for execution.
> The slave also uses the vHCR to pull slave-specific events from the master.
>
> Signed-off-by: Liran Liss <liranl@mellanox.co.il>
> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
> ---
> drivers/net/mlx4/cmd.c | 746 ++++++++++++++++++++++++++++++++++++++++++-
> drivers/net/mlx4/en_port.h | 5 -
> drivers/net/mlx4/eq.c | 67 ++++
> drivers/net/mlx4/fw.c | 8 +
> drivers/net/mlx4/mlx4.h | 72 ++++-
> include/linux/mlx4/cmd.h | 12 +-
> include/linux/mlx4/device.h | 3 +-
> 7 files changed, 895 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
> index 65ec77d..6c3d25c 100644
> --- a/drivers/net/mlx4/cmd.c
> +++ b/drivers/net/mlx4/cmd.c
> @@ -140,6 +140,46 @@ static int mlx4_status_to_errno(u8 status)
> return trans_table[status];
> }
>
> +static int comm_pending(struct mlx4_dev *dev)
> +{
> + struct mlx4_priv *priv = mlx4_priv(dev);
> + u32 status = readl(&priv->mfunc.comm->slave_read);
> +
> + return (swab32(status) >> 30) != priv->cmd.comm_toggle;
> +}
> +
> +int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, unsigned long timeout)
> +{
> + struct mlx4_priv *priv = mlx4_priv(dev);
> + unsigned long end;
> + u32 val;
> +
> + /* First, verify that the master reports correct status */
> + if (comm_pending(dev)) {
> + mlx4_warn(dev, "Communication channel is not idle\n");
> + return -EAGAIN;
> + }
> +
> + /* Write command */
> + if (cmd == MLX4_COMM_CMD_RESET)
> + priv->cmd.comm_toggle = 0;
> + else if (++priv->cmd.comm_toggle > 2)
> + priv->cmd.comm_toggle = 1;
> + val = param | (cmd << 16) | (priv->cmd.comm_toggle << 30);
> + __raw_writel((__force u32) cpu_to_be32(val), &priv->mfunc.comm->slave_write);
> + wmb();
I think you need a wmb() *before* writing the command, so that its
parameters are visible. I don't see why you would need a wmb()
afterward; maybe you want mmiowb()?
I also suggest you encapsulate this byte-swapping in inline functions:
static inline u32 comm_read(void __iomem *addr)
{
return be32_to_cpu((__force __be32) __raw_readl(addr));
}
static inline void comm_write(u32 val, void __iomem *addr)
{
__raw_writel((__force u32) cpu_to_be32(val), addr);
mmiowb();
}
[...]
> +static struct mlx4_cmd_info {
> + u16 opcode;
> + bool has_inbox;
> + bool has_outbox;
> + bool out_is_imm;
> + int (*verify)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
> + struct mlx4_cmd_mailbox *inbox);
> + int (*wrapper)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
> + struct mlx4_cmd_mailbox *inbox,
> + struct mlx4_cmd_mailbox *outbox);
> +} cmd_info[] = {
[...]
> + {
> + .opcode = MLX4_CMD_SW2HW_EQ,
> + .has_inbox = true,
> + .has_outbox = false,
> + .out_is_imm = false,
> + .verify = NULL, /*need verifier */
> + .wrapper = NULL
> + },
What does 'need verifier' mean? Is this implementation incomplete?
> +static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave)
> +{
[...]
> + /* Execute the command! */
> + if (cmd->wrapper)
> + vhcr->errno = cmd->wrapper(dev, slave, vhcr, inbox, outbox);
> + else {
> + in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param;
> + out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param;
> + vhcr->errno = __mlx4_cmd(dev, in_param, &out_param,
> + cmd->out_is_imm,
> + vhcr->in_modifier,
> + vhcr->op_modifier,
> + vhcr->op,
> + vhcr->timeout);
> + if (cmd->out_is_imm)
> + vhcr->out_param = out_param;
> + }
Both branches should be bracketed.
[...]
> +static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u16 param, u8 toggle)
> +{
[...]
> +reset_slave:
> + /* FIXME: cleanup any slave resources */
[...]
Maybe you should do that in the next version then?
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 04/23 v3] mlx4_core: add slave resource allocation
2010-02-04 15:54 ` [PATCH 04/23 v3] mlx4_core: add slave resource allocation Yevgeny Petrilin
@ 2010-02-09 14:44 ` Ben Hutchings
2010-02-09 17:32 ` Ben Hutchings
0 siblings, 1 reply; 34+ messages in thread
From: Ben Hutchings @ 2010-02-09 14:44 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, general, netdev, liranl, tziporet
On Thu, 2010-02-04 at 17:54 +0200, Yevgeny Petrilin wrote:
> All QPs/CQs/SRQs/MPTs/MTTs are allocated from shared pools, which are owned by
> the master. In addition, all backing ICM memory for these objects is managed by
> the master.
> To allow slaves to allocate resources, ICM allocation is separated from the rest
> of the object state, which is held at the slave.
> Slaves can then reserve resource ranges and allocate ICM over the comm channel.
>
> Signed-off-by: Liran Liss <liranl@mellanox.co.il>
> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
> ---
> drivers/net/mlx4/cmd.c | 110 +++++++++++++++++++++++++++++++++
> drivers/net/mlx4/cq.c | 91 +++++++++++++++++++++-------
> drivers/net/mlx4/mlx4.h | 27 ++++++++
> drivers/net/mlx4/mr.c | 125 ++++++++++++++++++++++++++++++++++----
> drivers/net/mlx4/qp.c | 151 +++++++++++++++++++++++++++++++++-------------
> drivers/net/mlx4/srq.c | 88 ++++++++++++++++++++-------
> include/linux/mlx4/cmd.h | 2 +
> 7 files changed, 496 insertions(+), 98 deletions(-)
>
> diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
> index 9e85330..533ce77 100644
> --- a/drivers/net/mlx4/cmd.c
> +++ b/drivers/net/mlx4/cmd.c
> @@ -417,6 +417,100 @@ static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
> MLX4_CMD_TIME_CLASS_A);
> }
>
> +static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
> + struct mlx4_cmd_mailbox *inbox,
> + struct mlx4_cmd_mailbox *outbox)
> +{
> + u32 param1 = *((u32 *) &vhcr->in_param);
> + u32 param2 = *(((u32 *) &vhcr->in_param) + 1);
> + int ret;
> +
> +#if 0
> + char *res[] = {"QP", "CQ", "SRQ", "MPT", "MTT"};
> + mlx4_warn(dev, "resource wrapper - %s (mode: %s) type:%s param1:%d param2:%d\n",
> + vhcr->op == MLX4_CMD_ALLOC_RES ? "allocate" : "free",
> + vhcr->op_modifier == ICM_RESERVE ? "reserve" :
> + (vhcr->op_modifier == ICM_ALLOC ? "alloc" : "reserve+alloc"),
> + res[vhcr->in_modifier], param1, param2);
> +#endif
Either make this really conditional or remove it. '#if 0' is not
useful.
[...]
> diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
> index ccfe276..3fb9f7f 100644
> --- a/drivers/net/mlx4/cq.c
> +++ b/drivers/net/mlx4/cq.c
[...]
> +void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
> +{
> + struct mlx4_priv *priv = mlx4_priv(dev);
> + struct mlx4_cq_table *cq_table = &priv->cq_table;
> + u64 in_param;
> + int err;
> +
> + if (mlx4_is_slave(dev)) {
> + *((u32 *) &in_param) = cqn;
> + *(((u32 *) &in_param) + 1) = 0;
> + err = mlx4_cmd(dev, in_param, RES_CQ, ICM_RESERVE_AND_ALLOC,
> + MLX4_CMD_FREE_RES,
> + MLX4_CMD_TIME_CLASS_A);
This is fairly disgusting, and surely only works for one byte order. I
think you really want:
in_param = cqn;
[...]
> diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
> index 9e4ab0f..0db7f88 100644
> --- a/drivers/net/mlx4/mr.c
> +++ b/drivers/net/mlx4/mr.c
> @@ -178,10 +178,26 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
> kfree(buddy->num_free);
> }
>
> -static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
> +u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
> {
> struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
> + u64 in_param;
> + u64 out_param;
> u32 seg;
> + int err;
> +
> + if (mlx4_is_slave(dev)) {
> + *((u32 *) &in_param) = order;
> + *(((u32 *) &in_param) + 1) = 0;
> + err = mlx4_cmd_imm(dev, in_param, &out_param, RES_MTT,
> + ICM_RESERVE_AND_ALLOC,
> + MLX4_CMD_ALLOC_RES,
> + MLX4_CMD_TIME_CLASS_A);
Again with the byte-ordering...
> + if (err)
> + return -1;
> + else
> + return out_param;
> + }
>
> seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, order);
> if (seg == -1)
> @@ -219,16 +235,33 @@ int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift,
> }
> EXPORT_SYMBOL_GPL(mlx4_mtt_init);
>
> -void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt)
> +void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order)
> {
> struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
> + u64 in_param;
> + int err;
> +
> + if (mlx4_is_slave(dev)) {
> + *((u32 *) &in_param) = first_seg;
> + *(((u32 *) &in_param) + 1) = order;
> + err = mlx4_cmd(dev, in_param, RES_MTT, ICM_RESERVE_AND_ALLOC,
> + MLX4_CMD_FREE_RES,
> + MLX4_CMD_TIME_CLASS_A);
and here:
in_param = first_seg | (u64)order << 32;
[...]
> +void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
> +{
> + struct mlx4_priv *priv = mlx4_priv(dev);
> + u64 in_param;
> + int err;
> +
> + if (mlx4_is_slave(dev)) {
> + *((u32 *) &in_param) = index;
> + *(((u32 *) &in_param) + 1) = 0;
etc. etc.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 17/23 v3] mlx4_core: Randomize Mac addresses for slaves
2010-02-04 15:56 ` [PATCH 17/23 v3] mlx4_core: Randomize Mac addresses for slaves Yevgeny Petrilin
@ 2010-02-09 17:22 ` Ben Hutchings
0 siblings, 0 replies; 34+ messages in thread
From: Ben Hutchings @ 2010-02-09 17:22 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, general, netdev, liranl, tziporet
On Thu, 2010-02-04 at 17:56 +0200, Yevgeny Petrilin wrote:
> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
> ---
> drivers/net/mlx4/fw.c | 9 +++++++++
> 1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
> index 6e3e1d1..202a256 100644
> --- a/drivers/net/mlx4/fw.c
> +++ b/drivers/net/mlx4/fw.c
> @@ -32,6 +32,7 @@
> * SOFTWARE.
> */
>
> +#include <linux/etherdevice.h>
> #include <linux/mlx4/cmd.h>
> #include <linux/cache.h>
>
> @@ -149,11 +150,19 @@ int mlx4_QUERY_SLAVE_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
> struct mlx4_cmd_mailbox *outbox)
> {
> struct mlx4_caps *caps = outbox->buf;
> + u8 rand_mac[6];
> + int i, j;
>
> memcpy(caps, &dev->caps, sizeof *caps);
>
> /* The Master function is in charge for qp1 of al slaves */
> caps->sqp_demux = 0;
> + for (i = 1; i <= dev->caps.num_ports; ++i) {
> + random_ether_addr(rand_mac);
> + caps->def_mac[i] = 0;
> + for (j = 0; j < ETH_ALEN - 1; j++)
> + caps->def_mac[i] |= ((u64)(rand_mac[j]) << 8 * j);
[...]
Do you really want the last byte to be 0 always?
Assuming you don't, you can avoid the inner loop by writing:
union {
u8 bytes[ETH_ALEN];
__le64 qword;
} rand_mac = {
.qword = 0
};
...
random_ether_addr(rand_mac.bytes);
caps->def_mac[i] = le64_to_cpup(&rand_mac.qword);
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 04/23 v3] mlx4_core: add slave resource allocation
2010-02-09 14:44 ` Ben Hutchings
@ 2010-02-09 17:32 ` Ben Hutchings
0 siblings, 0 replies; 34+ messages in thread
From: Ben Hutchings @ 2010-02-09 17:32 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, netdev, liranl, tziporet
On Tue, 2010-02-09 at 14:44 +0000, Ben Hutchings wrote:
> On Thu, 2010-02-04 at 17:54 +0200, Yevgeny Petrilin wrote:
> > All QPs/CQs/SRQs/MPTs/MTTs are allocated from shared pools, which are owned by
> > the master. In addition, all backing ICM memory for these objects is managed by
> > the master.
> > To allow slaves to allocate resources, ICM allocation is separated from the rest
> > of the object state, which is held at the slave.
> > Slaves can then reserve resource ranges and allocate ICM over the comm channel.
> >
> > Signed-off-by: Liran Liss <liranl@mellanox.co.il>
> > Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
> > ---
> > drivers/net/mlx4/cmd.c | 110 +++++++++++++++++++++++++++++++++
> > drivers/net/mlx4/cq.c | 91 +++++++++++++++++++++-------
> > drivers/net/mlx4/mlx4.h | 27 ++++++++
> > drivers/net/mlx4/mr.c | 125 ++++++++++++++++++++++++++++++++++----
> > drivers/net/mlx4/qp.c | 151 +++++++++++++++++++++++++++++++++-------------
> > drivers/net/mlx4/srq.c | 88 ++++++++++++++++++++-------
> > include/linux/mlx4/cmd.h | 2 +
> > 7 files changed, 496 insertions(+), 98 deletions(-)
> >
> > diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
> > index 9e85330..533ce77 100644
> > --- a/drivers/net/mlx4/cmd.c
> > +++ b/drivers/net/mlx4/cmd.c
> > @@ -417,6 +417,100 @@ static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
> > MLX4_CMD_TIME_CLASS_A);
> > }
> >
> > +static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
> > + struct mlx4_cmd_mailbox *inbox,
> > + struct mlx4_cmd_mailbox *outbox)
> > +{
> > + u32 param1 = *((u32 *) &vhcr->in_param);
> > + u32 param2 = *(((u32 *) &vhcr->in_param) + 1);
[...]
I failed to spot this in the first pass. Really, this is ridiculous.
If you are going to make a habit of passing around pairs of 32-bit
values, declare in_param as a union.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 16/23 v3] mlx4_core: Multi-Function MCG support
[not found] ` <4B6AEE30.30202-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org>
@ 2010-02-10 7:35 ` Or Gerlitz
0 siblings, 0 replies; 34+ messages in thread
From: Or Gerlitz @ 2010-02-10 7:35 UTC (permalink / raw)
To: Yevgeny Petrilin
Cc: Roland Dreier, netdev-u79uwXL29TY76Z2rM5mHXA,
liranl-VPRAkNaXOzVS1MOuV/RT9w, tziporet-VPRAkNaXOzVS1MOuV/RT9w,
linux-rdma
Yevgeny Petrilin <yevgenyp-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org> wrote:
> The multicast attachment mechanism is used both by IB and Ethernet,
> so we need to specify for each multicast address (whether it is gid or mac) its protocol.
> For Ethernet addresses, their VEP number should be specified [...] A Ethernet ports now need to [...]
With this patch touching a mechanism which is used by both IB and EN,
I believe it need to be separated into two patches, the 1st changing only
the core/common logic and the 2nd the EN one. Looking on V2, I see that you
did have there two patches: "[21/25 v2] mlx4: Adding protocol fields
to multicast group"
and "[22/25 v2] mlx4_en: Attaching Multicast addresses"
Or.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 13/23 v3] mlx4: Unicast Loopback support
2010-02-04 15:56 ` [PATCH 13/23 v3] mlx4: Unicast Loopback support Yevgeny Petrilin
@ 2010-02-10 8:22 ` Or Gerlitz
0 siblings, 0 replies; 34+ messages in thread
From: Or Gerlitz @ 2010-02-10 8:22 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, netdev, liranl, tziporet
Yevgeny Petrilin <yevgenyp@mellanox.co.il> wrote:
> All packets are subject to loopback.
I wasn't sure what is the use case here, isn't loopback handled by
higher levels at
the network stack?
Or.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 18/23 v3] mlx4_core: Managing common port filters by master function
2010-02-04 15:56 ` [PATCH 18/23 v3] mlx4_core: Managing common port filters by master function Yevgeny Petrilin
@ 2010-02-10 8:47 ` Or Gerlitz
0 siblings, 0 replies; 34+ messages in thread
From: Or Gerlitz @ 2010-02-10 8:47 UTC (permalink / raw)
To: Yevgeny Petrilin; +Cc: Roland Dreier, netdev, liranl, tziporet, Or Gerlitz
Yevgeny Petrilin <yevgenyp@mellanox.co.il> wrote:
> The Multicast filter configuration is done by the master,
> that manages the filter which is common for all the functions.
> The VLAN filter is a bitwise OR of all the VLAN filters for all functions,
> the result is a false-positive filter.
Reading through patches "18/23 v3 mlx4_core: Managing common port
filters..." &&
"16/23 v3 mlx4_core: Multi-Function MCG support" I have difficulties
to follow on the
vlan and multicast filtering related changes and proposed architecture.
Can you explain them in a bit more detailed fashion? For example, in
the multicast case I
believe that currently a bloom filter is applied at the port level
and each packet which
pass the filter and has no registered QP is consumed by the EN driver.
At some point
my understanding was that everyone (all PFs, all VFs, etc) move to
exact match, is it correct?
As for the false-positive vlan filter, I understand that this means
further filtering has to
be applied by some driver. Where you thinking on the 802q driver? what
about the case
where a VF driver is assigned a vlan, does the mlx4 VF code does such filtering?
Or.
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2010-02-10 8:47 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <49BFC313.1030901@mellanox.co.il>
2010-02-04 15:54 ` [PATCH 00/23 v3] mlx4: multi-function framework and Ethernet SRIOV Yevgeny Petrilin
2010-02-04 15:54 ` [PATCH 01/23 v3] mlx4_core: identify function as pf or vf Yevgeny Petrilin
2010-02-09 13:41 ` Ben Hutchings
2010-02-04 15:54 ` [PATCH 02/23 v3] mlx4_core: add multi-function communication channel Yevgeny Petrilin
2010-02-09 14:37 ` Ben Hutchings
2010-02-04 15:54 ` [PATCH 03/23 v3] mlx4_core: add WRITE_MTT support Yevgeny Petrilin
2010-02-04 15:54 ` [PATCH 04/23 v3] mlx4_core: add slave resource allocation Yevgeny Petrilin
2010-02-09 14:44 ` Ben Hutchings
2010-02-09 17:32 ` Ben Hutchings
2010-02-04 15:55 ` [PATCH 05/23 v3] mlx4_core: slave multicast support Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 06/23 v3] mlx4_core: add port para-virtualization Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 07/23 v3] mlx4_core: dispatch slave asynch events Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 08/23 v3] mlx4_core: track slave special qps Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 09/23 v3] mlx4_core: per-function capabilities Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 10/23 v3] mlx4_core: associate resources with specific functions Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 11/23 v3] mlx4_core: multi-function resource setup Yevgeny Petrilin
2010-02-04 15:55 ` [PATCH 12/23 v3] mlx4_core: boot sriov Yevgeny Petrilin
2010-02-04 15:56 ` [PATCH 13/23 v3] mlx4: Unicast Loopback support Yevgeny Petrilin
2010-02-10 8:22 ` Or Gerlitz
2010-02-04 15:56 ` [PATCH 14/23 v3] mlx4_core: Determine primary physical function Yevgeny Petrilin
2010-02-04 22:30 ` Roland Dreier
2010-02-06 6:26 ` Yevgeny Petrilin
2010-02-04 15:56 ` [PATCH 15/23 v3] mlx4_core: Activating ports according to function number Yevgeny Petrilin
2010-02-04 15:56 ` [PATCH 16/23 v3] mlx4_core: Multi-Function MCG support Yevgeny Petrilin
[not found] ` <4B6AEE30.30202-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org>
2010-02-10 7:35 ` Or Gerlitz
2010-02-04 15:56 ` [PATCH 17/23 v3] mlx4_core: Randomize Mac addresses for slaves Yevgeny Petrilin
2010-02-09 17:22 ` Ben Hutchings
2010-02-04 15:56 ` [PATCH 18/23 v3] mlx4_core: Managing common port filters by master function Yevgeny Petrilin
2010-02-10 8:47 ` Or Gerlitz
2010-02-04 15:56 ` [PATCH 19/23 v3] mlx4: SET port for Ethernet moved to mlx4_core Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 20/23 v3] mlx4_core: binding virtual function to physical function Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 21/23 v3] mlx4_core: Adding VEP number in resource allocation Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 22/23 v3] mlx4_en: Use reasonable resources for slaves Yevgeny Petrilin
2010-02-04 15:57 ` [PATCH 23/23 v3] mlx4_en: querying link state Yevgeny Petrilin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).