mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
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: Nelson Escobar <neescoba@cisco.com> Signed-off-by: Nelson Escobar <neescoba@cisco.com> Co-developed-by: John Daley <johndale@cisco.com> Signed-off-by: John Daley <johndale@cisco.com> Signed-off-by: Satish Kharat <satishkh@cisco.com> Link: https://patch.msgid.link/20250304-enic_cleanup_and_ext_cq-v2-4-85804263dad8@cisco.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
2be2eb7643
commit
bcb725c79c
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
||||
|
|
@ -348,8 +367,8 @@ int enic_alloc_vnic_resources(struct enic *enic)
|
|||
for (i = 0; i < enic->cq_count; i++) {
|
||||
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));
|
||||
enic->config.rq_desc_count,
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,24 +21,76 @@ 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;
|
||||
|
||||
/* 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();
|
||||
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
|
||||
* 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_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;
|
||||
}
|
||||
}
|
||||
|
||||
*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;
|
||||
*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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user