static void gve_handle_packet_completion()

in build/gve_tx_dqo.c [1133:1203]


static void gve_handle_packet_completion(struct gve_priv *priv,
					 struct gve_tx_ring *tx, bool is_napi,
					 u16 compl_tag, u64 *bytes, u64 *pkts,
					 bool is_reinjection)
{
	struct gve_tx_pending_packet_dqo *pending_packet;

	if (unlikely(compl_tag >= tx->dqo.num_pending_packets)) {
		net_err_ratelimited("%s: Invalid TX completion tag: %d\n",
				    priv->dev->name, (int)compl_tag);
		return;
	}

	pending_packet = &tx->dqo.pending_packets[compl_tag];

	if (unlikely(is_reinjection)) {
		if (unlikely(pending_packet->state ==
			     GVE_PACKET_STATE_TIMED_OUT_COMPL)) {
			net_err_ratelimited("%s: Re-injection completion: %d received after timeout.\n",
					    priv->dev->name, (int)compl_tag);
			/* Packet was already completed as a result of timeout,
			 * so just remove from list and free pending packet.
			 */
			remove_from_list(tx,
					 &tx->dqo_compl.timed_out_completions,
					 pending_packet);
			gve_free_pending_packet(tx, pending_packet);
			return;
		}
		if (unlikely(pending_packet->state !=
			     GVE_PACKET_STATE_PENDING_REINJECT_COMPL)) {
			/* No outstanding miss completion but packet allocated
			 * implies packet receives a re-injection completion
			 * without a prior miss completion. Return without
			 * completing the packet.
			 */
			net_err_ratelimited("%s: Re-injection completion received without corresponding miss completion: %d\n",
					    priv->dev->name, (int)compl_tag);
			return;
		}
		remove_from_list(tx, &tx->dqo_compl.miss_completions,
				 pending_packet);
	} else {
		/* Packet is allocated but not a pending data completion. */
		if (unlikely(pending_packet->state !=
			     GVE_PACKET_STATE_PENDING_DATA_COMPL)) {
			net_err_ratelimited("%s: No pending data completion: %d\n",
					    priv->dev->name, (int)compl_tag);
			return;
		}
	}
	tx->dqo_tx.completed_packet_desc_cnt += pending_packet->num_bufs;
	if (tx->dqo.qpl)
		gve_free_tx_qpl_bufs(tx, pending_packet);
	else
		gve_unmap_packet(tx->dev, pending_packet);

	*bytes += pending_packet->skb->len;
	(*pkts)++;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
	napi_consume_skb(pending_packet->skb, is_napi);
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
	dev_consume_skb_any(pending_packet->skb);
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) */
	dev_kfree_skb_any(pending_packet->skb);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) */
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) */
	pending_packet->skb = NULL;
	gve_free_pending_packet(tx, pending_packet);
}