From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtpcmd15177.aruba.it (smtpcmd15177.aruba.it [62.149.156.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16D742594BD for ; Fri, 19 Dec 2025 13:52:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=62.149.156.177 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766152334; cv=none; b=LS9adVxyrOt6UN5p7CW8fPHPoY1HUcJl73Q0jlC/JgwvX9n6ry9Mos4LA3lTpLla4IxWu2EJLG4RcWgF8i+2FwB16b1oOOYrBzUVmAAkAnwf3F8Tw2TshTWuKkFJyYDknOPZspFKOPens1xoc4DKCmzKaM2YY8CR2xVAqvO2P8E= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766152334; c=relaxed/simple; bh=mqn28SsATiSf6UVadu8K6UN1SU2l7HBwO5hv5OiMaS0=; h=Message-ID:Date:MIME-Version:Subject:To:References:From: In-Reply-To:Content-Type; b=cyeUvKHruoIVTrZ6m6Qb8j0Waneo4JpvYikdekgRGztX4noQw3W7CoWg9s9/5A7CsEE0bZzho/PYFON3geWRsaIFFGUEAwQ7cbQm1R3C0e0Ad/X0sl4Ctb/4baVlxhVuke9K4BjjhDHFiFFpxDkn+3+UIhEsHWCqfeS27U525Qo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=enneenne.com; spf=pass smtp.mailfrom=enneenne.com; dkim=pass (2048-bit key) header.d=aruba.it header.i=@aruba.it header.b=KLllHTDo; arc=none smtp.client-ip=62.149.156.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=enneenne.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=enneenne.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=aruba.it header.i=@aruba.it header.b="KLllHTDo" Received: from [192.168.1.57] ([79.0.204.227]) by Aruba SMTP with ESMTPSA id WaqqvsRBawf0DWaqrvhtVU; Fri, 19 Dec 2025 14:49:01 +0100 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=aruba.it; s=a1; t=1766152141; bh=mqn28SsATiSf6UVadu8K6UN1SU2l7HBwO5hv5OiMaS0=; h=Date:MIME-Version:Subject:To:From:Content-Type; b=KLllHTDoZQkjCeopcZ2PltNwqKgMxsCAFFxUTgrsaqPhvFUxyUyjAqcrcj+Ba515S 7dpvVY4LhjoLAZ4VZoT6QmPEnX2UdmSgdoWhnvcbx8X4DCJz/yVira/dzuqosIXzak I1wBcMS0YjMxNYKt/x2ekvZuVd/Wz2Xi8pGc1V5r7Dwft3euIOMK5qyV3dPm9qf34p eSnW8wmoosu093tCD/wK/KxYQdDWDJPr8Npz/2K+qRM0QzX+BfXX8eO49o76ST5PA2 OBLUdbKqXqtvsxNOF0pkaVceo+hlSEi/ZOfHVDYg6oyzqLYc6vtkmoTZA9qhmwqjHS 5xAQePvAui/sg== Message-ID: Date: Fri, 19 Dec 2025 14:49:00 +0100 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] pps: generators: remove broken pps_gen_parport driver To: Ethan Nelson-Moore , linux-kernel@vger.kernel.org References: <20251219031623.10957-1-enelsonmoore@gmail.com> From: Rodolfo Giometti Content-Language: en-US In-Reply-To: <20251219031623.10957-1-enelsonmoore@gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-CMAE-Envelope: MS4xfA4FUr1bj/y84MCcNI+VoVyydorcNmAMUpkGtSjyT7tkcbxauC76XrE/Ukhf05NQs7MTlQyefbue7njR7q6OwmxWWJmJKxAS07YoBBX+cc1FB5vEADMp cSQ94nvwZSjK/b/LQQPBiQGxlJaPKRRT2queg6A3lrOqN4aaY5UzFXV7V5F2bcjoP2gmDLEorkLT+VpLctFgn1gLl29B+ONAn3b6CXPfG4lR08OLY7apF3bL On 19/12/25 04:16, Ethan Nelson-Moore wrote: > This driver was introduced in January 2011 and has been marked > BROKEN for almost its entire existence (since commit > 95b90afec301f050f72740e8696f7cce8a37db5a in March 2011). > It is unlikely anyone will fix the driver at this point. > > Signed-off-by: Ethan Nelson-Moore Acked-by: Rodolfo Giometti > --- > drivers/pps/generators/Kconfig | 8 - > drivers/pps/generators/Makefile | 1 - > drivers/pps/generators/pps_gen_parport.c | 238 ----------------------- > 3 files changed, 247 deletions(-) > delete mode 100644 drivers/pps/generators/pps_gen_parport.c > > diff --git a/drivers/pps/generators/Kconfig b/drivers/pps/generators/Kconfig > index b3f340ed3163..4ef02b3f2576 100644 > --- a/drivers/pps/generators/Kconfig > +++ b/drivers/pps/generators/Kconfig > @@ -23,14 +23,6 @@ config PPS_GENERATOR_DUMMY > This driver can also be built as a module. If so, the module > will be called pps_gen-dummy. > > -config PPS_GENERATOR_PARPORT > - tristate "Parallel port PPS signal generator" > - depends on PARPORT && BROKEN > - help > - If you say yes here you get support for a PPS signal generator which > - utilizes STROBE pin of a parallel port to send PPS signals. It uses > - parport abstraction layer and hrtimers to precisely control the signal. > - > config PPS_GENERATOR_TIO > tristate "TIO PPS signal generator" > depends on X86 && CPU_SUP_INTEL > diff --git a/drivers/pps/generators/Makefile b/drivers/pps/generators/Makefile > index e109920e8a2d..5d38774b4a56 100644 > --- a/drivers/pps/generators/Makefile > +++ b/drivers/pps/generators/Makefile > @@ -7,7 +7,6 @@ pps_gen_core-y := pps_gen.o sysfs.o > obj-$(CONFIG_PPS_GENERATOR) := pps_gen_core.o > > obj-$(CONFIG_PPS_GENERATOR_DUMMY) += pps_gen-dummy.o > -obj-$(CONFIG_PPS_GENERATOR_PARPORT) += pps_gen_parport.o > obj-$(CONFIG_PPS_GENERATOR_TIO) += pps_gen_tio.o > > ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG > diff --git a/drivers/pps/generators/pps_gen_parport.c b/drivers/pps/generators/pps_gen_parport.c > deleted file mode 100644 > index 05bbf8d30ef1..000000000000 > --- a/drivers/pps/generators/pps_gen_parport.c > +++ /dev/null > @@ -1,238 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-or-later > -/* > - * pps_gen_parport.c -- kernel parallel port PPS signal generator > - * > - * Copyright (C) 2009 Alexander Gordeev > - */ > - > - > -/* > - * TODO: > - * fix issues when realtime clock is adjusted in a leap > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > - > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define SIGNAL 0 > -#define NO_SIGNAL PARPORT_CONTROL_STROBE > - > -/* module parameters */ > - > -#define SEND_DELAY_MAX 100000 > - > -static unsigned int send_delay = 30000; > -MODULE_PARM_DESC(delay, > - "Delay between setting and dropping the signal (ns)"); > -module_param_named(delay, send_delay, uint, 0); > - > - > -#define SAFETY_INTERVAL 3000 /* set the hrtimer earlier for safety (ns) */ > - > -/* internal per port structure */ > -struct pps_generator_pp { > - struct pardevice *pardev; /* parport device */ > - struct hrtimer timer; > - long port_write_time; /* calibrated port write time (ns) */ > -}; > - > -static struct pps_generator_pp device = { > - .pardev = NULL, > -}; > - > -static int attached; > - > -/* calibrated time between a hrtimer event and the reaction */ > -static long hrtimer_error = SAFETY_INTERVAL; > - > -/* the kernel hrtimer event */ > -static enum hrtimer_restart hrtimer_event(struct hrtimer *timer) > -{ > - struct timespec64 expire_time, ts1, ts2, ts3, dts; > - struct pps_generator_pp *dev; > - struct parport *port; > - long lim, delta; > - unsigned long flags; > - > - /* We have to disable interrupts here. The idea is to prevent > - * other interrupts on the same processor to introduce random > - * lags while polling the clock. ktime_get_real_ts64() takes <1us on > - * most machines while other interrupt handlers can take much > - * more potentially. > - * > - * NB: approx time with blocked interrupts = > - * send_delay + 3 * SAFETY_INTERVAL > - */ > - local_irq_save(flags); > - > - /* first of all we get the time stamp... */ > - ktime_get_real_ts64(&ts1); > - expire_time = ktime_to_timespec64(hrtimer_get_softexpires(timer)); > - dev = container_of(timer, struct pps_generator_pp, timer); > - lim = NSEC_PER_SEC - send_delay - dev->port_write_time; > - > - /* check if we are late */ > - if (expire_time.tv_sec != ts1.tv_sec || ts1.tv_nsec > lim) { > - local_irq_restore(flags); > - pr_err("we are late this time %ptSp\n", &ts1); > - goto done; > - } > - > - /* busy loop until the time is right for an assert edge */ > - do { > - ktime_get_real_ts64(&ts2); > - } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); > - > - /* set the signal */ > - port = dev->pardev->port; > - port->ops->write_control(port, SIGNAL); > - > - /* busy loop until the time is right for a clear edge */ > - lim = NSEC_PER_SEC - dev->port_write_time; > - do { > - ktime_get_real_ts64(&ts2); > - } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); > - > - /* unset the signal */ > - port->ops->write_control(port, NO_SIGNAL); > - > - ktime_get_real_ts64(&ts3); > - > - local_irq_restore(flags); > - > - /* update calibrated port write time */ > - dts = timespec64_sub(ts3, ts2); > - dev->port_write_time = > - (dev->port_write_time + timespec64_to_ns(&dts)) >> 1; > - > -done: > - /* update calibrated hrtimer error */ > - dts = timespec64_sub(ts1, expire_time); > - delta = timespec64_to_ns(&dts); > - /* If the new error value is bigger then the old, use the new > - * value, if not then slowly move towards the new value. This > - * way it should be safe in bad conditions and efficient in > - * good conditions. > - */ > - if (delta >= hrtimer_error) > - hrtimer_error = delta; > - else > - hrtimer_error = (3 * hrtimer_error + delta) >> 2; > - > - /* update the hrtimer expire time */ > - hrtimer_set_expires(timer, > - ktime_set(expire_time.tv_sec + 1, > - NSEC_PER_SEC - (send_delay + > - dev->port_write_time + SAFETY_INTERVAL + > - 2 * hrtimer_error))); > - > - return HRTIMER_RESTART; > -} > - > -/* calibrate port write time */ > -#define PORT_NTESTS_SHIFT 5 > -static void calibrate_port(struct pps_generator_pp *dev) > -{ > - struct parport *port = dev->pardev->port; > - int i; > - long acc = 0; > - > - for (i = 0; i < (1 << PORT_NTESTS_SHIFT); i++) { > - struct timespec64 a, b; > - unsigned long irq_flags; > - > - local_irq_save(irq_flags); > - ktime_get_real_ts64(&a); > - port->ops->write_control(port, NO_SIGNAL); > - ktime_get_real_ts64(&b); > - local_irq_restore(irq_flags); > - > - b = timespec64_sub(b, a); > - acc += timespec64_to_ns(&b); > - } > - > - dev->port_write_time = acc >> PORT_NTESTS_SHIFT; > - pr_info("port write takes %ldns\n", dev->port_write_time); > -} > - > -static inline ktime_t next_intr_time(struct pps_generator_pp *dev) > -{ > - struct timespec64 ts; > - > - ktime_get_real_ts64(&ts); > - > - return ktime_set(ts.tv_sec + > - ((ts.tv_nsec > 990 * NSEC_PER_MSEC) ? 1 : 0), > - NSEC_PER_SEC - (send_delay + > - dev->port_write_time + 3 * SAFETY_INTERVAL)); > -} > - > -static void parport_attach(struct parport *port) > -{ > - struct pardev_cb pps_cb; > - > - if (send_delay > SEND_DELAY_MAX) { > - pr_err("delay value should be not greater then %d\n", SEND_DELAY_MAX); > - return; > - } > - > - if (attached) { > - /* we already have a port */ > - return; > - } > - > - memset(&pps_cb, 0, sizeof(pps_cb)); > - pps_cb.private = &device; > - pps_cb.flags = PARPORT_FLAG_EXCL; > - device.pardev = parport_register_dev_model(port, KBUILD_MODNAME, > - &pps_cb, 0); > - if (!device.pardev) { > - pr_err("couldn't register with %s\n", port->name); > - return; > - } > - > - if (parport_claim_or_block(device.pardev) < 0) { > - pr_err("couldn't claim %s\n", port->name); > - goto err_unregister_dev; > - } > - > - pr_info("attached to %s\n", port->name); > - attached = 1; > - > - calibrate_port(&device); > - > - hrtimer_setup(&device.timer, hrtimer_event, CLOCK_REALTIME, HRTIMER_MODE_ABS); > - hrtimer_start(&device.timer, next_intr_time(&device), HRTIMER_MODE_ABS); > - > - return; > - > -err_unregister_dev: > - parport_unregister_device(device.pardev); > -} > - > -static void parport_detach(struct parport *port) > -{ > - if (port->cad != device.pardev) > - return; /* not our port */ > - > - hrtimer_cancel(&device.timer); > - parport_release(device.pardev); > - parport_unregister_device(device.pardev); > -} > - > -static struct parport_driver pps_gen_parport_driver = { > - .name = KBUILD_MODNAME, > - .match_port = parport_attach, > - .detach = parport_detach, > -}; > -module_parport_driver(pps_gen_parport_driver); > - > -MODULE_AUTHOR("Alexander Gordeev "); > -MODULE_DESCRIPTION("parallel port PPS signal generator"); > -MODULE_LICENSE("GPL"); -- GNU/Linux Solutions e-mail: giometti@enneenne.com Linux Device Driver giometti@linux.it Embedded Systems phone: +39 349 2432127 UNIX programming