From: Michal Kubiak <michal.kubiak@intel.com>
Now that AF_XDP functionality is fully implemented, advertise XSk XDP
feature and add .ndo_xsk_wakeup() callback to be able to use it with
this driver.
Signed-off-by: Michal Kubiak <michal.kubiak@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
drivers/net/ethernet/intel/idpf/idpf_lib.c | 5 ++-
drivers/net/ethernet/intel/idpf/idpf_xsk.c | 42 ++++++++++++++++++++++
drivers/net/ethernet/intel/idpf/idpf_xsk.h | 2 ++
3 files changed, 48 insertions(+), 1 deletion(-)
@@ -3,6 +3,7 @@
#include "idpf.h"
#include "idpf_xdp.h"
+#include "idpf_xsk.h"
static const struct net_device_ops idpf_netdev_ops_splitq;
static const struct net_device_ops idpf_netdev_ops_singleq;
@@ -844,7 +845,8 @@ static int idpf_cfg_netdev(struct idpf_vport *vport)
if (idpf_is_queue_model_split(vport->rxq_model))
xdp_set_features_flag(netdev, NETDEV_XDP_ACT_BASIC |
NETDEV_XDP_ACT_REDIRECT |
- NETDEV_XDP_ACT_RX_SG);
+ NETDEV_XDP_ACT_RX_SG |
+ NETDEV_XDP_ACT_XSK_ZEROCOPY);
idpf_set_ethtool_ops(netdev);
SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
@@ -2452,6 +2454,7 @@ static const struct net_device_ops idpf_netdev_ops_splitq = {
.ndo_tx_timeout = idpf_tx_timeout,
.ndo_bpf = idpf_xdp,
.ndo_xdp_xmit = idpf_xdp_xmit,
+ .ndo_xsk_wakeup = idpf_xsk_wakeup,
};
static const struct net_device_ops idpf_netdev_ops_singleq = {
@@ -1137,3 +1137,45 @@ bool idpf_xmit_zc(struct idpf_queue *complq)
return result;
}
+
+/**
+ * idpf_xsk_wakeup - Implements ndo_xsk_wakeup
+ * @netdev: net_device
+ * @queue_id: queue to wake up
+ * @flags: ignored in our case, since we have Rx and Tx in the same NAPI
+ *
+ * Returns negative on error, zero otherwise.
+ */
+int idpf_xsk_wakeup(struct net_device *netdev, u32 qid, u32 flags)
+{
+ struct idpf_netdev_priv *np = netdev_priv(netdev);
+ struct idpf_vport *vport = np->vport;
+ struct idpf_q_vector *q_vector;
+ struct idpf_queue *q;
+ int idx;
+
+ if (idpf_vport_ctrl_is_locked(netdev))
+ return -EBUSY;
+
+ if (unlikely(!vport->link_up))
+ return -ENETDOWN;
+
+ if (unlikely(!idpf_xdp_is_prog_ena(vport)))
+ return -ENXIO;
+
+ idx = qid + vport->xdp_txq_offset;
+
+ if (unlikely(idx >= vport->num_txq))
+ return -ENXIO;
+
+ if (unlikely(!test_bit(__IDPF_Q_XSK, vport->txqs[idx]->flags)))
+ return -ENXIO;
+
+ q = vport->txqs[idx];
+ q_vector = q->txq_grp->complq->q_vector;
+
+ if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+ idpf_trigger_sw_intr(&vport->adapter->hw, q_vector);
+
+ return 0;
+}
@@ -10,6 +10,7 @@ enum virtchnl2_queue_type;
struct idpf_queue;
struct idpf_vport;
+struct net_device;
struct xsk_buff_pool;
void idpf_xsk_setup_queue(struct idpf_queue *q, enum virtchnl2_queue_type t);
@@ -24,5 +25,6 @@ bool idpf_xmit_zc(struct idpf_queue *complq);
int idpf_xsk_pool_setup(struct idpf_vport *vport, struct xsk_buff_pool *pool,
u32 qid);
+int idpf_xsk_wakeup(struct net_device *netdev, u32 qid, u32 flags);
#endif /* !_IDPF_XSK_H_ */