Commit 5dcb50c0 authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'net-mana-add-pf-and-xdp_redirect-support'

Haiyang Zhang says:

====================
net: mana: Add PF and XDP_REDIRECT support

The patch set adds PF and XDP_REDIRECT support.
====================

Link: https://lore.kernel.org/r/1655238535-19257-1-git-send-email-haiyangz@microsoft.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 8bca4589 7a8938cd
...@@ -348,6 +348,7 @@ struct gdma_context { ...@@ -348,6 +348,7 @@ struct gdma_context {
struct completion eq_test_event; struct completion eq_test_event;
u32 test_event_eq_id; u32 test_event_eq_id;
bool is_pf;
void __iomem *bar0_va; void __iomem *bar0_va;
void __iomem *shm_base; void __iomem *shm_base;
void __iomem *db_page_base; void __iomem *db_page_base;
...@@ -469,6 +470,15 @@ struct gdma_eqe { ...@@ -469,6 +470,15 @@ struct gdma_eqe {
#define GDMA_REG_DB_PAGE_SIZE 0x10 #define GDMA_REG_DB_PAGE_SIZE 0x10
#define GDMA_REG_SHM_OFFSET 0x18 #define GDMA_REG_SHM_OFFSET 0x18
#define GDMA_PF_REG_DB_PAGE_SIZE 0xD0
#define GDMA_PF_REG_DB_PAGE_OFF 0xC8
#define GDMA_PF_REG_SHM_OFF 0x70
#define GDMA_SRIOV_REG_CFG_BASE_OFF 0x108
#define MANA_PF_DEVICE_ID 0x00B9
#define MANA_VF_DEVICE_ID 0x00BA
struct gdma_posted_wqe_info { struct gdma_posted_wqe_info {
u32 wqe_size_in_bu; u32 wqe_size_in_bu;
}; };
......
...@@ -18,7 +18,24 @@ static u64 mana_gd_r64(struct gdma_context *g, u64 offset) ...@@ -18,7 +18,24 @@ static u64 mana_gd_r64(struct gdma_context *g, u64 offset)
return readq(g->bar0_va + offset); return readq(g->bar0_va + offset);
} }
static void mana_gd_init_registers(struct pci_dev *pdev) static void mana_gd_init_pf_regs(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);
void __iomem *sriov_base_va;
u64 sriov_base_off;
gc->db_page_size = mana_gd_r32(gc, GDMA_PF_REG_DB_PAGE_SIZE) & 0xFFFF;
gc->db_page_base = gc->bar0_va +
mana_gd_r64(gc, GDMA_PF_REG_DB_PAGE_OFF);
sriov_base_off = mana_gd_r64(gc, GDMA_SRIOV_REG_CFG_BASE_OFF);
sriov_base_va = gc->bar0_va + sriov_base_off;
gc->shm_base = sriov_base_va +
mana_gd_r64(gc, sriov_base_off + GDMA_PF_REG_SHM_OFF);
}
static void mana_gd_init_vf_regs(struct pci_dev *pdev)
{ {
struct gdma_context *gc = pci_get_drvdata(pdev); struct gdma_context *gc = pci_get_drvdata(pdev);
...@@ -30,6 +47,16 @@ static void mana_gd_init_registers(struct pci_dev *pdev) ...@@ -30,6 +47,16 @@ static void mana_gd_init_registers(struct pci_dev *pdev)
gc->shm_base = gc->bar0_va + mana_gd_r64(gc, GDMA_REG_SHM_OFFSET); gc->shm_base = gc->bar0_va + mana_gd_r64(gc, GDMA_REG_SHM_OFFSET);
} }
static void mana_gd_init_registers(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);
if (gc->is_pf)
mana_gd_init_pf_regs(pdev);
else
mana_gd_init_vf_regs(pdev);
}
static int mana_gd_query_max_resources(struct pci_dev *pdev) static int mana_gd_query_max_resources(struct pci_dev *pdev)
{ {
struct gdma_context *gc = pci_get_drvdata(pdev); struct gdma_context *gc = pci_get_drvdata(pdev);
...@@ -1304,6 +1331,11 @@ static void mana_gd_cleanup(struct pci_dev *pdev) ...@@ -1304,6 +1331,11 @@ static void mana_gd_cleanup(struct pci_dev *pdev)
mana_gd_remove_irqs(pdev); mana_gd_remove_irqs(pdev);
} }
static bool mana_is_pf(unsigned short dev_id)
{
return dev_id == MANA_PF_DEVICE_ID;
}
static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
struct gdma_context *gc; struct gdma_context *gc;
...@@ -1340,10 +1372,10 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1340,10 +1372,10 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!bar0_va) if (!bar0_va)
goto free_gc; goto free_gc;
gc->is_pf = mana_is_pf(pdev->device);
gc->bar0_va = bar0_va; gc->bar0_va = bar0_va;
gc->dev = &pdev->dev; gc->dev = &pdev->dev;
err = mana_gd_setup(pdev); err = mana_gd_setup(pdev);
if (err) if (err)
goto unmap_bar; goto unmap_bar;
...@@ -1438,7 +1470,8 @@ static void mana_gd_shutdown(struct pci_dev *pdev) ...@@ -1438,7 +1470,8 @@ static void mana_gd_shutdown(struct pci_dev *pdev)
#endif #endif
static const struct pci_device_id mana_id_table[] = { static const struct pci_device_id mana_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MICROSOFT, 0x00BA) }, { PCI_DEVICE(PCI_VENDOR_ID_MICROSOFT, MANA_PF_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_MICROSOFT, MANA_VF_DEVICE_ID) },
{ } { }
}; };
......
...@@ -158,6 +158,14 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self, ...@@ -158,6 +158,14 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,
hwc->rxq->msg_buf->gpa_mkey = val; hwc->rxq->msg_buf->gpa_mkey = val;
hwc->txq->msg_buf->gpa_mkey = val; hwc->txq->msg_buf->gpa_mkey = val;
break; break;
case HWC_INIT_DATA_PF_DEST_RQ_ID:
hwc->pf_dest_vrq_id = val;
break;
case HWC_INIT_DATA_PF_DEST_CQ_ID:
hwc->pf_dest_vrcq_id = val;
break;
} }
break; break;
...@@ -773,10 +781,13 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) ...@@ -773,10 +781,13 @@ void mana_hwc_destroy_channel(struct gdma_context *gc)
int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len, int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
const void *req, u32 resp_len, void *resp) const void *req, u32 resp_len, void *resp)
{ {
struct gdma_context *gc = hwc->gdma_dev->gdma_context;
struct hwc_work_request *tx_wr; struct hwc_work_request *tx_wr;
struct hwc_wq *txq = hwc->txq; struct hwc_wq *txq = hwc->txq;
struct gdma_req_hdr *req_msg; struct gdma_req_hdr *req_msg;
struct hwc_caller_ctx *ctx; struct hwc_caller_ctx *ctx;
u32 dest_vrcq = 0;
u32 dest_vrq = 0;
u16 msg_id; u16 msg_id;
int err; int err;
...@@ -803,7 +814,12 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len, ...@@ -803,7 +814,12 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
tx_wr->msg_size = req_len; tx_wr->msg_size = req_len;
err = mana_hwc_post_tx_wqe(txq, tx_wr, 0, 0, false); if (gc->is_pf) {
dest_vrq = hwc->pf_dest_vrq_id;
dest_vrcq = hwc->pf_dest_vrcq_id;
}
err = mana_hwc_post_tx_wqe(txq, tx_wr, dest_vrq, dest_vrcq, false);
if (err) { if (err) {
dev_err(hwc->dev, "HWC: Failed to post send WQE: %d\n", err); dev_err(hwc->dev, "HWC: Failed to post send WQE: %d\n", err);
goto out; goto out;
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define HWC_INIT_DATA_MAX_NUM_CQS 7 #define HWC_INIT_DATA_MAX_NUM_CQS 7
#define HWC_INIT_DATA_PDID 8 #define HWC_INIT_DATA_PDID 8
#define HWC_INIT_DATA_GPA_MKEY 9 #define HWC_INIT_DATA_GPA_MKEY 9
#define HWC_INIT_DATA_PF_DEST_RQ_ID 10
#define HWC_INIT_DATA_PF_DEST_CQ_ID 11
/* Structures labeled with "HW DATA" are exchanged with the hardware. All of /* Structures labeled with "HW DATA" are exchanged with the hardware. All of
* them are naturally aligned and hence don't need __packed. * them are naturally aligned and hence don't need __packed.
...@@ -178,6 +180,9 @@ struct hw_channel_context { ...@@ -178,6 +180,9 @@ struct hw_channel_context {
struct semaphore sema; struct semaphore sema;
struct gdma_resource inflight_msg_res; struct gdma_resource inflight_msg_res;
u32 pf_dest_vrq_id;
u32 pf_dest_vrcq_id;
struct hwc_caller_ctx *caller_ctx; struct hwc_caller_ctx *caller_ctx;
}; };
......
...@@ -53,12 +53,14 @@ struct mana_stats_rx { ...@@ -53,12 +53,14 @@ struct mana_stats_rx {
u64 bytes; u64 bytes;
u64 xdp_drop; u64 xdp_drop;
u64 xdp_tx; u64 xdp_tx;
u64 xdp_redirect;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
}; };
struct mana_stats_tx { struct mana_stats_tx {
u64 packets; u64 packets;
u64 bytes; u64 bytes;
u64 xdp_xmit;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
}; };
...@@ -311,6 +313,8 @@ struct mana_rxq { ...@@ -311,6 +313,8 @@ struct mana_rxq {
struct bpf_prog __rcu *bpf_prog; struct bpf_prog __rcu *bpf_prog;
struct xdp_rxq_info xdp_rxq; struct xdp_rxq_info xdp_rxq;
struct page *xdp_save_page; struct page *xdp_save_page;
bool xdp_flush;
int xdp_rc; /* XDP redirect return code */
/* MUST BE THE LAST MEMBER: /* MUST BE THE LAST MEMBER:
* Each receive buffer has an associated mana_recv_buf_oob. * Each receive buffer has an associated mana_recv_buf_oob.
...@@ -374,6 +378,7 @@ struct mana_port_context { ...@@ -374,6 +378,7 @@ struct mana_port_context {
unsigned int num_queues; unsigned int num_queues;
mana_handle_t port_handle; mana_handle_t port_handle;
mana_handle_t pf_filter_handle;
u16 port_idx; u16 port_idx;
...@@ -395,6 +400,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming); ...@@ -395,6 +400,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming);
void mana_remove(struct gdma_dev *gd, bool suspending); void mana_remove(struct gdma_dev *gd, bool suspending);
void mana_xdp_tx(struct sk_buff *skb, struct net_device *ndev); void mana_xdp_tx(struct sk_buff *skb, struct net_device *ndev);
int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames,
u32 flags);
u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq, u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
struct xdp_buff *xdp, void *buf_va, uint pkt_len); struct xdp_buff *xdp, void *buf_va, uint pkt_len);
struct bpf_prog *mana_xdp_get(struct mana_port_context *apc); struct bpf_prog *mana_xdp_get(struct mana_port_context *apc);
...@@ -420,6 +427,12 @@ enum mana_command_code { ...@@ -420,6 +427,12 @@ enum mana_command_code {
MANA_FENCE_RQ = 0x20006, MANA_FENCE_RQ = 0x20006,
MANA_CONFIG_VPORT_RX = 0x20007, MANA_CONFIG_VPORT_RX = 0x20007,
MANA_QUERY_VPORT_CONFIG = 0x20008, MANA_QUERY_VPORT_CONFIG = 0x20008,
/* Privileged commands for the PF mode */
MANA_REGISTER_FILTER = 0x28000,
MANA_DEREGISTER_FILTER = 0x28001,
MANA_REGISTER_HW_PORT = 0x28003,
MANA_DEREGISTER_HW_PORT = 0x28004,
}; };
/* Query Device Configuration */ /* Query Device Configuration */
...@@ -547,6 +560,63 @@ struct mana_cfg_rx_steer_resp { ...@@ -547,6 +560,63 @@ struct mana_cfg_rx_steer_resp {
struct gdma_resp_hdr hdr; struct gdma_resp_hdr hdr;
}; /* HW DATA */ }; /* HW DATA */
/* Register HW vPort */
struct mana_register_hw_vport_req {
struct gdma_req_hdr hdr;
u16 attached_gfid;
u8 is_pf_default_vport;
u8 reserved1;
u8 allow_all_ether_types;
u8 reserved2;
u8 reserved3;
u8 reserved4;
}; /* HW DATA */
struct mana_register_hw_vport_resp {
struct gdma_resp_hdr hdr;
mana_handle_t hw_vport_handle;
}; /* HW DATA */
/* Deregister HW vPort */
struct mana_deregister_hw_vport_req {
struct gdma_req_hdr hdr;
mana_handle_t hw_vport_handle;
}; /* HW DATA */
struct mana_deregister_hw_vport_resp {
struct gdma_resp_hdr hdr;
}; /* HW DATA */
/* Register filter */
struct mana_register_filter_req {
struct gdma_req_hdr hdr;
mana_handle_t vport;
u8 mac_addr[6];
u8 reserved1;
u8 reserved2;
u8 reserved3;
u8 reserved4;
u16 reserved5;
u32 reserved6;
u32 reserved7;
u32 reserved8;
}; /* HW DATA */
struct mana_register_filter_resp {
struct gdma_resp_hdr hdr;
mana_handle_t filter_handle;
}; /* HW DATA */
/* Deregister filter */
struct mana_deregister_filter_req {
struct gdma_req_hdr hdr;
mana_handle_t filter_handle;
}; /* HW DATA */
struct mana_deregister_filter_resp {
struct gdma_resp_hdr hdr;
}; /* HW DATA */
#define MANA_MAX_NUM_QUEUES 64 #define MANA_MAX_NUM_QUEUES 64
#define MANA_SHORT_VPORT_OFFSET_MAX ((1U << 8) - 1) #define MANA_SHORT_VPORT_OFFSET_MAX ((1U << 8) - 1)
......
...@@ -32,9 +32,55 @@ void mana_xdp_tx(struct sk_buff *skb, struct net_device *ndev) ...@@ -32,9 +32,55 @@ void mana_xdp_tx(struct sk_buff *skb, struct net_device *ndev)
ndev->stats.tx_dropped++; ndev->stats.tx_dropped++;
} }
static int mana_xdp_xmit_fm(struct net_device *ndev, struct xdp_frame *frame,
u16 q_idx)
{
struct sk_buff *skb;
skb = xdp_build_skb_from_frame(frame, ndev);
if (unlikely(!skb))
return -ENOMEM;
skb_set_queue_mapping(skb, q_idx);
mana_xdp_tx(skb, ndev);
return 0;
}
int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames,
u32 flags)
{
struct mana_port_context *apc = netdev_priv(ndev);
struct mana_stats_tx *tx_stats;
int i, count = 0;
u16 q_idx;
if (unlikely(!apc->port_is_up))
return 0;
q_idx = smp_processor_id() % ndev->real_num_tx_queues;
for (i = 0; i < n; i++) {
if (mana_xdp_xmit_fm(ndev, frames[i], q_idx))
break;
count++;
}
tx_stats = &apc->tx_qp[q_idx].txq.stats;
u64_stats_update_begin(&tx_stats->syncp);
tx_stats->xdp_xmit += count;
u64_stats_update_end(&tx_stats->syncp);
return count;
}
u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq, u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
struct xdp_buff *xdp, void *buf_va, uint pkt_len) struct xdp_buff *xdp, void *buf_va, uint pkt_len)
{ {
struct mana_stats_rx *rx_stats;
struct bpf_prog *prog; struct bpf_prog *prog;
u32 act = XDP_PASS; u32 act = XDP_PASS;
...@@ -49,12 +95,30 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq, ...@@ -49,12 +95,30 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
act = bpf_prog_run_xdp(prog, xdp); act = bpf_prog_run_xdp(prog, xdp);
rx_stats = &rxq->stats;
switch (act) { switch (act) {
case XDP_PASS: case XDP_PASS:
case XDP_TX: case XDP_TX:
case XDP_DROP: case XDP_DROP:
break; break;
case XDP_REDIRECT:
rxq->xdp_rc = xdp_do_redirect(ndev, xdp, prog);
if (!rxq->xdp_rc) {
rxq->xdp_flush = true;
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->packets++;
rx_stats->bytes += pkt_len;
rx_stats->xdp_redirect++;
u64_stats_update_end(&rx_stats->syncp);
break;
}
fallthrough;
case XDP_ABORTED: case XDP_ABORTED:
trace_xdp_exception(ndev, prog, act); trace_xdp_exception(ndev, prog, act);
break; break;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/inetdevice.h> #include <linux/inetdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/filter.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <net/checksum.h> #include <net/checksum.h>
...@@ -382,6 +383,7 @@ static const struct net_device_ops mana_devops = { ...@@ -382,6 +383,7 @@ static const struct net_device_ops mana_devops = {
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_get_stats64 = mana_get_stats64, .ndo_get_stats64 = mana_get_stats64,
.ndo_bpf = mana_bpf, .ndo_bpf = mana_bpf,
.ndo_xdp_xmit = mana_xdp_xmit,
}; };
static void mana_cleanup_port_context(struct mana_port_context *apc) static void mana_cleanup_port_context(struct mana_port_context *apc)
...@@ -446,6 +448,119 @@ static int mana_verify_resp_hdr(const struct gdma_resp_hdr *resp_hdr, ...@@ -446,6 +448,119 @@ static int mana_verify_resp_hdr(const struct gdma_resp_hdr *resp_hdr,
return 0; return 0;
} }
static int mana_pf_register_hw_vport(struct mana_port_context *apc)
{
struct mana_register_hw_vport_resp resp = {};
struct mana_register_hw_vport_req req = {};
int err;
mana_gd_init_req_hdr(&req.hdr, MANA_REGISTER_HW_PORT,
sizeof(req), sizeof(resp));
req.attached_gfid = 1;
req.is_pf_default_vport = 1;
req.allow_all_ether_types = 1;
err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
sizeof(resp));
if (err) {
netdev_err(apc->ndev, "Failed to register hw vPort: %d\n", err);
return err;
}
err = mana_verify_resp_hdr(&resp.hdr, MANA_REGISTER_HW_PORT,
sizeof(resp));
if (err || resp.hdr.status) {
netdev_err(apc->ndev, "Failed to register hw vPort: %d, 0x%x\n",
err, resp.hdr.status);
return err ? err : -EPROTO;
}
apc->port_handle = resp.hw_vport_handle;
return 0;
}
static void mana_pf_deregister_hw_vport(struct mana_port_context *apc)
{
struct mana_deregister_hw_vport_resp resp = {};
struct mana_deregister_hw_vport_req req = {};
int err;
mana_gd_init_req_hdr(&req.hdr, MANA_DEREGISTER_HW_PORT,
sizeof(req), sizeof(resp));
req.hw_vport_handle = apc->port_handle;
err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
sizeof(resp));
if (err) {
netdev_err(apc->ndev, "Failed to unregister hw vPort: %d\n",
err);
return;
}
err = mana_verify_resp_hdr(&resp.hdr, MANA_DEREGISTER_HW_PORT,
sizeof(resp));
if (err || resp.hdr.status)
netdev_err(apc->ndev,
"Failed to deregister hw vPort: %d, 0x%x\n",
err, resp.hdr.status);
}
static int mana_pf_register_filter(struct mana_port_context *apc)
{
struct mana_register_filter_resp resp = {};
struct mana_register_filter_req req = {};
int err;
mana_gd_init_req_hdr(&req.hdr, MANA_REGISTER_FILTER,
sizeof(req), sizeof(resp));
req.vport = apc->port_handle;
memcpy(req.mac_addr, apc->mac_addr, ETH_ALEN);
err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
sizeof(resp));
if (err) {
netdev_err(apc->ndev, "Failed to register filter: %d\n", err);
return err;
}
err = mana_verify_resp_hdr(&resp.hdr, MANA_REGISTER_FILTER,
sizeof(resp));
if (err || resp.hdr.status) {
netdev_err(apc->ndev, "Failed to register filter: %d, 0x%x\n",
err, resp.hdr.status);
return err ? err : -EPROTO;
}
apc->pf_filter_handle = resp.filter_handle;
return 0;
}
static void mana_pf_deregister_filter(struct mana_port_context *apc)
{
struct mana_deregister_filter_resp resp = {};
struct mana_deregister_filter_req req = {};
int err;
mana_gd_init_req_hdr(&req.hdr, MANA_DEREGISTER_FILTER,
sizeof(req), sizeof(resp));
req.filter_handle = apc->pf_filter_handle;
err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
sizeof(resp));
if (err) {
netdev_err(apc->ndev, "Failed to unregister filter: %d\n",
err);
return;
}
err = mana_verify_resp_hdr(&resp.hdr, MANA_DEREGISTER_FILTER,
sizeof(resp));
if (err || resp.hdr.status)
netdev_err(apc->ndev,
"Failed to deregister filter: %d, 0x%x\n",
err, resp.hdr.status);
}
static int mana_query_device_cfg(struct mana_context *ac, u32 proto_major_ver, static int mana_query_device_cfg(struct mana_context *ac, u32 proto_major_ver,
u32 proto_minor_ver, u32 proto_micro_ver, u32 proto_minor_ver, u32 proto_micro_ver,
u16 *max_num_vports) u16 *max_num_vports)
...@@ -1007,6 +1122,9 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe, ...@@ -1007,6 +1122,9 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
act = mana_run_xdp(ndev, rxq, &xdp, buf_va, pkt_len); act = mana_run_xdp(ndev, rxq, &xdp, buf_va, pkt_len);
if (act == XDP_REDIRECT && !rxq->xdp_rc)
return;
if (act != XDP_PASS && act != XDP_TX) if (act != XDP_PASS && act != XDP_TX)
goto drop_xdp; goto drop_xdp;
...@@ -1162,11 +1280,14 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq, ...@@ -1162,11 +1280,14 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
static void mana_poll_rx_cq(struct mana_cq *cq) static void mana_poll_rx_cq(struct mana_cq *cq)
{ {
struct gdma_comp *comp = cq->gdma_comp_buf; struct gdma_comp *comp = cq->gdma_comp_buf;
struct mana_rxq *rxq = cq->rxq;
int comp_read, i; int comp_read, i;
comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER); comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER);
WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER); WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER);
rxq->xdp_flush = false;
for (i = 0; i < comp_read; i++) { for (i = 0; i < comp_read; i++) {
if (WARN_ON_ONCE(comp[i].is_sq)) if (WARN_ON_ONCE(comp[i].is_sq))
return; return;
...@@ -1175,8 +1296,11 @@ static void mana_poll_rx_cq(struct mana_cq *cq) ...@@ -1175,8 +1296,11 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
if (WARN_ON_ONCE(comp[i].wq_num != cq->rxq->gdma_id)) if (WARN_ON_ONCE(comp[i].wq_num != cq->rxq->gdma_id))
return; return;
mana_process_rx_cqe(cq->rxq, cq, &comp[i]); mana_process_rx_cqe(rxq, cq, &comp[i]);
} }
if (rxq->xdp_flush)
xdp_do_flush();
} }
static void mana_cq_handler(void *context, struct gdma_queue *gdma_queue) static void mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
...@@ -1653,6 +1777,7 @@ static int mana_add_rx_queues(struct mana_port_context *apc, ...@@ -1653,6 +1777,7 @@ static int mana_add_rx_queues(struct mana_port_context *apc,
static void mana_destroy_vport(struct mana_port_context *apc) static void mana_destroy_vport(struct mana_port_context *apc)
{ {
struct gdma_dev *gd = apc->ac->gdma_dev;
struct mana_rxq *rxq; struct mana_rxq *rxq;
u32 rxq_idx; u32 rxq_idx;
...@@ -1666,6 +1791,9 @@ static void mana_destroy_vport(struct mana_port_context *apc) ...@@ -1666,6 +1791,9 @@ static void mana_destroy_vport(struct mana_port_context *apc)
} }
mana_destroy_txq(apc); mana_destroy_txq(apc);
if (gd->gdma_context->is_pf)
mana_pf_deregister_hw_vport(apc);
} }
static int mana_create_vport(struct mana_port_context *apc, static int mana_create_vport(struct mana_port_context *apc,
...@@ -1676,6 +1804,12 @@ static int mana_create_vport(struct mana_port_context *apc, ...@@ -1676,6 +1804,12 @@ static int mana_create_vport(struct mana_port_context *apc,
apc->default_rxobj = INVALID_MANA_HANDLE; apc->default_rxobj = INVALID_MANA_HANDLE;
if (gd->gdma_context->is_pf) {
err = mana_pf_register_hw_vport(apc);
if (err)
return err;
}
err = mana_cfg_vport(apc, gd->pdid, gd->doorbell); err = mana_cfg_vport(apc, gd->pdid, gd->doorbell);
if (err) if (err)
return err; return err;
...@@ -1755,6 +1889,7 @@ static int mana_init_port(struct net_device *ndev) ...@@ -1755,6 +1889,7 @@ static int mana_init_port(struct net_device *ndev)
int mana_alloc_queues(struct net_device *ndev) int mana_alloc_queues(struct net_device *ndev)
{ {
struct mana_port_context *apc = netdev_priv(ndev); struct mana_port_context *apc = netdev_priv(ndev);
struct gdma_dev *gd = apc->ac->gdma_dev;
int err; int err;
err = mana_create_vport(apc, ndev); err = mana_create_vport(apc, ndev);
...@@ -1781,6 +1916,12 @@ int mana_alloc_queues(struct net_device *ndev) ...@@ -1781,6 +1916,12 @@ int mana_alloc_queues(struct net_device *ndev)
if (err) if (err)
goto destroy_vport; goto destroy_vport;
if (gd->gdma_context->is_pf) {
err = mana_pf_register_filter(apc);
if (err)
goto destroy_vport;
}
mana_chn_setxdp(apc, mana_xdp_get(apc)); mana_chn_setxdp(apc, mana_xdp_get(apc));
return 0; return 0;
...@@ -1825,6 +1966,7 @@ int mana_attach(struct net_device *ndev) ...@@ -1825,6 +1966,7 @@ int mana_attach(struct net_device *ndev)
static int mana_dealloc_queues(struct net_device *ndev) static int mana_dealloc_queues(struct net_device *ndev)
{ {
struct mana_port_context *apc = netdev_priv(ndev); struct mana_port_context *apc = netdev_priv(ndev);
struct gdma_dev *gd = apc->ac->gdma_dev;
struct mana_txq *txq; struct mana_txq *txq;
int i, err; int i, err;
...@@ -1833,6 +1975,9 @@ static int mana_dealloc_queues(struct net_device *ndev) ...@@ -1833,6 +1975,9 @@ static int mana_dealloc_queues(struct net_device *ndev)
mana_chn_setxdp(apc, NULL); mana_chn_setxdp(apc, NULL);
if (gd->gdma_context->is_pf)
mana_pf_deregister_filter(apc);
/* No packet can be transmitted now since apc->port_is_up is false. /* No packet can be transmitted now since apc->port_is_up is false.
* There is still a tiny chance that mana_poll_tx_cq() can re-enable * There is still a tiny chance that mana_poll_tx_cq() can re-enable
* a txq because it may not timely see apc->port_is_up being cleared * a txq because it may not timely see apc->port_is_up being cleared
...@@ -1915,6 +2060,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx, ...@@ -1915,6 +2060,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
apc->max_queues = gc->max_num_queues; apc->max_queues = gc->max_num_queues;
apc->num_queues = gc->max_num_queues; apc->num_queues = gc->max_num_queues;
apc->port_handle = INVALID_MANA_HANDLE; apc->port_handle = INVALID_MANA_HANDLE;
apc->pf_filter_handle = INVALID_MANA_HANDLE;
apc->port_idx = port_idx; apc->port_idx = port_idx;
ndev->netdev_ops = &mana_devops; ndev->netdev_ops = &mana_devops;
......
...@@ -23,7 +23,7 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset) ...@@ -23,7 +23,7 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
if (stringset != ETH_SS_STATS) if (stringset != ETH_SS_STATS)
return -EINVAL; return -EINVAL;
return ARRAY_SIZE(mana_eth_stats) + num_queues * 6; return ARRAY_SIZE(mana_eth_stats) + num_queues * 8;
} }
static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data) static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
...@@ -50,6 +50,8 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data) ...@@ -50,6 +50,8 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
sprintf(p, "rx_%d_xdp_tx", i); sprintf(p, "rx_%d_xdp_tx", i);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
sprintf(p, "rx_%d_xdp_redirect", i);
p += ETH_GSTRING_LEN;
} }
for (i = 0; i < num_queues; i++) { for (i = 0; i < num_queues; i++) {
...@@ -57,6 +59,8 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data) ...@@ -57,6 +59,8 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
sprintf(p, "tx_%d_bytes", i); sprintf(p, "tx_%d_bytes", i);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
sprintf(p, "tx_%d_xdp_xmit", i);
p += ETH_GSTRING_LEN;
} }
} }
...@@ -70,6 +74,8 @@ static void mana_get_ethtool_stats(struct net_device *ndev, ...@@ -70,6 +74,8 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
struct mana_stats_tx *tx_stats; struct mana_stats_tx *tx_stats;
unsigned int start; unsigned int start;
u64 packets, bytes; u64 packets, bytes;
u64 xdp_redirect;
u64 xdp_xmit;
u64 xdp_drop; u64 xdp_drop;
u64 xdp_tx; u64 xdp_tx;
int q, i = 0; int q, i = 0;
...@@ -89,12 +95,14 @@ static void mana_get_ethtool_stats(struct net_device *ndev, ...@@ -89,12 +95,14 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
bytes = rx_stats->bytes; bytes = rx_stats->bytes;
xdp_drop = rx_stats->xdp_drop; xdp_drop = rx_stats->xdp_drop;
xdp_tx = rx_stats->xdp_tx; xdp_tx = rx_stats->xdp_tx;
xdp_redirect = rx_stats->xdp_redirect;
} while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
data[i++] = packets; data[i++] = packets;
data[i++] = bytes; data[i++] = bytes;
data[i++] = xdp_drop; data[i++] = xdp_drop;
data[i++] = xdp_tx; data[i++] = xdp_tx;
data[i++] = xdp_redirect;
} }
for (q = 0; q < num_queues; q++) { for (q = 0; q < num_queues; q++) {
...@@ -104,10 +112,12 @@ static void mana_get_ethtool_stats(struct net_device *ndev, ...@@ -104,10 +112,12 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
start = u64_stats_fetch_begin_irq(&tx_stats->syncp); start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
packets = tx_stats->packets; packets = tx_stats->packets;
bytes = tx_stats->bytes; bytes = tx_stats->bytes;
xdp_xmit = tx_stats->xdp_xmit;
} while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
data[i++] = packets; data[i++] = packets;
data[i++] = bytes; data[i++] = bytes;
data[i++] = xdp_xmit;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment