Commit bcb725c7 authored by Satish Kharat's avatar Satish Kharat Committed by Paolo Abeni
Browse files

enic: enable rq extended cq support



Enables getting from hw all the supported rq cq sizes and
uses the highest supported cq size.

Co-developed-by: default avatarNelson Escobar <neescoba@cisco.com>
Signed-off-by: default avatarNelson Escobar <neescoba@cisco.com>
Co-developed-by: default avatarJohn Daley <johndale@cisco.com>
Signed-off-by: default avatarJohn Daley <johndale@cisco.com>
Signed-off-by: default avatarSatish Kharat <satishkh@cisco.com>
Link: https://patch.msgid.link/20250304-enic_cleanup_and_ext_cq-v2-4-85804263dad8@cisco.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 2be2eb76
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ struct cq_desc {
#define CQ_DESC_COMP_NDX_BITS    12
#define CQ_DESC_COMP_NDX_MASK    ((1 << CQ_DESC_COMP_NDX_BITS) - 1)

#define CQ_DESC_32_FI_MASK (BIT(0) | BIT(1))
#define CQ_DESC_64_FI_MASK (BIT(0) | BIT(1))

static inline void cq_desc_dec(const struct cq_desc *desc_arg,
	u8 *type, u8 *color, u16 *q_number, u16 *completed_index)
{
+9 −0
Original line number Diff line number Diff line
@@ -31,6 +31,13 @@

#define ENIC_AIC_LARGE_PKT_DIFF	3

enum ext_cq {
	ENIC_RQ_CQ_ENTRY_SIZE_16,
	ENIC_RQ_CQ_ENTRY_SIZE_32,
	ENIC_RQ_CQ_ENTRY_SIZE_64,
	ENIC_RQ_CQ_ENTRY_SIZE_MAX,
};

struct enic_msix_entry {
	int requested;
	char devname[IFNAMSIZ + 8];
@@ -228,6 +235,7 @@ struct enic {
	struct enic_rfs_flw_tbl rfs_h;
	u8 rss_key[ENIC_RSS_LEN];
	struct vnic_gen_stats gen_stats;
	enum ext_cq ext_cq;
};

static inline struct net_device *vnic_get_netdev(struct vnic_dev *vdev)
@@ -349,5 +357,6 @@ int enic_is_valid_vf(struct enic *enic, int vf);
int enic_is_dynamic(struct enic *enic);
void enic_set_ethtool_ops(struct net_device *netdev);
int __enic_set_rsskey(struct enic *enic);
void enic_ext_cq(struct enic *enic);

#endif /* _ENIC_H_ */
+4 −0
Original line number Diff line number Diff line
@@ -2192,6 +2192,7 @@ static void enic_reset(struct work_struct *work)
	enic_init_vnic_resources(enic);
	enic_set_rss_nic_cfg(enic);
	enic_dev_set_ig_vlan_rewrite_mode(enic);
	enic_ext_cq(enic);
	enic_open(enic->netdev);

	/* Allow infiniband to fiddle with the device again */
@@ -2218,6 +2219,7 @@ static void enic_tx_hang_reset(struct work_struct *work)
	enic_init_vnic_resources(enic);
	enic_set_rss_nic_cfg(enic);
	enic_dev_set_ig_vlan_rewrite_mode(enic);
	enic_ext_cq(enic);
	enic_open(enic->netdev);

	/* Allow infiniband to fiddle with the device again */
@@ -2592,6 +2594,8 @@ static int enic_dev_init(struct enic *enic)

	enic_get_res_counts(enic);

	enic_ext_cq(enic);

	err = enic_alloc_enic_resources(enic);
	if (err) {
		dev_err(dev, "Failed to allocate enic resources\n");
+55 −3
Original line number Diff line number Diff line
@@ -312,6 +312,7 @@ void enic_init_vnic_resources(struct enic *enic)
int enic_alloc_vnic_resources(struct enic *enic)
{
	enum vnic_dev_intr_mode intr_mode;
	int rq_cq_desc_size;
	unsigned int i;
	int err;

@@ -326,6 +327,24 @@ int enic_alloc_vnic_resources(struct enic *enic)
		intr_mode == VNIC_DEV_INTR_MODE_MSIX ? "MSI-X" :
		"unknown");

	switch (enic->ext_cq) {
	case ENIC_RQ_CQ_ENTRY_SIZE_16:
		rq_cq_desc_size = 16;
		break;
	case ENIC_RQ_CQ_ENTRY_SIZE_32:
		rq_cq_desc_size = 32;
		break;
	case ENIC_RQ_CQ_ENTRY_SIZE_64:
		rq_cq_desc_size = 64;
		break;
	default:
		dev_err(enic_get_dev(enic),
			"Unable to determine rq cq desc size: %d",
			enic->ext_cq);
		err = -ENODEV;
		goto err_out;
	}

	/* Allocate queue resources
	 */

@@ -349,7 +368,7 @@ int enic_alloc_vnic_resources(struct enic *enic)
		if (i < enic->rq_count)
			err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
					enic->config.rq_desc_count,
				sizeof(struct cq_enet_rq_desc));
					rq_cq_desc_size);
		else
			err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
				enic->config.wq_desc_count,
@@ -380,6 +399,39 @@ int enic_alloc_vnic_resources(struct enic *enic)

err_out_cleanup:
	enic_free_vnic_resources(enic);

err_out:
	return err;
}

/*
 * CMD_CQ_ENTRY_SIZE_SET can fail on older hw generations that don't support
 * that command
 */
void enic_ext_cq(struct enic *enic)
{
	u64 a0 = CMD_CQ_ENTRY_SIZE_SET, a1 = 0;
	int wait = 1000;
	int ret;

	spin_lock_bh(&enic->devcmd_lock);
	ret = vnic_dev_cmd(enic->vdev, CMD_CAPABILITY, &a0, &a1, wait);
	if (ret || a0) {
		dev_info(&enic->pdev->dev,
			 "CMD_CQ_ENTRY_SIZE_SET not supported.");
		enic->ext_cq = ENIC_RQ_CQ_ENTRY_SIZE_16;
		goto out;
	}
	a1 &= VNIC_RQ_CQ_ENTRY_SIZE_ALL_BIT;
	enic->ext_cq = fls(a1) - 1;
	a0 = VNIC_RQ_ALL;
	a1 = enic->ext_cq;
	ret = vnic_dev_cmd(enic->vdev, CMD_CQ_ENTRY_SIZE_SET, &a0, &a1, wait);
	if (ret) {
		dev_info(&enic->pdev->dev, "CMD_CQ_ENTRY_SIZE_SET failed.");
		enic->ext_cq = ENIC_RQ_CQ_ENTRY_SIZE_16;
	}
out:
	spin_unlock_bh(&enic->devcmd_lock);
	dev_info(&enic->pdev->dev, "CQ entry size set to %d bytes",
		 16 << enic->ext_cq);
}
+79 −26
Original line number Diff line number Diff line
@@ -21,11 +21,36 @@ static void enic_intr_update_pkt_size(struct vnic_rx_bytes_counter *pkt_size,
		pkt_size->small_pkt_bytes_cnt += pkt_len;
}

static void enic_rq_cq_desc_dec(struct cq_enet_rq_desc *desc, u8 *type,
static void enic_rq_cq_desc_dec(void *cq_desc, u8 cq_desc_size, u8 *type,
				u8 *color, u16 *q_number, u16 *completed_index)
{
	/* type_color is the last field for all cq structs */
	u8 type_color = desc->type_color;
	u8 type_color;

	switch (cq_desc_size) {
	case VNIC_RQ_CQ_ENTRY_SIZE_16: {
		struct cq_enet_rq_desc *desc =
			(struct cq_enet_rq_desc *)cq_desc;
		type_color = desc->type_color;

		/* Make sure color bit is read from desc *before* other fields
		 * are read from desc.  Hardware guarantees color bit is last
		 * bit (byte) written.  Adding the rmb() prevents the compiler
		 * and/or CPU from reordering the reads which would potentially
		 * result in reading stale values.
		 */
		rmb();

		*q_number = le16_to_cpu(desc->q_number_rss_type_flags) &
			    CQ_DESC_Q_NUM_MASK;
		*completed_index = le16_to_cpu(desc->completed_index_flags) &
				   CQ_DESC_COMP_NDX_MASK;
		break;
	}
	case VNIC_RQ_CQ_ENTRY_SIZE_32: {
		struct cq_enet_rq_desc_32 *desc =
			(struct cq_enet_rq_desc_32 *)cq_desc;
		type_color = desc->type_color;

		/* Make sure color bit is read from desc *before* other fields
		 * are read from desc.  Hardware guarantees color bit is last
@@ -39,6 +64,33 @@ static void enic_rq_cq_desc_dec(struct cq_enet_rq_desc *desc, u8 *type,
			    CQ_DESC_Q_NUM_MASK;
		*completed_index = le16_to_cpu(desc->completed_index_flags) &
				   CQ_DESC_COMP_NDX_MASK;
		*completed_index |= (desc->fetch_index_flags & CQ_DESC_32_FI_MASK) <<
				CQ_DESC_COMP_NDX_BITS;
		break;
	}
	case VNIC_RQ_CQ_ENTRY_SIZE_64: {
		struct cq_enet_rq_desc_64 *desc =
			(struct cq_enet_rq_desc_64 *)cq_desc;
		type_color = desc->type_color;

		/* Make sure color bit is read from desc *before* other fields
		 * are read from desc.  Hardware guarantees color bit is last
		 * bit (byte) written.  Adding the rmb() prevents the compiler
		 * and/or CPU from reordering the reads which would potentially
		 * result in reading stale values.
		 */
		rmb();

		*q_number = le16_to_cpu(desc->q_number_rss_type_flags) &
			    CQ_DESC_Q_NUM_MASK;
		*completed_index = le16_to_cpu(desc->completed_index_flags) &
				   CQ_DESC_COMP_NDX_MASK;
		*completed_index |= (desc->fetch_index_flags & CQ_DESC_64_FI_MASK) <<
				CQ_DESC_COMP_NDX_BITS;
		break;
	}
	}

	*color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK;
	*type = type_color & CQ_DESC_TYPE_MASK;
}
@@ -113,6 +165,10 @@ static void enic_rq_set_skb_flags(struct vnic_rq *vrq, u8 type, u32 rss_hash,
	}
}

/*
 * cq_enet_rq_desc accesses section uses only the 1st 15 bytes of the cq which
 * is identical for all type (16,32 and 64 byte) of cqs.
 */
static void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc, u8 *ingress_port,
				u8 *fcoe, u8 *eop, u8 *sop, u8 *rss_type,
				u8 *csum_not_calc, u32 *rss_hash,
@@ -258,9 +314,8 @@ void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
}

