drivers/net/wireless/intel/iwlwifi/mvm/ptp.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
Extension
.c
Size
9660 bytes
Lines
337
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 (!diff || new_diff < diff) {
			*sys_time = tmp_sys_time;
			*gp2 = tmp_gp2;
			diff = new_diff;
			IWL_DEBUG_INFO(mvm, "PTP: new times: gp2=%u sys=%lld\n",
				       *gp2, *sys_time);
		}
	}
}

static int
iwl_mvm_phc_get_crosstimestamp(struct ptp_clock_info *ptp,
			       struct system_device_crosststamp *xtstamp)
{
	struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
					   ptp_data.ptp_clock_info);
	int ret = 0;
	/* Raw value read from GP2 register in usec */
	u32 gp2;
	/* GP2 value in ns*/
	s64 gp2_ns;
	/* System (wall) time */
	ktime_t sys_time;

	if (!mvm->ptp_data.ptp_clock) {
		IWL_ERR(mvm, "No PHC clock registered\n");
		return -ENODEV;
	}

	if (xtstamp->clock_id != CLOCK_REALTIME)
		return -ENOTSUPP;

	mutex_lock(&mvm->mutex);
	if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SYNCED_TIME)) {
		ret = iwl_mvm_get_crosstimestamp_fw(mvm, &gp2, &sys_time);

		if (ret)
			goto out;
	} else {
		iwl_mvm_phc_get_crosstimestamp_loop(mvm, &sys_time, &gp2);
	}

	gp2_ns = iwl_mvm_ptp_get_adj_time(mvm, (u64)gp2 * NSEC_PER_USEC);

	IWL_INFO(mvm, "Got Sync Time: GP2:%u, last_GP2: %u, GP2_ns: %lld, sys_time: %lld\n",
		 gp2, mvm->ptp_data.last_gp2, gp2_ns, (s64)sys_time);

	/* System monotonic raw time is not used */
	xtstamp->device = (ktime_t)gp2_ns;
	xtstamp->sys_systime = sys_time;

out:
	mutex_unlock(&mvm->mutex);
	return ret;
}

static void iwl_mvm_ptp_work(struct work_struct *wk)
{
	struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm,
					   ptp_data.dwork.work);
	u32 gp2;

	mutex_lock(&mvm->mutex);
	gp2 = iwl_mvm_get_systime(mvm);
	iwl_mvm_ptp_update_new_read(mvm, gp2);
	mutex_unlock(&mvm->mutex);
}

static int iwl_mvm_ptp_gettime(struct ptp_clock_info *ptp,
			       struct timespec64 *ts)
{
	struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
					   ptp_data.ptp_clock_info);
	u64 gp2;
	u64 ns;

	mutex_lock(&mvm->mutex);
	gp2 = iwl_mvm_get_systime(mvm);
	ns = iwl_mvm_ptp_get_adj_time(mvm, gp2 * NSEC_PER_USEC);
	mutex_unlock(&mvm->mutex);

	*ts = ns_to_timespec64(ns);
	return 0;
}

static int iwl_mvm_ptp_settime(struct ptp_clock_info *ptp,
			       const struct timespec64 *ts)
{
	return -EOPNOTSUPP;
}

Annotation

Implementation Notes