drivers/net/ethernet/qlogic/qed/qed_hw.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/qlogic/qed/qed_hw.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/qlogic/qed/qed_hw.c
Extension
.c
Size
25685 bytes
Lines
923
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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 qed_ptt {
	struct list_head	list_entry;
	unsigned int		idx;
	struct pxp_ptt_entry	pxp;
	u8			hwfn_id;
};

struct qed_ptt_pool {
	struct list_head	free_list;
	spinlock_t		lock; /* ptt synchronized access */
	struct qed_ptt		ptts[PXP_EXTERNAL_BAR_PF_WINDOW_NUM];
};

int qed_ptt_pool_alloc(struct qed_hwfn *p_hwfn)
{
	struct qed_ptt_pool *p_pool = kmalloc_obj(*p_pool);
	int i;

	if (!p_pool)
		return -ENOMEM;

	INIT_LIST_HEAD(&p_pool->free_list);
	for (i = 0; i < PXP_EXTERNAL_BAR_PF_WINDOW_NUM; i++) {
		p_pool->ptts[i].idx = i;
		p_pool->ptts[i].pxp.offset = QED_BAR_INVALID_OFFSET;
		p_pool->ptts[i].pxp.pretend.control = 0;
		p_pool->ptts[i].hwfn_id = p_hwfn->my_id;
		if (i >= RESERVED_PTT_MAX)
			list_add(&p_pool->ptts[i].list_entry,
				 &p_pool->free_list);
	}

	p_hwfn->p_ptt_pool = p_pool;
	spin_lock_init(&p_pool->lock);

	return 0;
}

void qed_ptt_pool_free(struct qed_hwfn *p_hwfn)
{
	kfree(p_hwfn->p_ptt_pool);
	p_hwfn->p_ptt_pool = NULL;
}

struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
{
	return qed_ptt_acquire_context(p_hwfn, false);
}

struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, bool is_atomic)
{
	struct qed_ptt *p_ptt;
	unsigned int i, count;

	if (is_atomic)
		count = QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT;
	else
		count = QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT;

	/* Take the free PTT from the list */
	for (i = 0; i < count; i++) {
		spin_lock_bh(&p_hwfn->p_ptt_pool->lock);

		if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) {
			p_ptt = list_first_entry(&p_hwfn->p_ptt_pool->free_list,
						 struct qed_ptt, list_entry);
			list_del(&p_ptt->list_entry);

			spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);

			DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
				   "allocated ptt %d\n", p_ptt->idx);
			return p_ptt;
		}

		spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);

		if (is_atomic)
			udelay(QED_BAR_ACQUIRE_TIMEOUT_UDELAY);
		else
			usleep_range(QED_BAR_ACQUIRE_TIMEOUT_USLEEP,
				     QED_BAR_ACQUIRE_TIMEOUT_USLEEP * 2);
	}

	DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n");
	return NULL;
}

void qed_ptt_release(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{

Annotation

Implementation Notes