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 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 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 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 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 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