drivers/net/wireless/ath/ath11k/hal.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath11k/hal.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath11k/hal.c
Extension
.c
Size
44624 bytes
Lines
1463
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

if (hp != srng->u.dst_ring.cached_hp) {
			srng->u.dst_ring.cached_hp = hp;
			/* Make sure descriptor is read after the head
			 * pointer.
			 */
			dma_rmb();
		}

		/* Try to prefetch the next descriptor in the ring */
		if (srng->flags & HAL_SRNG_FLAGS_CACHED)
			ath11k_hal_srng_prefetch_desc(ab, srng);
	}
}

/* Update cached ring head/tail pointers to HW. ath11k_hal_srng_access_begin()
 * should have been called before this.
 */
void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng)
{
	lockdep_assert_held(&srng->lock);

	if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
		/* For LMAC rings, ring pointer updates are done through FW and
		 * hence written to a shared memory location that is read by FW
		 */
		if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
			srng->u.src_ring.last_tp =
				*(volatile u32 *)srng->u.src_ring.tp_addr;
			/* Make sure descriptor is written before updating the
			 * head pointer.
			 */
			dma_wmb();
			WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp);
		} else {
			srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
			/* Make sure descriptor is read before updating the
			 * tail pointer.
			 */
			dma_mb();
			WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp);
		}
	} else {
		if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
			srng->u.src_ring.last_tp =
				*(volatile u32 *)srng->u.src_ring.tp_addr;
			/* Assume implementation use an MMIO write accessor
			 * which has the required wmb() so that the descriptor
			 * is written before the updating the head pointer.
			 */
			ath11k_hif_write32(ab,
					   (unsigned long)srng->u.src_ring.hp_addr -
					   (unsigned long)ab->mem,
					   srng->u.src_ring.hp);
		} else {
			srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
			/* Make sure descriptor is read before updating the
			 * tail pointer.
			 */
			mb();
			ath11k_hif_write32(ab,
					   (unsigned long)srng->u.dst_ring.tp_addr -
					   (unsigned long)ab->mem,
					   srng->u.dst_ring.tp);
		}
	}

	srng->timestamp = jiffies;
}

void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab,
				     struct hal_wbm_idle_scatter_list *sbuf,
				     u32 nsbufs, u32 tot_link_desc,
				     u32 end_offset)
{
	struct ath11k_buffer_addr *link_addr;
	int i;
	u32 reg_scatter_buf_sz = HAL_WBM_IDLE_SCATTER_BUF_SIZE / 64;

	link_addr = (void *)sbuf[0].vaddr + HAL_WBM_IDLE_SCATTER_BUF_SIZE;

	for (i = 1; i < nsbufs; i++) {
		link_addr->info0 = sbuf[i].paddr & HAL_ADDR_LSB_REG_MASK;
		link_addr->info1 = FIELD_PREP(
				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
				(u64)sbuf[i].paddr >> HAL_ADDR_MSB_REG_SHIFT) |
				FIELD_PREP(
				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG,
				BASE_ADDR_MATCH_TAG_VAL);

		link_addr = (void *)sbuf[i].vaddr +

Annotation

Implementation Notes