Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64bb7e99 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlx4-next'



Or Gerlitz says:

====================
mlx4: Flexible (asymmetric) allocation of EQs and MSI-X vectors

This series from Matan Barak is built as follows:

The 1st two patches fix small bugs w.r.t firmware spec. Next
are two patches which do more re-factoring of the init/fini flow
and a patch that adds support for the QUERY_FUNC firmware command,
these are all pre-steps for the major patch of the series. In this
patch (#6) we change the order of talking/querying the firmware
and enabling SRIOV. This allows to remote worst-case assumption
w.r.t the number of available MSI-X vectors and EQs per function.

The last patch easily enjoys this ordering change, to enable
supports > 64 VFs over a firmware that allows for that.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9cf5476b de966c59
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1975,8 +1975,7 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
	    dev->caps.num_ports > dev->caps.comp_pool)
		return;

	eq_per_port = rounddown_pow_of_two(dev->caps.comp_pool/
					dev->caps.num_ports);
	eq_per_port = dev->caps.comp_pool / dev->caps.num_ports;

	/* Init eq table */
	added_eqs = 0;
+44 −32
Original line number Diff line number Diff line
@@ -2117,50 +2117,52 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
int mlx4_cmd_init(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	int flags = 0;

	if (!priv->cmd.initialized) {
		mutex_init(&priv->cmd.hcr_mutex);
		mutex_init(&priv->cmd.slave_cmd_mutex);
		sema_init(&priv->cmd.poll_sem, 1);
		priv->cmd.use_events = 0;
		priv->cmd.toggle     = 1;
		priv->cmd.initialized = 1;
		flags |= MLX4_CMD_CLEANUP_STRUCT;
	}

	priv->cmd.hcr = NULL;
	priv->mfunc.vhcr = NULL;

	if (!mlx4_is_slave(dev)) {
	if (!mlx4_is_slave(dev) && !priv->cmd.hcr) {
		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\n");
			return -ENOMEM;
			goto err;
		}
		flags |= MLX4_CMD_CLEANUP_HCR;
	}

	if (mlx4_is_mfunc(dev)) {
	if (mlx4_is_mfunc(dev) && !priv->mfunc.vhcr) {
		priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
						      &priv->mfunc.vhcr_dma,
						      GFP_KERNEL);
		if (!priv->mfunc.vhcr)
			goto err_hcr;
			goto err;

		flags |= MLX4_CMD_CLEANUP_VHCR;
	}

	if (!priv->cmd.pool) {
		priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev,
						 MLX4_MAILBOX_SIZE,
						 MLX4_MAILBOX_SIZE, 0);
		if (!priv->cmd.pool)
		goto err_vhcr;
			goto err;

	return 0;
		flags |= MLX4_CMD_CLEANUP_POOL;
	}

err_vhcr:
	if (mlx4_is_mfunc(dev))
		dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
				  priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
	priv->mfunc.vhcr = NULL;
	return 0;

err_hcr:
	if (!mlx4_is_slave(dev))
		iounmap(priv->cmd.hcr);
err:
	mlx4_cmd_cleanup(dev, flags);
	return -ENOMEM;
}

@@ -2184,19 +2186,29 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
	iounmap(priv->mfunc.comm);
}

void mlx4_cmd_cleanup(struct mlx4_dev *dev)
void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask)
{
	struct mlx4_priv *priv = mlx4_priv(dev);

	if (priv->cmd.pool && (cleanup_mask & MLX4_CMD_CLEANUP_POOL)) {
		pci_pool_destroy(priv->cmd.pool);
		priv->cmd.pool = NULL;
	}

	if (!mlx4_is_slave(dev))
	if (!mlx4_is_slave(dev) && priv->cmd.hcr &&
	    (cleanup_mask & MLX4_CMD_CLEANUP_HCR)) {
		iounmap(priv->cmd.hcr);
	if (mlx4_is_mfunc(dev))
		priv->cmd.hcr = NULL;
	}
	if (mlx4_is_mfunc(dev) && priv->mfunc.vhcr &&
	    (cleanup_mask & MLX4_CMD_CLEANUP_VHCR)) {
		dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
				  priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
		priv->mfunc.vhcr = NULL;
	}
	if (priv->cmd.initialized && (cleanup_mask & MLX4_CMD_CLEANUP_STRUCT))
		priv->cmd.initialized = 0;
}

