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

Commit 477f2d14 authored by Rahul Verma's avatar Rahul Verma Committed by David S. Miller
Browse files

qed: Add support for vf coalesce configuration.



This patch add the ethtool support to set RX/Tx coalesce
value to the VF associated Rx/Tx queues.

Signed-off-by: default avatarRahul Verma <Rahul.Verma@cavium.com>
Signed-off-by: default avatarYuval Mintz <yuval.mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c3dc48f7
Loading
Loading
Loading
Loading
+49 −24
Original line number Original line Diff line number Diff line
@@ -3694,7 +3694,7 @@ static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
	}
	}


	p_coal_timeset = p_eth_qzone;
	p_coal_timeset = p_eth_qzone;
	memset(p_coal_timeset, 0, eth_qzone_size);
	memset(p_eth_qzone, 0, eth_qzone_size);
	SET_FIELD(p_coal_timeset->value, COALESCING_TIMESET_TIMESET, timeset);
	SET_FIELD(p_coal_timeset->value, COALESCING_TIMESET_TIMESET, timeset);
	SET_FIELD(p_coal_timeset->value, COALESCING_TIMESET_VALID, 1);
	SET_FIELD(p_coal_timeset->value, COALESCING_TIMESET_VALID, 1);
	qed_memcpy_to(p_hwfn, p_ptt, hw_addr, p_eth_qzone, eth_qzone_size);
	qed_memcpy_to(p_hwfn, p_ptt, hw_addr, p_eth_qzone, eth_qzone_size);
@@ -3702,12 +3702,46 @@ static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
	return 0;
	return 0;
}
}


int qed_set_rxq_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
int qed_set_queue_coalesce(u16 rx_coal, u16 tx_coal, void *p_handle)
			 u16 coalesce, u16 qid, u16 sb_id)
{
	struct qed_queue_cid *p_cid = p_handle;
	struct qed_hwfn *p_hwfn;
	struct qed_ptt *p_ptt;
	int rc = 0;

	p_hwfn = p_cid->p_owner;

	if (IS_VF(p_hwfn->cdev))
		return qed_vf_pf_set_coalesce(p_hwfn, rx_coal, tx_coal, p_cid);

	p_ptt = qed_ptt_acquire(p_hwfn);
	if (!p_ptt)
		return -EAGAIN;

	if (rx_coal) {
		rc = qed_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
		if (rc)
			goto out;
		p_hwfn->cdev->rx_coalesce_usecs = rx_coal;
	}

	if (tx_coal) {
		rc = qed_set_txq_coalesce(p_hwfn, p_ptt, tx_coal, p_cid);
		if (rc)
			goto out;
		p_hwfn->cdev->tx_coalesce_usecs = tx_coal;
	}
out:
	qed_ptt_release(p_hwfn, p_ptt);
	return rc;
}

int qed_set_rxq_coalesce(struct qed_hwfn *p_hwfn,
			 struct qed_ptt *p_ptt,
			 u16 coalesce, struct qed_queue_cid *p_cid)
{
{
	struct ustorm_eth_queue_zone eth_qzone;
	struct ustorm_eth_queue_zone eth_qzone;
	u8 timeset, timer_res;
	u8 timeset, timer_res;
	u16 fw_qid = 0;
	u32 address;
	u32 address;
	int rc;
	int rc;


@@ -3724,32 +3758,29 @@ int qed_set_rxq_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
	}
	}
	timeset = (u8)(coalesce >> timer_res);
	timeset = (u8)(coalesce >> timer_res);


	rc = qed_fw_l2_queue(p_hwfn, qid, &fw_qid);
	rc = qed_int_set_timer_res(p_hwfn, p_ptt, timer_res,
	if (rc)
				   p_cid->sb_igu_id, false);
		return rc;

	rc = qed_int_set_timer_res(p_hwfn, p_ptt, timer_res, sb_id, false);
	if (rc)
	if (rc)
		goto out;
		goto out;


	address = BAR0_MAP_REG_USDM_RAM + USTORM_ETH_QUEUE_ZONE_OFFSET(fw_qid);
	address = BAR0_MAP_REG_USDM_RAM +
		  USTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id);


	rc = qed_set_coalesce(p_hwfn, p_ptt, address, &eth_qzone,
	rc = qed_set_coalesce(p_hwfn, p_ptt, address, &eth_qzone,
			      sizeof(struct ustorm_eth_queue_zone), timeset);
			      sizeof(struct ustorm_eth_queue_zone), timeset);
	if (rc)
	if (rc)
		goto out;
		goto out;


	p_hwfn->cdev->rx_coalesce_usecs = coalesce;
out:
out:
	return rc;
	return rc;
}
}


