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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath12k/hal.c
Extension
.c
Size
23414 bytes
Lines
872
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();
		}
	}
}
EXPORT_SYMBOL(ath12k_hal_srng_access_begin);

/* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin()
 * should have been called before this.
 */
void ath12k_hal_srng_access_end(struct ath12k_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.
			 */
			ath12k_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();
			ath12k_hif_write32(ab,
					   (unsigned long)srng->u.dst_ring.tp_addr -
					   (unsigned long)ab->mem,
					   srng->u.dst_ring.tp);
		}
	}

	srng->timestamp = jiffies;
}
EXPORT_SYMBOL(ath12k_hal_srng_access_end);

int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type,
			  int ring_num, int mac_id,
			  struct hal_srng_params *params)
{
	struct ath12k_hal *hal = &ab->hal;
	struct hal_srng_config *srng_config = &ab->hal.srng_config[type];
	struct hal_srng *srng;
	int ring_id;
	u32 idx;
	int i;

	ring_id = ath12k_hal_srng_get_ring_id(hal, type, ring_num, mac_id);
	if (ring_id < 0)
		return ring_id;

	srng = &hal->srng_list[ring_id];

	srng->ring_id = ring_id;
	srng->ring_dir = srng_config->ring_dir;
	srng->ring_base_paddr = params->ring_base_paddr;
	srng->ring_base_vaddr = params->ring_base_vaddr;
	srng->entry_size = srng_config->entry_size;
	srng->num_entries = params->num_entries;

Annotation

Implementation Notes