drivers/net/wireless/intel/iwlwifi/mvm/time-event.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
Extension
.c
Size
44085 bytes
Lines
1489
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 iwl_mvm_rx_roc_iterator_data {
	u32 activity;
	bool end_activity;
	bool found;
};

static void iwl_mvm_rx_roc_iterator(void *_data, u8 *mac,
				    struct ieee80211_vif *vif)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_rx_roc_iterator_data *data = _data;

	if (mvmvif->roc_activity == data->activity) {
		data->found = true;
		if (data->end_activity)
			mvmvif->roc_activity = ROC_NUM_ACTIVITIES;
	}
}

void iwl_mvm_rx_roc_notif(struct iwl_mvm *mvm,
			  struct iwl_rx_cmd_buffer *rxb)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_roc_notif *notif = (void *)pkt->data;
	u32 activity = le32_to_cpu(notif->activity);
	bool started = le32_to_cpu(notif->success) &&
		le32_to_cpu(notif->started);
	struct iwl_mvm_rx_roc_iterator_data data = {
		.activity = activity,
		.end_activity = !started,
	};

	/* Clear vif roc_activity if done (set to ROC_NUM_ACTIVITIES) */
	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
						   IEEE80211_IFACE_ITER_NORMAL,
						   iwl_mvm_rx_roc_iterator,
						   &data);
	/*
	 * It is possible that the ROC was canceled
	 * but the notification was already fired.
	 */
	if (!data.found)
		return;

	if (started) {
		set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
		ieee80211_ready_on_channel(mvm->hw);
	} else {
		iwl_mvm_roc_finished(mvm);
		ieee80211_remain_on_channel_expired(mvm->hw);
	}
}

/*
 * Handle A Aux ROC time event
 */
static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
					   struct iwl_time_event_notif *notif)
{
	struct iwl_mvm_time_event_data *aux_roc_te = NULL, *te_data;

	list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
		if (le32_to_cpu(notif->unique_id) == te_data->uid) {
			aux_roc_te = te_data;
			break;
		}
	}
	if (!aux_roc_te) /* Not a Aux ROC time event */
		return -EINVAL;

	iwl_mvm_te_check_trigger(mvm, notif, aux_roc_te);

	IWL_DEBUG_TE(mvm,
		     "Aux ROC time event notification  - UID = 0x%x action %d (error = %d)\n",
		     le32_to_cpu(notif->unique_id),
		     le32_to_cpu(notif->action), le32_to_cpu(notif->status));

	if (!le32_to_cpu(notif->status) ||
	    le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) {
		/* End TE, notify mac80211 */
		ieee80211_remain_on_channel_expired(mvm->hw);
		iwl_mvm_roc_finished(mvm); /* flush aux queue */
		list_del(&aux_roc_te->list); /* remove from list */
		aux_roc_te->running = false;
		aux_roc_te->vif = NULL;
		aux_roc_te->uid = 0;
		aux_roc_te->id = TE_MAX;
	} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
		set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
		aux_roc_te->running = true;

Annotation

Implementation Notes