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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath11k/pcic.c
Extension
.c
Size
21966 bytes
Lines
865
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 (ret) {
			ath11k_warn(ab,
				    "wakeup failed, data may be invalid: %d",
				    ret);
			/* Even though wakeup() failed, continue processing rather
			 * than returning because some parts of the data may still
			 * be valid and useful in some cases, e.g. could give us
			 * some clues on firmware crash.
			 * Mislead due to invalid data could be avoided because we
			 * are aware of the wakeup failure.
			 */
		}
	}

	for (i = start; i < end + 1; i += 4)
		*data++ = __ath11k_pcic_read32(ab, i);

	if (wakeup_required && ab->pci.ops->release)
		ab->pci.ops->release(ab);

	return 0;
}
EXPORT_SYMBOL(ath11k_pcic_read);

void ath11k_pcic_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
				 u32 *msi_addr_hi)
{
	*msi_addr_lo = ab->pci.msi.addr_lo;
	*msi_addr_hi = ab->pci.msi.addr_hi;
}
EXPORT_SYMBOL(ath11k_pcic_get_msi_address);

int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
					int *num_vectors, u32 *user_base_data,
					u32 *base_vector)
{
	const struct ath11k_msi_config *msi_config = ab->pci.msi.config;
	int idx;

	for (idx = 0; idx < msi_config->total_users; idx++) {
		if (strcmp(user_name, msi_config->users[idx].name) == 0) {
			*num_vectors = msi_config->users[idx].num_vectors;
			*base_vector =  msi_config->users[idx].base_vector;
			*user_base_data = *base_vector + ab->pci.msi.ep_base_data;

			ath11k_dbg(ab, ATH11K_DBG_PCI,
				   "msi assignment %s num_vectors %d user_base_data %u base_vector %u\n",
				   user_name, *num_vectors, *user_base_data,
				   *base_vector);

			return 0;
		}
	}

	ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);

	return -EINVAL;
}
EXPORT_SYMBOL(ath11k_pcic_get_user_msi_assignment);

void ath11k_pcic_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx)
{
	u32 i, msi_data_idx;

	for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
			continue;

		if (ce_id == i)
			break;

		msi_data_idx++;
	}
	*msi_idx = msi_data_idx;
}
EXPORT_SYMBOL(ath11k_pcic_get_ce_msi_idx);

static void ath11k_pcic_free_ext_irq(struct ath11k_base *ab)
{
	int i, j;

	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];

		for (j = 0; j < irq_grp->num_irq; j++)
			free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);

		netif_napi_del(&irq_grp->napi);
		free_netdev(irq_grp->napi_ndev);
	}

Annotation

Implementation Notes