All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: Dan Raymond <draymond@foxvalley.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-serial <linux-serial@vger.kernel.org>
Subject: Re: [PATCH] tty/serial: create debugfs interface for UART register tracing
Date: Thu, 24 Aug 2023 15:13:48 +0300 (EEST)	[thread overview]
Message-ID: <7d437f22-277-de25-6296-97483fb81792@linux.intel.com> (raw)
In-Reply-To: <9d0ff4b7-2584-6003-a213-6de11f6513fa@foxvalley.net>

[-- Attachment #1: Type: text/plain, Size: 5136 bytes --]

On Thu, 24 Aug 2023, Dan Raymond wrote:
> On 8/23/2023 2:30 AM, Ilpo Järvinen wrote:
> 
> > Thanks, looks useful (although it might have challenge in tracing hw
> > during early init).
> 
> I suppose there would need to be a mechanism to enable tracing by default
> (kernel cmd line?)  Is the UART driver even used very early in the boot
> process?

I mainly meant the time when the driver is initialized, when moving from 
univ8250 -> the actual 8250 driver for the particular HW. It's one of the 
points of interest.

I don't know if the tracing side has something more "standard" for this 
already and since you're looking to that already, it's good to take 
notice if there's something.

> > > +struct reg_event {
> > > +	uint32_t  cycle_lo;  /* CPU cycle count (lower 32-bits) */
> > > +	uint16_t  cycle_hi;  /* CPU cycle count (upper 16-bits) */
> > > +	uint8_t   access;    /* write flag + register number */
> > > +	uint8_t   data;      /* register data */
> > Some HW-specific registers are larger than 8 bits.
> 
> Not for 8250/16550?

Some drivers for 8250 variants have such registers. Not that they're 
common so it's perhaps not a big deal.

> Currently this feature only supports those and it also
> relies on the TSC which is an x86 thing.

I wonder why you have to rely on that. Why e.g. ktime_get_boottime() is 
not enough for this usecase?

> > > +		ptr = uart_debug->line + uart_debug->offset;
> > > +		len = strlen(ptr);
> > Why you need to calculate length? Shouldn't queue_remove() be able to return
> > this information?
> 
> Yes, we can return the string length from queue_remove() but we still need to
> call strlen() to accommodate all code paths.  The user might call read() with
> a very small buffer and that requires us to advance ptr past the beginning of
> the string on subsequent calls.

I still find it hard to believe you could not keep track of it all 
without strlen(), snprintf() returns the number of chars it wrote to 
uart_debug->line so it should be that length - uart_debug->offset?

> > > +	static uint64_t cpu_freq;  /* cycles per second */
> > > +	uint32_t h, m, s, us;
> > > +
> > > +	if (cpu_freq == 0)
> > > +		cpu_freq = arch_freq_get_on_cpu(0) * 1000ULL;
> > > +
> > > +	s = div64_u64_rem(cpu_cycles, cpu_freq, &cpu_cycles);
> > > +	us = div64_u64(cpu_cycles * 1000 * 1000 + 500 * 1000, cpu_freq);
> > > +
> > > +	m = s / 60; s = s % 60;
> > > +	h = m / 60; m = m % 60;
> > > +
> > > +	snprintf(buf, size, "%02d:%02d:%02d.%06u", h, m, s, us);
> > seconds.us is enough. If some additional formatting is to happen, it
> > should be done in userspace.
> 
> I can see your point.  If the user does want to reformat this it will be
> easier to start with the format you suggested.  Is this a general rule for
> kernel space?

I don't know if there's a rule. But having had to parse those :: inputs 
way too many times in the past, I have very little love for that format 
being forced on user ;-).

> > > +static noinline void queue_free(struct uart_port *port, bool force)
> > > +{
> > > +	struct uart_debug *uart_debug = port->private_data;
> > > +	struct reg_queue *queue = &uart_debug->register_queue;
> > > +
> > > +	if (force || queue->read_idx == queue->write_idx) {
> > Why cannot the only place where force=true just reset the indexes before
> > making the call so no force parameter is required? ...I think there's a
> > bug anyway with the indexes not getting properly reset in that case.
> 
> Only the queue_xxx() functions read or write the queue structure.  The indices
> are reset below when we memset() the entire structure to 0.

Ah, I see.

> > > +		vfree(queue->buf);
> > > +		memset(queue, 0, sizeof(*queue));
> > > +	}
> > > ...
> > > +	} else if (num_events) {
> > > +		reg = event.access & 0x07;
> > > +		sym = event.access & 0x08 ? out_regs[reg] : in_regs[reg];
> > Some uarts have registers beyond 0x07 so this doesn't seem enough.
> > It would be nice if the driver could provide alternative set of names for
> > the registers.
> 
> I'll have to look into how difficult it would be to support other UARTs
> besides 8250/16550.
>
> > > +/*
> > > + *  Create the debugfs interface.  This should be called during port
> > > registration after
> > > + *  port->name, port->serial_in, and port->serial_out have been
> > > initialized.
> > > We are
> > > + *  using port->private_data to store a pointer to our data structure.
> > > That
> > > field appears
> > > + *  to be otherwise unused.  If this is wrong we will need to create a
> > > new
> > > field.
> > > + */
> > > +void uart_debug_create(struct uart_port *port)
> > > +{
> > > +	struct uart_debug *uart_debug;
> > > +	struct dentry *dir;
> > > +
> > > +	uart_debug = port->private_data = kzalloc(sizeof(struct uart_debug),
> > > GFP_KERNEL);
> > How about the drivers which use port->private_data?
> 
> It didn't look like this field was used.  Was I wrong about this?

~/linux/uart/drivers/tty/serial/8250$ git grep 'private_data =' | wc -l
20

There are multiple 8250 variant drivers using it.

Some also come with additional registers so it's all relevant also in 
serial/8250/ domain.


-- 
 i.

  reply	other threads:[~2023-08-24 12:14 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-22 20:50 [PATCH] tty/serial: create debugfs interface for UART register tracing Dan Raymond
2023-08-23  7:01 ` Greg KH
2023-08-24  6:22   ` Dan Raymond
2023-08-23  8:30 ` Ilpo Järvinen
2023-08-24  6:24   ` Dan Raymond
2023-08-24 12:13     ` Ilpo Järvinen [this message]
2023-08-24 21:18       ` Dan Raymond

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7d437f22-277-de25-6296-97483fb81792@linux.intel.com \
    --to=ilpo.jarvinen@linux.intel.com \
    --cc=draymond@foxvalley.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.