int qed_set_txq_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
int qed_set_txq_coalesce(struct qed_hwfn *p_hwfn,
			 u16 coalesce, u16 qid, u16 sb_id)
			 struct qed_ptt *p_ptt,
			 u16 coalesce, struct qed_queue_cid *p_cid)
{
{
	struct xstorm_eth_queue_zone eth_qzone;
	struct xstorm_eth_queue_zone eth_qzone;
	u8 timeset, timer_res;
	u8 timeset, timer_res;
	u16 fw_qid = 0;
	u32 address;
	u32 address;
	int rc;
	int rc;


@@ -3766,22 +3797,16 @@ int qed_set_txq_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
	}
	}
	timeset = (u8)(coalesce >> timer_res);
	timeset = (u8)(coalesce >> timer_res);


	rc = qed_fw_l2_queue(p_hwfn, qid, &fw_qid);
	rc = qed_int_set_timer_res(p_hwfn, p_ptt, timer_res,
	if (rc)
				   p_cid->sb_igu_id, true);
		return rc;

	rc = qed_int_set_timer_res(p_hwfn, p_ptt, timer_res, sb_id, true);
	if (rc)
	if (rc)
		goto out;
		goto out;


	address = BAR0_MAP_REG_XSDM_RAM + XSTORM_ETH_QUEUE_ZONE_OFFSET(fw_qid);
	address = BAR0_MAP_REG_XSDM_RAM +
		  XSTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id);


	rc = qed_set_coalesce(p_hwfn, p_ptt, address, &eth_qzone,
	rc = qed_set_coalesce(p_hwfn, p_ptt, address, &eth_qzone,
			      sizeof(struct xstorm_eth_queue_zone), timeset);
			      sizeof(struct xstorm_eth_queue_zone), timeset);
	if (rc)
		goto out;

	p_hwfn->cdev->tx_coalesce_usecs = coalesce;
out:
out:
	return rc;
	return rc;
}
}
+13 −28
Original line number Original line Diff line number Diff line
@@ -443,38 +443,23 @@ int qed_final_cleanup(struct qed_hwfn *p_hwfn,
		      struct qed_ptt *p_ptt, u16 id, bool is_vf);
		      struct qed_ptt *p_ptt, u16 id, bool is_vf);


/**
/**
 * @brief qed_set_rxq_coalesce - Configure coalesce parameters for an Rx queue
 * @brief qed_set_queue_coalesce - Configure coalesce parameters for Rx or
 * The fact that we can configure coalescing to up to 511, but on varying
 * Tx queue. We can configure coalescing to up to 511, but on
 * accuracy [the bigger the value the less accurate] up to a mistake of 3usec
 * varying accuracy [the bigger the value the less accurate] up to a mistake
 * for the highest values.
 * of 3usec for the highest values.
 *
 * While the API allows setting coalescing per-qid, all queues sharing a SB
 * @param p_hwfn
 * should be in same range [i.e., either 0-0x7f, 0x80-0xff or 0x100-0x1ff]
 * @param p_ptt
 * @param coalesce - Coalesce value in micro seconds.
 * @param qid - Queue index.
 * @param qid - SB Id
 *
 * @return int
 */
int qed_set_rxq_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
			 u16 coalesce, u16 qid, u16 sb_id);

/**
 * @brief qed_set_txq_coalesce - Configure coalesce parameters for a Tx queue
 * While the API allows setting coalescing per-qid, all tx queues sharing a
 * SB should be in same range [i.e., either 0-0x7f, 0x80-0xff or 0x100-0x1ff]
 * otherwise configuration would break.
 * otherwise configuration would break.
 *
 *
 * @param p_hwfn
 * @param rx_coal - Rx Coalesce value in micro seconds.
 * @param p_ptt
 * @param tx_coal - TX Coalesce value in micro seconds.
 * @param coalesce - Coalesce value in micro seconds.
 * @param p_handle
 * @param qid - Queue index.
 * @param qid - SB Id
 *
 *
 * @return int
 * @return int
 */
 **/
int qed_set_txq_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
int
			 u16 coalesce, u16 qid, u16 sb_id);
qed_set_queue_coalesce(u16 rx_coal, u16 tx_coal, void *p_handle);



const char *qed_hw_get_resc_name(enum qed_resources res_id);
const char *qed_hw_get_resc_name(enum qed_resources res_id);
#endif
#endif
+7 −0
Original line number Original line Diff line number Diff line
@@ -400,4 +400,11 @@ qed_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn,


u8 qed_mcast_bin_from_mac(u8 *mac);
u8 qed_mcast_bin_from_mac(u8 *mac);


int qed_set_rxq_coalesce(struct qed_hwfn *p_hwfn,
			 struct qed_ptt *p_ptt,
			 u16 coalesce, struct qed_queue_cid *p_cid);

int qed_set_txq_coalesce(struct qed_hwfn *p_hwfn,
			 struct qed_ptt *p_ptt,
			 u16 coalesce, struct qed_queue_cid *p_cid);
#endif /* _QED_L2_H */
#endif /* _QED_L2_H */
+2 −22
Original line number Original line Diff line number Diff line
@@ -1575,29 +1575,9 @@ static void qed_get_coalesce(struct qed_dev *cdev, u16 *rx_coal, u16 *tx_coal)
}
}


