drivers/net/wireless/ath/ath10k/wmi.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath10k/wmi.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath10k/wmi.c
Extension
.c
Size
322247 bytes
Lines
9641
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

if (arg->freq > arg->band_center_freq1) {
			band_center_freq1 = arg->band_center_freq1 + 40;
			band_center_freq2 = arg->band_center_freq1 - 40;
		} else {
			band_center_freq1 = arg->band_center_freq1 - 40;
			band_center_freq2 = arg->band_center_freq1 + 40;
		}

		ch->band_center_freq1 =
					__cpu_to_le32(band_center_freq1);
		/* Minus 10 to get a defined 5G channel frequency*/
		chan = ieee80211_get_channel(ar->hw->wiphy,
					     band_center_freq2 - 10);
		/* The center frequency of the entire VHT160 */
		ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq1);
	}

	if (chan && chan->flags & IEEE80211_CHAN_RADAR)
		flags |= WMI_CHAN_FLAG_DFS_CFREQ2;

	ch->min_power = arg->min_power;
	ch->max_power = arg->max_power;
	ch->reg_power = arg->max_reg_power;
	ch->antenna_max = arg->max_antenna_gain;
	ch->max_tx_power = arg->max_power;

	/* mode & flags share storage */
	ch->mode = arg->mode;
	ch->flags |= __cpu_to_le32(flags);
}

int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
	unsigned long time_left, i;

	time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
						WMI_SERVICE_READY_TIMEOUT_HZ);
	if (!time_left) {
		/* Sometimes the PCI HIF doesn't receive interrupt
		 * for the service ready message even if the buffer
		 * was completed. PCIe sniffer shows that it's
		 * because the corresponding CE ring doesn't fires
		 * it. Workaround here by polling CE rings once.
		 */
		ath10k_warn(ar, "failed to receive service ready completion, polling..\n");

		for (i = 0; i < CE_COUNT; i++)
			ath10k_hif_send_complete_check(ar, i, 1);

		time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
							WMI_SERVICE_READY_TIMEOUT_HZ);
		if (!time_left) {
			ath10k_warn(ar, "polling timed out\n");
			return -ETIMEDOUT;
		}

		ath10k_warn(ar, "service ready completion received, continuing normally\n");
	}

	return 0;
}

int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
{
	unsigned long time_left;

	time_left = wait_for_completion_timeout(&ar->wmi.unified_ready,
						WMI_UNIFIED_READY_TIMEOUT_HZ);
	if (!time_left)
		return -ETIMEDOUT;
	return 0;
}

struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
{
	struct sk_buff *skb;
	u32 round_len = roundup(len, 4);

	skb = ath10k_htc_alloc_skb(ar, WMI_SKB_HEADROOM + round_len);
	if (!skb)
		return NULL;

	skb_reserve(skb, WMI_SKB_HEADROOM);
	if (!IS_ALIGNED((unsigned long)skb->data, 4))
		ath10k_warn(ar, "Unaligned WMI skb\n");

	skb_put(skb, round_len);
	memset(skb->data, 0, round_len);

	return skb;

Annotation

Implementation Notes