[PATCH] UART: add CSR SiRFprimaII SoC on-chip uart drivers

Alan Cox alan at linux.intel.com
Thu Oct 13 05:55:56 EDT 2011


Looks basically ok but somewhat outdated for the tty layer. In
particular it needs to be aware of the refcounting on tty objects and
of the fact we allow arbitary baud rate handling

> +static struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = {

const

> +static unsigned int
> +sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int
> max_rx_count) +{
> +	unsigned int ch, rx_count = 0;
> +	int temp;
> +	struct tty_struct *tty = port->state->port.tty;

tty = tty_port_tty_get(&port->state->port);

[the newer tty code is refcounting, also tty can be NULL here and needs
h handling accordingly]

> +	while (!(rd_regl(port, SIRFUART_RX_FIFO_STATUS) &
> +
> SIRFUART_FIFOEMPTY_MASK(port))) {
> +		temp =
> tty_buffer_request_room(port->state->port.tty, 1);
> +		if (unlikely(temp == 0)) {
> +			port->icount.buf_overrun++;
> +			break;
> +		}

You don't need to do this - just uart_insert_char. If we run out of mid
layer buffering it's not a port overrun as such (ie a fifo exceeded)
it's a system wide memory crunch and something pretty serious and
bigger is going on.

> +	port->icount.rx += rx_count;
> +	tty_flip_buffer_push(tty);

[Do these only if tty != NULL obviously)

and
	tty_kref_put(tty);



> +static void sirfsoc_uart_set_termios(struct uart_port *port,
> +				       struct ktermios *termios,
> +				       struct ktermios *old)
> +{

If you don't support CMSPAR then clear the bit in the passed termios.

> +	for (ic = 0; ic < SIRFUART_BAUD_RATE_SUPPORT_NR; ic++)
> +		if (baud_rate == baudrate_to_regv[ic].baud_rate)
> +			clk_div_reg = baudrate_to_regv[ic].reg_val;
> +	if (clk_div_reg == 0)
> +		pr_err("SiRF UART: Cannot set Baud Rate (9600 ~
> 4000000).\n");

The baud rate is not guaranteed to be one the Bxxxxx values, you should
be computing it not using a table.
Also the pr_err means any user can fill the logs with junk.

The correct behaviour here is

	compute the best timing for the baud rate requested
	compute the actual baud rate obtained

then report it back to the caller

	if (tty_termios_baud_rate(termios))
		tty_termios_encode_baud_rate(termios, baud. baud);

The above assuming you set the same input and output rate



> +static struct console sirfsoc_uart_console = {
> +	.name		= "ttyS",

ttyS is 8250 devces. Pick a new name for your own.

>
> +	.dev_name	= SIRFSOC_UART_NAME,
> +	.major		= SIRFSOC_UART_MAJOR,
> +	.minor		= SIRFSOC_UART_MINOR,

Use dynamic allocations


> +#define SIRFSOC_UART_NAME			"ttyS"
> +#define SIRFSOC_UART_MAJOR			TTY_MAJOR
> +#define SIRFSOC_UART_MINOR			64

These values belong to an existing inerface, don't reuse the names like
that, and please use dynamic allocation for the numbers

> +#define uart_tx_port_tty_invalid(port)   \
> +	(((port)->state == NULL) || ((port)->state->port.tty ==
> NULL)) 

This has no locking so little meaning - what guarantees it doesn't
change  under or after the call. I suspect you want to be checking and
referencing the tty in one shot as in the example I gave above for the
rx fix.




More information about the linux-arm-kernel mailing list