static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal,
static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal,
			    u16 qid, u16 sb_id)
			    void *handle)
{
{
	struct qed_hwfn *hwfn;
		return qed_set_queue_coalesce(rx_coal, tx_coal, handle);
	struct qed_ptt *ptt;
	int hwfn_index;
	int status = 0;

	hwfn_index = qid % cdev->num_hwfns;
	hwfn = &cdev->hwfns[hwfn_index];
	ptt = qed_ptt_acquire(hwfn);
	if (!ptt)
		return -EAGAIN;

	status = qed_set_rxq_coalesce(hwfn, ptt, rx_coal,
				      qid / cdev->num_hwfns, sb_id);
	if (status)
		goto out;
	status = qed_set_txq_coalesce(hwfn, ptt, tx_coal,
				      qid / cdev->num_hwfns, sb_id);
out:
	qed_ptt_release(hwfn, ptt);

	return status;
}
}


static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
+83 −0
Original line number Original line Diff line number Diff line
@@ -3400,6 +3400,86 @@ static void qed_iov_vf_mbx_release(struct qed_hwfn *p_hwfn,
			     length, status);
			     length, status);
}
}


static void qed_iov_vf_pf_set_coalesce(struct qed_hwfn *p_hwfn,
				       struct qed_ptt *p_ptt,
				       struct qed_vf_info *vf)
{
	struct qed_iov_vf_mbx *mbx = &vf->vf_mbx;
	struct vfpf_update_coalesce *req;
	u8 status = PFVF_STATUS_FAILURE;
	struct qed_queue_cid *p_cid;
	u16 rx_coal, tx_coal;
	int rc = 0, i;
	u16 qid;

	req = &mbx->req_virt->update_coalesce;

	rx_coal = req->rx_coal;
	tx_coal = req->tx_coal;
	qid = req->qid;

	if (!qed_iov_validate_rxq(p_hwfn, vf, qid,
				  QED_IOV_VALIDATE_Q_ENABLE) && rx_coal) {
		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
			   "VF[%d]: Invalid Rx queue_id = %d\n",
			   vf->abs_vf_id, qid);
		goto out;
	}

	if (!qed_iov_validate_txq(p_hwfn, vf, qid,
				  QED_IOV_VALIDATE_Q_ENABLE) && tx_coal) {
		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
			   "VF[%d]: Invalid Tx queue_id = %d\n",
			   vf->abs_vf_id, qid);
		goto out;
	}

	DP_VERBOSE(p_hwfn,
		   QED_MSG_IOV,
		   "VF[%d]: Setting coalesce for VF rx_coal = %d, tx_coal = %d at queue = %d\n",
		   vf->abs_vf_id, rx_coal, tx_coal, qid);

	if (rx_coal) {
		p_cid = qed_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);

		rc = qed_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
		if (rc) {
			DP_VERBOSE(p_hwfn,
				   QED_MSG_IOV,
				   "VF[%d]: Unable to set rx queue = %d coalesce\n",
				   vf->abs_vf_id, vf->vf_queues[qid].fw_rx_qid);
			goto out;
		}
	}

	if (tx_coal) {
		struct qed_vf_queue *p_queue = &vf->vf_queues[qid];

		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
			if (!p_queue->cids[i].p_cid)
				continue;

			if (!p_queue->cids[i].b_is_tx)
				continue;

			rc = qed_set_txq_coalesce(p_hwfn, p_ptt, tx_coal,
						  p_queue->cids[i].p_cid);

			if (rc) {
				DP_VERBOSE(p_hwfn,
					   QED_MSG_IOV,
					   "VF[%d]: Unable to set tx queue coalesce\n",
					   vf->abs_vf_id);
				goto out;
			}
		}
	}

	status = PFVF_STATUS_SUCCESS;
out:
	qed_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_COALESCE_UPDATE,
			     sizeof(struct pfvf_def_resp_tlv), status);
}
static int
static int
qed_iov_vf_flr_poll_dorq(struct qed_hwfn *p_hwfn,
qed_iov_vf_flr_poll_dorq(struct qed_hwfn *p_hwfn,
			 struct qed_vf_info *p_vf, struct qed_ptt *p_ptt)
			 struct qed_vf_info *p_vf, struct qed_ptt *p_ptt)
@@ -3725,6 +3805,9 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
		case CHANNEL_TLV_UPDATE_TUNN_PARAM:
		case CHANNEL_TLV_UPDATE_TUNN_PARAM:
			qed_iov_vf_mbx_update_tunn_param(p_hwfn, p_ptt, p_vf);
			qed_iov_vf_mbx_update_tunn_param(p_hwfn, p_ptt, p_vf);
			break;
			break;
		case CHANNEL_TLV_COALESCE_UPDATE:
			qed_iov_vf_pf_set_coalesce(p_hwfn, p_ptt, p_vf);
			break;
		}
		}
	} else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
	} else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
Loading