| From: Dmitry Torokhov <dmitry.torokhov@gmail.com> |
| Date: Tue, 14 Feb 2017 10:23:33 -0800 |
| Subject: ptp: use is_visible method to hide unused attributes |
| |
| commit af59e717d5ff9c8dbf9bcc581c0dfb3b2a9c9030 upstream. |
| |
| Instead of creating selected attributes after the device is created (and |
| after userspace potentially seen uevent), lets use attribute group |
| is_visible() method to control which attributes are shown. This will allow |
| us to create all attributes (except "pins" group, which will be taken care |
| of later) before userspace gets notified about new ptp class device. |
| |
| Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/ptp/ptp_sysfs.c | 125 ++++++++++++++++++---------------------- |
| 1 file changed, 55 insertions(+), 70 deletions(-) |
| |
| --- a/drivers/ptp/ptp_sysfs.c |
| +++ b/drivers/ptp/ptp_sysfs.c |
| @@ -46,27 +46,6 @@ PTP_SHOW_INT(n_periodic_outputs, n_per_o |
| PTP_SHOW_INT(n_programmable_pins, n_pins); |
| PTP_SHOW_INT(pps_available, pps); |
| |
| -static struct attribute *ptp_attrs[] = { |
| - &dev_attr_clock_name.attr, |
| - &dev_attr_max_adjustment.attr, |
| - &dev_attr_n_alarms.attr, |
| - &dev_attr_n_external_timestamps.attr, |
| - &dev_attr_n_periodic_outputs.attr, |
| - &dev_attr_n_programmable_pins.attr, |
| - &dev_attr_pps_available.attr, |
| - NULL, |
| -}; |
| - |
| -static const struct attribute_group ptp_group = { |
| - .attrs = ptp_attrs, |
| -}; |
| - |
| -const struct attribute_group *ptp_groups[] = { |
| - &ptp_group, |
| - NULL, |
| -}; |
| - |
| - |
| static ssize_t extts_enable_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| @@ -91,6 +70,7 @@ static ssize_t extts_enable_store(struct |
| out: |
| return err; |
| } |
| +static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store); |
| |
| static ssize_t extts_fifo_show(struct device *dev, |
| struct device_attribute *attr, char *page) |
| @@ -124,6 +104,7 @@ out: |
| mutex_unlock(&ptp->tsevq_mux); |
| return cnt; |
| } |
| +static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL); |
| |
| static ssize_t period_store(struct device *dev, |
| struct device_attribute *attr, |
| @@ -151,6 +132,7 @@ static ssize_t period_store(struct devic |
| out: |
| return err; |
| } |
| +static DEVICE_ATTR(period, 0220, NULL, period_store); |
| |
| static ssize_t pps_enable_store(struct device *dev, |
| struct device_attribute *attr, |
| @@ -177,6 +159,57 @@ static ssize_t pps_enable_store(struct d |
| out: |
| return err; |
| } |
| +static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store); |
| + |
| +static struct attribute *ptp_attrs[] = { |
| + &dev_attr_clock_name.attr, |
| + |
| + &dev_attr_max_adjustment.attr, |
| + &dev_attr_n_alarms.attr, |
| + &dev_attr_n_external_timestamps.attr, |
| + &dev_attr_n_periodic_outputs.attr, |
| + &dev_attr_n_programmable_pins.attr, |
| + &dev_attr_pps_available.attr, |
| + |
| + &dev_attr_extts_enable.attr, |
| + &dev_attr_fifo.attr, |
| + &dev_attr_period.attr, |
| + &dev_attr_pps_enable.attr, |
| + NULL |
| +}; |
| + |
| +static umode_t ptp_is_attribute_visible(struct kobject *kobj, |
| + struct attribute *attr, int n) |
| +{ |
| + struct device *dev = kobj_to_dev(kobj); |
| + struct ptp_clock *ptp = dev_get_drvdata(dev); |
| + struct ptp_clock_info *info = ptp->info; |
| + umode_t mode = attr->mode; |
| + |
| + if (attr == &dev_attr_extts_enable.attr || |
| + attr == &dev_attr_fifo.attr) { |
| + if (!info->n_ext_ts) |
| + mode = 0; |
| + } else if (attr == &dev_attr_period.attr) { |
| + if (!info->n_per_out) |
| + mode = 0; |
| + } else if (attr == &dev_attr_pps_enable.attr) { |
| + if (!info->pps) |
| + mode = 0; |
| + } |
| + |
| + return mode; |
| +} |
| + |
| +static const struct attribute_group ptp_group = { |
| + .is_visible = ptp_is_attribute_visible, |
| + .attrs = ptp_attrs, |
| +}; |
| + |
| +const struct attribute_group *ptp_groups[] = { |
| + &ptp_group, |
| + NULL |
| +}; |
| |
| static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name) |
| { |
| @@ -235,26 +268,11 @@ static ssize_t ptp_pin_store(struct devi |
| return count; |
| } |
| |
| -static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store); |
| -static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL); |
| -static DEVICE_ATTR(period, 0220, NULL, period_store); |
| -static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store); |
| - |
| int ptp_cleanup_sysfs(struct ptp_clock *ptp) |
| { |
| struct device *dev = ptp->dev; |
| struct ptp_clock_info *info = ptp->info; |
| |
| - if (info->n_ext_ts) { |
| - device_remove_file(dev, &dev_attr_extts_enable); |
| - device_remove_file(dev, &dev_attr_fifo); |
| - } |
| - if (info->n_per_out) |
| - device_remove_file(dev, &dev_attr_period); |
| - |
| - if (info->pps) |
| - device_remove_file(dev, &dev_attr_pps_enable); |
| - |
| if (info->n_pins) { |
| sysfs_remove_group(&dev->kobj, &ptp->pin_attr_group); |
| kfree(ptp->pin_attr); |
| @@ -307,46 +325,13 @@ no_dev_attr: |
| |
| int ptp_populate_sysfs(struct ptp_clock *ptp) |
| { |
| - struct device *dev = ptp->dev; |
| struct ptp_clock_info *info = ptp->info; |
| int err; |
| |
| - if (info->n_ext_ts) { |
| - err = device_create_file(dev, &dev_attr_extts_enable); |
| - if (err) |
| - goto out1; |
| - err = device_create_file(dev, &dev_attr_fifo); |
| - if (err) |
| - goto out2; |
| - } |
| - if (info->n_per_out) { |
| - err = device_create_file(dev, &dev_attr_period); |
| - if (err) |
| - goto out3; |
| - } |
| - if (info->pps) { |
| - err = device_create_file(dev, &dev_attr_pps_enable); |
| - if (err) |
| - goto out4; |
| - } |
| if (info->n_pins) { |
| err = ptp_populate_pins(ptp); |
| if (err) |
| - goto out5; |
| + return err; |
| } |
| return 0; |
| -out5: |
| - if (info->pps) |
| - device_remove_file(dev, &dev_attr_pps_enable); |
| -out4: |
| - if (info->n_per_out) |
| - device_remove_file(dev, &dev_attr_period); |
| -out3: |
| - if (info->n_ext_ts) |
| - device_remove_file(dev, &dev_attr_fifo); |
| -out2: |
| - if (info->n_ext_ts) |
| - device_remove_file(dev, &dev_attr_extts_enable); |
| -out1: |
| - return err; |
| } |