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

Commit 54679e14 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Roland Dreier
Browse files

mlx4: Implement QP paravirtualization and maintain phys_pkey_cache for smp_snoop



This requires:

1. Replacing the paravirtualized P_Key index (inserted by the guest)
   with the real P_Key index.

2. For UD QPs, placing the guest's true source GID index in the
   address path structure mgid field, and setting the ud_force_mgid
   bit so that the mgid is taken from the QP context and not from the
   WQE when posting sends.

3. For UC and RC QPs, placing the guest's true source GID index in the
   address path structure mgid field.

4. For tunnel and proxy QPs, setting the Q_Key value reserved for that
   proxy/tunnel pair.

Since not all the above adjustments occur in all the QP transitions,
the QP transitions require separate wrapper functions.

Secondly, initialize the P_Key virtualization table to its default
values: Master virtualized table is 1-1 with the real P_Key table,
guest virtualized table has P_Key index 0 mapped to the real P_Key
index 0, and all the other P_Key indices mapped to the reserved
(invalid) P_Key at index 127.

Finally, add logic in smp_snoop for maintaining the phys_P_Key_cache.
and generating events on the master only if a P_Key actually changed.

Signed-off-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent fc06573d
Loading
Loading
Loading
Loading
+31 −2
Original line number Original line Diff line number Diff line
@@ -185,6 +185,10 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
{
{
	struct ib_port_info *pinfo;
	struct ib_port_info *pinfo;
	u16 lid;
	u16 lid;
	__be16 *base;
	u32 bn, pkey_change_bitmap;
	int i;



	struct mlx4_ib_dev *dev = to_mdev(ibdev);
	struct mlx4_ib_dev *dev = to_mdev(ibdev);
	if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||
	if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||
@@ -209,9 +213,34 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
			break;
			break;


		case IB_SMP_ATTR_PKEY_TABLE:
		case IB_SMP_ATTR_PKEY_TABLE:
			if (!mlx4_is_mfunc(dev->dev)) {
				mlx4_ib_dispatch_event(dev, port_num,
				mlx4_ib_dispatch_event(dev, port_num,
						       IB_EVENT_PKEY_CHANGE);
						       IB_EVENT_PKEY_CHANGE);
				break;
				break;
			}

			bn  = be32_to_cpu(((struct ib_smp *)mad)->attr_mod) & 0xFFFF;
			base = (__be16 *) &(((struct ib_smp *)mad)->data[0]);
			pkey_change_bitmap = 0;
			for (i = 0; i < 32; i++) {
				pr_debug("PKEY[%d] = x%x\n",
					 i + bn*32, be16_to_cpu(base[i]));
				if (be16_to_cpu(base[i]) !=
				    dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32]) {
					pkey_change_bitmap |= (1 << i);
					dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32] =
						be16_to_cpu(base[i]);
				}
			}
			pr_debug("PKEY Change event: port=%d, "
				 "block=0x%x, change_bitmap=0x%x\n",
				 port_num, bn, pkey_change_bitmap);

			if (pkey_change_bitmap)
				mlx4_ib_dispatch_event(dev, port_num,
						       IB_EVENT_PKEY_CHANGE);

			break;


		case IB_SMP_ATTR_GUID_INFO:
		case IB_SMP_ATTR_GUID_INFO:
			/* paravirtualized master's guid is guid 0 -- does not change */
			/* paravirtualized master's guid is guid 0 -- does not change */
+35 −0
Original line number Original line Diff line number Diff line
@@ -1121,6 +1121,38 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event
	return NOTIFY_DONE;
	return NOTIFY_DONE;
}
}


static void init_pkeys(struct mlx4_ib_dev *ibdev)
{
	int port;
	int slave;
	int i;

	if (mlx4_is_master(ibdev->dev)) {
		for (slave = 0; slave <= ibdev->dev->num_vfs; ++slave) {
			for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) {
				for (i = 0;
				     i < ibdev->dev->phys_caps.pkey_phys_table_len[port];
				     ++i) {
					ibdev->pkeys.virt2phys_pkey[slave][port - 1][i] =
					/* master has the identity virt2phys pkey mapping */
						(slave == mlx4_master_func_num(ibdev->dev) || !i) ? i :
							ibdev->dev->phys_caps.pkey_phys_table_len[port] - 1;
					mlx4_sync_pkey_table(ibdev->dev, slave, port, i,
							     ibdev->pkeys.virt2phys_pkey[slave][port - 1][i]);
				}
			}
		}
		/* initialize pkey cache */
		for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) {
			for (i = 0;
			     i < ibdev->dev->phys_caps.pkey_phys_table_len[port];
			     ++i)
				ibdev->pkeys.phys_pkey_cache[port-1][i] =
					(i) ? 0 : 0xFFFF;
		}
	}
}

