Skip to content

Commit

Permalink
enic: added enic_wq.c and enic_wq.h
Browse files Browse the repository at this point in the history
Moves wq related function to enic_wq.c. Prepares for
a cleaup of enic wq code path.

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-6-85804263dad8@cisco.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Satish Kharat authored and Paolo Abeni committed Mar 11, 2025
1 parent 6dca618 commit e5f1bcd
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 117 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/cisco/enic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ obj-$(CONFIG_ENIC) := enic.o

enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \
enic_ethtool.o enic_api.o enic_clsf.o enic_rq.o
enic_ethtool.o enic_api.o enic_clsf.o enic_rq.o enic_wq.o

24 changes: 0 additions & 24 deletions drivers/net/ethernet/cisco/enic/cq_desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,4 @@ struct cq_desc {
#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)
{
const struct cq_desc *desc = desc_arg;
const u8 type_color = desc->type_color;

*color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK;

/*
* 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();

*type = type_color & CQ_DESC_TYPE_MASK;
*q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK;
*completed_index = le16_to_cpu(desc->completed_index) &
CQ_DESC_COMP_NDX_MASK;
}

#endif /* _CQ_DESC_H_ */
4 changes: 4 additions & 0 deletions drivers/net/ethernet/cisco/enic/enic.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ struct enic_rx_coal {
#define ENIC_SET_INSTANCE (1 << 3)
#define ENIC_SET_HOST (1 << 4)

#define MAX_TSO BIT(16)
#define WQ_ENET_MAX_DESC_LEN BIT(WQ_ENET_LEN_BITS)
#define ENIC_DESC_MAX_SPLITS (MAX_TSO / WQ_ENET_MAX_DESC_LEN + 1)

struct enic_port_profile {
u32 set;
u8 request;
Expand Down
52 changes: 1 addition & 51 deletions drivers/net/ethernet/cisco/enic/enic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,9 @@
#include "enic_pp.h"
#include "enic_clsf.h"
#include "enic_rq.h"
#include "enic_wq.h"

#define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ)
#define WQ_ENET_MAX_DESC_LEN (1 << WQ_ENET_LEN_BITS)
#define MAX_TSO (1 << 16)
#define ENIC_DESC_MAX_SPLITS (MAX_TSO / WQ_ENET_MAX_DESC_LEN + 1)

#define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */
#define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */
Expand Down Expand Up @@ -321,54 +319,6 @@ int enic_is_valid_vf(struct enic *enic, int vf)
#endif
}

static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
{
struct enic *enic = vnic_dev_priv(wq->vdev);

if (buf->sop)
dma_unmap_single(&enic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);
else
dma_unmap_page(&enic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);

if (buf->os_buf)
dev_kfree_skb_any(buf->os_buf);
}

static void enic_wq_free_buf(struct vnic_wq *wq,
struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque)
{
struct enic *enic = vnic_dev_priv(wq->vdev);

enic->wq[wq->index].stats.cq_work++;
enic->wq[wq->index].stats.cq_bytes += buf->len;
enic_free_wq_buf(wq, buf);
}

static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
u8 type, u16 q_number, u16 completed_index, void *opaque)
{
struct enic *enic = vnic_dev_priv(vdev);

spin_lock(&enic->wq[q_number].lock);

vnic_wq_service(&enic->wq[q_number].vwq, cq_desc,
completed_index, enic_wq_free_buf,
opaque);

if (netif_tx_queue_stopped(netdev_get_tx_queue(enic->netdev, q_number)) &&
vnic_wq_desc_avail(&enic->wq[q_number].vwq) >=
(MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)) {
netif_wake_subqueue(enic->netdev, q_number);
enic->wq[q_number].stats.wake++;
}

spin_unlock(&enic->wq[q_number].lock);

return 0;
}

static bool enic_log_q_error(struct enic *enic)
{
unsigned int i;
Expand Down
118 changes: 118 additions & 0 deletions drivers/net/ethernet/cisco/enic/enic_wq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2025 Cisco Systems, Inc. All rights reserved.

#include <net/netdev_queues.h>
#include "enic_res.h"
#include "enic.h"
#include "enic_wq.h"

static void cq_desc_dec(const struct cq_desc *desc_arg, u8 *type, u8 *color,
u16 *q_number, u16 *completed_index)
{
const struct cq_desc *desc = desc_arg;
const u8 type_color = desc->type_color;

*color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK;

/*
* 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();

*type = type_color & CQ_DESC_TYPE_MASK;
*q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK;
*completed_index = le16_to_cpu(desc->completed_index) &
CQ_DESC_COMP_NDX_MASK;
}

unsigned int vnic_cq_service(struct vnic_cq *cq, unsigned int work_to_do,
int (*q_service)(struct vnic_dev *vdev,
struct cq_desc *cq_desc, u8 type,
u16 q_number, u16 completed_index,
void *opaque), void *opaque)
{
struct cq_desc *cq_desc;
unsigned int work_done = 0;
u16 q_number, completed_index;
u8 type, color;

cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
cq->ring.desc_size * cq->to_clean);
cq_desc_dec(cq_desc, &type, &color,
&q_number, &completed_index);

while (color != cq->last_color) {
if ((*q_service)(cq->vdev, cq_desc, type, q_number,
completed_index, opaque))
break;

cq->to_clean++;
if (cq->to_clean == cq->ring.desc_count) {
cq->to_clean = 0;
cq->last_color = cq->last_color ? 0 : 1;
}

cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
cq->ring.desc_size * cq->to_clean);
cq_desc_dec(cq_desc, &type, &color,
&q_number, &completed_index);

work_done++;
if (work_done >= work_to_do)
break;
}

return work_done;
}

void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
{
struct enic *enic = vnic_dev_priv(wq->vdev);

if (buf->sop)
dma_unmap_single(&enic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);
else
dma_unmap_page(&enic->pdev->dev, buf->dma_addr, buf->len,
DMA_TO_DEVICE);

if (buf->os_buf)
dev_kfree_skb_any(buf->os_buf);
}

static void enic_wq_free_buf(struct vnic_wq *wq, struct cq_desc *cq_desc,
struct vnic_wq_buf *buf, void *opaque)
{
struct enic *enic = vnic_dev_priv(wq->vdev);

enic->wq[wq->index].stats.cq_work++;
enic->wq[wq->index].stats.cq_bytes += buf->len;
enic_free_wq_buf(wq, buf);
}

int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type,
u16 q_number, u16 completed_index, void *opaque)
{
struct enic *enic = vnic_dev_priv(vdev);

spin_lock(&enic->wq[q_number].lock);

vnic_wq_service(&enic->wq[q_number].vwq, cq_desc,
completed_index, enic_wq_free_buf, opaque);

if (netif_tx_queue_stopped(netdev_get_tx_queue(enic->netdev, q_number))
&& vnic_wq_desc_avail(&enic->wq[q_number].vwq) >=
(MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)) {
netif_wake_subqueue(enic->netdev, q_number);
enic->wq[q_number].stats.wake++;
}

spin_unlock(&enic->wq[q_number].lock);

return 0;
}

14 changes: 14 additions & 0 deletions drivers/net/ethernet/cisco/enic/enic_wq.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only
* Copyright 2025 Cisco Systems, Inc. All rights reserved.
*/

unsigned int vnic_cq_service(struct vnic_cq *cq, unsigned int work_to_do,
int (*q_service)(struct vnic_dev *vdev,
struct cq_desc *cq_desc, u8 type,
u16 q_number, u16 completed_index,
void *opaque), void *opaque);

void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);

int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type,
u16 q_number, u16 completed_index, void *opaque);
41 changes: 0 additions & 41 deletions drivers/net/ethernet/cisco/enic/vnic_cq.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,47 +56,6 @@ struct vnic_cq {
ktime_t prev_ts;
};

static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
unsigned int work_to_do,
int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc,
u8 type, u16 q_number, u16 completed_index, void *opaque),
void *opaque)
{
struct cq_desc *cq_desc;
unsigned int work_done = 0;
u16 q_number, completed_index;
u8 type, color;

cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
cq->ring.desc_size * cq->to_clean);
cq_desc_dec(cq_desc, &type, &color,
&q_number, &completed_index);

while (color != cq->last_color) {

if ((*q_service)(cq->vdev, cq_desc, type,
q_number, completed_index, opaque))
break;

cq->to_clean++;
if (cq->to_clean == cq->ring.desc_count) {
cq->to_clean = 0;
cq->last_color = cq->last_color ? 0 : 1;
}

cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
cq->ring.desc_size * cq->to_clean);
cq_desc_dec(cq_desc, &type, &color,
&q_number, &completed_index);

work_done++;
if (work_done >= work_to_do)
break;
}

return work_done;
}

static inline void *vnic_cq_to_clean(struct vnic_cq *cq)
{
return ((u8 *)cq->ring.descs + cq->ring.desc_size * cq->to_clean);
Expand Down

0 comments on commit e5f1bcd

Please sign in to comment.