1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Google virtual Ethernet (gve) driver
3 *
4 * Copyright (C) 2015-2021 Google, Inc.
5 */
6
7 #include "gve.h"
8 #include "gve_adminq.h"
9 #include "gve_utils.h"
10
gve_tx_remove_from_block(struct gve_priv * priv,int queue_idx)11 void gve_tx_remove_from_block(struct gve_priv *priv, int queue_idx)
12 {
13 struct gve_notify_block *block =
14 &priv->ntfy_blocks[gve_tx_idx_to_ntfy(priv, queue_idx)];
15
16 block->tx = NULL;
17 }
18
gve_tx_add_to_block(struct gve_priv * priv,int queue_idx)19 void gve_tx_add_to_block(struct gve_priv *priv, int queue_idx)
20 {
21 int ntfy_idx = gve_tx_idx_to_ntfy(priv, queue_idx);
22 struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
23 struct gve_tx_ring *tx = &priv->tx[queue_idx];
24
25 block->tx = tx;
26 tx->ntfy_id = ntfy_idx;
27 }
28
gve_rx_remove_from_block(struct gve_priv * priv,int queue_idx)29 void gve_rx_remove_from_block(struct gve_priv *priv, int queue_idx)
30 {
31 struct gve_notify_block *block =
32 &priv->ntfy_blocks[gve_rx_idx_to_ntfy(priv, queue_idx)];
33
34 block->rx = NULL;
35 }
36
gve_rx_add_to_block(struct gve_priv * priv,int queue_idx)37 void gve_rx_add_to_block(struct gve_priv *priv, int queue_idx)
38 {
39 u32 ntfy_idx = gve_rx_idx_to_ntfy(priv, queue_idx);
40 struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
41 struct gve_rx_ring *rx = &priv->rx[queue_idx];
42
43 block->rx = rx;
44 rx->ntfy_id = ntfy_idx;
45 }
46
gve_rx_copy(struct net_device * dev,struct napi_struct * napi,struct gve_rx_slot_page_info * page_info,u16 len,u16 pad)47 struct sk_buff *gve_rx_copy(struct net_device *dev, struct napi_struct *napi,
48 struct gve_rx_slot_page_info *page_info, u16 len,
49 u16 pad)
50 {
51 struct sk_buff *skb = napi_alloc_skb(napi, len);
52 void *va = page_info->page_address + pad +
53 page_info->page_offset;
54
55 if (unlikely(!skb))
56 return NULL;
57
58 __skb_put(skb, len);
59
60 skb_copy_to_linear_data(skb, va, len);
61
62 skb->protocol = eth_type_trans(skb, dev);
63
64 return skb;
65 }
66
gve_dec_pagecnt_bias(struct gve_rx_slot_page_info * page_info)67 void gve_dec_pagecnt_bias(struct gve_rx_slot_page_info *page_info)
68 {
69 page_info->pagecnt_bias--;
70 if (page_info->pagecnt_bias == 0) {
71 int pagecount = page_count(page_info->page);
72
73 /* If we have run out of bias - set it back up to INT_MAX
74 * minus the existing refs.
75 */
76 page_info->pagecnt_bias = INT_MAX - pagecount;
77
78 /* Set pagecount back up to max. */
79 page_ref_add(page_info->page, INT_MAX - pagecount);
80 }
81 }
82