Commit 548c4940 authored by Sameeh Jubran's avatar Sameeh Jubran Committed by David S. Miller

net: ena: Implement XDP_TX action

This commit implements the XDP_TX action in the ena driver. We allocate
separate tx queues for the XDP_TX. We currently allow xdp only when
there is enough queues to allocate for xdp.
Signed-off-by: default avatarSameeh Jubran <sameehj@amazon.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 838c93dc
...@@ -744,7 +744,9 @@ static int ena_set_channels(struct net_device *netdev, ...@@ -744,7 +744,9 @@ static int ena_set_channels(struct net_device *netdev,
struct ena_adapter *adapter = netdev_priv(netdev); struct ena_adapter *adapter = netdev_priv(netdev);
u32 count = channels->combined_count; u32 count = channels->combined_count;
/* The check for max value is already done in ethtool */ /* The check for max value is already done in ethtool */
if (count < ENA_MIN_NUM_IO_QUEUES) if (count < ENA_MIN_NUM_IO_QUEUES ||
(ena_xdp_present(adapter) &&
!ena_xdp_legal_queue_count(adapter, channels->combined_count)))
return -EINVAL; return -EINVAL;
return ena_update_queue_count(adapter, count); return ena_update_queue_count(adapter, count);
......
...@@ -152,6 +152,9 @@ ...@@ -152,6 +152,9 @@
#define ENA_XDP_MAX_MTU (ENA_PAGE_SIZE - ETH_HLEN - ETH_FCS_LEN - \ #define ENA_XDP_MAX_MTU (ENA_PAGE_SIZE - ETH_HLEN - ETH_FCS_LEN - \
VLAN_HLEN - XDP_PACKET_HEADROOM) VLAN_HLEN - XDP_PACKET_HEADROOM)
#define ENA_IS_XDP_INDEX(adapter, index) (((index) >= (adapter)->xdp_first_ring) && \
((index) < (adapter)->xdp_first_ring + (adapter)->xdp_num_queues))
struct ena_irq { struct ena_irq {
irq_handler_t handler; irq_handler_t handler;
void *data; void *data;
...@@ -165,6 +168,7 @@ struct ena_napi { ...@@ -165,6 +168,7 @@ struct ena_napi {
struct napi_struct napi ____cacheline_aligned; struct napi_struct napi ____cacheline_aligned;
struct ena_ring *tx_ring; struct ena_ring *tx_ring;
struct ena_ring *rx_ring; struct ena_ring *rx_ring;
struct ena_ring *xdp_ring;
u32 qid; u32 qid;
struct dim dim; struct dim dim;
}; };
...@@ -190,6 +194,17 @@ struct ena_tx_buffer { ...@@ -190,6 +194,17 @@ struct ena_tx_buffer {
/* num of buffers used by this skb */ /* num of buffers used by this skb */
u32 num_of_bufs; u32 num_of_bufs;
/* XDP buffer structure which is used for sending packets in
* the xdp queues
*/
struct xdp_frame *xdpf;
/* The rx page for the rx buffer that was received in rx and
* re transmitted on xdp tx queues as a result of XDP_TX action.
* We need to free the page once we finished cleaning the buffer in
* clean_xdp_irq()
*/
struct page *xdp_rx_page;
/* Indicate if bufs[0] map the linear data of the skb. */ /* Indicate if bufs[0] map the linear data of the skb. */
u8 map_linear_data; u8 map_linear_data;
...@@ -394,6 +409,8 @@ struct ena_adapter { ...@@ -394,6 +409,8 @@ struct ena_adapter {
enum ena_regs_reset_reason_types reset_reason; enum ena_regs_reset_reason_types reset_reason;
struct bpf_prog *xdp_bpf_prog; struct bpf_prog *xdp_bpf_prog;
u32 xdp_first_ring;
u32 xdp_num_queues;
}; };
void ena_set_ethtool_ops(struct net_device *netdev); void ena_set_ethtool_ops(struct net_device *netdev);
...@@ -410,6 +427,17 @@ int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count); ...@@ -410,6 +427,17 @@ int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count);
int ena_get_sset_count(struct net_device *netdev, int sset); int ena_get_sset_count(struct net_device *netdev, int sset);
enum ena_xdp_errors_t {
ENA_XDP_ALLOWED = 0,
ENA_XDP_CURRENT_MTU_TOO_LARGE,
ENA_XDP_NO_ENOUGH_QUEUES,
};
static inline bool ena_xdp_queues_present(struct ena_adapter *adapter)
{
return adapter->xdp_first_ring != 0;
}
static inline bool ena_xdp_present(struct ena_adapter *adapter) static inline bool ena_xdp_present(struct ena_adapter *adapter)
{ {
return !!adapter->xdp_bpf_prog; return !!adapter->xdp_bpf_prog;
...@@ -420,9 +448,22 @@ static inline bool ena_xdp_present_ring(struct ena_ring *ring) ...@@ -420,9 +448,22 @@ static inline bool ena_xdp_present_ring(struct ena_ring *ring)
return !!ring->xdp_bpf_prog; return !!ring->xdp_bpf_prog;
} }
static inline bool ena_xdp_allowed(struct ena_adapter *adapter) static inline int ena_xdp_legal_queue_count(struct ena_adapter *adapter,
u32 queues)
{ {
return adapter->netdev->mtu <= ENA_XDP_MAX_MTU; return 2 * queues <= adapter->max_num_io_queues;
}
static inline enum ena_xdp_errors_t ena_xdp_allowed(struct ena_adapter *adapter)
{
enum ena_xdp_errors_t rc = ENA_XDP_ALLOWED;
if (adapter->netdev->mtu > ENA_XDP_MAX_MTU)
rc = ENA_XDP_CURRENT_MTU_TOO_LARGE;
else if (!ena_xdp_legal_queue_count(adapter, adapter->num_io_queues))
rc = ENA_XDP_NO_ENOUGH_QUEUES;
return rc;
} }
#endif /* !(ENA_H) */ #endif /* !(ENA_H) */
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