/*
 * Switch to using events to issue FW commands (can only be called
+6 −2
Original line number Diff line number Diff line
@@ -1123,8 +1123,12 @@ 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,
			       roundup_pow_of_two(dev->caps.num_eqs),
			       dev->caps.num_eqs - 1,
			       dev->caps.reserved_eqs,
			       roundup_pow_of_two(dev->caps.num_eqs) -
			       dev->caps.num_eqs);
	if (err)
		goto err_out_free;

+100 −13
Original line number Diff line number Diff line
@@ -142,7 +142,9 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
		[13] = "Large cache line (>64B) EQE stride support",
		[14] = "Ethernet protocol control support",
		[15] = "Ethernet Backplane autoneg support",
		[16] = "CONFIG DEV support"
		[16] = "CONFIG DEV support",
		[17] = "Asymmetric EQs support",
		[18] = "More than 80 VFs support"
	};
	int i;

@@ -177,6 +179,61 @@ int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
	return err;
}

int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave)
{
	struct mlx4_cmd_mailbox *mailbox;
	u32 *outbox;
	u8 in_modifier;
	u8 field;
	u16 field16;
	int err;

#define QUERY_FUNC_BUS_OFFSET			0x00
#define QUERY_FUNC_DEVICE_OFFSET		0x01
#define QUERY_FUNC_FUNCTION_OFFSET		0x01
#define QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET	0x03
#define QUERY_FUNC_RSVD_EQS_OFFSET		0x04
#define QUERY_FUNC_MAX_EQ_OFFSET		0x06
#define QUERY_FUNC_RSVD_UARS_OFFSET		0x0b

	mailbox = mlx4_alloc_cmd_mailbox(dev);
	if (IS_ERR(mailbox))
		return PTR_ERR(mailbox);
	outbox = mailbox->buf;

	in_modifier = slave;

	err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, 0,
			   MLX4_CMD_QUERY_FUNC,
			   MLX4_CMD_TIME_CLASS_A,
			   MLX4_CMD_NATIVE);
	if (err)
		goto out;

	MLX4_GET(field, outbox, QUERY_FUNC_BUS_OFFSET);
	func->bus = field & 0xf;
	MLX4_GET(field, outbox, QUERY_FUNC_DEVICE_OFFSET);
	func->device = field & 0xf1;
	MLX4_GET(field, outbox, QUERY_FUNC_FUNCTION_OFFSET);
	func->function = field & 0x7;
	MLX4_GET(field, outbox, QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET);
	func->physical_function = field & 0xf;
	MLX4_GET(field16, outbox, QUERY_FUNC_RSVD_EQS_OFFSET);
	func->rsvd_eqs = field16 & 0xffff;
	MLX4_GET(field16, outbox, QUERY_FUNC_MAX_EQ_OFFSET);
	func->max_eq = field16 & 0xffff;
	MLX4_GET(field, outbox, QUERY_FUNC_RSVD_UARS_OFFSET);
	func->rsvd_uars = field & 0x0f;

	mlx4_dbg(dev, "Bus: %d, Device: %d, Function: %d, Physical function: %d, Max EQs: %d, Reserved EQs: %d, Reserved UARs: %d\n",
		 func->bus, func->device, func->function, func->physical_function,
		 func->max_eq, func->rsvd_eqs, func->rsvd_uars);

out:
	mlx4_free_cmd_mailbox(dev, mailbox);
	return err;
}

int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
				struct mlx4_vhcr *vhcr,
				struct mlx4_cmd_mailbox *inbox,
@@ -187,6 +244,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
	u8	field, port;
	u32	size, proxy_qp, qkey;
	int	err = 0;
	struct mlx4_func func;

#define QUERY_FUNC_CAP_FLAGS_OFFSET		0x0
#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET		0x1
@@ -231,6 +289,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
#define QUERY_FUNC_CAP_VF_ENABLE_QP0		0x08

#define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80
#define QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS (1 << 31)

	if (vhcr->op_modifier == 1) {
		struct mlx4_active_ports actv_ports =
@@ -309,11 +368,24 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
		size = dev->caps.num_cqs;
		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);

		size = dev->caps.num_eqs;
		if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) ||
		    mlx4_QUERY_FUNC(dev, &func, slave)) {
			size = vhcr->in_modifier &
				QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ?
				dev->caps.num_eqs :
				rounddown_pow_of_two(dev->caps.num_eqs);
			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);

			size = dev->caps.reserved_eqs;
			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
		} else {
			size = vhcr->in_modifier &
				QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ?
				func.max_eq :
				rounddown_pow_of_two(func.max_eq);
			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
			size = func.rsvd_eqs;
			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
		}

		size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave];
		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
@@ -335,7 +407,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
	return err;
}

int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,
			struct mlx4_func_cap *func_cap)
{
	struct mlx4_cmd_mailbox *mailbox;
@@ -343,14 +415,17 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
	u8			field, op_modifier;
	u32			size, qkey;
	int			err = 0, quotas = 0;
	u32                     in_modifier;

	op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
	in_modifier = op_modifier ? gen_or_port :
		QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS;

	mailbox = mlx4_alloc_cmd_mailbox(dev);
	if (IS_ERR(mailbox))
		return PTR_ERR(mailbox);

	err = mlx4_cmd_box(dev, 0, mailbox->dma, gen_or_port, op_modifier,
	err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, op_modifier,
			   MLX4_CMD_QUERY_FUNC_CAP,
			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
	if (err)
@@ -522,6 +597,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET		0x21
#define QUERY_DEV_CAP_RSVD_MRW_OFFSET		0x22
#define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET	0x23
#define QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET		0x26
#define QUERY_DEV_CAP_MAX_AV_OFFSET		0x27
#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET		0x29
#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET		0x2b
@@ -611,7 +687,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 = 1 << (field & 0xf);
	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);
@@ -622,6 +698,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
	dev_cap->reserved_mrws = 1 << (field & 0xf);
	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET);
	dev_cap->max_mtt_seg = 1 << (field & 0x3f);
	MLX4_GET(size, outbox, QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET);
	dev_cap->num_sys_eqs = size & 0xfff;
	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET);
	dev_cap->max_requester_per_qp = 1 << (field & 0x3f);
	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET);
@@ -783,6 +861,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
	if (field32 & (1 << 20))
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;
	if (field32 & (1 << 21))
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS;

	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
		for (i = 1; i <= dev_cap->num_ports; ++i) {
@@ -849,8 +929,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
	 * we can't use any EQs whose doorbell falls on that page,
	 * even if the EQ itself isn't reserved.
	 */
	if (dev_cap->num_sys_eqs == 0)
		dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4,
					    dev_cap->reserved_eqs);
	else
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SYS_EQS;

	mlx4_dbg(dev, "Max ICM size %lld MB\n",
		 (unsigned long long) dev_cap->max_icm_sz >> 20);
