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 
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 
19 void gve_tx_add_to_block(struct gve_priv *priv, int queue_idx)
20 {
21 	unsigned int active_cpus = min_t(int, priv->num_ntfy_blks / 2,
22 					 num_online_cpus());
23 	int ntfy_idx = gve_tx_idx_to_ntfy(priv, queue_idx);
24 	struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
25 	struct gve_tx_ring *tx = &priv->tx[queue_idx];
26 
27 	block->tx = tx;
28 	tx->ntfy_id = ntfy_idx;
29 	netif_set_xps_queue(priv->dev, get_cpu_mask(ntfy_idx % active_cpus),
30 			    queue_idx);
31 }
32 
33 void gve_rx_remove_from_block(struct gve_priv *priv, int queue_idx)
34 {
35 	struct gve_notify_block *block =
36 			&priv->ntfy_blocks[gve_rx_idx_to_ntfy(priv, queue_idx)];
37 
38 	block->rx = NULL;
39 }
40 
41 void gve_rx_add_to_block(struct gve_priv *priv, int queue_idx)
42 {
43 	u32 ntfy_idx = gve_rx_idx_to_ntfy(priv, queue_idx);
44 	struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
45 	struct gve_rx_ring *rx = &priv->rx[queue_idx];
46 
47 	block->rx = rx;
48 	rx->ntfy_id = ntfy_idx;
49 }
50 
51 struct sk_buff *gve_rx_copy(struct net_device *dev, struct napi_struct *napi,
52 			    struct gve_rx_slot_page_info *page_info, u16 len,
53 			    u16 pad)
54 {
55 	struct sk_buff *skb = napi_alloc_skb(napi, len);
56 	void *va = page_info->page_address + pad +
57 		   page_info->page_offset;
58 
59 	if (unlikely(!skb))
60 		return NULL;
61 
62 	__skb_put(skb, len);
63 
64 	skb_copy_to_linear_data(skb, va, len);
65 
66 	skb->protocol = eth_type_trans(skb, dev);
67 
68 	return skb;
69 }
70 
71 void gve_dec_pagecnt_bias(struct gve_rx_slot_page_info *page_info)
72 {
73 	page_info->pagecnt_bias--;
74 	if (page_info->pagecnt_bias == 0) {
75 		int pagecount = page_count(page_info->page);
76 
77 		/* If we have run out of bias - set it back up to INT_MAX
78 		 * minus the existing refs.
79 		 */
80 		page_info->pagecnt_bias = INT_MAX - pagecount;
81 
82 		/* Set pagecount back up to max. */
83 		page_ref_add(page_info->page, INT_MAX - pagecount);
84 	}
85 }
86