[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <151316398635.14967.13125869420970564092.stgit@firesoul>
Date: Wed, 13 Dec 2017 12:19:46 +0100
From: Jesper Dangaard Brouer <brouer@...hat.com>
To: Daniel Borkmann <borkmann@...earbox.net>,
Alexei Starovoitov <alexei.starovoitov@...il.com>
Cc: bjorn.topel@...el.com, netdev@...r.kernel.org,
Jesper Dangaard Brouer <brouer@...hat.com>,
Ariel Elior <Ariel.Elior@...ium.com>, dsahern@...il.com,
gospo@...adcom.com, everest-linux-l2@...ium.com,
michael.chan@...adcom.com
Subject: [bpf-next V1-RFC PATCH 05/14] xdp/qede: setup xdp_rxq_info and
intro xdp_rxq_info_is_reg
The driver code qede_free_fp_array() depend on kfree() can be called
with a NULL pointer. This stems from the qede_alloc_fp_array()
function which either (kz)alloc memory for fp->txq or fp->rxq.
This also simplifies error handling code in case of memory allocation
failures, but xdp_rxq_info_unreg need to know the difference.
Introduce xdp_rxq_info_is_reg() to handle if a memory allocation fails
and detect this is the failure path by seeing that xdp_rxq_info was
not registred yet, which first happens after successful alloaction in
qede_init_fp().
Driver hook points for xdp_rxq_info:
* init+reg: qede_init_fp
* unreg : qede_free_fp_array
Tested on actual hardware with samples/bpf program.
Cc: everest-linux-l2@...ium.com
Cc: Ariel Elior <Ariel.Elior@...ium.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@...hat.com>
---
drivers/net/ethernet/qlogic/qede/qede.h | 2 ++
drivers/net/ethernet/qlogic/qede/qede_fp.c | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 12 ++++++++++++
include/net/xdp.h | 1 +
net/core/xdp.c | 11 +++++++++++
5 files changed, 27 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index a3a70ade411f..62f47736511b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -40,6 +40,7 @@
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/bpf.h>
+#include <net/xdp.h>
#include <linux/qed/qede_rdma.h>
#include <linux/io.h>
#ifdef CONFIG_RFS_ACCEL
@@ -345,6 +346,7 @@ struct qede_rx_queue {
u64 xdp_no_pass;
void *handle;
+ struct xdp_rxq_info xdp_rxq;
};
union db_prod {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index 48ec4c56cddf..dafc079ab6b9 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1006,6 +1006,7 @@ static bool qede_rx_xdp(struct qede_dev *edev,
xdp.data = xdp.data_hard_start + *data_offset;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + *len;
+ xdp.rxq = &rxq->xdp_rxq;
/* Queues always have a full reset currently, so for the time
* being until there's atomic program replace just mark read
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 57332b3e5e64..a7264fdf4112 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -762,6 +762,12 @@ static void qede_free_fp_array(struct qede_dev *edev)
fp = &edev->fp_array[i];
kfree(fp->sb_info);
+ /* Handle mem alloc failure case where qede_init_fp
+ * didn't register xdp_rxq_info yet.
+ * Implicit only (fp->type & QEDE_FASTPATH_RX)
+ */
+ if (fp->rxq && xdp_rxq_info_is_reg(&fp->rxq->xdp_rxq))
+ xdp_rxq_info_unreg(&fp->rxq->xdp_rxq);
kfree(fp->rxq);
kfree(fp->xdp_tx);
kfree(fp->txq);
@@ -1498,6 +1504,12 @@ static void qede_init_fp(struct qede_dev *edev)
else
fp->rxq->data_direction = DMA_FROM_DEVICE;
fp->rxq->dev = &edev->pdev->dev;
+
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&fp->rxq->xdp_rxq);
+ fp->rxq->xdp_rxq.dev = edev->ndev;
+ fp->rxq->xdp_rxq.queue_index = fp->rxq->rxq_id;
+ xdp_rxq_info_reg(&fp->rxq->xdp_rxq);
}
if (fp->type & QEDE_FASTPATH_TX) {
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 5be560d943e1..106ec8ed4db5 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -42,6 +42,7 @@ struct xdp_rxq_info {
void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq);
void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq);
void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq);
+bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq);
/**
* DOC: XDP RX-queue type
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 2a111f5987f6..f0203b8fc04c 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -44,3 +44,14 @@ void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq)
xdp_rxq->reg_state = REG_STATE_REGISTRED;
}
EXPORT_SYMBOL_GPL(xdp_rxq_info_reg);
+
+bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq)
+{
+ if (!xdp_rxq) {
+ WARN(1, "API violation, xdp_rxq is NULL");
+ return false;
+ }
+
+ return (xdp_rxq->reg_state == REG_STATE_REGISTRED);
+}
+EXPORT_SYMBOL_GPL(xdp_rxq_info_is_reg);
Powered by blists - more mailing lists