static void enic_rq_indicate_buf(struct enic *enic, struct vnic_rq *rq,
				 struct vnic_rq_buf *buf,
				 struct cq_enet_rq_desc *cq_desc, u8 type,
				 u16 q_number, u16 completed_index)
				 struct vnic_rq_buf *buf, void *cq_desc,
				 u8 type, u16 q_number, u16 completed_index)
{
	struct sk_buff *skb;
	struct vnic_cq *cq = &enic->cq[enic_cq_rq(enic, rq->index)];
@@ -277,7 +332,7 @@ static void enic_rq_indicate_buf(struct enic *enic, struct vnic_rq *rq,

	rqstats->packets++;

	cq_enet_rq_desc_dec(cq_desc, &ingress_port,
	cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc, &ingress_port,
			    &fcoe, &eop, &sop, &rss_type, &csum_not_calc,
			    &rss_hash, &bytes_written, &packet_error,
			    &vlan_stripped, &vlan_tci, &checksum, &fcoe_sof,
@@ -329,8 +384,8 @@ static void enic_rq_indicate_buf(struct enic *enic, struct vnic_rq *rq,
	}
}

static void enic_rq_service(struct enic *enic, struct cq_enet_rq_desc *cq_desc,
			    u8 type, u16 q_number, u16 completed_index)
static void enic_rq_service(struct enic *enic, void *cq_desc, u8 type,
			    u16 q_number, u16 completed_index)
{
	struct enic_rq_stats *rqstats = &enic->rq[q_number].stats;
	struct vnic_rq *vrq = &enic->rq[q_number].vrq;
@@ -357,14 +412,12 @@ unsigned int enic_rq_cq_service(struct enic *enic, unsigned int cq_index,
				unsigned int work_to_do)
{
	struct vnic_cq *cq = &enic->cq[cq_index];
	struct cq_enet_rq_desc *cq_desc;
	void *cq_desc = vnic_cq_to_clean(cq);
	u16 q_number, completed_index;
	unsigned int work_done = 0;
	u8 type, color;

	cq_desc = (struct cq_enet_rq_desc *)vnic_cq_to_clean(cq);

	enic_rq_cq_desc_dec(cq_desc,  &type, &color, &q_number,
	enic_rq_cq_desc_dec(cq_desc, enic->ext_cq, &type, &color, &q_number,
			    &completed_index);

	while (color != cq->last_color) {
@@ -374,9 +427,9 @@ unsigned int enic_rq_cq_service(struct enic *enic, unsigned int cq_index,
		if (++work_done >= work_to_do)
			break;

		cq_desc = (struct cq_enet_rq_desc *)vnic_cq_to_clean(cq);
		enic_rq_cq_desc_dec(cq_desc, &type, &color, &q_number,
				    &completed_index);
		cq_desc = vnic_cq_to_clean(cq);
		enic_rq_cq_desc_dec(cq_desc, enic->ext_cq, &type, &color,
				    &q_number, &completed_index);
	}

	return work_done;