in google/gve/gve_tx_dqo.c [283:376]
static int gve_tx_alloc_ring_dqo(struct gve_priv *priv,
struct gve_tx_alloc_rings_cfg *cfg,
struct gve_tx_ring *tx,
int idx)
{
struct device *hdev = &priv->pdev->dev;
int num_pending_packets;
int qpl_page_cnt;
size_t bytes;
u32 qpl_id;
int i;
memset(tx, 0, sizeof(*tx));
tx->q_num = idx;
tx->dev = hdev;
atomic_set_release(&tx->dqo_compl.hw_tx_head, 0);
/* Queue sizes must be a power of 2 */
tx->mask = cfg->ring_size - 1;
tx->dqo.complq_mask = tx->mask;
/* The max number of pending packets determines the maximum number of
* descriptors which maybe written to the completion queue.
*
* We must set the number small enough to make sure we never overrun the
* completion queue.
*/
num_pending_packets = tx->dqo.complq_mask + 1;
/* Reserve space for descriptor completions, which will be reported at
* most every GVE_TX_MIN_RE_INTERVAL packets.
*/
num_pending_packets -=
(tx->dqo.complq_mask + 1) / GVE_TX_MIN_RE_INTERVAL;
/* Each packet may have at most 2 buffer completions if it receives both
* a miss and reinjection completion.
*/
num_pending_packets /= 2;
tx->dqo.num_pending_packets = min_t(int, num_pending_packets, S16_MAX);
tx->dqo.pending_packets = kvcalloc(tx->dqo.num_pending_packets,
sizeof(tx->dqo.pending_packets[0]),
GFP_KERNEL);
if (!tx->dqo.pending_packets)
goto err;
/* Set up linked list of pending packets */
for (i = 0; i < tx->dqo.num_pending_packets - 1; i++)
tx->dqo.pending_packets[i].next = i + 1;
tx->dqo.pending_packets[tx->dqo.num_pending_packets - 1].next = -1;
atomic_set_release(&tx->dqo_compl.free_pending_packets, -1);
tx->dqo_compl.miss_completions.head = -1;
tx->dqo_compl.miss_completions.tail = -1;
tx->dqo_compl.timed_out_completions.head = -1;
tx->dqo_compl.timed_out_completions.tail = -1;
bytes = sizeof(tx->dqo.tx_ring[0]) * (tx->mask + 1);
tx->dqo.tx_ring = dma_alloc_coherent(hdev, bytes, &tx->bus, GFP_KERNEL);
if (!tx->dqo.tx_ring)
goto err;
bytes = sizeof(tx->dqo.compl_ring[0]) * (tx->dqo.complq_mask + 1);
tx->dqo.compl_ring = dma_alloc_coherent(hdev, bytes,
&tx->complq_bus_dqo,
GFP_KERNEL);
if (!tx->dqo.compl_ring)
goto err;
tx->q_resources = dma_alloc_coherent(hdev, sizeof(*tx->q_resources),
&tx->q_resources_bus, GFP_KERNEL);
if (!tx->q_resources)
goto err;
if (!cfg->raw_addressing) {
qpl_id = gve_tx_qpl_id(priv, tx->q_num);
qpl_page_cnt = priv->tx_pages_per_qpl;
tx->dqo.qpl = gve_alloc_queue_page_list(priv, qpl_id,
qpl_page_cnt);
if (!tx->dqo.qpl)
goto err;
if (gve_tx_qpl_buf_init(tx))
goto err;
}
return 0;
err:
gve_tx_free_ring_dqo(priv, tx, cfg);
return -ENOMEM;
}