mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-27 21:14:44 +08:00
a57e5de476
TX SKBs will have their buffers DMA mapped with the device. Each buffer will have at least one TX descriptor associated. Each SKB will also have a metadata descriptor. Each TX queue maintains an array of `gve_tx_pending_packet_dqo` objects. Every TX SKB will have an associated pending_packet object. A TX SKB's descriptors will use its pending_packet's index as the completion tag, which will be returned on the TX completion queue. The device implements a "flow-miss model". Most packets will simply receive a packet completion. The flow-miss system may choose to process a packet based on its contents. A TX packet which experiences a flow miss would receive a miss completion followed by a later reinjection completion. The miss-completion is received when the packet starts to be processed by the flow-miss system and the reinjection completion is received when the flow-miss system completes processing the packet and sends it on the wire. Notable mentions: - Buffers may be freed after receiving the miss-completion, but in order to avoid packet reordering, we do not complete the SKB until receiving the reinjection completion. - The driver must robustly handle the unlikely scenario where a miss completion does not have an associated reinjection completion. This is accomplished by maintaining a list of packets which have a pending reinjection completion. After a short timeout (5 seconds), the SKB and buffers are released and the pending_packet is moved to a second list which has a longer timeout (60 seconds), where the pending_packet will not be reused. When the longer timeout elapses, the driver may assume the reinjection completion would never be received and the pending_packet may be reused. - Completion handling is triggered by an interrupt and is done in the NAPI poll function. Because the TX path and completion exist in different threading contexts they maintain their own lists for free pending_packet objects. The TX path uses a lock-free approach to steal the list from the completion path. - Both the TSO context and general context descriptors have metadata bytes. The device requires that if multiple descriptors contain the same field, each descriptor must have the same value set for that field. Signed-off-by: Bailey Forrest <bcf@google.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Reviewed-by: Catherine Sullivan <csully@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
82 lines
2.4 KiB
C
82 lines
2.4 KiB
C
/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
|
* Google virtual Ethernet (gve) driver
|
|
*
|
|
* Copyright (C) 2015-2021 Google, Inc.
|
|
*/
|
|
|
|
#ifndef _GVE_DQO_H_
|
|
#define _GVE_DQO_H_
|
|
|
|
#include "gve_adminq.h"
|
|
|
|
#define GVE_ITR_ENABLE_BIT_DQO BIT(0)
|
|
#define GVE_ITR_CLEAR_PBA_BIT_DQO BIT(1)
|
|
#define GVE_ITR_NO_UPDATE_DQO (3 << 3)
|
|
|
|
#define GVE_ITR_INTERVAL_DQO_SHIFT 5
|
|
#define GVE_ITR_INTERVAL_DQO_MASK ((1 << 12) - 1)
|
|
|
|
#define GVE_TX_IRQ_RATELIMIT_US_DQO 50
|
|
#define GVE_RX_IRQ_RATELIMIT_US_DQO 20
|
|
|
|
/* Timeout in seconds to wait for a reinjection completion after receiving
|
|
* its corresponding miss completion.
|
|
*/
|
|
#define GVE_REINJECT_COMPL_TIMEOUT 1
|
|
|
|
/* Timeout in seconds to deallocate the completion tag for a packet that was
|
|
* prematurely freed for not receiving a valid completion. This should be large
|
|
* enough to rule out the possibility of receiving the corresponding valid
|
|
* completion after this interval.
|
|
*/
|
|
#define GVE_DEALLOCATE_COMPL_TIMEOUT 60
|
|
|
|
netdev_tx_t gve_tx_dqo(struct sk_buff *skb, struct net_device *dev);
|
|
bool gve_tx_poll_dqo(struct gve_notify_block *block, bool do_clean);
|
|
int gve_rx_poll_dqo(struct gve_notify_block *block, int budget);
|
|
int gve_tx_alloc_rings_dqo(struct gve_priv *priv);
|
|
void gve_tx_free_rings_dqo(struct gve_priv *priv);
|
|
int gve_rx_alloc_rings_dqo(struct gve_priv *priv);
|
|
void gve_rx_free_rings_dqo(struct gve_priv *priv);
|
|
int gve_clean_tx_done_dqo(struct gve_priv *priv, struct gve_tx_ring *tx,
|
|
struct napi_struct *napi);
|
|
void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx);
|
|
void gve_rx_write_doorbell_dqo(const struct gve_priv *priv, int queue_idx);
|
|
|
|
static inline void
|
|
gve_tx_put_doorbell_dqo(const struct gve_priv *priv,
|
|
const struct gve_queue_resources *q_resources, u32 val)
|
|
{
|
|
u64 index;
|
|
|
|
index = be32_to_cpu(q_resources->db_index);
|
|
iowrite32(val, &priv->db_bar2[index]);
|
|
}
|
|
|
|
/* Builds register value to write to DQO IRQ doorbell to enable with specified
|
|
* ratelimit.
|
|
*/
|
|
static inline u32 gve_set_itr_ratelimit_dqo(u32 ratelimit_us)
|
|
{
|
|
u32 result = GVE_ITR_ENABLE_BIT_DQO;
|
|
|
|
/* Interval has 2us granularity. */
|
|
ratelimit_us >>= 1;
|
|
|
|
ratelimit_us &= GVE_ITR_INTERVAL_DQO_MASK;
|
|
result |= (ratelimit_us << GVE_ITR_INTERVAL_DQO_SHIFT);
|
|
|
|
return result;
|
|
}
|
|
|
|
static inline void
|
|
gve_write_irq_doorbell_dqo(const struct gve_priv *priv,
|
|
const struct gve_notify_block *block, u32 val)
|
|
{
|
|
u32 index = be32_to_cpu(block->irq_db_index);
|
|
|
|
iowrite32(val, &priv->db_bar2[index]);
|
|
}
|
|
|
|
#endif /* _GVE_DQO_H_ */
|