/* When the hardware/firmware supports additional capabilities, * additional header is filled-in by Octeon after length field in * Rx packets. this header contains additional packet information.
*/ if (oct->conf->fw_info.rx_ol_flags)
oq->max_single_buffer_size -= OCTEP_OQ_RESP_HW_EXT_SIZE;
if (unlikely(!oq->desc_ring)) {
dev_err(oq->dev, "Failed to allocate DMA memory for OQ-%d !!\n", q_no); goto desc_dma_alloc_err;
}
oq->buff_info = vcalloc(oq->max_count, OCTEP_OQ_RECVBUF_SIZE); if (unlikely(!oq->buff_info)) {
dev_err(&oct->pdev->dev, "Failed to allocate buffer info for OQ-%d\n", q_no); goto buf_list_err;
}
if (octep_oq_fill_ring_buffers(oq)) goto oq_fill_buff_err;
/** * octep_setup_oqs() - setup resources for all Rx queues. * * @oct: Octeon device private data structure.
*/ int octep_setup_oqs(struct octep_device *oct)
{ int i, retval = 0;
oct->num_oqs = 0; for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) {
retval = octep_setup_oq(oct, i); if (retval) {
dev_err(&oct->pdev->dev, "Failed to setup OQ(RxQ)-%d.\n", i); goto oq_setup_err;
}
dev_dbg(&oct->pdev->dev, "Successfully setup OQ(RxQ)-%d.\n", i);
}
return 0;
oq_setup_err: while (i) {
i--;
octep_free_oq(oct->oq[i]);
} return -1;
}
/** * octep_oq_dbell_init() - Initialize Rx queue doorbell. * * @oct: Octeon device private data structure. * * Write number of descriptors to Rx queue doorbell register.
*/ void octep_oq_dbell_init(struct octep_device *oct)
{ int i;
for (i = 0; i < oct->num_oqs; i++)
writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg);
}
/** * octep_free_oqs() - Free resources of all Rx queues. * * @oct: Octeon device private data structure.
*/ void octep_free_oqs(struct octep_device *oct)
{ int i;
for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { if (!oct->oq[i]) continue;
octep_free_oq(oct->oq[i]);
dev_dbg(&oct->pdev->dev, "Successfully freed OQ(RxQ)-%d.\n", i);
}
}
/** * octep_oq_check_hw_for_pkts() - Check for new Rx packets. * * @oct: Octeon device private data structure. * @oq: Octeon Rx queue data structure. * * Return: packets received after previous check.
*/ staticint octep_oq_check_hw_for_pkts(struct octep_device *oct, struct octep_oq *oq)
{
u32 pkt_count, new_pkts;
/* Clear the hardware packets counter register if the rx queue is * being processed continuously with-in a single interrupt and * reached half its max value. * this counter is not cleared every time read, to save write cycles.
*/ if (unlikely(pkt_count > 0xF0000000U)) {
writel(pkt_count, oq->pkts_sent_reg);
pkt_count = readl(oq->pkts_sent_reg);
new_pkts += pkt_count;
}
oq->last_pkt_count = pkt_count;
oq->pkts_pending += new_pkts; return new_pkts;
}
/** * octep_oq_next_pkt() - Move to the next packet in Rx queue. * * @oq: Octeon Rx queue data structure. * @buff_info: Current packet buffer info. * @read_idx: Current packet index in the ring. * @desc_used: Current packet descriptor number. * * Free the resources associated with a packet. * Increment packet index in the ring and packet descriptor number.
*/ staticvoid octep_oq_next_pkt(struct octep_oq *oq, struct octep_rx_buffer *buff_info,
u32 *read_idx, u32 *desc_used)
{
dma_unmap_page(oq->dev, oq->desc_ring[*read_idx].buffer_ptr,
PAGE_SIZE, DMA_FROM_DEVICE);
buff_info->page = NULL;
(*read_idx)++;
(*desc_used)++; if (*read_idx == oq->max_count)
*read_idx = 0;
}
/** * octep_oq_drop_rx() - Free the resources associated with a packet. * * @oq: Octeon Rx queue data structure. * @buff_info: Current packet buffer info. * @read_idx: Current packet index in the ring. * @desc_used: Current packet descriptor number. *
*/ staticvoid octep_oq_drop_rx(struct octep_oq *oq, struct octep_rx_buffer *buff_info,
u32 *read_idx, u32 *desc_used)
{ int data_len = buff_info->len - oq->max_single_buffer_size;
/** * __octep_oq_process_rx() - Process hardware Rx queue and push to stack. * * @oct: Octeon device private data structure. * @oq: Octeon Rx queue data structure. * @pkts_to_process: number of packets to be processed. * * Process the new packets in Rx queue. * Packets larger than single Rx buffer arrive in consecutive descriptors. * But, count returned by the API only accounts full packets, not fragments. * * Return: number of packets processed and pushed to stack.
*/ staticint __octep_oq_process_rx(struct octep_device *oct, struct octep_oq *oq, u16 pkts_to_process)
{ struct octep_oq_resp_hw_ext *resp_hw_ext = NULL;
netdev_features_t feat = oq->netdev->features; struct octep_rx_buffer *buff_info; struct octep_oq_resp_hw *resp_hw;
u32 pkt, rx_bytes, desc_used; struct sk_buff *skb;
u16 data_offset;
u16 rx_ol_flags;
u32 read_idx;
/** * octep_oq_process_rx() - Process Rx queue. * * @oq: Octeon Rx queue data structure. * @budget: max number of packets can be processed in one invocation. * * Check for newly received packets and process them. * Keeps checking for new packets until budget is used or no new packets seen. * * Return: number of packets processed.
*/ int octep_oq_process_rx(struct octep_oq *oq, int budget)
{
u32 pkts_available, pkts_processed, total_pkts_processed; struct octep_device *oct = oq->octep_dev;
pkts_available = 0;
pkts_processed = 0;
total_pkts_processed = 0; while (total_pkts_processed < budget) { /* update pending count only when current one exhausted */ if (oq->pkts_pending == 0)
octep_oq_check_hw_for_pkts(oct, oq);
pkts_available = min(budget - total_pkts_processed,
oq->pkts_pending); if (!pkts_available) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.