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

Commit 40aa306f authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qed-Status-block-changes'



Yuval Mintz says:

====================
qed: Status block changes

The device maintains a CAM mapping of the internal status blocks
and the various PF/VF MSI-x vector mappings.
During initialization, the driver reads the HW memory and constructs
a shadow SW implementation which it would later use for manipulation
of interrupts. E.g., when enabling VFs and setting their MSI-x tables.

The driver currently has some very strict assumptions on the order the
entries are placed in the CAM. Specifically, it assumes that all entries
belonging to a PF would be consecutive and in-order in the CAM, and that
the VF entries would then follow. But there's no actual HW constraint
enforcing this assumption [although management firmware does set it
accordingly to same assumption initially].

Since the CAM is re-configurable, there are now SW flows employeed
by other OSes that might cause the assumption to be invalid.
Such flows allow the PF to forfeit some of it's available interrupts
in favor of its VFs or vice versa.
While those are not employeed today by qed, we want to relax the
assumptions as much as we can -
both to allow functionality after PDA as well as allowing future
compatibility where the driver would be loaded after a newer one has
'dirtied' the CAM configuration.

In addition to patches meant for the above relaxation, the series
also contains various cleanups & refactoring for interrupt logic
[most of which is !semantic].
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7b954ed7 1ee240e3
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -495,10 +495,6 @@ struct qed_hwfn {
	bool b_rdma_enabled_in_prs;
	u32 rdma_prs_search_reg;

	/* Array of sb_info of all status blocks */
	struct qed_sb_info		*sbs_info[MAX_SB_PER_PF_MIMD];
	u16				num_sbs;

	struct qed_cxt_mngr		*p_cxt_mngr;

	/* Flag indicating whether interrupts are enabled or not*/
+25 −24
Original line number Diff line number Diff line
@@ -1030,7 +1030,7 @@ void qed_resc_setup(struct qed_dev *cdev)

		qed_int_setup(p_hwfn, p_hwfn->p_main_ptt);

		qed_iov_setup(p_hwfn, p_hwfn->p_main_ptt);
		qed_iov_setup(p_hwfn);
#ifdef CONFIG_QED_LL2
		if (p_hwfn->using_ll2)
			qed_ll2_setup(p_hwfn);
@@ -1155,7 +1155,7 @@ static int qed_calc_hw_mode(struct qed_hwfn *p_hwfn)
static void qed_init_cau_rt_data(struct qed_dev *cdev)
{
	u32 offset = CAU_REG_SB_VAR_MEMORY_RT_OFFSET;
	int i, sb_id;
	int i, igu_sb_id;

	for_each_hwfn(cdev, i) {
		struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
@@ -1165,15 +1165,17 @@ static void qed_init_cau_rt_data(struct qed_dev *cdev)

		p_igu_info = p_hwfn->hw_info.p_igu_info;

		for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(cdev);
		     sb_id++) {
			p_block = &p_igu_info->igu_map.igu_blocks[sb_id];
		for (igu_sb_id = 0;
		     igu_sb_id < QED_MAPPING_MEMORY_SIZE(cdev); igu_sb_id++) {
			p_block = &p_igu_info->entry[igu_sb_id];

			if (!p_block->is_pf)
				continue;

			qed_init_cau_sb_entry(p_hwfn, &sb_entry,
					      p_block->function_id, 0, 0);
			STORE_RT_REG_AGG(p_hwfn, offset + sb_id * 2, sb_entry);
			STORE_RT_REG_AGG(p_hwfn, offset + igu_sb_id * 2,
					 sb_entry);
		}
	}
}
@@ -2036,9 +2038,12 @@ static void get_function_id(struct qed_hwfn *p_hwfn)
static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
{
	u32 *feat_num = p_hwfn->hw_info.feat_num;
	struct qed_sb_cnt_info sb_cnt_info;
	struct qed_sb_cnt_info sb_cnt;
	u32 non_l2_sbs = 0;

	memset(&sb_cnt, 0, sizeof(sb_cnt));
	qed_int_get_num_sbs(p_hwfn, &sb_cnt);

	if (IS_ENABLED(CONFIG_QED_RDMA) &&
	    p_hwfn->hw_info.personality == QED_PCI_ETH_ROCE) {
		/* Roce CNQ each requires: 1 status block + 1 CNQ. We divide
@@ -2046,7 +2051,7 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
		 * consideration as to how many l2 queues / cnqs we have.
		 */
		feat_num[QED_RDMA_CNQ] =
			min_t(u32, RESC_NUM(p_hwfn, QED_SB) / 2,
			min_t(u32, sb_cnt.cnt / 2,
			      RESC_NUM(p_hwfn, QED_RDMA_CNQ_RAM));

		non_l2_sbs = feat_num[QED_RDMA_CNQ];
@@ -2055,14 +2060,11 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
	if (p_hwfn->hw_info.personality == QED_PCI_ETH_ROCE ||
	    p_hwfn->hw_info.personality == QED_PCI_ETH) {
		/* Start by allocating VF queues, then PF's */
		memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
		qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
		feat_num[QED_VF_L2_QUE] = min_t(u32,
						RESC_NUM(p_hwfn, QED_L2_QUEUE),
						sb_cnt_info.sb_iov_cnt);
						sb_cnt.iov_cnt);
		feat_num[QED_PF_L2_QUE] = min_t(u32,
						RESC_NUM(p_hwfn, QED_SB) -
						non_l2_sbs,
						sb_cnt.cnt - non_l2_sbs,
						RESC_NUM(p_hwfn,
							 QED_L2_QUEUE) -
						FEAT_NUM(p_hwfn,
@@ -2070,7 +2072,7 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
	}

	if (p_hwfn->hw_info.personality == QED_PCI_ISCSI)
		feat_num[QED_ISCSI_CQ] = min_t(u32, RESC_NUM(p_hwfn, QED_SB),
		feat_num[QED_ISCSI_CQ] = min_t(u32, sb_cnt.cnt,
					       RESC_NUM(p_hwfn,
							QED_CMDQS_CQS));
	DP_VERBOSE(p_hwfn,
@@ -2080,7 +2082,7 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
		   (int)FEAT_NUM(p_hwfn, QED_VF_L2_QUE),
		   (int)FEAT_NUM(p_hwfn, QED_RDMA_CNQ),
		   (int)FEAT_NUM(p_hwfn, QED_ISCSI_CQ),
		   RESC_NUM(p_hwfn, QED_SB));
		   (int)sb_cnt.cnt);
}

const char *qed_hw_get_resc_name(enum qed_resources res_id)
@@ -2199,7 +2201,6 @@ int qed_hw_get_dflt_resc(struct qed_hwfn *p_hwfn,
{
	u8 num_funcs = p_hwfn->num_funcs_on_engine;
	bool b_ah = QED_IS_AH(p_hwfn->cdev);
	struct qed_sb_cnt_info sb_cnt_info;

	switch (res_id) {
	case QED_L2_QUEUE:
@@ -2251,9 +2252,10 @@ int qed_hw_get_dflt_resc(struct qed_hwfn *p_hwfn,
			*p_resc_num = 1;
		break;
	case QED_SB:
		memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
		qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
		*p_resc_num = sb_cnt_info.sb_cnt;
		/* Since we want its value to reflect whether MFW supports
		 * the new scheme, have a default of 0.
		 */
		*p_resc_num = 0;
		break;
	default:
		return -EINVAL;
@@ -2322,11 +2324,6 @@ static int __qed_hw_set_resc_info(struct qed_hwfn *p_hwfn,
		goto out;
	}

	/* Special handling for status blocks; Would be revised in future */
	if (res_id == QED_SB) {
		*p_resc_num -= 1;
		*p_resc_start -= p_hwfn->enabled_func_idx;
	}
out:
	/* PQs have to divide by 8 [that's the HW granularity].
	 * Reduce number so it would fit.
@@ -2424,6 +2421,10 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
		return -EINVAL;
	}

	/* This will also learn the number of SBs from MFW */
	if (qed_int_igu_reset_cam(p_hwfn, p_ptt))
		return -EINVAL;

	qed_hw_set_feat(p_hwfn);

	for (res_id = 0; res_id < QED_MAX_RESC; res_id++)
+4 −1
Original line number Diff line number Diff line
@@ -183,7 +183,10 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,
	p_data->q_params.queue_relative_offset = (u8)tmp;

	for (i = 0; i < fcoe_pf_params->num_cqs; i++) {
		tmp = cpu_to_le16(p_hwfn->sbs_info[i]->igu_sb_id);
		u16 igu_sb_id;

		igu_sb_id = qed_get_igu_sb_id(p_hwfn, i);
		tmp = cpu_to_le16(igu_sb_id);
		p_data->q_params.cq_cmdq_sb_num_arr[i] = tmp;
	}

Loading