コード例 #1
0
ファイル: phc_ctl.c プロジェクト: nwtime/linuxptp
static clockid_t clock_open(char *device)
{
	struct sk_ts_info ts_info;
	char phc_device[19];
	int clkid;

	/* check if device is CLOCK_REALTIME */
	if (!strcasecmp(device, "CLOCK_REALTIME"))
		return CLOCK_REALTIME;

	/* check if device is valid phc device */
	clkid = phc_open(device);
	if (clkid != CLOCK_INVALID)
		return clkid;

	/* check if device is a valid ethernet device */
	if (sk_get_ts_info(device, &ts_info) || !ts_info.valid) {
		pr_err("unknown clock %s: %m", device);
		return CLOCK_INVALID;
	}

	if (ts_info.phc_index < 0) {
		pr_err("interface %s does not have a PHC", device);
		return CLOCK_INVALID;
	}

	sprintf(phc_device, "/dev/ptp%d", ts_info.phc_index);
	clkid = phc_open(phc_device);
	if (clkid == CLOCK_INVALID)
		pr_err("cannot open %s for %s: %m", phc_device, device);
	return clkid;
}
コード例 #2
0
static int add_ptp_source(struct ptp_domain *source,
			  struct timemaster_config *config, int *shm_segment,
			  int ***allocated_phcs, char **ntp_config,
			  struct script *script)
{
	struct config_file *config_file;
	char **command, *uds_path, **interfaces;
	int i, j, num_interfaces, *phc, *phcs, hw_ts;
	struct sk_ts_info ts_info;

	pr_debug("adding PTP domain %d", source->domain);

	hw_ts = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE |
		SOF_TIMESTAMPING_RAW_HARDWARE;

	for (num_interfaces = 0;
	     source->interfaces[num_interfaces]; num_interfaces++)
		;

	if (!num_interfaces)
		return 0;

	/* get PHCs used by specified interfaces */
	phcs = xmalloc(num_interfaces * sizeof(int));
	for (i = 0; i < num_interfaces; i++) {
		phcs[i] = -1;

		/* check if the interface has a usable PHC */
		if (sk_get_ts_info(source->interfaces[i], &ts_info)) {
			pr_err("failed to get time stamping info for %s",
			       source->interfaces[i]);
			free(phcs);
			return 1;
		}

		if (!ts_info.valid ||
		    ((ts_info.so_timestamping & hw_ts) != hw_ts)) {
			pr_debug("interface %s: no PHC", source->interfaces[i]);
			continue;
		}

		pr_debug("interface %s: PHC %d", source->interfaces[i],
			 ts_info.phc_index);

		/* and the PHC isn't already used in another source */
		for (j = 0; (*allocated_phcs)[j]; j++) {
			if (*(*allocated_phcs)[j] == ts_info.phc_index) {
				pr_debug("PHC %d already allocated",
					 ts_info.phc_index);
				break;
			}
		}
		if (!(*allocated_phcs)[j])
			phcs[i] = ts_info.phc_index;
	}

	for (i = 0; i < num_interfaces; i++) {
		/* skip if already used by ptp4l in this domain */
		if (phcs[i] == -2)
			continue;

		interfaces = (char **)parray_new();
		parray_append((void ***)&interfaces, source->interfaces[i]);

		/* merge all interfaces sharing PHC to one ptp4l command */
		if (phcs[i] >= 0) {
			for (j = i + 1; j < num_interfaces; j++) {
				if (phcs[i] == phcs[j]) {
					parray_append((void ***)&interfaces,
						      source->interfaces[j]);
					/* mark the interface as used */
					phcs[j] = -2;
				}
			}

			/* don't use this PHC in other sources */
			phc = xmalloc(sizeof(int));
			*phc = phcs[i];
			parray_append((void ***)allocated_phcs, phc);
		}

		uds_path = string_newf("%s/ptp4l.%d.socket",
				       config->rundir, *shm_segment);

		config_file = xmalloc(sizeof(*config_file));
		config_file->path = string_newf("%s/ptp4l.%d.conf",
						config->rundir, *shm_segment);
		config_file->content = xstrdup("[global]\n");
		extend_config_string(&config_file->content,
				     config->ptp4l.settings);
		extend_config_string(&config_file->content,
				     source->ptp4l_settings);
		string_appendf(&config_file->content,
			       "slaveOnly 1\n"
			       "domainNumber %d\n"
			       "uds_address %s\n",
			       source->domain, uds_path);

		if (phcs[i] >= 0) {
			/* HW time stamping */
			command = get_ptp4l_command(&config->ptp4l, config_file,
						    interfaces, 1);
			parray_append((void ***)&script->commands, command);

			command = get_phc2sys_command(&config->phc2sys,
						      source->domain,
						      source->phc2sys_poll,
						      *shm_segment, uds_path);
			parray_append((void ***)&script->commands, command);
		} else {
			/* SW time stamping */
			command = get_ptp4l_command(&config->ptp4l, config_file,
						    interfaces, 0);
			parray_append((void ***)&script->commands, command);

			string_appendf(&config_file->content,
				       "clock_servo ntpshm\n"
				       "ntpshm_segment %d\n", *shm_segment);
		}

		parray_append((void ***)&script->configs, config_file);

		add_shm_source(*shm_segment, source->ntp_poll,
			       source->phc2sys_poll, source->delay,
			       source->ntp_options, "PTP", config, ntp_config);

		(*shm_segment)++;

		free(uds_path);
		free(interfaces);
	}

	free(phcs);

	return 0;
}