@@ -860,8 +943,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		 dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz);
	mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
		 dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz);
	mlx4_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
		 dev_cap->max_eqs, dev_cap->reserved_eqs, dev_cap->eqc_entry_sz);
	mlx4_dbg(dev, "Num sys EQs: %d, max EQs: %d, reserved EQs: %d, entry size: %d\n",
		 dev_cap->num_sys_eqs, dev_cap->max_eqs, dev_cap->reserved_eqs,
		 dev_cap->eqc_entry_sz);
	mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
		 dev_cap->reserved_mrws, dev_cap->reserved_mtts);
	mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
@@ -1407,6 +1491,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
#define	 INIT_HCA_AUXC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x50)
#define	 INIT_HCA_EQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x60)
#define	 INIT_HCA_LOG_EQ_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x67)
#define	INIT_HCA_NUM_SYS_EQS_OFFSET	(INIT_HCA_QPC_OFFSET + 0x6a)
#define	 INIT_HCA_RDMARC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x70)
#define	 INIT_HCA_LOG_RD_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x77)
#define INIT_HCA_MCAST_OFFSET		 0x0c0
@@ -1510,6 +1595,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
	MLX4_PUT(inbox, param->auxc_base,     INIT_HCA_AUXC_BASE_OFFSET);
	MLX4_PUT(inbox, param->eqc_base,      INIT_HCA_EQC_BASE_OFFSET);
	MLX4_PUT(inbox, param->log_num_eqs,   INIT_HCA_LOG_EQ_OFFSET);
	MLX4_PUT(inbox, param->num_sys_eqs,   INIT_HCA_NUM_SYS_EQS_OFFSET);
	MLX4_PUT(inbox, param->rdmarc_base,   INIT_HCA_RDMARC_BASE_OFFSET);
	MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET);

@@ -1620,6 +1706,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
	MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
	MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
	MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
	MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
	MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
	MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);

+14 −1
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ struct mlx4_dev_cap {
	int max_mpts;
	int reserved_eqs;
	int max_eqs;
	int num_sys_eqs;
	int reserved_mtts;
	int max_mrw_sz;
	int reserved_mrws;
@@ -145,6 +146,16 @@ struct mlx4_func_cap {
	u64	phys_port_id;
};

struct mlx4_func {
	int	bus;
	int	device;
	int	function;
	int	physical_function;
	int	rsvd_eqs;
	int	max_eq;
	int	rsvd_uars;
};

struct mlx4_adapter {
	char board_id[MLX4_BOARD_ID_LEN];
	u8   inta_pin;
@@ -170,6 +181,7 @@ struct mlx4_init_hca_param {
	u8  log_num_srqs;
	u8  log_num_cqs;
	u8  log_num_eqs;
	u16 num_sys_eqs;
	u8  log_rd_per_qp;
	u8  log_mc_table_sz;
	u8  log_mpt_sz;
@@ -204,13 +216,14 @@ struct mlx4_set_ib_param {
};

int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap);
int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,
			struct mlx4_func_cap *func_cap);
int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
				struct mlx4_vhcr *vhcr,
				struct mlx4_cmd_mailbox *inbox,
				struct mlx4_cmd_mailbox *outbox,
				struct mlx4_cmd_info *cmd);
int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave);
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);
Loading