Skip to content

Commit c0124f3

Browse files
netoptimizerAlexei Starovoitov
authored andcommitted
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: * reg : qede_init_fp * unreg: qede_free_fp_array Tested on actual hardware with samples/bpf program. V2: Driver have no proper error path for failed XDP RX-queue info reg, as qede_init_fp() is a void function. Cc: [email protected] Cc: Ariel Elior <[email protected]> Signed-off-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 99ffc5a commit c0124f3

File tree

5 files changed

+20
-0
lines changed

5 files changed

+20
-0
lines changed

drivers/net/ethernet/qlogic/qede/qede.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <linux/kernel.h>
4141
#include <linux/mutex.h>
4242
#include <linux/bpf.h>
43+
#include <net/xdp.h>
4344
#include <linux/qed/qede_rdma.h>
4445
#include <linux/io.h>
4546
#ifdef CONFIG_RFS_ACCEL
@@ -345,6 +346,7 @@ struct qede_rx_queue {
345346
u64 xdp_no_pass;
346347

347348
void *handle;
349+
struct xdp_rxq_info xdp_rxq;
348350
};
349351

350352
union db_prod {

drivers/net/ethernet/qlogic/qede/qede_fp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ static bool qede_rx_xdp(struct qede_dev *edev,
10061006
xdp.data = xdp.data_hard_start + *data_offset;
10071007
xdp_set_data_meta_invalid(&xdp);
10081008
xdp.data_end = xdp.data + *len;
1009+
xdp.rxq = &rxq->xdp_rxq;
10091010

10101011
/* Queues always have a full reset currently, so for the time
10111012
* being until there's atomic program replace just mark read

drivers/net/ethernet/qlogic/qede/qede_main.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,12 @@ static void qede_free_fp_array(struct qede_dev *edev)
765765
fp = &edev->fp_array[i];
766766

767767
kfree(fp->sb_info);
768+
/* Handle mem alloc failure case where qede_init_fp
769+
* didn't register xdp_rxq_info yet.
770+
* Implicit only (fp->type & QEDE_FASTPATH_RX)
771+
*/
772+
if (fp->rxq && xdp_rxq_info_is_reg(&fp->rxq->xdp_rxq))
773+
xdp_rxq_info_unreg(&fp->rxq->xdp_rxq);
768774
kfree(fp->rxq);
769775
kfree(fp->xdp_tx);
770776
kfree(fp->txq);
@@ -1493,6 +1499,10 @@ static void qede_init_fp(struct qede_dev *edev)
14931499
else
14941500
fp->rxq->data_direction = DMA_FROM_DEVICE;
14951501
fp->rxq->dev = &edev->pdev->dev;
1502+
1503+
/* Driver have no error path from here */
1504+
WARN_ON(xdp_rxq_info_reg(&fp->rxq->xdp_rxq, edev->ndev,
1505+
fp->rxq->rxq_id) < 0);
14961506
}
14971507

14981508
if (fp->type & QEDE_FASTPATH_TX) {

include/net/xdp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ int xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq,
4343
struct net_device *dev, u32 queue_index);
4444
void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq);
4545
void xdp_rxq_info_unused(struct xdp_rxq_info *xdp_rxq);
46+
bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq);
4647

4748
#endif /* __LINUX_NET_XDP_H__ */

net/core/xdp.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,9 @@ void xdp_rxq_info_unused(struct xdp_rxq_info *xdp_rxq)
6565
xdp_rxq->reg_state = REG_STATE_UNUSED;
6666
}
6767
EXPORT_SYMBOL_GPL(xdp_rxq_info_unused);
68+
69+
bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq)
70+
{
71+
return (xdp_rxq->reg_state == REG_STATE_REGISTERED);
72+
}
73+
EXPORT_SYMBOL_GPL(xdp_rxq_info_is_reg);

0 commit comments

Comments
 (0)