summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r--drivers/tty/serial/8250/8250_dw.c28
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.c10
-rw-r--r--drivers/tty/serial/8250/8250_dwlib.h1
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c8
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c9
-rw-r--r--drivers/tty/serial/8250/8250_pci.c143
-rw-r--r--drivers/tty/serial/8250/8250_pnp.c4
-rw-r--r--drivers/tty/serial/8250/8250_port.c31
-rw-r--r--drivers/tty/serial/8250/Kconfig2
9 files changed, 111 insertions, 125 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a3a0154da567..53f57c3b9f42 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -338,23 +338,16 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
rate = clk_round_rate(d->clk, newrate);
if (rate > 0) {
/*
- * Premilinary set the uartclk to the new clock rate so the
- * clock update event handler caused by the clk_set_rate()
- * calling wouldn't actually update the UART divisor since
- * we about to do this anyway.
+ * Note that any clock-notifer worker will block in
+ * serial8250_update_uartclk() until we are done.
*/
- swap(p->uartclk, rate);
ret = clk_set_rate(d->clk, newrate);
- if (ret)
- swap(p->uartclk, rate);
+ if (!ret)
+ p->uartclk = rate;
}
clk_prepare_enable(d->clk);
- p->status &= ~UPSTAT_AUTOCTS;
- if (termios->c_cflag & CRTSCTS)
- p->status |= UPSTAT_AUTOCTS;
-
- serial8250_do_set_termios(p, termios, old);
+ dw8250_do_set_termios(p, termios, old);
}
static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios)
@@ -393,8 +386,9 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
- if (p->dev->of_node) {
- struct device_node *np = p->dev->of_node;
+ struct device_node *np = p->dev->of_node;
+
+ if (np) {
int id;
/* get index of serial line, if found in DT aliases */
@@ -411,11 +405,13 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
data->skip_autocfg = true;
}
#endif
- if (of_device_is_big_endian(p->dev->of_node)) {
+
+ if (of_device_is_big_endian(np)) {
p->iotype = UPIO_MEM32BE;
p->serial_in = dw8250_serial_in32be;
p->serial_out = dw8250_serial_out32be;
}
+
if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
p->serial_out = dw8250_serial_out38x;
@@ -726,7 +722,7 @@ static struct platform_driver dw8250_platform_driver = {
.name = "dw-apb-uart",
.pm = &dw8250_pm_ops,
.of_match_table = dw8250_of_match,
- .acpi_match_table = ACPI_PTR(dw8250_acpi_match),
+ .acpi_match_table = dw8250_acpi_match,
},
.probe = dw8250_probe,
.remove = dw8250_remove,
diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c
index 6d6a78eead3e..622d3b0d89e7 100644
--- a/drivers/tty/serial/8250/8250_dwlib.c
+++ b/drivers/tty/serial/8250/8250_dwlib.c
@@ -77,6 +77,16 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
serial8250_do_set_divisor(p, baud, quot, quot_frac);
}
+void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old)
+{
+ p->status &= ~UPSTAT_AUTOCTS;
+ if (termios->c_cflag & CRTSCTS)
+ p->status |= UPSTAT_AUTOCTS;
+
+ serial8250_do_set_termios(p, termios, old);
+}
+EXPORT_SYMBOL_GPL(dw8250_do_set_termios);
+
void dw8250_setup_port(struct uart_port *p)
{
struct uart_8250_port *up = up_to_u8250p(p);
diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
index 9a12953832d3..83d528e5cc21 100644
--- a/drivers/tty/serial/8250/8250_dwlib.h
+++ b/drivers/tty/serial/8250/8250_dwlib.h
@@ -16,4 +16,5 @@ struct dw8250_port_data {
u8 dlf_size;
};
+void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);
void dw8250_setup_port(struct uart_port *p);
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index fc65a2293ce9..9c01c531349d 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -23,10 +23,6 @@
#include "8250.h"
-struct fsl8250_data {
- int line;
-};
-
int fsl8250_handle_irq(struct uart_port *port)
{
unsigned char lsr, orig_lsr;
@@ -90,6 +86,10 @@ int fsl8250_handle_irq(struct uart_port *port)
EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
#ifdef CONFIG_ACPI
+struct fsl8250_data {
+ int line;
+};
+
static int fsl8250_acpi_probe(struct platform_device *pdev)
{
struct fsl8250_data *data;
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 848d81e3838c..d3bafec7619d 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -100,11 +100,7 @@ static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
- p->status &= ~UPSTAT_AUTOCTS;
- if (termios->c_cflag & CRTSCTS)
- p->status |= UPSTAT_AUTOCTS;
-
- serial8250_do_set_termios(p, termios, old);
+ dw8250_do_set_termios(p, termios, old);
}
static unsigned int byt_get_mctrl(struct uart_port *port)
@@ -168,6 +164,9 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
* matching with the registered General Purpose DMA controllers.
*/
up->dma = dma;
+
+ port->set_termios = dw8250_do_set_termios;
+
return 0;
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 726912b16a55..5d43de143f33 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -75,13 +75,12 @@ static int pci_default_setup(struct serial_private*,
static void moan_device(const char *str, struct pci_dev *dev)
{
- dev_err(&dev->dev,
- "%s: %s\n"
+ pci_err(dev, "%s\n"
"Please send the output of lspci -vv, this\n"
"message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
"manufacturer and name of serial board or\n"
"modem board to <linux-serial@vger.kernel.org>.\n",
- pci_name(dev), str, dev->vendor, dev->device,
+ str, dev->vendor, dev->device,
dev->subsystem_vendor, dev->subsystem_device);
}
@@ -238,7 +237,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev)
/* is firmware started? */
pci_read_config_dword(dev, 0x44, &oldval);
if (oldval == 0x00001000L) { /* RESET value */
- dev_dbg(&dev->dev, "Local i960 firmware missing\n");
+ pci_dbg(dev, "Local i960 firmware missing\n");
return -ENODEV;
}
return 0;
@@ -515,7 +514,7 @@ static int pci_siig_init(struct pci_dev *dev)
if (type == 0x1000)
return pci_siig10x_init(dev);
- else if (type == 0x2000)
+ if (type == 0x2000)
return pci_siig20x_init(dev);
moan_device("Unknown SIIG card", dev);
@@ -588,9 +587,8 @@ static int pci_timedia_probe(struct pci_dev *dev)
* (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
*/
if ((dev->subsystem_device & 0x00f0) >= 0x70) {
- dev_info(&dev->dev,
- "ignoring Timedia subdevice %04x for parport_serial\n",
- dev->subsystem_device);
+ pci_info(dev, "ignoring Timedia subdevice %04x for parport_serial\n",
+ dev->subsystem_device);
return -ENODEV;
}
@@ -792,9 +790,9 @@ static int pci_netmos_9900_setup(struct serial_private *priv,
bar = 3 * idx;
return setup_port(priv, port, bar, 0, board->reg_shift);
- } else {
- return pci_default_setup(priv, board, port, idx);
}
+
+ return pci_default_setup(priv, board, port, idx);
}
/* the 99xx series comes with a range of device IDs and a variety
@@ -827,8 +825,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev)
if (sub_serports > 0)
return sub_serports;
- dev_err(&dev->dev,
- "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+ pci_err(dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
return 0;
}
@@ -897,18 +894,16 @@ static int pci_netmos_init(struct pci_dev *dev)
/* enable IO_Space bit */
#define ITE_887x_POSIO_ENABLE (1 << 31)
+/* inta_addr are the configuration addresses of the ITE */
+static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280 };
static int pci_ite887x_init(struct pci_dev *dev)
{
- /* inta_addr are the configuration addresses of the ITE */
- static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
- 0x200, 0x280, 0 };
int ret, i, type;
struct resource *iobase = NULL;
u32 miscr, uartbar, ioport;
/* search for the base-ioport */
- i = 0;
- while (inta_addr[i] && iobase == NULL) {
+ for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
"ite887x");
if (iobase != NULL) {
@@ -925,13 +920,11 @@ static int pci_ite887x_init(struct pci_dev *dev)
break;
}
release_region(iobase->start, ITE_887x_IOSIZE);
- iobase = NULL;
}
- i++;
}
- if (!inta_addr[i]) {
- dev_err(&dev->dev, "ite887x: could not find iobase\n");
+ if (i == ARRAY_SIZE(inta_addr)) {
+ pci_err(dev, "could not find iobase\n");
return -ENODEV;
}
@@ -1026,9 +1019,7 @@ static int pci_endrun_init(struct pci_dev *dev)
/* EndRun device */
if (deviceID == 0x07000200) {
number_uarts = ioread8(p + 4);
- dev_dbg(&dev->dev,
- "%d ports detected on EndRun PCI Express device\n",
- number_uarts);
+ pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
}
pci_iounmap(dev, p);
return number_uarts;
@@ -1058,9 +1049,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
/* Tornado device */
if (deviceID == 0x07000200) {
number_uarts = ioread8(p + 4);
- dev_dbg(&dev->dev,
- "%d ports detected on Oxford PCI Express device\n",
- number_uarts);
+ pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
}
pci_iounmap(dev, p);
return number_uarts;
@@ -1074,13 +1063,6 @@ static int pci_asix_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx);
}
-/* Quatech devices have their own extra interface features */
-
-struct quatech_feature {
- u16 devid;
- bool amcc;
-};
-
#define QPCR_TEST_FOR1 0x3F
#define QPCR_TEST_GET1 0x00
#define QPCR_TEST_FOR2 0x40
@@ -1096,42 +1078,30 @@ struct quatech_feature {
#define QOPR_CLOCK_X8 0x0003
#define QOPR_CLOCK_RATE_MASK 0x0003
-
-static struct quatech_feature quatech_cards[] = {
- { PCI_DEVICE_ID_QUATECH_QSC100, 1 },
- { PCI_DEVICE_ID_QUATECH_DSC100, 1 },
- { PCI_DEVICE_ID_QUATECH_DSC100E, 0 },
- { PCI_DEVICE_ID_QUATECH_DSC200, 1 },
- { PCI_DEVICE_ID_QUATECH_DSC200E, 0 },
- { PCI_DEVICE_ID_QUATECH_ESC100D, 1 },
- { PCI_DEVICE_ID_QUATECH_ESC100M, 1 },
- { PCI_DEVICE_ID_QUATECH_QSCP100, 1 },
- { PCI_DEVICE_ID_QUATECH_DSCP100, 1 },
- { PCI_DEVICE_ID_QUATECH_QSCP200, 1 },
- { PCI_DEVICE_ID_QUATECH_DSCP200, 1 },
- { PCI_DEVICE_ID_QUATECH_ESCLP100, 0 },
- { PCI_DEVICE_ID_QUATECH_QSCLP100, 0 },
- { PCI_DEVICE_ID_QUATECH_DSCLP100, 0 },
- { PCI_DEVICE_ID_QUATECH_SSCLP100, 0 },
- { PCI_DEVICE_ID_QUATECH_QSCLP200, 0 },
- { PCI_DEVICE_ID_QUATECH_DSCLP200, 0 },
- { PCI_DEVICE_ID_QUATECH_SSCLP200, 0 },
- { PCI_DEVICE_ID_QUATECH_SPPXP_100, 0 },
+/* Quatech devices have their own extra interface features */
+static struct pci_device_id quatech_cards[] = {
+ { PCI_DEVICE_DATA(QUATECH, QSC100, 1) },
+ { PCI_DEVICE_DATA(QUATECH, DSC100, 1) },
+ { PCI_DEVICE_DATA(QUATECH, DSC100E, 0) },
+ { PCI_DEVICE_DATA(QUATECH, DSC200, 1) },
+ { PCI_DEVICE_DATA(QUATECH, DSC200E, 0) },
+ { PCI_DEVICE_DATA(QUATECH, ESC100D, 1) },
+ { PCI_DEVICE_DATA(QUATECH, ESC100M, 1) },
+ { PCI_DEVICE_DATA(QUATECH, QSCP100, 1) },
+ { PCI_DEVICE_DATA(QUATECH, DSCP100, 1) },
+ { PCI_DEVICE_DATA(QUATECH, QSCP200, 1) },
+ { PCI_DEVICE_DATA(QUATECH, DSCP200, 1) },
+ { PCI_DEVICE_DATA(QUATECH, ESCLP100, 0) },
+ { PCI_DEVICE_DATA(QUATECH, QSCLP100, 0) },
+ { PCI_DEVICE_DATA(QUATECH, DSCLP100, 0) },
+ { PCI_DEVICE_DATA(QUATECH, SSCLP100, 0) },
+ { PCI_DEVICE_DATA(QUATECH, QSCLP200, 0) },
+ { PCI_DEVICE_DATA(QUATECH, DSCLP200, 0) },
+ { PCI_DEVICE_DATA(QUATECH, SSCLP200, 0) },
+ { PCI_DEVICE_DATA(QUATECH, SPPXP_100, 0) },
{ 0, }
};
-static int pci_quatech_amcc(u16 devid)
-{
- struct quatech_feature *qf = &quatech_cards[0];
- while (qf->devid) {
- if (qf->devid == devid)
- return qf->amcc;
- qf++;
- }
- pr_err("quatech: unknown port type '0x%04X'.\n", devid);
- return 0;
-};
-
static int pci_quatech_rqopr(struct uart_8250_port *port)
{
unsigned long base = port->port.iobase;
@@ -1291,7 +1261,16 @@ static int pci_quatech_rs422(struct uart_8250_port *port)
static int pci_quatech_init(struct pci_dev *dev)
{
- if (pci_quatech_amcc(dev->device)) {
+ const struct pci_device_id *match;
+ bool amcc = false;
+
+ match = pci_match_id(quatech_cards, dev);
+ if (match)
+ amcc = match->driver_data;
+ else
+ pci_err(dev, "unknown port type '0x%04X'.\n", dev->device);
+
+ if (amcc) {
unsigned long base = pci_resource_start(dev, 0);
if (base) {
u32 tmp;
@@ -1315,14 +1294,10 @@ static int pci_quatech_setup(struct serial_private *priv,
port->port.uartclk = pci_quatech_clock(port);
/* For now just warn about RS422 */
if (pci_quatech_rs422(port))
- pr_warn("quatech: software control of RS422 features not currently supported.\n");
+ pci_warn(priv->dev, "software control of RS422 features not currently supported.\n");
return pci_default_setup(priv, board, port, idx);
}
-static void pci_quatech_exit(struct pci_dev *dev)
-{
-}
-
static int pci_default_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@@ -1525,7 +1500,7 @@ static int pci_fintek_setup(struct serial_private *priv,
/* Get the io address from configuration space */
pci_read_config_word(pdev, config_base + 4, &iobase);
- dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase);
+ pci_dbg(pdev, "idx=%d iobase=0x%x", idx, iobase);
port->port.iotype = UPIO_PORT;
port->port.iobase = iobase;
@@ -1689,7 +1664,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
struct uart_8250_port *port, int idx)
{
port->port.quirks |= UPQ_NO_TXEN_TEST;
- dev_dbg(&priv->dev->dev,
+ pci_dbg(priv->dev,
"serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
priv->dev->vendor, priv->dev->device,
priv->dev->subsystem_vendor, priv->dev->subsystem_device);
@@ -2197,7 +2172,6 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.subdevice = PCI_ANY_ID,
.init = pci_quatech_init,
.setup = pci_quatech_setup,
- .exit = pci_quatech_exit,
},
/*
* Panacom
@@ -3981,9 +3955,7 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
nr_ports = rc;
}
- priv = kzalloc(sizeof(struct serial_private) +
- sizeof(unsigned int) * nr_ports,
- GFP_KERNEL);
+ priv = kzalloc(struct_size(priv, line, nr_ports), GFP_KERNEL);
if (!priv) {
priv = ERR_PTR(-ENOMEM);
goto err_deinit;
@@ -4000,12 +3972,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
uart.port.irq = 0;
} else {
if (pci_match_id(pci_use_msi, dev)) {
- dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
+ pci_dbg(dev, "Using MSI(-X) interrupts\n");
pci_set_master(dev);
uart.port.flags &= ~UPF_SHARE_IRQ;
rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
} else {
- dev_dbg(&dev->dev, "Using legacy interrupts\n");
+ pci_dbg(dev, "Using legacy interrupts\n");
rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
}
if (rc < 0) {
@@ -4023,12 +3995,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
if (quirk->setup(priv, board, &uart, i))
break;
- dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
+ pci_dbg(dev, "Setup PCI port: port %lx, irq %d, type %d\n",
uart.port.iobase, uart.port.irq, uart.port.iotype);
priv->line[i] = serial8250_register_8250_port(&uart);
if (priv->line[i] < 0) {
- dev_err(&dev->dev,
+ pci_err(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]);
@@ -4124,8 +4096,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
}
if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
- dev_err(&dev->dev, "invalid driver_data: %ld\n",
- ent->driver_data);
+ pci_err(dev, "invalid driver_data: %ld\n", ent->driver_data);
return -EINVAL;
}
@@ -4208,7 +4179,7 @@ static int pciserial_resume_one(struct device *dev)
err = pci_enable_device(pdev);
/* FIXME: We cannot simply error out here */
if (err)
- dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
+ pci_err(pdev, "Unable to re-enable ports, trying to continue.\n");
pciserial_resume_ports(priv);
}
return 0;
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index 98e5ee4d0d08..1974bbadc975 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -56,10 +56,6 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "BRI1400", 0 },
/* Boca 33.6 Kbps Internal FD34FSVD */
{ "BRI3400", 0 },
- /* Boca 33.6 Kbps Internal FD34FSVD */
- { "BRI0A49", 0 },
- /* Best Data Products Inc. Smart One 336F PnP Modem */
- { "BDP3336", 0 },
/* Computer Peripherals Inc */
/* EuroViVa CommCenter-33.6 SP PnP */
{ "CPI4050", 0 },
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 66374704747e..5775cbff8f6e 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1338,7 +1338,7 @@ static void autoconfig(struct uart_8250_port *up)
up->tx_loadsz = uart_config[port->type].tx_loadsz;
if (port->type == PORT_UNKNOWN)
- goto out_lock;
+ goto out_unlock;
/*
* Reset the UART.
@@ -1355,7 +1355,7 @@ static void autoconfig(struct uart_8250_port *up)
else
serial_out(up, UART_IER, 0);
-out_lock:
+out_unlock:
spin_unlock_irqrestore(&port->lock, flags);
/*
@@ -2696,21 +2696,32 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ struct tty_port *tport = &port->state->port;
unsigned int baud, quot, frac = 0;
struct ktermios *termios;
+ struct tty_struct *tty;
unsigned long flags;
- mutex_lock(&port->state->port.mutex);
+ tty = tty_port_tty_get(tport);
+ if (!tty) {
+ mutex_lock(&tport->mutex);
+ port->uartclk = uartclk;
+ mutex_unlock(&tport->mutex);
+ return;
+ }
+
+ down_write(&tty->termios_rwsem);
+ mutex_lock(&tport->mutex);
if (port->uartclk == uartclk)
- goto out_lock;
+ goto out_unlock;
port->uartclk = uartclk;
- if (!tty_port_initialized(&port->state->port))
- goto out_lock;
+ if (!tty_port_initialized(tport))
+ goto out_unlock;
- termios = &port->state->port.tty->termios;
+ termios = &tty->termios;
baud = serial8250_get_baud_rate(port, termios, NULL);
quot = serial8250_get_divisor(port, baud, &frac);
@@ -2726,8 +2737,10 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
-out_lock:
- mutex_unlock(&port->state->port.mutex);
+out_unlock:
+ mutex_unlock(&tport->mutex);
+ up_write(&tty->termios_rwsem);
+ tty_kref_put(tty);
}
EXPORT_SYMBOL_GPL(serial8250_update_uartclk);
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 39fc96dc2531..8cd11aa63ed5 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -380,7 +380,7 @@ config SERIAL_8250_DW
config SERIAL_8250_EM
tristate "Support for Emma Mobile integrated serial port"
depends on SERIAL_8250 && HAVE_CLK
- depends on ARM || COMPILE_TEST
+ depends on (ARM && ARCH_RENESAS) || COMPILE_TEST
help
Selecting this option will add support for the integrated serial
port hardware found on the Emma Mobile line of processors.