Re: [PATCH v4 tty-next 1/3] 8250: microchip: pci1xxxx: Add driver for quad-uart support.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Nov 11, 2022 at 09:41:28PM +0530, Kumaravel Thiagarajan wrote:
> pci1xxxx is a PCIe switch with a multi-function endpoint on one of
> its downstream ports. Quad-uart is one of the functions in the
> multi-function endpoint. This driver loads for the quad-uart and
> enumerates single or multiple instances of uart based on the PCIe
> subsystem device ID.

> Signed-off-by: Tharun Kumar P <tharunkumar.pasumarthi@xxxxxxxxxxxxx>
> Signed-off-by: Kumaravel Thiagarajan <kumaravel.thiagarajan@xxxxxxxxxxxxx>

Are you submitter only and not a co-developer?

...

> +MICROCHIP PCIe UART DRIVER
> +M:	Kumaravel Thiagarajan <kumaravel.thiagarajan@xxxxxxxxxxxxx>
> +M:	Tharun Kumar P <tharunkumar.pasumarthi@xxxxxxxxxxxxx>
> +L:	linux-serial@xxxxxxxxxxxxxxx
> +S:	Maintained
> +F:	drivers/tty/serial/8250/8250_pci1xxxx.c

Have you checked if 8250_pcilib.c needs to be added to the MAINTAINERS?
That's why it's better to split that change from this patch.

...

> +#include <asm/byteorder.h>

asm/* are usually going after linux/*...

> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/serial_core.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/units.h>
> +#include <linux/tty.h>

...like here (as a separate group).

> +#include "8250.h"
> +#include "8250_pcilib.h"

...

> +#define PCI_DEVICE_ID_EFAR_PCI12000 0xa002
> +#define PCI_DEVICE_ID_EFAR_PCI11010 0xa012
> +#define PCI_DEVICE_ID_EFAR_PCI11101 0xa022
> +#define PCI_DEVICE_ID_EFAR_PCI11400 0xa032
> +#define PCI_DEVICE_ID_EFAR_PCI11414 0xa042
> +
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_4p 0x0001
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p012 0x0002
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013 0x0003
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023 0x0004
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123 0x0005
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p01 0x0006
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02 0x0007
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03 0x0008
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12 0x0009
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13 0x000a
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23 0x000b
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p0 0x000c
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1 0x000d
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2 0x000e
> +#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3 0x000f
> +
> +#define PCI_SUBDEVICE_ID_EFAR_PCI12000 0xa002
> +#define PCI_SUBDEVICE_ID_EFAR_PCI11010 0xa012
> +#define PCI_SUBDEVICE_ID_EFAR_PCI11101 0xa022
> +#define PCI_SUBDEVICE_ID_EFAR_PCI11400 0xa032
> +#define PCI_SUBDEVICE_ID_EFAR_PCI11414 0xa042

With TAB delimiter(s) the values would be easier to read / parse.
Ditto for the rest.

...

> +#define UART_WAKE_SRCS (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT)

With above in mind this can be written as

#define UART_WAKE_SRCS	\
	UART_WAKE_SRCS (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT)

...

> +	switch (dev->subsystem_device) {
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p01:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23:
> +		return 2;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p012:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023:
> +		return 3;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_4p:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI11414:
> +		return 4;

> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p0:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3:
> +	default:
> +		return 1;

You can put this block the first one, so they will be ordered by the returned
value.

> +	}

...

> +	switch (priv->dev->subsystem_device) {
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123:
> +		first_offset = 256;
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23:
> +		first_offset = 512;
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3:
> +		first_offset = 768;
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023:
> +		if (idx > 0)
> +			idx++;
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03:
> +		if (idx > 0)
> +			idx += 2;
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13:
> +		first_offset = 256;
> +		if (idx > 0)
> +			idx++;
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013:
> +		if (idx > 1)
> +			idx++;
> +		break;
> +	default:
> +		first_offset = 0;
> +		break;
> +	}

I would split this to two switch-cases, one for idx, one for first_offset.

...

> +	switch (priv->dev->subsystem_device) {
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1:

> +		uart->port.irq = pci_irq_vector(priv->dev, 1);

This can be deduplicated by assigning irq_idx in the switch and maybe using idx
when it's not assigned (like -1).

> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2:
> +		uart->port.irq = pci_irq_vector(priv->dev, 2);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3:
> +		uart->port.irq = pci_irq_vector(priv->dev, 3);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p01:
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02:
> +		if (idx > 0)
> +			idx++;
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03:
> +		if (idx > 0)
> +			idx += 2;
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12:
> +		uart->port.irq = pci_irq_vector(priv->dev, idx + 1);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13:
> +		if (idx > 0)
> +			idx += 1;
> +		uart->port.irq = pci_irq_vector(priv->dev, idx + 1);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23:
> +		uart->port.irq = pci_irq_vector(priv->dev, idx + 2);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p012:
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013:
> +		if (idx > 1)
> +			idx++;
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023:
> +		if (idx > 0)
> +			idx++;
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123:
> +		uart->port.irq = pci_irq_vector(priv->dev, idx + 1);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_4p:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI11414:
> +		uart->port.irq = pci_irq_vector(priv->dev, idx);
> +		break;
> +	case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p0:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI12000:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI11010:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI11101:
> +	case PCI_SUBDEVICE_ID_EFAR_PCI11400:
> +	default:
> +		uart->port.irq = pci_irq_vector(priv->dev, 0);
> +		break;
> +	}

...

> +static int pci1xxxx_serial_probe(struct pci_dev *dev,
> +				 const struct pci_device_id *ent)

You can replace ent by id as it's more usual for this parameter.

> +{
> +	unsigned int nr_ports, i, j;
> +	struct pci1xxxx_8250 *priv;
> +	struct uart_8250_port uart;

> +	int num_vectors = 0;

Why do you need this assignment?

> +	int rc;
> +
> +	rc = pcim_enable_device(dev);
> +	if (rc)
> +		return rc;
> +
> +	nr_ports = pci1xxxx_get_num_ports(dev);
> +
> +	priv = devm_kzalloc(&dev->dev, struct_size(priv, line, nr_ports),
> +			    GFP_KERNEL);

You can place it on one line, but even better all these will look when you use
pdev for PCI device (parameter to this function) and define a temporary
variable

	struct device *dev = &pdev->dev;

> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->membase = pcim_iomap(dev, 0, 0);
> +	priv->dev = dev;
> +	priv->nr = nr_ports;
> +	pci_set_master(dev);
> +
> +	num_vectors = pci_alloc_irq_vectors(dev, 1, 4, PCI_IRQ_ALL_TYPES);
> +	if (num_vectors < 0)
> +		return num_vectors;
> +
> +	memset(&uart, 0, sizeof(uart));
> +	uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT;
> +	uart.port.uartclk = UART_CLOCK_DEFAULT;
> +	uart.port.dev = &dev->dev;
> +
> +	if (num_vectors == 4)
> +		writeb(UART_PCI_CTRL_SET_MULTIPLE_MSI,
> +		       priv->membase + UART_PCI_CTRL_REG);
> +	else
> +		uart.port.irq = pci_irq_vector(dev, 0);
> +
> +	for (i = 0; i < nr_ports; i++) {
> +		if (num_vectors == 4)
> +			pci1xxxx_irq_assign(priv, &uart, i);

> +		priv->line[i] = -ENOSPC;

Why do you need this?

> +		rc = pci1xxxx_setup(priv, &uart, i);
> +		if (rc) {
> +			dev_err(&dev->dev, "Failed to setup port %u\n", i);
> +			break;

It's not an error? Perhaps dev_warn()? Ditto for the below.

> +		}

> +		priv->line[i] = serial8250_register_8250_port(&uart);

> +

This blank line is in a wrong place, should be after conditional.

> +		if (priv->line[i] < 0) {

> +			for (j = i + 1; j < nr_ports; j++)
> +				priv->line[j] = -ENOSPC;

Instead, you may once assign this to all beforehand:

	memset32(prov->line, -ENOSPC, nr_ports);

> +			dev_err(&dev->dev,
> +				"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
> +				uart.port.iobase, uart.port.irq,
> +				uart.port.iotype, priv->line[i]);
> +			break;
> +		}
> +	}
> +
> +	pci_set_drvdata(dev, priv);
> +
> +	return 0;
> +}

...

> +static struct pci_driver pci1xxxx_pci_driver = {
> +	.name = "pci1xxxx serial",
> +	.probe = pci1xxxx_serial_probe,
> +	.remove = pci1xxxx_serial_remove,
> +	.id_table = pci1xxxx_pci_tbl,
> +};

> +

Redundant blank line.

> +module_pci_driver(pci1xxxx_pci_driver);

...

> +++ b/drivers/tty/serial/8250/8250_pcilib.c

Yeah, please split this to a separate change, with the changes in 8250_pci.c.

> +#include <linux/pci.h>

Missing errno.h.
Missing ioport.h.
Missing types.h.

+ Blank line.

> +#include "8250.h"

...

> +++ b/drivers/tty/serial/8250/8250_pcilib.h
> @@ -0,0 +1,5 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Microchip pci1xxxx 8250 library header file. */

Microchip?! I thought you have fixed this.
Another point why this change should be separated.

-- 
With Best Regards,
Andy Shevchenko





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux