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

Commit d8c2c7e3 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller
Browse files

qed*: Add support for VFs over legacy PFs



Modern VFs can't run on old non-compatible as the fastpath HSI is
slightly changed - but as the HSI is actually very close [basically,
a single bit whose meaning flipped] this can be supported with small
modifications.

The major differences would be in:
  - Recognizing that VF is running on top of a legacy PF.
  - Returning some slowpath configurations that are no longer needed
    on top of modern PFs, but would be required when working over
    the legacy ones.

Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 11a85d75
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1685,6 +1685,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
		qed_vf_get_num_vlan_filters(&cdev->hwfns[0],
					    &info->num_vlan_filters);
		qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac);

		info->is_legacy = !!cdev->hwfns[0].vf_iov_info->b_pre_fp_hsi;
	}

	qed_fill_dev_info(cdev, &info->common);
+87 −20
Original line number Diff line number Diff line
@@ -191,6 +191,9 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
		DP_VERBOSE(p_hwfn,
			   QED_MSG_IOV, "attempting to acquire resources\n");

		/* Clear response buffer, as this might be a re-send */
		memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));

		/* send acquire request */
		rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
		if (rc)
@@ -205,9 +208,12 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
			/* PF agrees to allocate our resources */
			if (!(resp->pfdev_info.capabilities &
			      PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) {
				DP_INFO(p_hwfn,
					"PF is using old incompatible driver; Either downgrade driver or request provider to update hypervisor version\n");
				return -EINVAL;
				/* It's possible legacy PF mistakenly accepted;
				 * but we don't care - simply mark it as
				 * legacy and continue.
				 */
				req->vfdev_info.capabilities |=
				    VFPF_ACQUIRE_CAP_PRE_FP_HSI;
			}
			DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n");
			resources_acquired = true;
@@ -215,27 +221,55 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
			   attempts < VF_ACQUIRE_THRESH) {
			qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc,
						      &resp->resc);

			/* Clear response buffer */
			memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));
		} else if ((resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) &&
			   pfdev_info->major_fp_hsi &&
		} else if (resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) {
			if (pfdev_info->major_fp_hsi &&
			    (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) {
				DP_NOTICE(p_hwfn,
					  "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n",
					  pfdev_info->major_fp_hsi,
					  pfdev_info->minor_fp_hsi,
					  ETH_HSI_VER_MAJOR,
				  ETH_HSI_VER_MINOR, pfdev_info->major_fp_hsi);
			return -EINVAL;
					  ETH_HSI_VER_MINOR,
					  pfdev_info->major_fp_hsi);
				rc = -EINVAL;
				goto exit;
			}

			if (!pfdev_info->major_fp_hsi) {
				if (req->vfdev_info.capabilities &
				    VFPF_ACQUIRE_CAP_PRE_FP_HSI) {
					DP_NOTICE(p_hwfn,
						  "PF uses very old drivers. Please change to a VF driver using no later than 8.8.x.x.\n");
					rc = -EINVAL;
					goto exit;
				} else {
					DP_INFO(p_hwfn,
						"PF is old - try re-acquire to see if it supports FW-version override\n");
					req->vfdev_info.capabilities |=
					    VFPF_ACQUIRE_CAP_PRE_FP_HSI;
					continue;
				}
			}

			/* If PF/VF are using same Major, PF must have had
			 * it's reasons. Simply fail.
			 */
			DP_NOTICE(p_hwfn, "PF rejected acquisition by VF\n");
			rc = -EINVAL;
			goto exit;
		} else {
			DP_ERR(p_hwfn,
			       "PF returned error %d to VF acquisition request\n",
			       resp->hdr.status);
			return -EAGAIN;
			rc = -EAGAIN;
			goto exit;
		}
	}

	/* Mark the PF as legacy, if needed */
	if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_PRE_FP_HSI)
		p_iov->b_pre_fp_hsi = true;

	/* Update bulletin board size with response from PF */
	p_iov->bulletin.size = resp->bulletin_size;