static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
{
{
	char name[32];
	char name[32];
@@ -1375,6 +1407,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)


	ibdev->ib_active = true;
	ibdev->ib_active = true;


	if (mlx4_is_mfunc(ibdev->dev))
		init_pkeys(ibdev);

	return ibdev;
	return ibdev;


err_notif:
err_notif:
+6 −6
Original line number Original line Diff line number Diff line
@@ -950,7 +950,7 @@ static struct mlx4_cmd_info cmd_info[] = {
		.out_is_imm = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.encode_slave_id = false,
		.verify = NULL,
		.verify = NULL,
		.wrapper = mlx4_GEN_QP_wrapper
		.wrapper = mlx4_INIT2INIT_QP_wrapper
	},
	},
	{
	{
		.opcode = MLX4_CMD_INIT2RTR_QP,
		.opcode = MLX4_CMD_INIT2RTR_QP,
@@ -968,7 +968,7 @@ static struct mlx4_cmd_info cmd_info[] = {
		.out_is_imm = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.encode_slave_id = false,
		.verify = NULL,
		.verify = NULL,
		.wrapper = mlx4_GEN_QP_wrapper
		.wrapper = mlx4_RTR2RTS_QP_wrapper
	},
	},
	{
	{
		.opcode = MLX4_CMD_RTS2RTS_QP,
		.opcode = MLX4_CMD_RTS2RTS_QP,
@@ -977,7 +977,7 @@ static struct mlx4_cmd_info cmd_info[] = {
		.out_is_imm = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.encode_slave_id = false,
		.verify = NULL,
		.verify = NULL,
		.wrapper = mlx4_GEN_QP_wrapper
		.wrapper = mlx4_RTS2RTS_QP_wrapper
	},
	},
	{
	{
		.opcode = MLX4_CMD_SQERR2RTS_QP,
		.opcode = MLX4_CMD_SQERR2RTS_QP,
@@ -986,7 +986,7 @@ static struct mlx4_cmd_info cmd_info[] = {
		.out_is_imm = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.encode_slave_id = false,
		.verify = NULL,
		.verify = NULL,
		.wrapper = mlx4_GEN_QP_wrapper
		.wrapper = mlx4_SQERR2RTS_QP_wrapper
	},
	},
	{
	{
		.opcode = MLX4_CMD_2ERR_QP,
		.opcode = MLX4_CMD_2ERR_QP,
@@ -1013,7 +1013,7 @@ static struct mlx4_cmd_info cmd_info[] = {
		.out_is_imm = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.encode_slave_id = false,
		.verify = NULL,
		.verify = NULL,
		.wrapper = mlx4_GEN_QP_wrapper
		.wrapper = mlx4_SQD2SQD_QP_wrapper
	},
	},
	{
	{
		.opcode = MLX4_CMD_SQD2RTS_QP,
		.opcode = MLX4_CMD_SQD2RTS_QP,
@@ -1022,7 +1022,7 @@ static struct mlx4_cmd_info cmd_info[] = {
		.out_is_imm = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.encode_slave_id = false,
		.verify = NULL,
		.verify = NULL,
		.wrapper = mlx4_GEN_QP_wrapper
		.wrapper = mlx4_SQD2RTS_QP_wrapper
	},
	},
	{
	{
		.opcode = MLX4_CMD_2RST_QP,
		.opcode = MLX4_CMD_2RST_QP,
+11 −0
Original line number Original line Diff line number Diff line
@@ -424,6 +424,17 @@ int mlx4_get_parav_qkey(struct mlx4_dev *dev, u32 qpn, u32 *qkey)
}
}
EXPORT_SYMBOL(mlx4_get_parav_qkey);
EXPORT_SYMBOL(mlx4_get_parav_qkey);


void mlx4_sync_pkey_table(struct mlx4_dev *dev, int slave, int port, int i, int val)
{
	struct mlx4_priv *priv = container_of(dev, struct mlx4_priv, dev);

	if (!mlx4_is_master(dev))
		return;

	priv->virt2phys_pkey[slave][port - 1][i] = val;
}
EXPORT_SYMBOL(mlx4_sync_pkey_table);

int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
{
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_priv *priv = mlx4_priv(dev);
+47 −0
Original line number Original line Diff line number Diff line
@@ -807,6 +807,8 @@ struct mlx4_priv {
	struct io_mapping	*bf_mapping;
	struct io_mapping	*bf_mapping;
	int			reserved_mtts;
	int			reserved_mtts;
	int			fs_hash_mode;
	int			fs_hash_mode;
	u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];

};
};


static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
@@ -1011,16 +1013,61 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
			     struct mlx4_cmd_mailbox *inbox,
			     struct mlx4_cmd_mailbox *inbox,
			     struct mlx4_cmd_mailbox *outbox,
			     struct mlx4_cmd_mailbox *outbox,
			     struct mlx4_cmd_info *cmd);
			     struct mlx4_cmd_info *cmd);
int mlx4_INIT2INIT_QP_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_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
			     struct mlx4_vhcr *vhcr,
			     struct mlx4_vhcr *vhcr,
			     struct mlx4_cmd_mailbox *inbox,
			     struct mlx4_cmd_mailbox *inbox,
			     struct mlx4_cmd_mailbox *outbox,
			     struct mlx4_cmd_mailbox *outbox,
			     struct mlx4_cmd_info *cmd);
			     struct mlx4_cmd_info *cmd);
int mlx4_RTR2RTS_QP_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_RTS2RTS_QP_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_SQERR2RTS_QP_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_2ERR_QP_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_RTS2SQD_QP_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_SQD2SQD_QP_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_SQD2RTS_QP_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_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,
int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,
			 struct mlx4_vhcr *vhcr,
			 struct mlx4_vhcr *vhcr,
			 struct mlx4_cmd_mailbox *inbox,
			 struct mlx4_cmd_mailbox *inbox,
			 struct mlx4_cmd_mailbox *outbox,
			 struct mlx4_cmd_mailbox *outbox,
			 struct mlx4_cmd_info *cmd);
			 struct mlx4_cmd_info *cmd);
int mlx4_QUERY_QP_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_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe);
int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe);


Loading