drivers/net/ethernet/cavium/liquidio/octeon_droq.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/cavium/liquidio/octeon_droq.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/cavium/liquidio/octeon_droq.c
Extension
.c
Size
25441 bytes
Lines
969
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct __dispatch {
	struct list_head list;
	struct octeon_recv_info *rinfo;
	octeon_dispatch_fn_t disp_fn;
};

/** Get the argument that the user set when registering dispatch
 *  function for a given opcode/subcode.
 *  @param  octeon_dev - the octeon device pointer.
 *  @param  opcode     - the opcode for which the dispatch argument
 *                       is to be checked.
 *  @param  subcode    - the subcode for which the dispatch argument
 *                       is to be checked.
 *  @return  Success: void * (argument to the dispatch function)
 *  @return  Failure: NULL
 *
 */
void *octeon_get_dispatch_arg(struct octeon_device *octeon_dev,
			      u16 opcode, u16 subcode)
{
	int idx;
	struct list_head *dispatch;
	void *fn_arg = NULL;
	u16 combined_opcode = OPCODE_SUBCODE(opcode, subcode);

	idx = combined_opcode & OCTEON_OPCODE_MASK;

	spin_lock_bh(&octeon_dev->dispatch.lock);

	if (octeon_dev->dispatch.count == 0) {
		spin_unlock_bh(&octeon_dev->dispatch.lock);
		return NULL;
	}

	if (octeon_dev->dispatch.dlist[idx].opcode == combined_opcode) {
		fn_arg = octeon_dev->dispatch.dlist[idx].arg;
	} else {
		list_for_each(dispatch,
			      &octeon_dev->dispatch.dlist[idx].list) {
			if (((struct octeon_dispatch *)dispatch)->opcode ==
			    combined_opcode) {
				fn_arg = ((struct octeon_dispatch *)
					  dispatch)->arg;
				break;
			}
		}
	}

	spin_unlock_bh(&octeon_dev->dispatch.lock);
	return fn_arg;
}

/** Check for packets on Droq. This function should be called with lock held.
 *  @param  droq - Droq on which count is checked.
 *  @return Returns packet count.
 */
u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq)
{
	u32 pkt_count = 0;
	u32 last_count;

	pkt_count = readl(droq->pkts_sent_reg);

	last_count = pkt_count - droq->pkt_count;
	droq->pkt_count = pkt_count;

	/* we shall write to cnts  at napi irq enable or end of droq tasklet */
	if (last_count)
		atomic_add(last_count, &droq->pkts_pending);

	return last_count;
}
EXPORT_SYMBOL_GPL(octeon_droq_check_hw_for_pkts);

static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq)
{
	u32 count = 0;

	/* max_empty_descs is the max. no. of descs that can have no buffers.
	 * If the empty desc count goes beyond this value, we cannot safely
	 * read in a 64K packet sent by Octeon
	 * (64K is max pkt size from Octeon)
	 */
	droq->max_empty_descs = 0;

	do {
		droq->max_empty_descs++;
		count += droq->buffer_size;
	} while (count < (64 * 1024));

Annotation

Implementation Notes