drivers/net/wireless/intel/iwlwifi/mld/stats.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/mld/stats.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/stats.c
Extension
.c
Size
17471 bytes
Lines
625
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_mld_stats_data {
	u8 fw_sta_id;
	struct station_info *sinfo;
	struct iwl_mld *mld;
};

static bool iwl_mld_wait_stats_handler(struct iwl_notif_wait_data *notif_data,
				       struct iwl_rx_packet *pkt, void *data)
{
	struct iwl_mld_stats_data *stats_data = data;
	u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);

	switch (cmd) {
	case WIDE_ID(STATISTICS_GROUP, STATISTICS_OPER_NOTIF):
		iwl_mld_fill_stats_from_oper_notif(stats_data->mld, pkt,
						   stats_data->fw_sta_id,
						   stats_data->sinfo);
		break;
	case WIDE_ID(STATISTICS_GROUP, STATISTICS_OPER_PART1_NOTIF):
		break;
	case WIDE_ID(SYSTEM_GROUP, SYSTEM_STATISTICS_END_NOTIF):
		return true;
	}

	return false;
}

static int
iwl_mld_fw_stats_to_mac80211(struct iwl_mld *mld, struct iwl_mld_sta *mld_sta,
			     struct station_info *sinfo)
{
	u32 cfg_mask = IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK |
		       IWL_STATS_CFG_FLG_RESET_MSK;
	u32 type_mask = IWL_STATS_NTFY_TYPE_ID_OPER |
			IWL_STATS_NTFY_TYPE_ID_OPER_PART1;
	static const u16 notifications[] = {
		WIDE_ID(STATISTICS_GROUP, STATISTICS_OPER_NOTIF),
		WIDE_ID(STATISTICS_GROUP, STATISTICS_OPER_PART1_NOTIF),
		WIDE_ID(SYSTEM_GROUP, SYSTEM_STATISTICS_END_NOTIF),
	};
	struct iwl_mld_stats_data wait_stats_data = {
		/* We don't support drv_sta_statistics in EMLSR */
		.fw_sta_id = mld_sta->deflink.fw_id,
		.sinfo = sinfo,
		.mld = mld,
	};
	struct iwl_notification_wait stats_wait;
	int ret;

	iwl_init_notification_wait(&mld->notif_wait, &stats_wait,
				   notifications, ARRAY_SIZE(notifications),
				   iwl_mld_wait_stats_handler,
				   &wait_stats_data);

	ret = iwl_mld_send_fw_stats_cmd(mld, cfg_mask, 0, type_mask);
	if (ret) {
		iwl_remove_notification(&mld->notif_wait, &stats_wait);
		return ret;
	}

	/* Wait 500ms for OPERATIONAL, PART1, and END notifications,
	 * which should be sufficient for the firmware to gather data
	 * from all LMACs and send notifications to the host.
	 */
	ret = iwl_wait_notification(&mld->notif_wait, &stats_wait, HZ / 2);
	if (ret)
		return ret;

	/* When periodic statistics are sent, FW will clear its statistics DB.
	 * If the statistics request here happens shortly afterwards,
	 * the response will contain data collected over a short time
	 * interval. The response we got here shouldn't be processed by
	 * the general statistics processing because it's incomplete.
	 * So, we delete it from the list so it won't be processed.
	 */
	iwl_mld_delete_handlers(mld, notifications, ARRAY_SIZE(notifications));

	return 0;
}

#define PERIODIC_STATS_SECONDS 5

int iwl_mld_request_periodic_fw_stats(struct iwl_mld *mld, bool enable)
{
	u32 cfg_mask = enable ? 0 : IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK;
	u32 type_mask = enable ? (IWL_STATS_NTFY_TYPE_ID_OPER |
				  IWL_STATS_NTFY_TYPE_ID_OPER_PART1) : 0;
	u32 cfg_time = enable ? PERIODIC_STATS_SECONDS : 0;

	return iwl_mld_send_fw_stats_cmd(mld, cfg_mask, cfg_time, type_mask);

Annotation

Implementation Notes