@@ -253,14 +287,16 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
		}
	}

	if (ETH_HSI_VER_MINOR &&
	if (!p_iov->b_pre_fp_hsi &&
	    ETH_HSI_VER_MINOR &&
	    (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) {
		DP_INFO(p_hwfn,
			"PF is using older fastpath HSI; %02x.%02x is configured\n",
			ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi);
	}

	return 0;
exit:
	return rc;
}

int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
@@ -347,6 +383,9 @@ int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)

	return -ENOMEM;
}
#define TSTORM_QZONE_START   PXP_VF_BAR0_START_SDM_ZONE_A
#define MSTORM_QZONE_START(dev)   (TSTORM_QZONE_START +	\
				   (TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev)))

int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
			u8 rx_qid,
@@ -374,6 +413,21 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
	req->bd_max_bytes = bd_max_bytes;
	req->stat_id = -1;

	/* If PF is legacy, we'll need to calculate producers ourselves
	 * as well as clean them.
	 */
	if (pp_prod && p_iov->b_pre_fp_hsi) {
		u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid];
		u32 init_prod_val = 0;

		*pp_prod = (u8 __iomem *)p_hwfn->regview +
					 MSTORM_QZONE_START(p_hwfn->cdev) +
					 hw_qid * MSTORM_QZONE_SIZE;

		/* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
		__internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
				  (u32 *)(&init_prod_val));
	}
	/* add list termination tlv */
	qed_add_tlv(p_hwfn, &p_iov->offset,
		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
@@ -387,7 +441,7 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
		return -EINVAL;

	/* Learn the address of the producer from the response */
	if (pp_prod) {
	if (pp_prod && !p_iov->b_pre_fp_hsi) {
		u32 init_prod_val = 0;

		*pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset;
@@ -470,7 +524,20 @@ int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
	}

	if (pp_doorbell) {
		*pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + resp->offset;
		/* Modern PFs provide the actual offsets, while legacy
		 * provided only the queue id.
		 */
		if (!p_iov->b_pre_fp_hsi) {
			*pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
						     resp->offset;
		} else {
			u8 cid = p_iov->acquire_resp.resc.cid[tx_queue_id];
			u32 db_addr;

			db_addr = qed_db_addr(cid, DQ_DEMS_LEGACY);
			*pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
						     db_addr;
		}

		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
			   "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n",
+5 −0
Original line number Diff line number Diff line
@@ -551,6 +551,11 @@ struct qed_vf_iov {

	/* we set aside a copy of the acquire response */
	struct pfvf_acquire_resp_tlv acquire_resp;

	/* In case PF originates prior to the fp-hsi version comparison,
	 * this has to be propagated as it affects the fastpath.
	 */
	bool b_pre_fp_hsi;
};

#ifdef CONFIG_QED_SRIOV
+2 −0
Original line number Diff line number Diff line
@@ -268,6 +268,8 @@ struct qede_tx_queue {
	u16			num_tx_buffers;
	u64			xmit_pkts;
	u64			stopped_cnt;

	bool			is_legacy;
};

#define BD_UNMAP_ADDR(bd)		HILO_U64(le32_to_cpu((bd)->addr.hi), \
+10 −0
Original line number Diff line number Diff line
@@ -598,6 +598,14 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
			    1 << ETH_TX_DATA_1ST_BD_TUNN_FLAG_SHIFT;
		}

		/* Legacy FW had flipped behavior in regard to this bit -
		 * I.e., needed to set to prevent FW from touching encapsulated
		 * packets when it didn't need to.
		 */
		if (unlikely(txq->is_legacy))
			first_bd->data.bitfields ^=
			    1 << ETH_TX_DATA_1ST_BD_TUNN_FLAG_SHIFT;

		/* If the packet is IPv6 with extension header, indicate that
		 * to FW and pass few params, since the device cracker doesn't
		 * support parsing IPv6 with extension header/s.
@@ -2991,6 +2999,8 @@ static void qede_init_fp(struct qede_dev *edev)
		for (tc = 0; tc < edev->num_tc; tc++) {
			txq_index = tc * QEDE_RSS_CNT(edev) + rss_id;
			fp->txqs[tc].index = txq_index;
			if (edev->dev_info.is_legacy)
				fp->txqs[tc].is_legacy = true;
		}

		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
Loading