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

Commit f69c3331 authored by Ismail, Mustafa's avatar Ismail, Mustafa Committed by Doug Ledford
Browse files

RDMA/i40iw: Add virtual channel message queue



Queue users of virtual channel on a waitqueue until the channel is
clear instead of failing the call when the channel is occupied.

Signed-off-by: default avatarMustafa Ismail <mustafa.ismail@intel.com>
Signed-off-by: default avatarFaisal Latif <faisal.latif@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent f606d893
Loading
Loading
Loading
Loading
+39 −8
Original line number Diff line number Diff line
@@ -1528,7 +1528,10 @@ static enum i40iw_status_code i40iw_setup_init_state(struct i40iw_handler *hdl,
		goto exit;
	iwdev->obj_next = iwdev->obj_mem;
	iwdev->push_mode = push_mode;

	init_waitqueue_head(&iwdev->vchnl_waitq);
	init_waitqueue_head(&dev->vf_reqs);

	status = i40iw_initialize_dev(iwdev, ldev);
exit:
	if (status) {
@@ -1707,7 +1710,6 @@ static void i40iw_vf_reset(struct i40e_info *ldev, struct i40e_client *client, u
	for (i = 0; i < I40IW_MAX_PE_ENABLED_VF_COUNT; i++) {
		if (!dev->vf_dev[i] || (dev->vf_dev[i]->vf_id != vf_id))
			continue;

		/* free all resources allocated on behalf of vf */
		tmp_vfdev = dev->vf_dev[i];
		spin_lock_irqsave(&dev->dev_pestat.stats_lock, flags);
@@ -1816,8 +1818,6 @@ static int i40iw_virtchnl_receive(struct i40e_info *ldev,
	dev = &hdl->device.sc_dev;
	iwdev = dev->back_dev;

	i40iw_debug(dev, I40IW_DEBUG_VIRT, "msg %p, message length %u\n", msg, len);

	if (dev->vchnl_if.vchnl_recv) {
		ret_code = dev->vchnl_if.vchnl_recv(dev, vf_id, msg, len);
		if (!dev->is_pf) {
@@ -1828,6 +1828,39 @@ static int i40iw_virtchnl_receive(struct i40e_info *ldev,
	return ret_code;
}

/**
 * i40iw_vf_clear_to_send - wait to send virtual channel message
 * @dev: iwarp device *
 * Wait for until virtual channel is clear
 * before sending the next message
 *
 * Returns false if error
 * Returns true if clear to send
 */
bool i40iw_vf_clear_to_send(struct i40iw_sc_dev *dev)
{
	struct i40iw_device *iwdev;
	wait_queue_t wait;

	iwdev = dev->back_dev;

	if (!wq_has_sleeper(&dev->vf_reqs) &&
	    (atomic_read(&iwdev->vchnl_msgs) == 0))
		return true; /* virtual channel is clear */

	init_wait(&wait);
	add_wait_queue_exclusive(&dev->vf_reqs, &wait);

	if (!wait_event_timeout(dev->vf_reqs,
				(atomic_read(&iwdev->vchnl_msgs) == 0),
				I40IW_VCHNL_EVENT_TIMEOUT))
		dev->vchnl_up = false;

	remove_wait_queue(&dev->vf_reqs, &wait);

	return dev->vchnl_up;
}

/**
 * i40iw_virtchnl_send - send a message through the virtual channel
 * @dev: iwarp device
@@ -1845,18 +1878,16 @@ static enum i40iw_status_code i40iw_virtchnl_send(struct i40iw_sc_dev *dev,
{
	struct i40iw_device *iwdev;
	struct i40e_info *ldev;
	enum i40iw_status_code ret_code = I40IW_ERR_BAD_PTR;

	if (!dev || !dev->back_dev)
		return ret_code;
		return I40IW_ERR_BAD_PTR;

	iwdev = dev->back_dev;
	ldev = iwdev->ldev;

	if (ldev && ldev->ops && ldev->ops->virtchnl_send)
		ret_code = ldev->ops->virtchnl_send(ldev, &i40iw_client, vf_id, msg, len);

	return ret_code;
		return ldev->ops->virtchnl_send(ldev, &i40iw_client, vf_id, msg, len);
	return I40IW_ERR_BAD_PTR;
}

/* client interface functions */
+1 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ struct i40iw_hw;
u8 __iomem *i40iw_get_hw_addr(void *dev);
void i40iw_ieq_mpa_crc_ae(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
enum i40iw_status_code i40iw_vf_wait_vchnl_resp(struct i40iw_sc_dev *dev);
bool i40iw_vf_clear_to_send(struct i40iw_sc_dev *dev);
enum i40iw_status_code i40iw_ieq_check_mpacrc(struct shash_desc *desc, void *addr,
					      u32 length, u32 value);
struct i40iw_sc_qp *i40iw_ieq_get_qp(struct i40iw_sc_dev *dev, struct i40iw_puda_buf *buf);
+2 −1
Original line number Diff line number Diff line
@@ -489,6 +489,7 @@ struct i40iw_sc_dev {
	bool is_pf;
	bool vchnl_up;
	u8 vf_id;
	wait_queue_head_t vf_reqs;
	u64 cqp_cmd_stats[OP_SIZE_CQP_STAT_ARRAY];
	struct i40iw_vchnl_vf_msg_buffer vchnl_vf_msg_buf;
	u8 hw_rev;
+7 −4
Original line number Diff line number Diff line
@@ -990,21 +990,24 @@ enum i40iw_status_code i40iw_cqp_commit_fpm_values_cmd(struct i40iw_sc_dev *dev,
enum i40iw_status_code i40iw_vf_wait_vchnl_resp(struct i40iw_sc_dev *dev)
{
	struct i40iw_device *iwdev = dev->back_dev;
	enum i40iw_status_code err_code = 0;
	int timeout_ret;

	i40iw_debug(dev, I40IW_DEBUG_VIRT, "%s[%u] dev %p, iwdev %p\n",
		    __func__, __LINE__, dev, iwdev);
	atomic_add(2, &iwdev->vchnl_msgs);

	atomic_set(&iwdev->vchnl_msgs, 2);
	timeout_ret = wait_event_timeout(iwdev->vchnl_waitq,
					 (atomic_read(&iwdev->vchnl_msgs) == 1),
					 I40IW_VCHNL_EVENT_TIMEOUT);
	atomic_dec(&iwdev->vchnl_msgs);
	if (!timeout_ret) {
		i40iw_pr_err("virt channel completion timeout = 0x%x\n", timeout_ret);
		err_code = I40IW_ERR_TIMEOUT;
		atomic_set(&iwdev->vchnl_msgs, 0);
		dev->vchnl_up = false;
		return I40IW_ERR_TIMEOUT;
	}
	return err_code;
	wake_up(&dev->vf_reqs);
	return 0;
}

/**
+2 −6
Original line number Diff line number Diff line
@@ -2148,7 +2148,6 @@ static int i40iw_get_protocol_stats(struct ib_device *ibdev,
	struct i40iw_dev_hw_stats *hw_stats = &devstat->hw_stats;
	struct timespec curr_time;
	static struct timespec last_rd_time = {0, 0};
	enum i40iw_status_code status = 0;
	unsigned long flags;

	curr_time = current_kernel_time();
@@ -2161,10 +2160,7 @@ static int i40iw_get_protocol_stats(struct ib_device *ibdev,
		spin_unlock_irqrestore(&devstat->stats_lock, flags);
	} else {
		if (((u64)curr_time.tv_sec - (u64)last_rd_time.tv_sec) > 1)
			status = i40iw_vchnl_vf_get_pe_stats(dev,
							     &devstat->hw_stats);

		if (status)
			if (i40iw_vchnl_vf_get_pe_stats(dev, &devstat->hw_stats))
				return -ENOSYS;
	}

Loading