Commit cfd433ce authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'ptp-ocp-fix-serial-port-information-export'

Vadim Fedorenko says:

====================
ptp: ocp: fix serial port information export

Starting v6.8 the serial port subsystem changed the hierarchy of devices
and symlinks are not working anymore. Previous discussion made it clear
that the idea of symlinks for tty devices was wrong by design [1].
This series implements additional attributes to expose the information
and removes symlinks for tty devices.

[1] https://lore.kernel.org/netdev/2024060503-subsonic-pupil-bbee@gregkh/

v6 -> v7:
- fix issues with applying patches
v5 -> v6:
- split conversion to array to separate patch per Jiri's feedback
- move changelog to cover letter
v4 -> v5:
- remove unused variable in ptp_ocp_tty_show
v3 -> v4:
- re-organize info printing to use ptp_ocp_tty_port_name()
- keep uintptr_t to be consistent with other code
v2 -> v3:
- replace serial ports definitions with array and enum for index
- replace pointer math with direct array access
- nit in documentation spelling
v1 -> v2:
- add Documentation/ABI changes
====================

Link: https://patch.msgid.link/20240829183603.1156671-1-vadfed@meta.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 2560db6e 40bec579
...@@ -258,24 +258,29 @@ Description: (RW) When retrieving the PHC with the PTP SYS_OFFSET_EXTENDED ...@@ -258,24 +258,29 @@ Description: (RW) When retrieving the PHC with the PTP SYS_OFFSET_EXTENDED
the estimated point where the FPGA latches the PHC time. This the estimated point where the FPGA latches the PHC time. This
value may be changed by writing an unsigned integer. value may be changed by writing an unsigned integer.
What: /sys/class/timecard/ocpN/ttyGNSS What: /sys/class/timecard/ocpN/tty
What: /sys/class/timecard/ocpN/ttyGNSS2 Date: August 2024
Date: September 2021 Contact: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Description: (RO) Directory containing the sysfs nodes for TTY attributes
What: /sys/class/timecard/ocpN/tty/ttyGNSS
What: /sys/class/timecard/ocpN/tty/ttyGNSS2
Date: August 2024
Contact: Jonathan Lemon <jonathan.lemon@gmail.com> Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
Description: These optional attributes link to the TTY serial ports Description: (RO) These optional attributes contain names of the TTY serial
associated with the GNSS devices. ports associated with the GNSS devices.
What: /sys/class/timecard/ocpN/ttyMAC What: /sys/class/timecard/ocpN/tty/ttyMAC
Date: September 2021 Date: August 2024
Contact: Jonathan Lemon <jonathan.lemon@gmail.com> Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
Description: This optional attribute links to the TTY serial port Description: (RO) This optional attribute contains name of the TTY serial
associated with the Miniature Atomic Clock. port associated with the Miniature Atomic Clock.
What: /sys/class/timecard/ocpN/ttyNMEA What: /sys/class/timecard/ocpN/tty/ttyNMEA
Date: September 2021 Date: August 2024
Contact: Jonathan Lemon <jonathan.lemon@gmail.com> Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
Description: This optional attribute links to the TTY serial port Description: (RO) This optional attribute contains name of the TTY serial
which outputs the PHC time in NMEA ZDA format. port which outputs the PHC time in NMEA ZDA format.
What: /sys/class/timecard/ocpN/utc_tai_offset What: /sys/class/timecard/ocpN/utc_tai_offset
Date: September 2021 Date: September 2021
......
...@@ -316,6 +316,15 @@ struct ptp_ocp_serial_port { ...@@ -316,6 +316,15 @@ struct ptp_ocp_serial_port {
#define OCP_SERIAL_LEN 6 #define OCP_SERIAL_LEN 6
#define OCP_SMA_NUM 4 #define OCP_SMA_NUM 4
enum {
PORT_GNSS,
PORT_GNSS2,
PORT_MAC, /* miniature atomic clock */
PORT_NMEA,
__PORT_COUNT,
};
struct ptp_ocp { struct ptp_ocp {
struct pci_dev *pdev; struct pci_dev *pdev;
struct device dev; struct device dev;
...@@ -357,10 +366,7 @@ struct ptp_ocp { ...@@ -357,10 +366,7 @@ struct ptp_ocp {
struct delayed_work sync_work; struct delayed_work sync_work;
int id; int id;
int n_irqs; int n_irqs;
struct ptp_ocp_serial_port gnss_port; struct ptp_ocp_serial_port port[__PORT_COUNT];
struct ptp_ocp_serial_port gnss2_port;
struct ptp_ocp_serial_port mac_port; /* miniature atomic clock */
struct ptp_ocp_serial_port nmea_port;
bool fw_loader; bool fw_loader;
u8 fw_tag; u8 fw_tag;
u16 fw_version; u16 fw_version;
...@@ -655,28 +661,28 @@ static struct ocp_resource ocp_fb_resource[] = { ...@@ -655,28 +661,28 @@ static struct ocp_resource ocp_fb_resource[] = {
}, },
}, },
{ {
OCP_SERIAL_RESOURCE(gnss_port), OCP_SERIAL_RESOURCE(port[PORT_GNSS]),
.offset = 0x00160000 + 0x1000, .irq_vec = 3, .offset = 0x00160000 + 0x1000, .irq_vec = 3,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 115200, .baud = 115200,
}, },
}, },
{ {
OCP_SERIAL_RESOURCE(gnss2_port), OCP_SERIAL_RESOURCE(port[PORT_GNSS2]),
.offset = 0x00170000 + 0x1000, .irq_vec = 4, .offset = 0x00170000 + 0x1000, .irq_vec = 4,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 115200, .baud = 115200,
}, },
}, },
{ {
OCP_SERIAL_RESOURCE(mac_port), OCP_SERIAL_RESOURCE(port[PORT_MAC]),
.offset = 0x00180000 + 0x1000, .irq_vec = 5, .offset = 0x00180000 + 0x1000, .irq_vec = 5,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 57600, .baud = 57600,
}, },
}, },
{ {
OCP_SERIAL_RESOURCE(nmea_port), OCP_SERIAL_RESOURCE(port[PORT_NMEA]),
.offset = 0x00190000 + 0x1000, .irq_vec = 10, .offset = 0x00190000 + 0x1000, .irq_vec = 10,
}, },
{ {
...@@ -740,7 +746,7 @@ static struct ocp_resource ocp_art_resource[] = { ...@@ -740,7 +746,7 @@ static struct ocp_resource ocp_art_resource[] = {
.offset = 0x01000000, .size = 0x10000, .offset = 0x01000000, .size = 0x10000,
}, },
{ {
OCP_SERIAL_RESOURCE(gnss_port), OCP_SERIAL_RESOURCE(port[PORT_GNSS]),
.offset = 0x00160000 + 0x1000, .irq_vec = 3, .offset = 0x00160000 + 0x1000, .irq_vec = 3,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 115200, .baud = 115200,
...@@ -839,7 +845,7 @@ static struct ocp_resource ocp_art_resource[] = { ...@@ -839,7 +845,7 @@ static struct ocp_resource ocp_art_resource[] = {
}, },
}, },
{ {
OCP_SERIAL_RESOURCE(mac_port), OCP_SERIAL_RESOURCE(port[PORT_MAC]),
.offset = 0x00190000, .irq_vec = 7, .offset = 0x00190000, .irq_vec = 7,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 9600, .baud = 9600,
...@@ -950,14 +956,14 @@ static struct ocp_resource ocp_adva_resource[] = { ...@@ -950,14 +956,14 @@ static struct ocp_resource ocp_adva_resource[] = {
.offset = 0x00220000, .size = 0x1000, .offset = 0x00220000, .size = 0x1000,
}, },
{ {
OCP_SERIAL_RESOURCE(gnss_port), OCP_SERIAL_RESOURCE(port[PORT_GNSS]),
.offset = 0x00160000 + 0x1000, .irq_vec = 3, .offset = 0x00160000 + 0x1000, .irq_vec = 3,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 9600, .baud = 9600,
}, },
}, },
{ {
OCP_SERIAL_RESOURCE(mac_port), OCP_SERIAL_RESOURCE(port[PORT_MAC]),
.offset = 0x00180000 + 0x1000, .irq_vec = 5, .offset = 0x00180000 + 0x1000, .irq_vec = 5,
.extra = &(struct ptp_ocp_serial_port) { .extra = &(struct ptp_ocp_serial_port) {
.baud = 115200, .baud = 115200,
...@@ -1649,6 +1655,15 @@ ptp_ocp_tod_gnss_name(int idx) ...@@ -1649,6 +1655,15 @@ ptp_ocp_tod_gnss_name(int idx)
return gnss_name[idx]; return gnss_name[idx];
} }
static const char *
ptp_ocp_tty_port_name(int idx)
{
static const char * const tty_name[] = {
"GNSS", "GNSS2", "MAC", "NMEA"
};
return tty_name[idx];
}
struct ptp_ocp_nvmem_match_info { struct ptp_ocp_nvmem_match_info {
struct ptp_ocp *bp; struct ptp_ocp *bp;
const void * const tag; const void * const tag;
...@@ -3346,6 +3361,54 @@ static EXT_ATTR_RO(freq, frequency, 1); ...@@ -3346,6 +3361,54 @@ static EXT_ATTR_RO(freq, frequency, 1);
static EXT_ATTR_RO(freq, frequency, 2); static EXT_ATTR_RO(freq, frequency, 2);
static EXT_ATTR_RO(freq, frequency, 3); static EXT_ATTR_RO(freq, frequency, 3);
static ssize_t
ptp_ocp_tty_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dev_ext_attribute *ea = to_ext_attr(attr);
struct ptp_ocp *bp = dev_get_drvdata(dev);
return sysfs_emit(buf, "ttyS%d", bp->port[(uintptr_t)ea->var].line);
}
static umode_t
ptp_ocp_timecard_tty_is_visible(struct kobject *kobj, struct attribute *attr, int n)
{
struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
struct ptp_ocp_serial_port *port;
struct device_attribute *dattr;
struct dev_ext_attribute *ea;
if (strncmp(attr->name, "tty", 3))
return attr->mode;
dattr = container_of(attr, struct device_attribute, attr);
ea = container_of(dattr, struct dev_ext_attribute, attr);
port = &bp->port[(uintptr_t)ea->var];
return port->line == -1 ? 0 : 0444;
}
#define EXT_TTY_ATTR_RO(_name, _val) \
struct dev_ext_attribute dev_attr_tty##_name = \
{ __ATTR(tty##_name, 0444, ptp_ocp_tty_show, NULL), (void *)_val }
static EXT_TTY_ATTR_RO(GNSS, PORT_GNSS);
static EXT_TTY_ATTR_RO(GNSS2, PORT_GNSS2);
static EXT_TTY_ATTR_RO(MAC, PORT_MAC);
static EXT_TTY_ATTR_RO(NMEA, PORT_NMEA);
static struct attribute *ptp_ocp_timecard_tty_attrs[] = {
&dev_attr_ttyGNSS.attr.attr,
&dev_attr_ttyGNSS2.attr.attr,
&dev_attr_ttyMAC.attr.attr,
&dev_attr_ttyNMEA.attr.attr,
NULL,
};
static const struct attribute_group ptp_ocp_timecard_tty_group = {
.name = "tty",
.attrs = ptp_ocp_timecard_tty_attrs,
.is_visible = ptp_ocp_timecard_tty_is_visible,
};
static ssize_t static ssize_t
serialnum_show(struct device *dev, struct device_attribute *attr, char *buf) serialnum_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
...@@ -3775,6 +3838,7 @@ static const struct attribute_group fb_timecard_group = { ...@@ -3775,6 +3838,7 @@ static const struct attribute_group fb_timecard_group = {
static const struct ocp_attr_group fb_timecard_groups[] = { static const struct ocp_attr_group fb_timecard_groups[] = {
{ .cap = OCP_CAP_BASIC, .group = &fb_timecard_group }, { .cap = OCP_CAP_BASIC, .group = &fb_timecard_group },
{ .cap = OCP_CAP_BASIC, .group = &ptp_ocp_timecard_tty_group },
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group }, { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group },
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal1_group }, { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal1_group },
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal2_group }, { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal2_group },
...@@ -3814,6 +3878,7 @@ static const struct attribute_group art_timecard_group = { ...@@ -3814,6 +3878,7 @@ static const struct attribute_group art_timecard_group = {
static const struct ocp_attr_group art_timecard_groups[] = { static const struct ocp_attr_group art_timecard_groups[] = {
{ .cap = OCP_CAP_BASIC, .group = &art_timecard_group }, { .cap = OCP_CAP_BASIC, .group = &art_timecard_group },
{ .cap = OCP_CAP_BASIC, .group = &ptp_ocp_timecard_tty_group },
{ }, { },
}; };
...@@ -3841,6 +3906,7 @@ static const struct attribute_group adva_timecard_group = { ...@@ -3841,6 +3906,7 @@ static const struct attribute_group adva_timecard_group = {
static const struct ocp_attr_group adva_timecard_groups[] = { static const struct ocp_attr_group adva_timecard_groups[] = {
{ .cap = OCP_CAP_BASIC, .group = &adva_timecard_group }, { .cap = OCP_CAP_BASIC, .group = &adva_timecard_group },
{ .cap = OCP_CAP_BASIC, .group = &ptp_ocp_timecard_tty_group },
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group }, { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal0_group },
{ .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal1_group }, { .cap = OCP_CAP_SIGNAL, .group = &fb_timecard_signal1_group },
{ .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq0_group }, { .cap = OCP_CAP_FREQ, .group = &fb_timecard_freq0_group },
...@@ -3960,16 +4026,11 @@ ptp_ocp_summary_show(struct seq_file *s, void *data) ...@@ -3960,16 +4026,11 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
bp = dev_get_drvdata(dev); bp = dev_get_drvdata(dev);
seq_printf(s, "%7s: /dev/ptp%d\n", "PTP", ptp_clock_index(bp->ptp)); seq_printf(s, "%7s: /dev/ptp%d\n", "PTP", ptp_clock_index(bp->ptp));
if (bp->gnss_port.line != -1) for (i = 0; i < __PORT_COUNT; i++) {
seq_printf(s, "%7s: /dev/ttyS%d\n", "GNSS1", if (bp->port[i].line != -1)
bp->gnss_port.line); seq_printf(s, "%7s: /dev/ttyS%d\n", ptp_ocp_tty_port_name(i),
if (bp->gnss2_port.line != -1) bp->port[i].line);
seq_printf(s, "%7s: /dev/ttyS%d\n", "GNSS2", }
bp->gnss2_port.line);
if (bp->mac_port.line != -1)
seq_printf(s, "%7s: /dev/ttyS%d\n", "MAC", bp->mac_port.line);
if (bp->nmea_port.line != -1)
seq_printf(s, "%7s: /dev/ttyS%d\n", "NMEA", bp->nmea_port.line);
memset(sma_val, 0xff, sizeof(sma_val)); memset(sma_val, 0xff, sizeof(sma_val));
if (bp->sma_map1) { if (bp->sma_map1) {
...@@ -4279,7 +4340,7 @@ ptp_ocp_dev_release(struct device *dev) ...@@ -4279,7 +4340,7 @@ ptp_ocp_dev_release(struct device *dev)
static int static int
ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
{ {
int err; int i, err;
mutex_lock(&ptp_ocp_lock); mutex_lock(&ptp_ocp_lock);
err = idr_alloc(&ptp_ocp_idr, bp, 0, 0, GFP_KERNEL); err = idr_alloc(&ptp_ocp_idr, bp, 0, 0, GFP_KERNEL);
...@@ -4292,10 +4353,10 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) ...@@ -4292,10 +4353,10 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
bp->ptp_info = ptp_ocp_clock_info; bp->ptp_info = ptp_ocp_clock_info;
spin_lock_init(&bp->lock); spin_lock_init(&bp->lock);
bp->gnss_port.line = -1;
bp->gnss2_port.line = -1; for (i = 0; i < __PORT_COUNT; i++)
bp->mac_port.line = -1; bp->port[i].line = -1;
bp->nmea_port.line = -1;
bp->pdev = pdev; bp->pdev = pdev;
device_initialize(&bp->dev); device_initialize(&bp->dev);
...@@ -4352,22 +4413,6 @@ ptp_ocp_complete(struct ptp_ocp *bp) ...@@ -4352,22 +4413,6 @@ ptp_ocp_complete(struct ptp_ocp *bp)
struct pps_device *pps; struct pps_device *pps;
char buf[32]; char buf[32];
if (bp->gnss_port.line != -1) {
sprintf(buf, "ttyS%d", bp->gnss_port.line);
ptp_ocp_link_child(bp, buf, "ttyGNSS");
}
if (bp->gnss2_port.line != -1) {
sprintf(buf, "ttyS%d", bp->gnss2_port.line);
ptp_ocp_link_child(bp, buf, "ttyGNSS2");
}
if (bp->mac_port.line != -1) {
sprintf(buf, "ttyS%d", bp->mac_port.line);
ptp_ocp_link_child(bp, buf, "ttyMAC");
}
if (bp->nmea_port.line != -1) {
sprintf(buf, "ttyS%d", bp->nmea_port.line);
ptp_ocp_link_child(bp, buf, "ttyNMEA");
}
sprintf(buf, "ptp%d", ptp_clock_index(bp->ptp)); sprintf(buf, "ptp%d", ptp_clock_index(bp->ptp));
ptp_ocp_link_child(bp, buf, "ptp"); ptp_ocp_link_child(bp, buf, "ptp");
...@@ -4416,23 +4461,20 @@ ptp_ocp_info(struct ptp_ocp *bp) ...@@ -4416,23 +4461,20 @@ ptp_ocp_info(struct ptp_ocp *bp)
}; };
struct device *dev = &bp->pdev->dev; struct device *dev = &bp->pdev->dev;
u32 reg; u32 reg;
int i;
ptp_ocp_phc_info(bp); ptp_ocp_phc_info(bp);
ptp_ocp_serial_info(dev, "GNSS", bp->gnss_port.line, for (i = 0; i < __PORT_COUNT; i++) {
bp->gnss_port.baud); if (i == PORT_NMEA && bp->nmea_out && bp->port[PORT_NMEA].line != -1) {
ptp_ocp_serial_info(dev, "GNSS2", bp->gnss2_port.line, bp->port[PORT_NMEA].baud = -1;
bp->gnss2_port.baud);
ptp_ocp_serial_info(dev, "MAC", bp->mac_port.line, bp->mac_port.baud);
if (bp->nmea_out && bp->nmea_port.line != -1) {
bp->nmea_port.baud = -1;
reg = ioread32(&bp->nmea_out->uart_baud); reg = ioread32(&bp->nmea_out->uart_baud);
if (reg < ARRAY_SIZE(nmea_baud)) if (reg < ARRAY_SIZE(nmea_baud))
bp->nmea_port.baud = nmea_baud[reg]; bp->port[PORT_NMEA].baud = nmea_baud[reg];
}
ptp_ocp_serial_info(dev, "NMEA", bp->nmea_port.line, ptp_ocp_serial_info(dev, ptp_ocp_tty_port_name(i), bp->port[i].line,
bp->nmea_port.baud); bp->port[i].baud);
} }
} }
...@@ -4441,9 +4483,6 @@ ptp_ocp_detach_sysfs(struct ptp_ocp *bp) ...@@ -4441,9 +4483,6 @@ ptp_ocp_detach_sysfs(struct ptp_ocp *bp)
{ {
struct device *dev = &bp->dev; struct device *dev = &bp->dev;
sysfs_remove_link(&dev->kobj, "ttyGNSS");
sysfs_remove_link(&dev->kobj, "ttyGNSS2");
sysfs_remove_link(&dev->kobj, "ttyMAC");
sysfs_remove_link(&dev->kobj, "ptp"); sysfs_remove_link(&dev->kobj, "ptp");
sysfs_remove_link(&dev->kobj, "pps"); sysfs_remove_link(&dev->kobj, "pps");
} }
...@@ -4473,14 +4512,9 @@ ptp_ocp_detach(struct ptp_ocp *bp) ...@@ -4473,14 +4512,9 @@ ptp_ocp_detach(struct ptp_ocp *bp)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
if (bp->signal_out[i]) if (bp->signal_out[i])
ptp_ocp_unregister_ext(bp->signal_out[i]); ptp_ocp_unregister_ext(bp->signal_out[i]);
if (bp->gnss_port.line != -1) for (i = 0; i < __PORT_COUNT; i++)
serial8250_unregister_port(bp->gnss_port.line); if (bp->port[i].line != -1)
if (bp->gnss2_port.line != -1) serial8250_unregister_port(bp->port[i].line);
serial8250_unregister_port(bp->gnss2_port.line);
if (bp->mac_port.line != -1)
serial8250_unregister_port(bp->mac_port.line);
if (bp->nmea_port.line != -1)
serial8250_unregister_port(bp->nmea_port.line);
platform_device_unregister(bp->spi_flash); platform_device_unregister(bp->spi_flash);
platform_device_unregister(bp->i2c_ctrl); platform_device_unregister(bp->i2c_ctrl);
if (bp->i2c_clk) if (bp->i2c_clk)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment