diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c index d69f27fd5cf3b2..4a838b961912e5 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c @@ -6,6 +6,7 @@ #include "idpf.h" #include "idpf_virtchnl.h" #include "xdp.h" +#include "xsk.h" static const struct net_device_ops idpf_netdev_ops; @@ -2366,4 +2367,5 @@ static const struct net_device_ops idpf_netdev_ops = { .ndo_tx_timeout = idpf_tx_timeout, .ndo_bpf = idpf_xdp, .ndo_xdp_xmit = idpf_xdp_xmit, + .ndo_xsk_wakeup = idpf_xsk_wakeup, }; diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c index 37dca018068bb0..d299506bc1374f 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c @@ -1360,6 +1360,8 @@ static int idpf_qp_enable(struct idpf_queue_set *qs, u32 qid) if (!idpf_queue_has(XSK, q->txq)) continue; + idpf_xsk_init_wakeup(q_vector); + q->txq->q_vector = q_vector; q_vector->xsksq[q_vector->num_xsksq++] = q->txq; } @@ -4669,6 +4671,7 @@ static void idpf_vport_intr_map_vector_to_qs(struct idpf_vport *vport) continue; qv = idpf_find_rxq_vec(vport, i); + idpf_xsk_init_wakeup(qv); xdpsq->q_vector = qv; qv->xsksq[qv->num_xsksq++] = xdpsq; diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h index 5a4f47adef69e3..729c064977425a 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h @@ -395,9 +395,10 @@ struct idpf_intr_reg { * @complq: array of completion queues * @xsksq: array of XSk send queues * @intr_reg: See struct idpf_intr_reg - * @napi: napi handler + * @csd: XSk wakeup CSD * @total_events: Number of interrupts processed * @wb_on_itr: WB on ITR enabled or not + * @napi: napi handler * @tx_dim: Data for TX net_dim algorithm * @tx_itr_value: TX interrupt throttling rate * @tx_intr_mode: Dynamic ITR or not @@ -428,9 +429,11 @@ struct idpf_q_vector { __cacheline_group_end_aligned(read_mostly); __cacheline_group_begin_aligned(read_write); - struct napi_struct napi; + call_single_data_t csd; + u16 total_events; bool wb_on_itr; + struct napi_struct napi; struct dim tx_dim; u16 tx_itr_value; @@ -450,7 +453,7 @@ struct idpf_q_vector { __cacheline_group_end_aligned(cold); }; libeth_cacheline_set_assert(struct idpf_q_vector, 128, - 424 + 2 * sizeof(struct dim), + 456 + 2 * sizeof(struct dim), 8 + sizeof(cpumask_var_t)); #define IDPF_ITR_DYNAMIC 1 diff --git a/drivers/net/ethernet/intel/idpf/xdp.c b/drivers/net/ethernet/intel/idpf/xdp.c index 9377cabef56c82..9b0de9a0d2d3f9 100644 --- a/drivers/net/ethernet/intel/idpf/xdp.c +++ b/drivers/net/ethernet/intel/idpf/xdp.c @@ -454,7 +454,9 @@ void idpf_xdp_set_features(const struct idpf_vport *vport) if (!idpf_is_queue_model_split(vport->rxq_model)) return; - libeth_xdp_set_features_noredir(vport->netdev, &idpf_xdpmo); + libeth_xdp_set_features_noredir(vport->netdev, &idpf_xdpmo, + idpf_get_max_tx_bufs(vport->adapter), + libeth_xsktmo); } /** diff --git a/drivers/net/ethernet/intel/idpf/xsk.c b/drivers/net/ethernet/intel/idpf/xsk.c index 5c19c3a6be028e..7ef6dd407b798b 100644 --- a/drivers/net/ethernet/intel/idpf/xsk.c +++ b/drivers/net/ethernet/intel/idpf/xsk.c @@ -167,6 +167,11 @@ void idpf_xsk_clear_queue(void *q, enum virtchnl2_queue_type type) } } +void idpf_xsk_init_wakeup(struct idpf_q_vector *qv) +{ + libeth_xsk_init_wakeup(&qv->csd, &qv->napi); +} + static void idpf_xskfqe_init(const struct libeth_xskfq_fp *fq, u32 i) { struct virtchnl2_splitq_rx_buf_desc *desc = fq->descs; @@ -653,3 +658,35 @@ int idpf_xsk_pool_setup(struct idpf_vport *vport, struct netdev_bpf *bpf) return ret; } + +/** + * idpf_xsk_wakeup - wake up a queue pair + * @dev: network device + * @qid: queue to wake up + * @flags: wakeup flags + * + * Return: 0 on success, -errno otherwise. + */ +int idpf_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags) +{ + const struct idpf_netdev_priv *np = netdev_priv(dev); + const struct idpf_vport *vport = np->vport; + struct idpf_q_vector *q_vector; + + if (unlikely(idpf_vport_ctrl_is_locked(dev))) + return -EBUSY; + + if (unlikely(!vport->link_up)) + return -ENETDOWN; + + if (unlikely(!vport->num_xdp_txq)) + return -ENXIO; + + q_vector = idpf_find_rxq_vec(vport, qid); + if (unlikely(!q_vector->xsksq)) + return -ENXIO; + + libeth_xsk_wakeup(&q_vector->csd, qid); + + return 0; +} diff --git a/drivers/net/ethernet/intel/idpf/xsk.h b/drivers/net/ethernet/intel/idpf/xsk.h index d9f028d688cd86..d8e31462677c45 100644 --- a/drivers/net/ethernet/intel/idpf/xsk.h +++ b/drivers/net/ethernet/intel/idpf/xsk.h @@ -8,14 +8,17 @@ enum virtchnl2_queue_type; struct idpf_buf_queue; +struct idpf_q_vector; struct idpf_rx_queue; struct idpf_tx_queue; struct idpf_vport; +struct net_device; struct netdev_bpf; void idpf_xsk_setup_queue(const struct idpf_vport *vport, void *q, enum virtchnl2_queue_type type); void idpf_xsk_clear_queue(void *q, enum virtchnl2_queue_type type); +void idpf_xsk_init_wakeup(struct idpf_q_vector *qv); int idpf_xsk_bufs_init(struct idpf_buf_queue *bufq); void idpf_xsk_buf_rel(struct idpf_buf_queue *bufq); @@ -25,5 +28,6 @@ int idpf_clean_rx_irq_zc(struct idpf_rx_queue *rxq, u32 budget); bool idpf_xsk_xmit(struct idpf_tx_queue *xsksq); int idpf_xsk_pool_setup(struct idpf_vport *vport, struct netdev_bpf *xdp); +int idpf_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags); #endif /* !_IDPF_XSK_H_ */