cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptp_sysfs.c (10953B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * PTP 1588 clock support - sysfs interface.
      4 *
      5 * Copyright (C) 2010 OMICRON electronics GmbH
      6 * Copyright 2021 NXP
      7 */
      8#include <linux/capability.h>
      9#include <linux/slab.h>
     10
     11#include "ptp_private.h"
     12
     13static ssize_t clock_name_show(struct device *dev,
     14			       struct device_attribute *attr, char *page)
     15{
     16	struct ptp_clock *ptp = dev_get_drvdata(dev);
     17	return sysfs_emit(page, "%s\n", ptp->info->name);
     18}
     19static DEVICE_ATTR_RO(clock_name);
     20
     21#define PTP_SHOW_INT(name, var)						\
     22static ssize_t var##_show(struct device *dev,				\
     23			   struct device_attribute *attr, char *page)	\
     24{									\
     25	struct ptp_clock *ptp = dev_get_drvdata(dev);			\
     26	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->var);	\
     27}									\
     28static DEVICE_ATTR(name, 0444, var##_show, NULL);
     29
     30PTP_SHOW_INT(max_adjustment, max_adj);
     31PTP_SHOW_INT(n_alarms, n_alarm);
     32PTP_SHOW_INT(n_external_timestamps, n_ext_ts);
     33PTP_SHOW_INT(n_periodic_outputs, n_per_out);
     34PTP_SHOW_INT(n_programmable_pins, n_pins);
     35PTP_SHOW_INT(pps_available, pps);
     36
     37static ssize_t extts_enable_store(struct device *dev,
     38				  struct device_attribute *attr,
     39				  const char *buf, size_t count)
     40{
     41	struct ptp_clock *ptp = dev_get_drvdata(dev);
     42	struct ptp_clock_info *ops = ptp->info;
     43	struct ptp_clock_request req = { .type = PTP_CLK_REQ_EXTTS };
     44	int cnt, enable;
     45	int err = -EINVAL;
     46
     47	cnt = sscanf(buf, "%u %d", &req.extts.index, &enable);
     48	if (cnt != 2)
     49		goto out;
     50	if (req.extts.index >= ops->n_ext_ts)
     51		goto out;
     52
     53	err = ops->enable(ops, &req, enable ? 1 : 0);
     54	if (err)
     55		goto out;
     56
     57	return count;
     58out:
     59	return err;
     60}
     61static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
     62
     63static ssize_t extts_fifo_show(struct device *dev,
     64			       struct device_attribute *attr, char *page)
     65{
     66	struct ptp_clock *ptp = dev_get_drvdata(dev);
     67	struct timestamp_event_queue *queue = &ptp->tsevq;
     68	struct ptp_extts_event event;
     69	unsigned long flags;
     70	size_t qcnt;
     71	int cnt = 0;
     72
     73	memset(&event, 0, sizeof(event));
     74
     75	if (mutex_lock_interruptible(&ptp->tsevq_mux))
     76		return -ERESTARTSYS;
     77
     78	spin_lock_irqsave(&queue->lock, flags);
     79	qcnt = queue_cnt(queue);
     80	if (qcnt) {
     81		event = queue->buf[queue->head];
     82		queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
     83	}
     84	spin_unlock_irqrestore(&queue->lock, flags);
     85
     86	if (!qcnt)
     87		goto out;
     88
     89	cnt = snprintf(page, PAGE_SIZE, "%u %lld %u\n",
     90		       event.index, event.t.sec, event.t.nsec);
     91out:
     92	mutex_unlock(&ptp->tsevq_mux);
     93	return cnt;
     94}
     95static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);
     96
     97static ssize_t period_store(struct device *dev,
     98			    struct device_attribute *attr,
     99			    const char *buf, size_t count)
    100{
    101	struct ptp_clock *ptp = dev_get_drvdata(dev);
    102	struct ptp_clock_info *ops = ptp->info;
    103	struct ptp_clock_request req = { .type = PTP_CLK_REQ_PEROUT };
    104	int cnt, enable, err = -EINVAL;
    105
    106	cnt = sscanf(buf, "%u %lld %u %lld %u", &req.perout.index,
    107		     &req.perout.start.sec, &req.perout.start.nsec,
    108		     &req.perout.period.sec, &req.perout.period.nsec);
    109	if (cnt != 5)
    110		goto out;
    111	if (req.perout.index >= ops->n_per_out)
    112		goto out;
    113
    114	enable = req.perout.period.sec || req.perout.period.nsec;
    115	err = ops->enable(ops, &req, enable);
    116	if (err)
    117		goto out;
    118
    119	return count;
    120out:
    121	return err;
    122}
    123static DEVICE_ATTR(period, 0220, NULL, period_store);
    124
    125static ssize_t pps_enable_store(struct device *dev,
    126				struct device_attribute *attr,
    127				const char *buf, size_t count)
    128{
    129	struct ptp_clock *ptp = dev_get_drvdata(dev);
    130	struct ptp_clock_info *ops = ptp->info;
    131	struct ptp_clock_request req = { .type = PTP_CLK_REQ_PPS };
    132	int cnt, enable;
    133	int err = -EINVAL;
    134
    135	if (!capable(CAP_SYS_TIME))
    136		return -EPERM;
    137
    138	cnt = sscanf(buf, "%d", &enable);
    139	if (cnt != 1)
    140		goto out;
    141
    142	err = ops->enable(ops, &req, enable ? 1 : 0);
    143	if (err)
    144		goto out;
    145
    146	return count;
    147out:
    148	return err;
    149}
    150static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
    151
    152static int unregister_vclock(struct device *dev, void *data)
    153{
    154	struct ptp_clock *ptp = dev_get_drvdata(dev);
    155	struct ptp_clock_info *info = ptp->info;
    156	struct ptp_vclock *vclock;
    157	u32 *num = data;
    158
    159	vclock = info_to_vclock(info);
    160	dev_info(dev->parent, "delete virtual clock ptp%d\n",
    161		 vclock->clock->index);
    162
    163	ptp_vclock_unregister(vclock);
    164	(*num)--;
    165
    166	/* For break. Not error. */
    167	if (*num == 0)
    168		return -EINVAL;
    169
    170	return 0;
    171}
    172
    173static ssize_t n_vclocks_show(struct device *dev,
    174			      struct device_attribute *attr, char *page)
    175{
    176	struct ptp_clock *ptp = dev_get_drvdata(dev);
    177	ssize_t size;
    178
    179	if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
    180		return -ERESTARTSYS;
    181
    182	size = snprintf(page, PAGE_SIZE - 1, "%u\n", ptp->n_vclocks);
    183
    184	mutex_unlock(&ptp->n_vclocks_mux);
    185
    186	return size;
    187}
    188
    189static ssize_t n_vclocks_store(struct device *dev,
    190			       struct device_attribute *attr,
    191			       const char *buf, size_t count)
    192{
    193	struct ptp_clock *ptp = dev_get_drvdata(dev);
    194	struct ptp_vclock *vclock;
    195	int err = -EINVAL;
    196	u32 num, i;
    197
    198	if (kstrtou32(buf, 0, &num))
    199		return err;
    200
    201	if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
    202		return -ERESTARTSYS;
    203
    204	if (num > ptp->max_vclocks) {
    205		dev_err(dev, "max value is %d\n", ptp->max_vclocks);
    206		goto out;
    207	}
    208
    209	/* Need to create more vclocks */
    210	if (num > ptp->n_vclocks) {
    211		for (i = 0; i < num - ptp->n_vclocks; i++) {
    212			vclock = ptp_vclock_register(ptp);
    213			if (!vclock)
    214				goto out;
    215
    216			*(ptp->vclock_index + ptp->n_vclocks + i) =
    217				vclock->clock->index;
    218
    219			dev_info(dev, "new virtual clock ptp%d\n",
    220				 vclock->clock->index);
    221		}
    222	}
    223
    224	/* Need to delete vclocks */
    225	if (num < ptp->n_vclocks) {
    226		i = ptp->n_vclocks - num;
    227		device_for_each_child_reverse(dev, &i,
    228					      unregister_vclock);
    229
    230		for (i = 1; i <= ptp->n_vclocks - num; i++)
    231			*(ptp->vclock_index + ptp->n_vclocks - i) = -1;
    232	}
    233
    234	/* Need to inform about changed physical clock behavior */
    235	if (!ptp->has_cycles) {
    236		if (num == 0)
    237			dev_info(dev, "only physical clock in use now\n");
    238		else
    239			dev_info(dev, "guarantee physical clock free running\n");
    240	}
    241
    242	ptp->n_vclocks = num;
    243	mutex_unlock(&ptp->n_vclocks_mux);
    244
    245	return count;
    246out:
    247	mutex_unlock(&ptp->n_vclocks_mux);
    248	return err;
    249}
    250static DEVICE_ATTR_RW(n_vclocks);
    251
    252static ssize_t max_vclocks_show(struct device *dev,
    253				struct device_attribute *attr, char *page)
    254{
    255	struct ptp_clock *ptp = dev_get_drvdata(dev);
    256	ssize_t size;
    257
    258	size = snprintf(page, PAGE_SIZE - 1, "%u\n", ptp->max_vclocks);
    259
    260	return size;
    261}
    262
    263static ssize_t max_vclocks_store(struct device *dev,
    264				 struct device_attribute *attr,
    265				 const char *buf, size_t count)
    266{
    267	struct ptp_clock *ptp = dev_get_drvdata(dev);
    268	unsigned int *vclock_index;
    269	int err = -EINVAL;
    270	size_t size;
    271	u32 max;
    272
    273	if (kstrtou32(buf, 0, &max) || max == 0)
    274		return -EINVAL;
    275
    276	if (max == ptp->max_vclocks)
    277		return count;
    278
    279	if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
    280		return -ERESTARTSYS;
    281
    282	if (max < ptp->n_vclocks)
    283		goto out;
    284
    285	size = sizeof(int) * max;
    286	vclock_index = kzalloc(size, GFP_KERNEL);
    287	if (!vclock_index) {
    288		err = -ENOMEM;
    289		goto out;
    290	}
    291
    292	size = sizeof(int) * ptp->n_vclocks;
    293	memcpy(vclock_index, ptp->vclock_index, size);
    294
    295	kfree(ptp->vclock_index);
    296	ptp->vclock_index = vclock_index;
    297	ptp->max_vclocks = max;
    298
    299	mutex_unlock(&ptp->n_vclocks_mux);
    300
    301	return count;
    302out:
    303	mutex_unlock(&ptp->n_vclocks_mux);
    304	return err;
    305}
    306static DEVICE_ATTR_RW(max_vclocks);
    307
    308static struct attribute *ptp_attrs[] = {
    309	&dev_attr_clock_name.attr,
    310
    311	&dev_attr_max_adjustment.attr,
    312	&dev_attr_n_alarms.attr,
    313	&dev_attr_n_external_timestamps.attr,
    314	&dev_attr_n_periodic_outputs.attr,
    315	&dev_attr_n_programmable_pins.attr,
    316	&dev_attr_pps_available.attr,
    317
    318	&dev_attr_extts_enable.attr,
    319	&dev_attr_fifo.attr,
    320	&dev_attr_period.attr,
    321	&dev_attr_pps_enable.attr,
    322	&dev_attr_n_vclocks.attr,
    323	&dev_attr_max_vclocks.attr,
    324	NULL
    325};
    326
    327static umode_t ptp_is_attribute_visible(struct kobject *kobj,
    328					struct attribute *attr, int n)
    329{
    330	struct device *dev = kobj_to_dev(kobj);
    331	struct ptp_clock *ptp = dev_get_drvdata(dev);
    332	struct ptp_clock_info *info = ptp->info;
    333	umode_t mode = attr->mode;
    334
    335	if (attr == &dev_attr_extts_enable.attr ||
    336	    attr == &dev_attr_fifo.attr) {
    337		if (!info->n_ext_ts)
    338			mode = 0;
    339	} else if (attr == &dev_attr_period.attr) {
    340		if (!info->n_per_out)
    341			mode = 0;
    342	} else if (attr == &dev_attr_pps_enable.attr) {
    343		if (!info->pps)
    344			mode = 0;
    345	} else if (attr == &dev_attr_n_vclocks.attr ||
    346		   attr == &dev_attr_max_vclocks.attr) {
    347		if (ptp->is_virtual_clock)
    348			mode = 0;
    349	}
    350
    351	return mode;
    352}
    353
    354static const struct attribute_group ptp_group = {
    355	.is_visible	= ptp_is_attribute_visible,
    356	.attrs		= ptp_attrs,
    357};
    358
    359const struct attribute_group *ptp_groups[] = {
    360	&ptp_group,
    361	NULL
    362};
    363
    364static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name)
    365{
    366	int i;
    367	for (i = 0; i < ptp->info->n_pins; i++) {
    368		if (!strcmp(ptp->info->pin_config[i].name, name))
    369			return i;
    370	}
    371	return -1;
    372}
    373
    374static ssize_t ptp_pin_show(struct device *dev, struct device_attribute *attr,
    375			    char *page)
    376{
    377	struct ptp_clock *ptp = dev_get_drvdata(dev);
    378	unsigned int func, chan;
    379	int index;
    380
    381	index = ptp_pin_name2index(ptp, attr->attr.name);
    382	if (index < 0)
    383		return -EINVAL;
    384
    385	if (mutex_lock_interruptible(&ptp->pincfg_mux))
    386		return -ERESTARTSYS;
    387
    388	func = ptp->info->pin_config[index].func;
    389	chan = ptp->info->pin_config[index].chan;
    390
    391	mutex_unlock(&ptp->pincfg_mux);
    392
    393	return sysfs_emit(page, "%u %u\n", func, chan);
    394}
    395
    396static ssize_t ptp_pin_store(struct device *dev, struct device_attribute *attr,
    397			     const char *buf, size_t count)
    398{
    399	struct ptp_clock *ptp = dev_get_drvdata(dev);
    400	unsigned int func, chan;
    401	int cnt, err, index;
    402
    403	cnt = sscanf(buf, "%u %u", &func, &chan);
    404	if (cnt != 2)
    405		return -EINVAL;
    406
    407	index = ptp_pin_name2index(ptp, attr->attr.name);
    408	if (index < 0)
    409		return -EINVAL;
    410
    411	if (mutex_lock_interruptible(&ptp->pincfg_mux))
    412		return -ERESTARTSYS;
    413	err = ptp_set_pinfunc(ptp, index, func, chan);
    414	mutex_unlock(&ptp->pincfg_mux);
    415	if (err)
    416		return err;
    417
    418	return count;
    419}
    420
    421int ptp_populate_pin_groups(struct ptp_clock *ptp)
    422{
    423	struct ptp_clock_info *info = ptp->info;
    424	int err = -ENOMEM, i, n_pins = info->n_pins;
    425
    426	if (!n_pins)
    427		return 0;
    428
    429	ptp->pin_dev_attr = kcalloc(n_pins, sizeof(*ptp->pin_dev_attr),
    430				    GFP_KERNEL);
    431	if (!ptp->pin_dev_attr)
    432		goto no_dev_attr;
    433
    434	ptp->pin_attr = kcalloc(1 + n_pins, sizeof(*ptp->pin_attr), GFP_KERNEL);
    435	if (!ptp->pin_attr)
    436		goto no_pin_attr;
    437
    438	for (i = 0; i < n_pins; i++) {
    439		struct device_attribute *da = &ptp->pin_dev_attr[i];
    440		sysfs_attr_init(&da->attr);
    441		da->attr.name = info->pin_config[i].name;
    442		da->attr.mode = 0644;
    443		da->show = ptp_pin_show;
    444		da->store = ptp_pin_store;
    445		ptp->pin_attr[i] = &da->attr;
    446	}
    447
    448	ptp->pin_attr_group.name = "pins";
    449	ptp->pin_attr_group.attrs = ptp->pin_attr;
    450
    451	ptp->pin_attr_groups[0] = &ptp->pin_attr_group;
    452
    453	return 0;
    454
    455no_pin_attr:
    456	kfree(ptp->pin_dev_attr);
    457no_dev_attr:
    458	return err;
    459}
    460
    461void ptp_cleanup_pin_groups(struct ptp_clock *ptp)
    462{
    463	kfree(ptp->pin_attr);
    464	kfree(ptp->pin_dev_attr);
    465}