TTY/Serial patches for 5.9-rc1

Here is the large set of TTY and Serial driver patches for 5.9-rc1.
 
 Lots of bugfixes in here, thanks to syzbot fuzzing for serial and vt and
 console code.
 
 Other highlights include:
 	- much needed vt/vc code cleanup from Jiri Slaby
 	- 8250 driver fixes and additions
 	- various serial driver updates and feature enhancements
 	- locking cleanup for serial/console initializations
 	- other minor cleanups
 
 All of these have been in linux-next with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXyv30A8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ynW+gCgv+OqxT0jeNRAMSQcpMvP3wTBMKIAn1StfjJ4
 y8uwZuQQimD49uj8XtDq
 =bKSv
 -----END PGP SIGNATURE-----

Merge tag 'tty-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial updates from Greg KH:
 "Here is the large set of TTY and Serial driver patches for 5.9-rc1.

  Lots of bugfixes in here, thanks to syzbot fuzzing for serial and vt
  and console code.

  Other highlights include:

   - much needed vt/vc code cleanup from Jiri Slaby

   - 8250 driver fixes and additions

   - various serial driver updates and feature enhancements

   - locking cleanup for serial/console initializations

   - other minor cleanups

  All of these have been in linux-next with no reported issues"

* tag 'tty-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits)
  MAINTAINERS: enlist Greg formally for console stuff
  vgacon: Fix for missing check in scrollback handling
  Revert "serial: 8250: Let serial core initialise spin lock"
  serial: 8250: Let serial core initialise spin lock
  tty: keyboard, do not speculate on func_table index
  serial: stm32: Add RS485 RTS GPIO control
  serial: 8250_dw: Fix common clocks usage race condition
  serial: 8250_dw: Pass the same rate to the clk round and set rate methods
  serial: 8250_dw: Simplify the ref clock rate setting procedure
  serial: 8250: Add 8250 port clock update method
  tty: serial: imx: add imx earlycon driver
  tty: serial: imx: enable imx serial console port as module
  tty/synclink: remove leftover bits of non-PCI card support
  tty: Use the preferred form for passing the size of a structure type
  tty: Fix identation issues in struct serial_struct32
  tty: Avoid the use of one-element arrays
  serial: msm_serial: add sparse context annotation
  serial: pmac_zilog: add sparse context annotation
  newport_con: vc_color is now in state
  serial: imx: use hrtimers for rs485 delays
  ...
This commit is contained in:
Linus Torvalds 2020-08-06 14:56:11 -07:00
commit d6efb3ac3e
63 changed files with 1846 additions and 1612 deletions

View File

@ -35,9 +35,11 @@ properties:
description: label associated with this uart description: label associated with this uart
st,hw-flow-ctrl: st,hw-flow-ctrl:
description: enable hardware flow control description: enable hardware flow control (deprecated)
$ref: /schemas/types.yaml#/definitions/flag $ref: /schemas/types.yaml#/definitions/flag
uart-has-rtscts: true
dmas: dmas:
minItems: 1 minItems: 1
maxItems: 2 maxItems: 2

View File

@ -5,7 +5,7 @@ GSM 0710 tty multiplexor HOWTO
This line discipline implements the GSM 07.10 multiplexing protocol This line discipline implements the GSM 07.10 multiplexing protocol
detailed in the following 3GPP document: detailed in the following 3GPP document:
http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
This document give some hints on how to use this driver with GPRS and 3G This document give some hints on how to use this driver with GPRS and 3G
modems connected to a physical serial port. modems connected to a physical serial port.

View File

@ -4386,6 +4386,12 @@ L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/connector/ F: drivers/connector/
CONSOLE SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Supported
F: drivers/video/console/
F: include/linux/console*
CONTROL GROUP (CGROUP) CONTROL GROUP (CGROUP)
M: Tejun Heo <tj@kernel.org> M: Tejun Heo <tj@kernel.org>
M: Li Zefan <lizefan@huawei.com> M: Li Zefan <lizefan@huawei.com>

View File

@ -184,11 +184,6 @@ void line_flush_chars(struct tty_struct *tty)
line_flush_buffer(tty); line_flush_buffer(tty);
} }
int line_put_char(struct tty_struct *tty, unsigned char ch)
{
return line_write(tty, &ch, sizeof(ch));
}
int line_write(struct tty_struct *tty, const unsigned char *buf, int len) int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
{ {
struct line *line = tty->driver_data; struct line *line = tty->driver_data;

View File

@ -66,7 +66,6 @@ extern int line_setup(char **conf, unsigned nlines, char **def,
char *init, char *name); char *init, char *name);
extern int line_write(struct tty_struct *tty, const unsigned char *buf, extern int line_write(struct tty_struct *tty, const unsigned char *buf,
int len); int len);
extern int line_put_char(struct tty_struct *tty, unsigned char ch);
extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
extern int line_chars_in_buffer(struct tty_struct *tty); extern int line_chars_in_buffer(struct tty_struct *tty);
extern void line_flush_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty);

View File

@ -95,7 +95,6 @@ static const struct tty_operations ssl_ops = {
.open = line_open, .open = line_open,
.close = line_close, .close = line_close,
.write = line_write, .write = line_write,
.put_char = line_put_char,
.write_room = line_write_room, .write_room = line_write_room,
.chars_in_buffer = line_chars_in_buffer, .chars_in_buffer = line_chars_in_buffer,
.flush_buffer = line_flush_buffer, .flush_buffer = line_flush_buffer,

View File

@ -102,7 +102,6 @@ static const struct tty_operations console_ops = {
.install = con_install, .install = con_install,
.close = line_close, .close = line_close,
.write = line_write, .write = line_write,
.put_char = line_put_char,
.write_room = line_write_room, .write_room = line_write_room,
.chars_in_buffer = line_chars_in_buffer, .chars_in_buffer = line_chars_in_buffer,
.flush_buffer = line_flush_buffer, .flush_buffer = line_flush_buffer,

View File

@ -109,16 +109,16 @@ static void braille_write(u16 *buf)
/* Follow the VC cursor*/ /* Follow the VC cursor*/
static void vc_follow_cursor(struct vc_data *vc) static void vc_follow_cursor(struct vc_data *vc)
{ {
vc_x = vc->vc_x - (vc->vc_x % WIDTH); vc_x = vc->state.x - (vc->state.x % WIDTH);
vc_y = vc->vc_y; vc_y = vc->state.y;
lastvc_x = vc->vc_x; lastvc_x = vc->state.x;
lastvc_y = vc->vc_y; lastvc_y = vc->state.y;
} }
/* Maybe the VC cursor moved, if so follow it */ /* Maybe the VC cursor moved, if so follow it */
static void vc_maybe_cursor_moved(struct vc_data *vc) static void vc_maybe_cursor_moved(struct vc_data *vc)
{ {
if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y) if (vc->state.x != lastvc_x || vc->state.y != lastvc_y)
vc_follow_cursor(vc); vc_follow_cursor(vc);
} }

View File

@ -263,8 +263,8 @@ static unsigned char get_attributes(struct vc_data *vc, u16 *pos)
static void speakup_date(struct vc_data *vc) static void speakup_date(struct vc_data *vc)
{ {
spk_x = spk_cx = vc->vc_x; spk_x = spk_cx = vc->state.x;
spk_y = spk_cy = vc->vc_y; spk_y = spk_cy = vc->state.y;
spk_pos = spk_cp = vc->vc_pos; spk_pos = spk_cp = vc->vc_pos;
spk_old_attr = spk_attr; spk_old_attr = spk_attr;
spk_attr = get_attributes(vc, (u_short *)spk_pos); spk_attr = get_attributes(vc, (u_short *)spk_pos);
@ -1551,9 +1551,9 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
*/ */
is_cursor = value + 1; is_cursor = value + 1;
old_cursor_pos = vc->vc_pos; old_cursor_pos = vc->vc_pos;
old_cursor_x = vc->vc_x; old_cursor_x = vc->state.x;
old_cursor_y = vc->vc_y; old_cursor_y = vc->state.y;
speakup_console[vc->vc_num]->ht.cy = vc->vc_y; speakup_console[vc->vc_num]->ht.cy = vc->state.y;
cursor_con = vc->vc_num; cursor_con = vc->vc_num;
if (cursor_track == CT_Highlight) if (cursor_track == CT_Highlight)
reset_highlight_buffers(vc); reset_highlight_buffers(vc);
@ -1574,8 +1574,8 @@ static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
i = 0; i = 0;
if (speakup_console[vc_num]->ht.highsize[bi] == 0) { if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos; speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
speakup_console[vc_num]->ht.rx[bi] = vc->vc_x; speakup_console[vc_num]->ht.rx[bi] = vc->state.x;
speakup_console[vc_num]->ht.ry[bi] = vc->vc_y; speakup_console[vc_num]->ht.ry[bi] = vc->state.y;
} }
while ((hi < COLOR_BUFFER_SIZE) && (i < len)) { while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
if (ic[i] > 32) { if (ic[i] > 32) {
@ -1664,9 +1664,9 @@ static int speak_highlight(struct vc_data *vc)
return 0; return 0;
hc = get_highlight_color(vc); hc = get_highlight_color(vc);
if (hc != -1) { if (hc != -1) {
d = vc->vc_y - speakup_console[vc_num]->ht.cy; d = vc->state.y - speakup_console[vc_num]->ht.cy;
if ((d == 1) || (d == -1)) if ((d == 1) || (d == -1))
if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y) if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y)
return 0; return 0;
spk_parked |= 0x01; spk_parked |= 0x01;
spk_do_flush(); spk_do_flush();
@ -1693,8 +1693,8 @@ static void cursor_done(struct timer_list *unused)
} }
speakup_date(vc); speakup_date(vc);
if (win_enabled) { if (win_enabled) {
if (vc->vc_x >= win_left && vc->vc_x <= win_right && if (vc->state.x >= win_left && vc->state.x <= win_right &&
vc->vc_y >= win_top && vc->vc_y <= win_bottom) { vc->state.y >= win_top && vc->state.y <= win_bottom) {
spk_keydown = 0; spk_keydown = 0;
is_cursor = 0; is_cursor = 0;
goto out; goto out;
@ -1757,7 +1757,7 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
if (!spin_trylock_irqsave(&speakup_info.spinlock, flags)) if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
/* Speakup output, discard */ /* Speakup output, discard */
return; return;
if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1)) if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1))
bleep(3); bleep(3);
if ((is_cursor) || (cursor_track == read_all_mode)) { if ((is_cursor) || (cursor_track == read_all_mode)) {
if (cursor_track == CT_Highlight) if (cursor_track == CT_Highlight)
@ -1766,8 +1766,8 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
return; return;
} }
if (win_enabled) { if (win_enabled) {
if (vc->vc_x >= win_left && vc->vc_x <= win_right && if (vc->state.x >= win_left && vc->state.x <= win_right &&
vc->vc_y >= win_top && vc->vc_y <= win_bottom) { vc->state.y >= win_top && vc->state.y <= win_bottom) {
spin_unlock_irqrestore(&speakup_info.spinlock, flags); spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return; return;
} }

View File

@ -138,7 +138,7 @@
#define IntrQuit 0x40 /* received QUIT code */ #define IntrQuit 0x40 /* received QUIT code */
#define IntrEOF 0x80 /* received EOF code */ #define IntrEOF 0x80 /* received EOF code */
#define IntrRxTrigger 0x100 /* rx data count reach tigger value */ #define IntrRxTrigger 0x100 /* rx data count reach trigger value */
#define IntrTxTrigger 0x200 /* tx data count below trigger value */ #define IntrTxTrigger 0x200 /* tx data count below trigger value */
#define Magic_no (Config_base + 0) #define Magic_no (Config_base + 0)

View File

@ -19,6 +19,8 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/notifier.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/clk.h> #include <linux/clk.h>
@ -43,6 +45,8 @@ struct dw8250_data {
int msr_mask_off; int msr_mask_off;
struct clk *clk; struct clk *clk;
struct clk *pclk; struct clk *pclk;
struct notifier_block clk_notifier;
struct work_struct clk_work;
struct reset_control *rst; struct reset_control *rst;
unsigned int skip_autocfg:1; unsigned int skip_autocfg:1;
@ -54,6 +58,16 @@ static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
return container_of(data, struct dw8250_data, data); return container_of(data, struct dw8250_data, data);
} }
static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
{
return container_of(nb, struct dw8250_data, clk_notifier);
}
static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work)
{
return container_of(work, struct dw8250_data, clk_work);
}
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = to_dw8250_data(p->private_data); struct dw8250_data *d = to_dw8250_data(p->private_data);
@ -260,6 +274,46 @@ static int dw8250_handle_irq(struct uart_port *p)
return 0; return 0;
} }
static void dw8250_clk_work_cb(struct work_struct *work)
{
struct dw8250_data *d = work_to_dw8250_data(work);
struct uart_8250_port *up;
unsigned long rate;
rate = clk_get_rate(d->clk);
if (rate <= 0)
return;
up = serial8250_get_port(d->data.line);
serial8250_update_uartclk(&up->port, rate);
}
static int dw8250_clk_notifier_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
struct dw8250_data *d = clk_to_dw8250_data(nb);
/*
* We have no choice but to defer the uartclk update due to two
* deadlocks. First one is caused by a recursive mutex lock which
* happens when clk_set_rate() is called from dw8250_set_termios().
* Second deadlock is more tricky and is caused by an inverted order of
* the clk and tty-port mutexes lock. It happens if clock rate change
* is requested asynchronously while set_termios() is executed between
* tty-port mutex lock and clk_set_rate() function invocation and
* vise-versa. Anyway if we didn't have the reference clock alteration
* in the dw8250_set_termios() method we wouldn't have needed this
* deferred event handling complication.
*/
if (event == POST_RATE_CHANGE) {
queue_work(system_unbound_wq, &d->clk_work);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static void static void
dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
{ {
@ -275,27 +329,27 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
unsigned int baud = tty_termios_baud_rate(termios); unsigned long newrate = tty_termios_baud_rate(termios) * 16;
struct dw8250_data *d = to_dw8250_data(p->private_data); struct dw8250_data *d = to_dw8250_data(p->private_data);
long rate; long rate;
int ret; int ret;
clk_disable_unprepare(d->clk); clk_disable_unprepare(d->clk);
rate = clk_round_rate(d->clk, baud * 16); rate = clk_round_rate(d->clk, newrate);
if (rate < 0) if (rate > 0) {
ret = rate; /*
else if (rate == 0) * Premilinary set the uartclk to the new clock rate so the
ret = -ENOENT; * clock update event handler caused by the clk_set_rate()
else * calling wouldn't actually update the UART divisor since
ret = clk_set_rate(d->clk, rate); * we about to do this anyway.
*/
swap(p->uartclk, rate);
ret = clk_set_rate(d->clk, newrate);
if (ret)
swap(p->uartclk, rate);
}
clk_prepare_enable(d->clk); clk_prepare_enable(d->clk);
if (ret)
goto out;
p->uartclk = rate;
out:
p->status &= ~UPSTAT_AUTOCTS; p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS) if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS; p->status |= UPSTAT_AUTOCTS;
@ -319,6 +373,39 @@ static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios)
serial8250_do_set_ldisc(p, termios); serial8250_do_set_ldisc(p, termios);
} }
static int dw8250_startup(struct uart_port *p)
{
struct dw8250_data *d = to_dw8250_data(p->private_data);
int ret;
/*
* Some platforms may provide a reference clock shared between several
* devices. In this case before using the serial port first we have to
* make sure that any clock state change is known to the UART port at
* least post factum.
*/
if (d->clk) {
ret = clk_notifier_register(d->clk, &d->clk_notifier);
if (ret)
dev_warn(p->dev, "Failed to set the clock notifier\n");
}
return serial8250_do_startup(p);
}
static void dw8250_shutdown(struct uart_port *p)
{
struct dw8250_data *d = to_dw8250_data(p->private_data);
serial8250_do_shutdown(p);
if (d->clk) {
clk_notifier_unregister(d->clk, &d->clk_notifier);
flush_work(&d->clk_work);
}
}
/* /*
* dw8250_fallback_dma_filter will prevent the UART from getting just any free * dw8250_fallback_dma_filter will prevent the UART from getting just any free
* channel on platforms that have DMA engines, but don't have any channels * channel on platforms that have DMA engines, but don't have any channels
@ -414,6 +501,8 @@ static int dw8250_probe(struct platform_device *pdev)
p->serial_out = dw8250_serial_out; p->serial_out = dw8250_serial_out;
p->set_ldisc = dw8250_set_ldisc; p->set_ldisc = dw8250_set_ldisc;
p->set_termios = dw8250_set_termios; p->set_termios = dw8250_set_termios;
p->startup = dw8250_startup;
p->shutdown = dw8250_shutdown;
p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
if (!p->membase) if (!p->membase)
@ -475,6 +564,9 @@ static int dw8250_probe(struct platform_device *pdev)
if (IS_ERR(data->clk)) if (IS_ERR(data->clk))
return PTR_ERR(data->clk); return PTR_ERR(data->clk);
INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
err = clk_prepare_enable(data->clk); err = clk_prepare_enable(data->clk);
if (err) if (err)
dev_warn(dev, "could not enable optional baudclk: %d\n", err); dev_warn(dev, "could not enable optional baudclk: %d\n", err);

View File

@ -78,14 +78,18 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
static int serial8250_em_probe(struct platform_device *pdev) static int serial8250_em_probe(struct platform_device *pdev)
{ {
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct serial8250_em_priv *priv; struct serial8250_em_priv *priv;
struct uart_8250_port up; struct uart_8250_port up;
int ret; struct resource *regs;
int irq, ret;
if (!regs || !irq) { irq = platform_get_irq(pdev, 0);
dev_err(&pdev->dev, "missing registers or irq\n"); if (irq < 0)
return irq;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_err(&pdev->dev, "missing registers\n");
return -EINVAL; return -EINVAL;
} }
@ -101,7 +105,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
memset(&up, 0, sizeof(up)); memset(&up, 0, sizeof(up));
up.port.mapbase = regs->start; up.port.mapbase = regs->start;
up.port.irq = irq->start; up.port.irq = irq;
up.port.type = PORT_UNKNOWN; up.port.type = PORT_UNKNOWN;
up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
up.port.dev = &pdev->dev; up.port.dev = &pdev->dev;

View File

@ -207,12 +207,11 @@ static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset)
static int ingenic_uart_probe(struct platform_device *pdev) static int ingenic_uart_probe(struct platform_device *pdev)
{ {
struct uart_8250_port uart = {}; struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct ingenic_uart_data *data; struct ingenic_uart_data *data;
const struct ingenic_uart_config *cdata; const struct ingenic_uart_config *cdata;
const struct of_device_id *match; const struct of_device_id *match;
int err, line; struct resource *regs;
int irq, err, line;
match = of_match_device(of_match, &pdev->dev); match = of_match_device(of_match, &pdev->dev);
if (!match) { if (!match) {
@ -221,8 +220,13 @@ static int ingenic_uart_probe(struct platform_device *pdev)
} }
cdata = match->data; cdata = match->data;
if (!regs || !irq) { irq = platform_get_irq(pdev, 0);
dev_err(&pdev->dev, "no registers/irq defined\n"); if (irq < 0)
return irq;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_err(&pdev->dev, "no registers defined\n");
return -EINVAL; return -EINVAL;
} }
@ -238,7 +242,7 @@ static int ingenic_uart_probe(struct platform_device *pdev)
uart.port.regshift = 2; uart.port.regshift = 2;
uart.port.serial_out = ingenic_uart_serial_out; uart.port.serial_out = ingenic_uart_serial_out;
uart.port.serial_in = ingenic_uart_serial_in; uart.port.serial_in = ingenic_uart_serial_in;
uart.port.irq = irq->start; uart.port.irq = irq;
uart.port.dev = &pdev->dev; uart.port.dev = &pdev->dev;
uart.port.fifosize = cdata->fifosize; uart.port.fifosize = cdata->fifosize;
uart.tx_loadsz = cdata->tx_loadsz; uart.tx_loadsz = cdata->tx_loadsz;

View File

@ -51,7 +51,7 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev)
return clkval; return clkval;
} }
static unsigned int get_num_ports(struct mcb_device *mdev, static int get_num_ports(struct mcb_device *mdev,
void __iomem *membase) void __iomem *membase)
{ {
switch (mdev->id) { switch (mdev->id) {
@ -140,7 +140,7 @@ static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
return; return;
num_ports = get_num_ports(mdev, data[0].uart.port.membase); num_ports = get_num_ports(mdev, data[0].uart.port.membase);
if (num_ports < 0 || num_ports > 4) { if (num_ports <= 0 || num_ports > 4) {
dev_err(&mdev->dev, "error retrieving number of ports!\n"); dev_err(&mdev->dev, "error retrieving number of ports!\n");
return; return;
} }

View File

@ -512,13 +512,17 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
static int mtk8250_probe(struct platform_device *pdev) static int mtk8250_probe(struct platform_device *pdev)
{ {
struct uart_8250_port uart = {}; struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct mtk8250_data *data; struct mtk8250_data *data;
int err; struct resource *regs;
int irq, err;
if (!regs || !irq) { irq = platform_get_irq(pdev, 0);
dev_err(&pdev->dev, "no registers/irq defined\n"); if (irq < 0)
return irq;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_err(&pdev->dev, "no registers defined\n");
return -EINVAL; return -EINVAL;
} }
@ -542,7 +546,7 @@ static int mtk8250_probe(struct platform_device *pdev)
spin_lock_init(&uart.port.lock); spin_lock_init(&uart.port.lock);
uart.port.mapbase = regs->start; uart.port.mapbase = regs->start;
uart.port.irq = irq->start; uart.port.irq = irq;
uart.port.pm = mtk8250_do_pm; uart.port.pm = mtk8250_do_pm;
uart.port.type = PORT_16550; uart.port.type = PORT_16550;
uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;

View File

@ -1209,17 +1209,21 @@ MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
static int omap8250_probe(struct platform_device *pdev) static int omap8250_probe(struct platform_device *pdev)
{ {
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct omap8250_priv *priv; struct omap8250_priv *priv;
const struct omap8250_platdata *pdata; const struct omap8250_platdata *pdata;
struct uart_8250_port up; struct uart_8250_port up;
int ret; struct resource *regs;
void __iomem *membase; void __iomem *membase;
int irq, ret;
if (!regs || !irq) { irq = platform_get_irq(pdev, 0);
dev_err(&pdev->dev, "missing registers or irq\n"); if (irq < 0)
return irq;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_err(&pdev->dev, "missing registers\n");
return -EINVAL; return -EINVAL;
} }
@ -1236,7 +1240,7 @@ static int omap8250_probe(struct platform_device *pdev)
up.port.dev = &pdev->dev; up.port.dev = &pdev->dev;
up.port.mapbase = regs->start; up.port.mapbase = regs->start;
up.port.membase = membase; up.port.membase = membase;
up.port.irq = irq->start; up.port.irq = irq;
/* /*
* It claims to be 16C750 compatible however it is a little different. * It claims to be 16C750 compatible however it is a little different.
* It has EFR and has no FCR7_64byte bit. The AFE (which it claims to * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to

View File

@ -16,6 +16,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/gpio/consumer.h>
#include <linux/sysrq.h> #include <linux/sysrq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -2631,6 +2632,46 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
(port->uartclk + tolerance) / 16); (port->uartclk + tolerance) / 16);
} }
/*
* Note in order to avoid the tty port mutex deadlock don't use the next method
* within the uart port callbacks. Primarily it's supposed to be utilized to
* handle a sudden reference clock rate change.
*/
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int baud, quot, frac = 0;
struct ktermios *termios;
unsigned long flags;
mutex_lock(&port->state->port.mutex);
if (port->uartclk == uartclk)
goto out_lock;
port->uartclk = uartclk;
termios = &port->state->port.tty->termios;
baud = serial8250_get_baud_rate(port, termios, NULL);
quot = serial8250_get_divisor(port, baud, &frac);
serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
uart_update_timeout(port, termios->c_cflag, baud);
serial8250_set_divisor(port, baud, quot, frac);
serial_port_out(port, UART_LCR, up->lcr);
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
out_lock:
mutex_unlock(&port->state->port.mutex);
}
EXPORT_SYMBOL_GPL(serial8250_update_uartclk);
void void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)

View File

@ -18,7 +18,6 @@
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -93,12 +92,15 @@ static int serial_pxa_probe(struct platform_device *pdev)
{ {
struct uart_8250_port uart = {}; struct uart_8250_port uart = {};
struct pxa8250_data *data; struct pxa8250_data *data;
struct resource *mmres, *irqres; struct resource *mmres;
int ret; int irq, ret;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!mmres)
if (!mmres || !irqres)
return -ENODEV; return -ENODEV;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@ -121,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev)
uart.port.iotype = UPIO_MEM32; uart.port.iotype = UPIO_MEM32;
uart.port.mapbase = mmres->start; uart.port.mapbase = mmres->start;
uart.port.regshift = 2; uart.port.regshift = 2;
uart.port.irq = irqres->start; uart.port.irq = irq;
uart.port.fifosize = 64; uart.port.fifosize = 64;
uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;
uart.port.dev = &pdev->dev; uart.port.dev = &pdev->dev;

View File

@ -222,7 +222,7 @@ config SERIAL_8250_MANY_PORTS
Say Y here if you have dumb serial boards other than the four Say Y here if you have dumb serial boards other than the four
standard COM 1/2/3/4 ports. This may happen if you have an AST standard COM 1/2/3/4 ports. This may happen if you have an AST
FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
from <http://www.tldp.org/docs.html#howto>), or other custom from <https://www.tldp.org/docs.html#howto>), or other custom
serial port hardware which acts similar to standard serial port serial port hardware which acts similar to standard serial port
hardware. If you only use the standard COM 1/2/3/4 ports, you can hardware. If you only use the standard COM 1/2/3/4 ports, you can
say N here to save some memory. You can also say Y if you have an say N here to save some memory. You can also say Y if you have an
@ -266,7 +266,7 @@ config SERIAL_8250_BOCA
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
help help
Say Y here if you have a Boca serial board. Please read the Boca Say Y here if you have a Boca serial board. Please read the Boca
mini-HOWTO, available from <http://www.tldp.org/docs.html#howto> mini-HOWTO, available from <https://www.tldp.org/docs.html#howto>
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called 8250_boca. will be called 8250_boca.

View File

@ -502,20 +502,27 @@ config SERIAL_IMX
can enable its onboard serial port by enabling this option. can enable its onboard serial port by enabling this option.
config SERIAL_IMX_CONSOLE config SERIAL_IMX_CONSOLE
bool "Console on IMX serial port" tristate "Console on IMX serial port"
depends on SERIAL_IMX=y depends on SERIAL_IMX
select SERIAL_CORE_CONSOLE select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON if OF
help help
If you have enabled the serial port on the Freescale IMX If you have enabled the serial port on the Freescale IMX
CPU you can make it the console by answering Y to this option. CPU you can make it the console by answering Y/M to this option.
Even if you say Y here, the currently visible virtual console Even if you say Y/M here, the currently visible virtual console
(/dev/tty0) will still be used as the system console by default, but (/dev/tty0) will still be used as the system console by default, but
you can alter that using a kernel command line option such as you can alter that using a kernel command line option such as
"console=ttymxc0". (Try "man bootparam" or see the documentation of "console=ttymxc0". (Try "man bootparam" or see the documentation of
your bootloader about how to pass options to the kernel at boot time.) your bootloader about how to pass options to the kernel at boot time.)
config SERIAL_IMX_EARLYCON
bool "Earlycon on IMX serial port"
depends on OF
select SERIAL_EARLYCON
help
If you have enabled the earlycon on the Freescale IMX
CPU you can make it the earlycon by answering Y to this option.
config SERIAL_UARTLITE config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support" tristate "Xilinx uartlite serial port support"
depends on HAS_IOMEM depends on HAS_IOMEM

View File

@ -27,7 +27,7 @@
/* /*
* Altera JTAG UART register definitions according to the Altera JTAG UART * Altera JTAG UART register definitions according to the Altera JTAG UART
* datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf * datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
*/ */
#define ALTERA_JTAGUART_SIZE 8 #define ALTERA_JTAGUART_SIZE 8

View File

@ -2607,7 +2607,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE);
uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = index; uap->port.line = index;
spin_lock_init(&uap->port.lock);
amba_ports[index] = uap; amba_ports[index] = uap;

View File

@ -1925,6 +1925,9 @@ static void __lpuart32_serial_setbrg(struct uart_port *port,
tmp_sbr++; tmp_sbr++;
} }
if (tmp_sbr > UARTBAUD_SBR_MASK)
continue;
if (tmp_diff <= baud_diff) { if (tmp_diff <= baud_diff) {
baud_diff = tmp_diff; baud_diff = tmp_diff;
osr = tmp_osr; osr = tmp_osr;

View File

@ -20,6 +20,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/rational.h> #include <linux/rational.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -188,6 +189,13 @@ struct imx_uart_data {
enum imx_uart_type devtype; enum imx_uart_type devtype;
}; };
enum imx_tx_state {
OFF,
WAIT_AFTER_RTS,
SEND,
WAIT_AFTER_SEND,
};
struct imx_port { struct imx_port {
struct uart_port port; struct uart_port port;
struct timer_list timer; struct timer_list timer;
@ -224,6 +232,10 @@ struct imx_port {
unsigned int dma_tx_nents; unsigned int dma_tx_nents;
unsigned int saved_reg[10]; unsigned int saved_reg[10];
bool context_saved; bool context_saved;
enum imx_tx_state tx_state;
struct hrtimer trigger_start_tx;
struct hrtimer trigger_stop_tx;
}; };
struct imx_port_ucrs { struct imx_port_ucrs {
@ -361,7 +373,7 @@ static inline int imx_uart_is_imx6q(struct imx_port *sport)
/* /*
* Save and restore functions for UCR1, UCR2 and UCR3 registers * Save and restore functions for UCR1, UCR2 and UCR3 registers
*/ */
#if defined(CONFIG_SERIAL_IMX_CONSOLE) #if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_ucrs_save(struct imx_port *sport, static void imx_uart_ucrs_save(struct imx_port *sport,
struct imx_port_ucrs *ucr) struct imx_port_ucrs *ucr)
{ {
@ -400,6 +412,15 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
mctrl_gpio_set(sport->gpios, sport->port.mctrl); mctrl_gpio_set(sport->gpios, sport->port.mctrl);
} }
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
{
long sec = msec / MSEC_PER_SEC;
long nsec = (msec % MSEC_PER_SEC) * 1000000;
ktime_t t = ktime_set(sec, nsec);
hrtimer_start(hrt, t, HRTIMER_MODE_REL);
}
/* called with port.lock taken and irqs off */ /* called with port.lock taken and irqs off */
static void imx_uart_start_rx(struct uart_port *port) static void imx_uart_start_rx(struct uart_port *port)
{ {
@ -427,7 +448,10 @@ static void imx_uart_start_rx(struct uart_port *port)
static void imx_uart_stop_tx(struct uart_port *port) static void imx_uart_stop_tx(struct uart_port *port)
{ {
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
u32 ucr1; u32 ucr1, ucr4, usr2;
if (sport->tx_state == OFF)
return;
/* /*
* We are maybe in the SMP context, so if the DMA TX thread is running * We are maybe in the SMP context, so if the DMA TX thread is running
@ -439,10 +463,32 @@ static void imx_uart_stop_tx(struct uart_port *port)
ucr1 = imx_uart_readl(sport, UCR1); ucr1 = imx_uart_readl(sport, UCR1);
imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1); imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1);
/* in rs485 mode disable transmitter if shifter is empty */ usr2 = imx_uart_readl(sport, USR2);
if (port->rs485.flags & SER_RS485_ENABLED && if (!(usr2 & USR2_TXDC)) {
imx_uart_readl(sport, USR2) & USR2_TXDC) { /* The shifter is still busy, so retry once TC triggers */
u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4; return;
}
ucr4 = imx_uart_readl(sport, UCR4);
ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4);
/* in rs485 mode disable transmitter */
if (port->rs485.flags & SER_RS485_ENABLED) {
if (sport->tx_state == SEND) {
sport->tx_state = WAIT_AFTER_SEND;
start_hrtimer_ms(&sport->trigger_stop_tx,
port->rs485.delay_rts_after_send);
return;
}
if (sport->tx_state == WAIT_AFTER_RTS ||
sport->tx_state == WAIT_AFTER_SEND) {
u32 ucr2;
hrtimer_try_to_cancel(&sport->trigger_start_tx);
ucr2 = imx_uart_readl(sport, UCR2);
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
imx_uart_rts_active(sport, &ucr2); imx_uart_rts_active(sport, &ucr2);
else else
@ -451,9 +497,10 @@ static void imx_uart_stop_tx(struct uart_port *port)
imx_uart_start_rx(port); imx_uart_start_rx(port);
ucr4 = imx_uart_readl(sport, UCR4); sport->tx_state = OFF;
ucr4 &= ~UCR4_TCEN; }
imx_uart_writel(sport, ucr4, UCR4); } else {
sport->tx_state = OFF;
} }
} }
@ -651,10 +698,15 @@ static void imx_uart_start_tx(struct uart_port *port)
if (!sport->port.x_char && uart_circ_empty(&port->state->xmit)) if (!sport->port.x_char && uart_circ_empty(&port->state->xmit))
return; return;
if (port->rs485.flags & SER_RS485_ENABLED) { /*
u32 ucr2; * We cannot simply do nothing here if sport->tx_state == SEND already
* because UCR1_TXMPTYEN might already have been cleared in
* imx_uart_stop_tx(), but tx_state is still SEND.
*/
ucr2 = imx_uart_readl(sport, UCR2); if (port->rs485.flags & SER_RS485_ENABLED) {
if (sport->tx_state == OFF) {
u32 ucr2 = imx_uart_readl(sport, UCR2);
if (port->rs485.flags & SER_RS485_RTS_ON_SEND) if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
imx_uart_rts_active(sport, &ucr2); imx_uart_rts_active(sport, &ucr2);
else else
@ -664,15 +716,32 @@ static void imx_uart_start_tx(struct uart_port *port)
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
imx_uart_stop_rx(port); imx_uart_stop_rx(port);
sport->tx_state = WAIT_AFTER_RTS;
start_hrtimer_ms(&sport->trigger_start_tx,
port->rs485.delay_rts_before_send);
return;
}
if (sport->tx_state == WAIT_AFTER_SEND
|| sport->tx_state == WAIT_AFTER_RTS) {
hrtimer_try_to_cancel(&sport->trigger_stop_tx);
/* /*
* Enable transmitter and shifter empty irq only if DMA is off. * Enable transmitter and shifter empty irq only if DMA
* In the DMA case this is done in the tx-callback. * is off. In the DMA case this is done in the
* tx-callback.
*/ */
if (!sport->dma_is_enabled) { if (!sport->dma_is_enabled) {
u32 ucr4 = imx_uart_readl(sport, UCR4); u32 ucr4 = imx_uart_readl(sport, UCR4);
ucr4 |= UCR4_TCEN; ucr4 |= UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4); imx_uart_writel(sport, ucr4, UCR4);
} }
sport->tx_state = SEND;
}
} else {
sport->tx_state = SEND;
} }
if (!sport->dma_is_enabled) { if (!sport->dma_is_enabled) {
@ -1630,7 +1699,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & CRTSCTS) if (termios->c_cflag & CRTSCTS)
ucr2 &= ~UCR2_IRTS; ucr2 &= ~UCR2_IRTS;
if (termios->c_cflag & CSTOPB) if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB; ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARENB) {
@ -1857,10 +1925,6 @@ static int imx_uart_rs485_config(struct uart_port *port,
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
u32 ucr2; u32 ucr2;
/* unimplemented */
rs485conf->delay_rts_before_send = 0;
rs485conf->delay_rts_after_send = 0;
/* RTS is required to control the transmitter */ /* RTS is required to control the transmitter */
if (!sport->have_rtscts && !sport->have_rtsgpio) if (!sport->have_rtscts && !sport->have_rtsgpio)
rs485conf->flags &= ~SER_RS485_ENABLED; rs485conf->flags &= ~SER_RS485_ENABLED;
@ -1915,7 +1979,7 @@ static const struct uart_ops imx_uart_pops = {
static struct imx_port *imx_uart_ports[UART_NR]; static struct imx_port *imx_uart_ports[UART_NR];
#ifdef CONFIG_SERIAL_IMX_CONSOLE #if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_uart_console_putchar(struct uart_port *port, int ch) static void imx_uart_console_putchar(struct uart_port *port, int ch)
{ {
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
@ -2112,39 +2176,6 @@ static struct console imx_uart_console = {
#define IMX_CONSOLE &imx_uart_console #define IMX_CONSOLE &imx_uart_console
#ifdef CONFIG_OF
static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
{
struct imx_port *sport = (struct imx_port *)port;
while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL)
cpu_relax();
imx_uart_writel(sport, ch, URTX0);
}
static void imx_uart_console_early_write(struct console *con, const char *s,
unsigned count)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
}
static int __init
imx_console_early_setup(struct earlycon_device *dev, const char *opt)
{
if (!dev->port.membase)
return -ENODEV;
dev->con->write = imx_uart_console_early_write;
return 0;
}
OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
#endif
#else #else
#define IMX_CONSOLE NULL #define IMX_CONSOLE NULL
#endif #endif
@ -2223,6 +2254,32 @@ static void imx_uart_probe_pdata(struct imx_port *sport,
sport->have_rtscts = 1; sport->have_rtscts = 1;
} }
static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t)
{
struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx);
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
if (sport->tx_state == WAIT_AFTER_RTS)
imx_uart_start_tx(&sport->port);
spin_unlock_irqrestore(&sport->port.lock, flags);
return HRTIMER_NORESTART;
}
static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
{
struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx);
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
if (sport->tx_state == WAIT_AFTER_SEND)
imx_uart_stop_tx(&sport->port);
spin_unlock_irqrestore(&sport->port.lock, flags);
return HRTIMER_NORESTART;
}
static int imx_uart_probe(struct platform_device *pdev) static int imx_uart_probe(struct platform_device *pdev)
{ {
struct imx_port *sport; struct imx_port *sport;
@ -2369,6 +2426,11 @@ static int imx_uart_probe(struct platform_device *pdev)
clk_disable_unprepare(sport->clk_ipg); clk_disable_unprepare(sport->clk_ipg);
hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
sport->trigger_start_tx.function = imx_trigger_start_tx;
sport->trigger_stop_tx.function = imx_trigger_stop_tx;
/* /*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt. * chips only have one interrupt.
@ -2406,9 +2468,6 @@ static int imx_uart_probe(struct platform_device *pdev)
} }
} }
/* We need to initialize lock even for non-registered console */
spin_lock_init(&sport->port.lock);
imx_uart_ports[sport->port.line] = sport; imx_uart_ports[sport->port.line] = sport;
platform_set_drvdata(pdev, sport); platform_set_drvdata(pdev, sport);

View File

@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 NXP
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/io.h>
#define URTX0 0x40 /* Transmitter Register */
#define UTS_TXFULL (1<<4) /* TxFIFO full */
#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
{
while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
cpu_relax();
writel_relaxed(ch, port->membase + URTX0);
}
static void imx_uart_console_early_write(struct console *con, const char *s,
unsigned count)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
}
static int __init
imx_console_early_setup(struct earlycon_device *dev, const char *opt)
{
if (!dev->port.membase)
return -ENODEV;
dev->con->write = imx_uart_console_early_write;
return 0;
}
OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
MODULE_AUTHOR("NXP");
MODULE_DESCRIPTION("IMX earlycon driver");
MODULE_LICENSE("GPL");

View File

@ -16,7 +16,7 @@
#include "jsm.h" #include "jsm.h"
MODULE_AUTHOR("Digi International, http://www.digi.com"); MODULE_AUTHOR("Digi International, https://www.digi.com");
MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line"); MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("jsm"); MODULE_SUPPORTED_DEVICE("jsm");

View File

@ -538,7 +538,8 @@ static int __init kgdboc_earlycon_init(char *opt)
if (!con) { if (!con) {
/* /*
* Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets * Both earlycon and kgdboc_earlycon are initialized during
* early parameter parsing. We cannot guarantee earlycon gets
* in first and, in any case, on ACPI systems earlycon may * in first and, in any case, on ACPI systems earlycon may
* defer its own initialization (usually to somewhere within * defer its own initialization (usually to somewhere within
* setup_arch() ). To cope with either of these situations * setup_arch() ). To cope with either of these situations

View File

@ -696,6 +696,7 @@ static void msm_enable_ms(struct uart_port *port)
} }
static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
__must_hold(&port->lock)
{ {
struct tty_port *tport = &port->state->port; struct tty_port *tport = &port->state->port;
unsigned int sr; unsigned int sr;
@ -771,6 +772,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
} }
static void msm_handle_rx(struct uart_port *port) static void msm_handle_rx(struct uart_port *port)
__must_hold(&port->lock)
{ {
struct tty_port *tport = &port->state->port; struct tty_port *tport = &port->state->port;
unsigned int sr; unsigned int sr;

View File

@ -1857,41 +1857,24 @@ static void pch_uart_pci_remove(struct pci_dev *pdev)
kfree(priv); kfree(priv);
return; return;
} }
#ifdef CONFIG_PM
static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int __maybe_unused pch_uart_pci_suspend(struct device *dev)
{ {
struct eg20t_port *priv = pci_get_drvdata(pdev); struct eg20t_port *priv = dev_get_drvdata(dev);
uart_suspend_port(&pch_uart_driver, &priv->port); uart_suspend_port(&pch_uart_driver, &priv->port);
pci_save_state(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0; return 0;
} }
static int pch_uart_pci_resume(struct pci_dev *pdev) static int __maybe_unused pch_uart_pci_resume(struct device *dev)
{ {
struct eg20t_port *priv = pci_get_drvdata(pdev); struct eg20t_port *priv = dev_get_drvdata(dev);
int ret;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev,
"%s-pci_enable_device failed(ret=%d) ", __func__, ret);
return ret;
}
uart_resume_port(&pch_uart_driver, &priv->port); uart_resume_port(&pch_uart_driver, &priv->port);
return 0; return 0;
} }
#else
#define pch_uart_pci_suspend NULL
#define pch_uart_pci_resume NULL
#endif
static const struct pci_device_id pch_uart_pci_id[] = { static const struct pci_device_id pch_uart_pci_id[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
@ -1945,13 +1928,16 @@ probe_error:
return ret; return ret;
} }
static SIMPLE_DEV_PM_OPS(pch_uart_pci_pm_ops,
pch_uart_pci_suspend,
pch_uart_pci_resume);
static struct pci_driver pch_uart_pci_driver = { static struct pci_driver pch_uart_pci_driver = {
.name = "pch_uart", .name = "pch_uart",
.id_table = pch_uart_pci_id, .id_table = pch_uart_pci_id,
.probe = pch_uart_pci_probe, .probe = pch_uart_pci_probe,
.remove = pch_uart_pci_remove, .remove = pch_uart_pci_remove,
.suspend = pch_uart_pci_suspend, .driver.pm = &pch_uart_pci_pm_ops,
.resume = pch_uart_pci_resume,
}; };
static int __init pch_uart_module_init(void) static int __init pch_uart_module_init(void)

View File

@ -213,6 +213,7 @@ static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable)
} }
static bool pmz_receive_chars(struct uart_pmac_port *uap) static bool pmz_receive_chars(struct uart_pmac_port *uap)
__must_hold(&uap->port.lock)
{ {
struct tty_port *port; struct tty_port *port;
unsigned char ch, r1, drop, flag; unsigned char ch, r1, drop, flag;

View File

@ -768,7 +768,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
u8 buf[sizeof(u32)]; u8 buf[sizeof(u32)];
int c; int c;
memset(buf, 0, ARRAY_SIZE(buf)); memset(buf, 0, sizeof(buf));
tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD); tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD);
for (c = 0; c < tx_bytes ; c++) { for (c = 0; c < tx_bytes ; c++) {

View File

@ -6,7 +6,7 @@
* http://armlinux.simtec.co.uk/ * http://armlinux.simtec.co.uk/
*/ */
/* Hote on 2410 error handling /* Note on 2410 error handling
* *
* The s3c2410 manual has a love/hate affair with the contents of the * The s3c2410 manual has a love/hate affair with the contents of the
* UERSTAT register in the UART blocks, and keeps marking some of the * UERSTAT register in the UART blocks, and keeps marking some of the
@ -327,7 +327,6 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
unsigned long flags; unsigned long flags;
int count; int count;
dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
count = dma->tx_bytes_requested - state.residue; count = dma->tx_bytes_requested - state.residue;
async_tx_ack(dma->tx_desc); async_tx_ack(dma->tx_desc);
@ -409,7 +408,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
struct circ_buf *xmit = &port->state->xmit; struct circ_buf *xmit = &port->state->xmit;
struct s3c24xx_uart_dma *dma = ourport->dma; struct s3c24xx_uart_dma *dma = ourport->dma;
if (ourport->tx_mode != S3C24XX_TX_DMA) if (ourport->tx_mode != S3C24XX_TX_DMA)
enable_tx_dma(ourport); enable_tx_dma(ourport);
@ -816,7 +814,6 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id) static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
{ {
struct s3c24xx_uart_port *ourport = dev_id; struct s3c24xx_uart_port *ourport = dev_id;
@ -1589,7 +1586,6 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
return 0; return 0;
} }
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
static struct console s3c24xx_serial_console; static struct console s3c24xx_serial_console;
@ -1672,7 +1668,6 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
} }
}, },
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2 #if CONFIG_SERIAL_SAMSUNG_UARTS > 2
[2] = { [2] = {
.port = { .port = {
.lock = __PORT_LOCK_UNLOCKED(2), .lock = __PORT_LOCK_UNLOCKED(2),
@ -1728,7 +1723,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
udelay(1); udelay(1);
} }
#ifdef CONFIG_ARM_S3C24XX_CPUFREQ #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
@ -1903,9 +1897,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
port->mapbase = res->start; port->mapbase = res->start;
ret = platform_get_irq(platdev, 0); ret = platform_get_irq(platdev, 0);
if (ret < 0) if (ret < 0) {
port->irq = 0; port->irq = 0;
else { } else {
port->irq = ret; port->irq = ret;
ourport->rx_irq = ret; ourport->rx_irq = ret;
ourport->tx_irq = ret + 1; ourport->tx_irq = ret + 1;
@ -1977,8 +1971,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[];
static int probe_index; static int probe_index;
static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( static inline struct s3c24xx_serial_drv_data *
struct platform_device *pdev) s3c24xx_get_driver_data(struct platform_device *pdev)
{ {
#ifdef CONFIG_OF #ifdef CONFIG_OF
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
@ -2329,7 +2323,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
*baud = rate / (16 * (ubrdiv + 1)); *baud = rate / (16 * (ubrdiv + 1));
dev_dbg(port->dev, "calculated baud %d\n", *baud); dev_dbg(port->dev, "calculated baud %d\n", *baud);
} }
} }
static int __init static int __init
@ -2696,6 +2689,7 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device,
device->port.private_data = &s3c2410_early_console_data; device->port.private_data = &s3c2410_early_console_data;
return samsung_early_console_setup(device, opt); return samsung_early_console_setup(device, opt);
} }
OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart", OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
s3c2410_early_console_setup); s3c2410_early_console_setup);
@ -2710,6 +2704,7 @@ static int __init s3c2440_early_console_setup(struct earlycon_device *device,
device->port.private_data = &s3c2440_early_console_data; device->port.private_data = &s3c2440_early_console_data;
return samsung_early_console_setup(device, opt); return samsung_early_console_setup(device, opt);
} }
OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart", OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",
s3c2440_early_console_setup); s3c2440_early_console_setup);
OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart", OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
@ -2728,6 +2723,7 @@ static int __init s5pv210_early_console_setup(struct earlycon_device *device,
device->port.private_data = &s5pv210_early_console_data; device->port.private_data = &s5pv210_early_console_data;
return samsung_early_console_setup(device, opt); return samsung_early_console_setup(device, opt);
} }
OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
s5pv210_early_console_setup); s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",

View File

@ -439,16 +439,16 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup,
/* Overrrun error */ /* Overrrun error */
flag = TTY_OVERRUN; flag = TTY_OVERRUN;
tup->uport.icount.overrun++; tup->uport.icount.overrun++;
dev_err(tup->uport.dev, "Got overrun errors\n"); dev_dbg(tup->uport.dev, "Got overrun errors\n");
} else if (lsr & UART_LSR_PE) { } else if (lsr & UART_LSR_PE) {
/* Parity error */ /* Parity error */
flag = TTY_PARITY; flag = TTY_PARITY;
tup->uport.icount.parity++; tup->uport.icount.parity++;
dev_err(tup->uport.dev, "Got Parity errors\n"); dev_dbg(tup->uport.dev, "Got Parity errors\n");
} else if (lsr & UART_LSR_FE) { } else if (lsr & UART_LSR_FE) {
flag = TTY_FRAME; flag = TTY_FRAME;
tup->uport.icount.frame++; tup->uport.icount.frame++;
dev_err(tup->uport.dev, "Got frame errors\n"); dev_dbg(tup->uport.dev, "Got frame errors\n");
} else if (lsr & UART_LSR_BI) { } else if (lsr & UART_LSR_BI) {
/* /*
* Break error * Break error

View File

@ -14,6 +14,7 @@
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
@ -1523,6 +1524,7 @@ static void uart_set_termios(struct tty_struct *tty,
/* Handle transition away from B0 status */ /* Handle transition away from B0 status */
else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
unsigned int mask = TIOCM_DTR; unsigned int mask = TIOCM_DTR;
if (!(cflag & CRTSCTS) || !tty_throttled(tty)) if (!(cflag & CRTSCTS) || !tty_throttled(tty))
mask |= TIOCM_RTS; mask |= TIOCM_RTS;
uart_set_mctrl(uport, mask); uart_set_mctrl(uport, mask);
@ -2279,6 +2281,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
if (console_suspend_enabled || !uart_console(uport)) { if (console_suspend_enabled || !uart_console(uport)) {
/* Protected by port mutex for now */ /* Protected by port mutex for now */
struct tty_struct *tty = port->tty; struct tty_struct *tty = port->tty;
ret = ops->startup(uport); ret = ops->startup(uport);
if (ret == 0) { if (ret == 0) {
if (tty) if (tty)

View File

@ -3301,9 +3301,6 @@ static int sci_probe_single(struct platform_device *dev,
sciport->port.flags |= UPF_HARD_FLOW; sciport->port.flags |= UPF_HARD_FLOW;
} }
if (sci_uart_driver.cons->index == sciport->port.line)
spin_lock_init(&sciport->port.lock);
ret = uart_add_one_port(&sci_uart_driver, &sciport->port); ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
if (ret) { if (ret) {
sci_cleanup_single(sciport); sci_cleanup_single(sciport);

View File

@ -883,7 +883,6 @@ console_initcall(sifive_console_init);
static void __ssp_add_console_port(struct sifive_serial_port *ssp) static void __ssp_add_console_port(struct sifive_serial_port *ssp)
{ {
spin_lock_init(&ssp->port.lock);
sifive_serial_console_ports[ssp->port.line] = ssp; sifive_serial_console_ports[ssp->port.line] = ssp;
} }

View File

@ -129,9 +129,13 @@ static int stm32_config_rs485(struct uart_port *port,
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
cr3 &= ~USART_CR3_DEP; cr3 &= ~USART_CR3_DEP;
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl & ~TIOCM_RTS);
} else { } else {
cr3 |= USART_CR3_DEP; cr3 |= USART_CR3_DEP;
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl | TIOCM_RTS);
} }
writel_relaxed(cr3, port->membase + ofs->cr3); writel_relaxed(cr3, port->membase + ofs->cr3);
@ -847,9 +851,13 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
cr3 &= ~USART_CR3_DEP; cr3 &= ~USART_CR3_DEP;
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl & ~TIOCM_RTS);
} else { } else {
cr3 |= USART_CR3_DEP; cr3 |= USART_CR3_DEP;
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl | TIOCM_RTS);
} }
} else { } else {
@ -1033,8 +1041,9 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
if (WARN_ON(id >= STM32_MAX_PORTS)) if (WARN_ON(id >= STM32_MAX_PORTS))
return NULL; return NULL;
stm32_ports[id].hw_flow_control = of_property_read_bool(np, stm32_ports[id].hw_flow_control =
"st,hw-flow-ctrl"); of_property_read_bool (np, "st,hw-flow-ctrl") /*deprecated*/ ||
of_property_read_bool (np, "uart-has-rtscts");
stm32_ports[id].port.line = id; stm32_ports[id].port.line = id;
stm32_ports[id].cr1_irq = USART_CR1_RXNEIE; stm32_ports[id].cr1_irq = USART_CR1_RXNEIE;
stm32_ports[id].cr3_irq = 0; stm32_ports[id].cr3_irq = 0;

View File

@ -567,9 +567,6 @@ static int hv_probe(struct platform_device *op)
sunserial_console_match(&sunhv_console, op->dev.of_node, sunserial_console_match(&sunhv_console, op->dev.of_node,
&sunhv_reg, port->line, false); &sunhv_reg, port->line, false);
/* We need to initialize lock even for non-registered console */
spin_lock_init(&port->lock);
err = uart_add_one_port(&sunhv_reg, port); err = uart_add_one_port(&sunhv_reg, port);
if (err) if (err)
goto out_unregister_driver; goto out_unregister_driver;

View File

@ -32,7 +32,7 @@
* Register definitions * Register definitions
* *
* For register details see datasheet: * For register details see datasheet:
* http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf * https://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf
*/ */
#define ULITE_RX 0x00 #define ULITE_RX 0x00

View File

@ -252,7 +252,6 @@ struct mgsl_struct {
char device_name[25]; /* device instance name */ char device_name[25]; /* device instance name */
unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */
unsigned char bus; /* expansion bus number (zero based) */ unsigned char bus; /* expansion bus number (zero based) */
unsigned char function; /* PCI device number */ unsigned char function; /* PCI device number */
@ -3432,15 +3431,9 @@ static inline void line_info(struct seq_file *m, struct mgsl_struct *info)
char stat_buf[30]; char stat_buf[30];
unsigned long flags; unsigned long flags;
if (info->bus_type == MGSL_BUS_TYPE_PCI) {
seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
info->device_name, info->io_base, info->irq_level, info->device_name, info->io_base, info->irq_level,
info->phys_memory_base, info->phys_lcr_base); info->phys_memory_base, info->phys_lcr_base);
} else {
seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d",
info->device_name, info->io_base,
info->irq_level, info->dma_level);
}
/* output current serial signal states */ /* output current serial signal states */
spin_lock_irqsave(&info->irq_spinlock,flags); spin_lock_irqsave(&info->irq_spinlock,flags);
@ -3556,54 +3549,27 @@ static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
if ( info->max_frame_size % DMABUFFERSIZE ) if ( info->max_frame_size % DMABUFFERSIZE )
BuffersPerFrame++; BuffersPerFrame++;
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
/* /*
* The PCI adapter has 256KBytes of shared memory to use. * The PCI adapter has 256KBytes of shared memory to use. This is 64
* This is 64 PAGE_SIZE buffers. * PAGE_SIZE buffers.
* *
* The first page is used for padding at this time so the * The first page is used for padding at this time so the buffer list
* buffer list does not begin at offset 0 of the PCI * does not begin at offset 0 of the PCI adapter's shared memory.
* adapter's shared memory.
* *
* The 2nd page is used for the buffer list. A 4K buffer * The 2nd page is used for the buffer list. A 4K buffer list can hold
* list can hold 128 DMA_BUFFER structures at 32 bytes * 128 DMA_BUFFER structures at 32 bytes each.
* each.
* *
* This leaves 62 4K pages. * This leaves 62 4K pages.
* *
* The next N pages are used for transmit frame(s). We * The next N pages are used for transmit frame(s). We reserve enough
* reserve enough 4K page blocks to hold the required * 4K page blocks to hold the required number of transmit dma buffers
* number of transmit dma buffers (num_tx_dma_buffers), * (num_tx_dma_buffers), each of MaxFrameSize size.
* each of MaxFrameSize size.
* *
* Of the remaining pages (62-N), determine how many can * Of the remaining pages (62-N), determine how many can be used to
* be used to receive full MaxFrameSize inbound frames * receive full MaxFrameSize inbound frames
*/ */
info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
info->rx_buffer_count = 62 - info->tx_buffer_count; info->rx_buffer_count = 62 - info->tx_buffer_count;
} else {
/* Calculate the number of PAGE_SIZE buffers needed for */
/* receive and transmit DMA buffers. */
/* Calculate the number of DMA buffers necessary to */
/* hold 7 max size receive frames and one max size transmit frame. */
/* The receive buffer count is bumped by one so we avoid an */
/* End of List condition if all receive buffers are used when */
/* using linked list DMA buffers. */
info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
/*
* limit total TxBuffers & RxBuffers to 62 4K total
* (ala PCI Allocation)
*/
if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 )
info->rx_buffer_count = 62 - info->tx_buffer_count;
}
if ( debug_level >= DEBUG_LEVEL_INFO ) if ( debug_level >= DEBUG_LEVEL_INFO )
printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n", printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",
@ -3652,23 +3618,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
{ {
unsigned int i; unsigned int i;
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
/* PCI adapter uses shared memory. */ /* PCI adapter uses shared memory. */
info->buffer_list = info->memory_base + info->last_mem_alloc; info->buffer_list = info->memory_base + info->last_mem_alloc;
info->buffer_list_phys = info->last_mem_alloc; info->buffer_list_phys = info->last_mem_alloc;
info->last_mem_alloc += BUFFERLISTSIZE; info->last_mem_alloc += BUFFERLISTSIZE;
} else {
/* ISA adapter uses system memory. */
/* The buffer lists are allocated as a common buffer that both */
/* the processor and adapter can access. This allows the driver to */
/* inspect portions of the buffer while other portions are being */
/* updated by the adapter using Bus Master DMA. */
info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL);
if (info->buffer_list == NULL)
return -ENOMEM;
info->buffer_list_phys = (u32)(info->buffer_list_dma_addr);
}
/* We got the memory for the buffer entry lists. */ /* We got the memory for the buffer entry lists. */
/* Initialize the memory block to all zeros. */ /* Initialize the memory block to all zeros. */
@ -3734,9 +3687,6 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
*/ */
static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
{ {
if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI)
dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr);
info->buffer_list = NULL; info->buffer_list = NULL;
info->rx_buffer_list = NULL; info->rx_buffer_list = NULL;
info->tx_buffer_list = NULL; info->tx_buffer_list = NULL;
@ -3762,24 +3712,13 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
{ {
int i; int i;
u32 phys_addr;
/* Allocate page sized buffers for the receive buffer list */ /* Allocate page sized buffers for the receive buffer list */
for ( i = 0; i < Buffercount; i++ ) { for ( i = 0; i < Buffercount; i++ ) {
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
/* PCI adapter uses shared memory buffers. */
BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
phys_addr = info->last_mem_alloc; BufferList[i].phys_addr = info->last_mem_alloc;
info->last_mem_alloc += DMABUFFERSIZE; info->last_mem_alloc += DMABUFFERSIZE;
} else {
/* ISA adapter uses system memory. */
BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL);
if (BufferList[i].virt_addr == NULL)
return -ENOMEM;
phys_addr = (u32)(BufferList[i].dma_addr);
}
BufferList[i].phys_addr = phys_addr;
} }
return 0; return 0;
@ -3807,8 +3746,6 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf
if ( BufferList ) { if ( BufferList ) {
for ( i = 0 ; i < Buffercount ; i++ ) { for ( i = 0 ; i < Buffercount ; i++ ) {
if ( BufferList[i].virt_addr ) { if ( BufferList[i].virt_addr ) {
if ( info->bus_type != MGSL_BUS_TYPE_PCI )
dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr);
BufferList[i].virt_addr = NULL; BufferList[i].virt_addr = NULL;
} }
} }
@ -4040,7 +3977,6 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
} }
info->irq_requested = true; info->irq_requested = true;
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
__FILE__,__LINE__,info->device_name, info->phys_memory_base); __FILE__,__LINE__,info->device_name, info->phys_memory_base);
@ -4054,8 +3990,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
} }
info->lcr_mem_requested = true; info->lcr_mem_requested = true;
info->memory_base = ioremap(info->phys_memory_base, info->memory_base = ioremap(info->phys_memory_base, 0x40000);
0x40000);
if (!info->memory_base) { if (!info->memory_base) {
printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n",
__FILE__,__LINE__,info->device_name, info->phys_memory_base ); __FILE__,__LINE__,info->device_name, info->phys_memory_base );
@ -4068,8 +4003,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
goto errout; goto errout;
} }
info->lcr_base = ioremap(info->phys_lcr_base, info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE);
PAGE_SIZE);
if (!info->lcr_base) { if (!info->lcr_base) {
printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n",
__FILE__,__LINE__,info->device_name, info->phys_lcr_base ); __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
@ -4077,21 +4011,6 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
} }
info->lcr_base += info->lcr_offset; info->lcr_base += info->lcr_offset;
} else {
/* claim DMA channel */
if (request_dma(info->dma_level,info->device_name) < 0){
printk( "%s(%d):Can't request DMA channel on device %s DMA=%d\n",
__FILE__,__LINE__,info->device_name, info->dma_level );
goto errout;
}
info->dma_requested = true;
/* ISA adapter uses bus master DMA */
set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
enable_dma(info->dma_level);
}
if ( mgsl_allocate_dma_buffers(info) < 0 ) { if ( mgsl_allocate_dma_buffers(info) < 0 ) {
printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n", printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n",
__FILE__,__LINE__,info->device_name, info->dma_level ); __FILE__,__LINE__,info->device_name, info->dma_level );
@ -4200,16 +4119,10 @@ static void mgsl_add_device( struct mgsl_struct *info )
else if ( info->max_frame_size > 65535 ) else if ( info->max_frame_size > 65535 )
info->max_frame_size = 65535; info->max_frame_size = 65535;
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
info->hw_version + 1, info->device_name, info->io_base, info->irq_level, info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
info->phys_memory_base, info->phys_lcr_base, info->phys_memory_base, info->phys_lcr_base,
info->max_frame_size ); info->max_frame_size );
} else {
printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
info->device_name, info->io_base, info->irq_level, info->dma_level,
info->max_frame_size );
}
#if SYNCLINK_GENERIC_HDLC #if SYNCLINK_GENERIC_HDLC
hdlcdev_init(info); hdlcdev_init(info);
@ -4420,7 +4333,6 @@ static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
outw( Cmd + info->loopback_bits, info->io_base + CCAR ); outw( Cmd + info->loopback_bits, info->io_base + CCAR );
/* Read to flush write to CCAR */ /* Read to flush write to CCAR */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
inw( info->io_base + CCAR ); inw( info->io_base + CCAR );
} /* end of usc_RTCmd() */ } /* end of usc_RTCmd() */
@ -4445,7 +4357,6 @@ static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
outw( Cmd + info->mbre_bit, info->io_base ); outw( Cmd + info->mbre_bit, info->io_base );
/* Read to flush write to DCAR */ /* Read to flush write to DCAR */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
inw( info->io_base ); inw( info->io_base );
} /* end of usc_DmaCmd() */ } /* end of usc_DmaCmd() */
@ -4475,7 +4386,6 @@ static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
outw( RegValue, info->io_base ); outw( RegValue, info->io_base );
/* Read to flush write to DCAR */ /* Read to flush write to DCAR */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
inw( info->io_base ); inw( info->io_base );
} /* end of usc_OutDmaReg() */ } /* end of usc_OutDmaReg() */
@ -4528,7 +4438,6 @@ static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
outw( RegValue, info->io_base + CCAR ); outw( RegValue, info->io_base + CCAR );
/* Read to flush write to CCAR */ /* Read to flush write to CCAR */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
inw( info->io_base + CCAR ); inw( info->io_base + CCAR );
} /* end of usc_OutReg() */ } /* end of usc_OutReg() */
@ -4728,10 +4637,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
RegValue = usc_InReg( info, RICR ) & 0xc0; RegValue = usc_InReg( info, RICR ) & 0xc0;
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
else
usc_OutReg( info, RICR, (u16)(0x140a | RegValue) );
/* Unlatch all Rx status bits and clear Rx status IRQ Pending */ /* Unlatch all Rx status bits and clear Rx status IRQ Pending */
@ -4792,10 +4698,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
* 0000 0000 0011 0110 = 0x0036 * 0000 0000 0011 0110 = 0x0036
*/ */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
usc_OutReg( info, TICR, 0x0736 ); usc_OutReg( info, TICR, 0x0736 );
else
usc_OutReg( info, TICR, 0x1436 );
usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
@ -4885,10 +4788,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
/* DPLL is enabled. Use BRG1 to provide continuous reference clock */ /* DPLL is enabled. Use BRG1 to provide continuous reference clock */
/* for DPLL. DPLL mode in HCR is dependent on the encoding used. */ /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
XtalSpeed = 11059200; XtalSpeed = 11059200;
else
XtalSpeed = 14745600;
if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
DpllDivisor = 16; DpllDivisor = 16;
@ -5011,13 +4911,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
* 0110 0000 0000 1011 = 0x600b * 0110 0000 0000 1011 = 0x600b
*/ */
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
/* PCI adapter does not need DMA wait state */ /* PCI adapter does not need DMA wait state */
usc_OutDmaReg( info, DCR, 0xa00b ); usc_OutDmaReg( info, DCR, 0xa00b );
}
else
usc_OutDmaReg( info, DCR, 0x800b );
/* Receive DMA mode Register (RDMR) /* Receive DMA mode Register (RDMR)
* *
@ -5109,12 +5004,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
* <7..0> 0x00 Maximum number of clock cycles per bus grant * <7..0> 0x00 Maximum number of clock cycles per bus grant
*/ */
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
/* don't limit bus occupancy on PCI adapter */ /* don't limit bus occupancy on PCI adapter */
usc_OutDmaReg( info, BDCR, 0x0000 ); usc_OutDmaReg( info, BDCR, 0x0000 );
}
else
usc_OutDmaReg( info, BDCR, 0x2000 );
usc_stop_transmitter(info); usc_stop_transmitter(info);
usc_stop_receiver(info); usc_stop_receiver(info);
@ -5155,10 +5046,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable)
/* Write 16-bit Time Constant for BRG0 */ /* Write 16-bit Time Constant for BRG0 */
/* use clock speed if available, otherwise use 8 for diagnostics */ /* use clock speed if available, otherwise use 8 for diagnostics */
if (info->params.clock_speed) { if (info->params.clock_speed) {
if (info->bus_type == MGSL_BUS_TYPE_PCI)
usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
else
usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1));
} else } else
usc_OutReg(info, TC0R, (u16)8); usc_OutReg(info, TC0R, (u16)8);
@ -5201,10 +5089,7 @@ static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
u16 Tc; u16 Tc;
if ( data_rate ) { if ( data_rate ) {
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
XtalSpeed = 11059200; XtalSpeed = 11059200;
else
XtalSpeed = 14745600;
/* Tc = (Xtal/Speed) - 1 */ /* Tc = (Xtal/Speed) - 1 */
@ -5682,7 +5567,6 @@ static void usc_load_txfifo( struct mgsl_struct *info )
*/ */
static void usc_reset( struct mgsl_struct *info ) static void usc_reset( struct mgsl_struct *info )
{ {
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
int i; int i;
u32 readval; u32 readval;
@ -5696,9 +5580,8 @@ static void usc_reset( struct mgsl_struct *info )
*MiscCtrl = info->misc_ctrl_value; *MiscCtrl = info->misc_ctrl_value;
/* /*
* Force at least 170ns delay before clearing * Force at least 170ns delay before clearing reset bit. Each read from
* reset bit. Each read from LCR takes at least * LCR takes at least 30ns so 10 times for 300ns to be safe.
* 30ns so 10 times for 300ns to be safe.
*/ */
for(i=0;i<10;i++) for(i=0;i<10;i++)
readval = *MiscCtrl; readval = *MiscCtrl;
@ -5716,10 +5599,6 @@ static void usc_reset( struct mgsl_struct *info )
0, // NRDD (Read Data-Data) (0-3) 0, // NRDD (Read Data-Data) (0-3)
5 // NRAD (Read Addr-Data) (0-31) 5 // NRAD (Read Addr-Data) (0-31)
); );
} else {
/* do HW reset */
outb( 0,info->io_base + 8 );
}
info->mbre_bit = 0; info->mbre_bit = 0;
info->loopback_bits = 0; info->loopback_bits = 0;
@ -6228,11 +6107,7 @@ static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
* ClkSpeed = 921600 (ISA), 691200 (PCI) * ClkSpeed = 921600 (ISA), 691200 (PCI)
*/ */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
else
usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) );
/* /*
* Hardware Configuration Register (HCR) * Hardware Configuration Register (HCR)
@ -6837,10 +6712,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
/* Actually copy data from source buffer to DMA buffer. */ /* Actually copy data from source buffer to DMA buffer. */
/* Also set the data count for this individual DMA buffer. */ /* Also set the data count for this individual DMA buffer. */
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
else
memcpy(pBufEntry->virt_addr, Buffer, Copycount);
pBufEntry->count = Copycount; pBufEntry->count = Copycount;
@ -7315,9 +7187,6 @@ static bool mgsl_memory_test( struct mgsl_struct *info )
unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long); unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
unsigned long * TestAddr; unsigned long * TestAddr;
if ( info->bus_type != MGSL_BUS_TYPE_PCI )
return true;
TestAddr = (unsigned long *)info->memory_base; TestAddr = (unsigned long *)info->memory_base;
/* Test data lines with test pattern at one location. */ /* Test data lines with test pattern at one location. */
@ -8003,7 +7872,6 @@ static int synclink_init_one (struct pci_dev *dev,
info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1);
info->phys_lcr_base &= ~(PAGE_SIZE-1); info->phys_lcr_base &= ~(PAGE_SIZE-1);
info->bus_type = MGSL_BUS_TYPE_PCI;
info->io_addr_size = 8; info->io_addr_size = 8;
info->irq_flags = IRQF_SHARED; info->irq_flags = IRQF_SHARED;

View File

@ -1405,7 +1405,7 @@ void tty_save_termios(struct tty_struct *tty)
/* Stash the termios data */ /* Stash the termios data */
tp = tty->driver->termios[idx]; tp = tty->driver->termios[idx];
if (tp == NULL) { if (tp == NULL) {
tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); tp = kmalloc(sizeof(*tp), GFP_KERNEL);
if (tp == NULL) if (tp == NULL)
return; return;
tty->driver->termios[idx] = tp; tty->driver->termios[idx] = tp;
@ -2489,7 +2489,7 @@ static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *
struct serial_struct v; struct serial_struct v;
int flags; int flags;
if (copy_from_user(&v, ss, sizeof(struct serial_struct))) if (copy_from_user(&v, ss, sizeof(*ss)))
return -EFAULT; return -EFAULT;
flags = v.flags & ASYNC_DEPRECATED; flags = v.flags & ASYNC_DEPRECATED;
@ -2507,11 +2507,11 @@ static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user *
struct serial_struct v; struct serial_struct v;
int err; int err;
memset(&v, 0, sizeof(struct serial_struct)); memset(&v, 0, sizeof(v));
if (!tty->ops->get_serial) if (!tty->ops->get_serial)
return -ENOTTY; return -ENOTTY;
err = tty->ops->get_serial(tty, &v); err = tty->ops->get_serial(tty, &v);
if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct))) if (!err && copy_to_user(ss, &v, sizeof(v)))
err = -EFAULT; err = -EFAULT;
return err; return err;
} }
@ -2683,7 +2683,7 @@ struct serial_struct32 {
compat_int_t baud_base; compat_int_t baud_base;
unsigned short close_delay; unsigned short close_delay;
char io_type; char io_type;
char reserved_char[1]; char reserved_char;
compat_int_t hub6; compat_int_t hub6;
unsigned short closing_wait; /* time to wait before closing */ unsigned short closing_wait; /* time to wait before closing */
unsigned short closing_wait2; /* no longer used... */ unsigned short closing_wait2; /* no longer used... */
@ -2691,7 +2691,7 @@ struct serial_struct32 {
unsigned short iomem_reg_shift; unsigned short iomem_reg_shift;
unsigned int port_high; unsigned int port_high;
/* compat_ulong_t iomap_base FIXME */ /* compat_ulong_t iomap_base FIXME */
compat_int_t reserved[1]; compat_int_t reserved;
}; };
static int compat_tty_tiocsserial(struct tty_struct *tty, static int compat_tty_tiocsserial(struct tty_struct *tty,
@ -2705,7 +2705,7 @@ static int compat_tty_tiocsserial(struct tty_struct *tty,
struct serial_struct v; struct serial_struct v;
int flags; int flags;
if (copy_from_user(&v32, ss, sizeof(struct serial_struct32))) if (copy_from_user(&v32, ss, sizeof(*ss)))
return -EFAULT; return -EFAULT;
memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base)); memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base));
@ -2743,7 +2743,7 @@ static int compat_tty_tiocgserial(struct tty_struct *tty,
0xfffffff : ptr_to_compat(v.iomem_base); 0xfffffff : ptr_to_compat(v.iomem_base);
v32.iomem_reg_shift = v.iomem_reg_shift; v32.iomem_reg_shift = v.iomem_reg_shift;
v32.port_high = v.port_high; v32.port_high = v.port_high;
if (copy_to_user(ss, &v32, sizeof(struct serial_struct32))) if (copy_to_user(ss, &v32, sizeof(v32)))
err = -EFAULT; err = -EFAULT;
} }
return err; return err;
@ -3215,7 +3215,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1)) if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); driver = kzalloc(sizeof(*driver), GFP_KERNEL);
if (!driver) if (!driver)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);

View File

@ -542,7 +542,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
if (!ct) if (!ct)
return 0; return 0;
unilist = vmemdup_user(list, ct * sizeof(struct unipair)); unilist = vmemdup_user(list, array_size(sizeof(struct unipair), ct));
if (IS_ERR(unilist)) if (IS_ERR(unilist))
return PTR_ERR(unilist); return PTR_ERR(unilist);

View File

@ -32,6 +32,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/nospec.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -2019,7 +2020,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
goto reterr; goto reterr;
} }
kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
i = kbs->kb_func; i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
switch (cmd) { switch (cmd) {
case KDGKBSENT: case KDGKBSENT:

View File

@ -193,7 +193,7 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
/* Allocate a new buffer before freeing the old one ... */ /* Allocate a new buffer before freeing the old one ... */
/* chars can take up to 4 bytes with unicode */ /* chars can take up to 4 bytes with unicode */
bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1, bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
GFP_KERNEL); GFP_KERNEL | __GFP_NOWARN);
if (!bp) { if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n"); printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection(); clear_selection();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -302,14 +302,15 @@ sisusbcon_deinit(struct vc_data *c)
/* interface routine */ /* interface routine */
static u8 static u8
sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, sisusbcon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity,
u8 blink, u8 underline, u8 reverse, u8 unused) bool blink, bool underline, bool reverse,
bool unused)
{ {
u8 attr = color; u8 attr = color;
if (underline) if (underline)
attr = (attr & 0xf0) | c->vc_ulcolor; attr = (attr & 0xf0) | c->vc_ulcolor;
else if (intensity == 0) else if (intensity == VCI_HALF_BRIGHT)
attr = (attr & 0xf0) | c->vc_halfcolor; attr = (attr & 0xf0) | c->vc_halfcolor;
if (reverse) if (reverse)
@ -320,7 +321,7 @@ sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
if (blink) if (blink)
attr ^= 0x80; attr ^= 0x80;
if (intensity == 2) if (intensity == VCI_BOLD)
attr ^= 0x08; attr ^= 0x08;
return attr; return attr;
@ -726,7 +727,7 @@ sisusbcon_cursor(struct vc_data *c, int mode)
baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2); baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
switch (c->vc_cursor_type & 0x0f) { switch (CUR_SIZE(c->vc_cursor_type)) {
case CUR_BLOCK: from = 1; case CUR_BLOCK: from = 1;
to = c->vc_font.height; to = c->vc_font.height;
break; break;

View File

@ -394,8 +394,10 @@ static inline u16 mda_convert_attr(u16 ch)
(ch & 0x00ff) | attr; (ch & 0x00ff) | attr;
} }
static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, static u8 mdacon_build_attr(struct vc_data *c, u8 color,
u8 blink, u8 underline, u8 reverse, u8 italic) enum vc_intensity intensity,
bool blink, bool underline, bool reverse,
bool italic)
{ {
/* The attribute is just a bit vector: /* The attribute is just a bit vector:
* *
@ -405,11 +407,11 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
* Bit 7 : blink * Bit 7 : blink
*/ */
return (intensity & 3) | return (intensity & VCI_MASK) |
((underline & 1) << 2) | (underline << 2) |
((reverse & 1) << 3) | (reverse << 3) |
(!!italic << 4) | (italic << 4) |
((blink & 1) << 7); (blink << 7);
} }
static void mdacon_invert_region(struct vc_data *c, u16 *p, int count) static void mdacon_invert_region(struct vc_data *c, u16 *p, int count)
@ -488,9 +490,9 @@ static void mdacon_cursor(struct vc_data *c, int mode)
return; return;
} }
mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2); mda_set_cursor(c->state.y * mda_num_columns * 2 + c->state.x * 2);
switch (c->vc_cursor_type & 0x0f) { switch (CUR_SIZE(c->vc_cursor_type)) {
case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break; case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break;
case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break; case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break;

View File

@ -362,12 +362,12 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
if (ystart < yend) { if (ystart < yend) {
newport_clear_screen(sx << 3, ystart, xend, yend, newport_clear_screen(sx << 3, ystart, xend, yend,
(vc->vc_color & 0xf0) >> 4); (vc->state.color & 0xf0) >> 4);
} else { } else {
newport_clear_screen(sx << 3, ystart, xend, 1023, newport_clear_screen(sx << 3, ystart, xend, 1023,
(vc->vc_color & 0xf0) >> 4); (vc->state.color & 0xf0) >> 4);
newport_clear_screen(sx << 3, 0, xend, yend, newport_clear_screen(sx << 3, 0, xend, yend,
(vc->vc_color & 0xf0) >> 4); (vc->state.color & 0xf0) >> 4);
} }
} }
@ -591,11 +591,11 @@ static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
topscan = (topscan + (lines << 4)) & 0x3ff; topscan = (topscan + (lines << 4)) & 0x3ff;
newport_clear_lines(vc->vc_rows - lines, newport_clear_lines(vc->vc_rows - lines,
vc->vc_rows - 1, vc->vc_rows - 1,
(vc->vc_color & 0xf0) >> 4); (vc->state.color & 0xf0) >> 4);
} else { } else {
topscan = (topscan + (-lines << 4)) & 0x3ff; topscan = (topscan + (-lines << 4)) & 0x3ff;
newport_clear_lines(0, lines - 1, newport_clear_lines(0, lines - 1,
(vc->vc_color & 0xf0) >> 4); (vc->state.color & 0xf0) >> 4);
} }
npregs->cset.topscan = (topscan - 1) & 0x3ff; npregs->cset.topscan = (topscan - 1) & 0x3ff;
return false; return false;

View File

@ -132,21 +132,21 @@ static void sticon_cursor(struct vc_data *conp, int mode)
{ {
unsigned short car1; unsigned short car1;
car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols]; car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
switch (mode) { switch (mode) {
case CM_ERASE: case CM_ERASE:
sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x); sti_putc(sticon_sti, car1, conp->state.y, conp->state.x);
break; break;
case CM_MOVE: case CM_MOVE:
case CM_DRAW: case CM_DRAW:
switch (conp->vc_cursor_type & 0x0f) { switch (CUR_SIZE(conp->vc_cursor_type)) {
case CUR_UNDERLINE: case CUR_UNDERLINE:
case CUR_LOWER_THIRD: case CUR_LOWER_THIRD:
case CUR_LOWER_HALF: case CUR_LOWER_HALF:
case CUR_TWO_THIRDS: case CUR_TWO_THIRDS:
case CUR_BLOCK: case CUR_BLOCK:
sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
conp->vc_y, conp->vc_x); conp->state.y, conp->state.x);
break; break;
} }
break; break;
@ -288,8 +288,10 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
return ret; return ret;
} }
static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, static u8 sticon_build_attr(struct vc_data *conp, u8 color,
u8 blink, u8 underline, u8 reverse, u8 italic) enum vc_intensity intens,
bool blink, bool underline, bool reverse,
bool italic)
{ {
u8 attr = ((color & 0x70) >> 1) | ((color & 7)); u8 attr = ((color & 0x70) >> 1) | ((color & 7));

View File

@ -251,6 +251,10 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
p = (void *) (c->vc_origin + t * c->vc_size_row); p = (void *) (c->vc_origin + t * c->vc_size_row);
while (count--) { while (count--) {
if ((vgacon_scrollback_cur->tail + c->vc_size_row) >
vgacon_scrollback_cur->size)
vgacon_scrollback_cur->tail = 0;
scr_memcpyw(vgacon_scrollback_cur->data + scr_memcpyw(vgacon_scrollback_cur->data +
vgacon_scrollback_cur->tail, vgacon_scrollback_cur->tail,
p, c->vc_size_row); p, c->vc_size_row);
@ -629,8 +633,10 @@ static void vgacon_deinit(struct vc_data *c)
con_set_default_unimap(c); con_set_default_unimap(c);
} }
static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, static u8 vgacon_build_attr(struct vc_data *c, u8 color,
u8 blink, u8 underline, u8 reverse, u8 italic) enum vc_intensity intensity,
bool blink, bool underline, bool reverse,
bool italic)
{ {
u8 attr = color; u8 attr = color;
@ -639,7 +645,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
attr = (attr & 0xF0) | c->vc_itcolor; attr = (attr & 0xF0) | c->vc_itcolor;
else if (underline) else if (underline)
attr = (attr & 0xf0) | c->vc_ulcolor; attr = (attr & 0xf0) | c->vc_ulcolor;
else if (intensity == 0) else if (intensity == VCI_HALF_BRIGHT)
attr = (attr & 0xf0) | c->vc_halfcolor; attr = (attr & 0xf0) | c->vc_halfcolor;
} }
if (reverse) if (reverse)
@ -648,14 +654,14 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
0x77); 0x77);
if (blink) if (blink)
attr ^= 0x80; attr ^= 0x80;
if (intensity == 2) if (intensity == VCI_BOLD)
attr ^= 0x08; attr ^= 0x08;
if (!vga_can_do_color) { if (!vga_can_do_color) {
if (italic) if (italic)
attr = (attr & 0xF8) | 0x02; attr = (attr & 0xF8) | 0x02;
else if (underline) else if (underline)
attr = (attr & 0xf8) | 0x01; attr = (attr & 0xf8) | 0x01;
else if (intensity == 0) else if (intensity == VCI_HALF_BRIGHT)
attr = (attr & 0xf0) | 0x08; attr = (attr & 0xf0) | 0x08;
} }
return attr; return attr;
@ -718,17 +724,17 @@ static void vgacon_cursor(struct vc_data *c, int mode)
case CM_ERASE: case CM_ERASE:
write_vga(14, (c->vc_pos - vga_vram_base) / 2); write_vga(14, (c->vc_pos - vga_vram_base) / 2);
if (vga_video_type >= VIDEO_TYPE_VGAC) if (vga_video_type >= VIDEO_TYPE_VGAC)
vgacon_set_cursor_size(c->vc_x, 31, 30); vgacon_set_cursor_size(c->state.x, 31, 30);
else else
vgacon_set_cursor_size(c->vc_x, 31, 31); vgacon_set_cursor_size(c->state.x, 31, 31);
break; break;
case CM_MOVE: case CM_MOVE:
case CM_DRAW: case CM_DRAW:
write_vga(14, (c->vc_pos - vga_vram_base) / 2); write_vga(14, (c->vc_pos - vga_vram_base) / 2);
switch (c->vc_cursor_type & 0x0f) { switch (CUR_SIZE(c->vc_cursor_type)) {
case CUR_UNDERLINE: case CUR_UNDERLINE:
vgacon_set_cursor_size(c->vc_x, vgacon_set_cursor_size(c->state.x,
c->vc_font.height - c->vc_font.height -
(c->vc_font.height < (c->vc_font.height <
10 ? 2 : 3), 10 ? 2 : 3),
@ -737,21 +743,21 @@ static void vgacon_cursor(struct vc_data *c, int mode)
10 ? 1 : 2)); 10 ? 1 : 2));
break; break;
case CUR_TWO_THIRDS: case CUR_TWO_THIRDS:
vgacon_set_cursor_size(c->vc_x, vgacon_set_cursor_size(c->state.x,
c->vc_font.height / 3, c->vc_font.height / 3,
c->vc_font.height - c->vc_font.height -
(c->vc_font.height < (c->vc_font.height <
10 ? 1 : 2)); 10 ? 1 : 2));
break; break;
case CUR_LOWER_THIRD: case CUR_LOWER_THIRD:
vgacon_set_cursor_size(c->vc_x, vgacon_set_cursor_size(c->state.x,
(c->vc_font.height * 2) / 3, (c->vc_font.height * 2) / 3,
c->vc_font.height - c->vc_font.height -
(c->vc_font.height < (c->vc_font.height <
10 ? 1 : 2)); 10 ? 1 : 2));
break; break;
case CUR_LOWER_HALF: case CUR_LOWER_HALF:
vgacon_set_cursor_size(c->vc_x, vgacon_set_cursor_size(c->state.x,
c->vc_font.height / 2, c->vc_font.height / 2,
c->vc_font.height - c->vc_font.height -
(c->vc_font.height < (c->vc_font.height <
@ -759,12 +765,12 @@ static void vgacon_cursor(struct vc_data *c, int mode)
break; break;
case CUR_NONE: case CUR_NONE:
if (vga_video_type >= VIDEO_TYPE_VGAC) if (vga_video_type >= VIDEO_TYPE_VGAC)
vgacon_set_cursor_size(c->vc_x, 31, 30); vgacon_set_cursor_size(c->state.x, 31, 30);
else else
vgacon_set_cursor_size(c->vc_x, 31, 31); vgacon_set_cursor_size(c->state.x, 31, 31);
break; break;
default: default:
vgacon_set_cursor_size(c->vc_x, 1, vgacon_set_cursor_size(c->state.x, 1,
c->vc_font.height); c->vc_font.height);
break; break;
} }
@ -1352,8 +1358,8 @@ static void vgacon_save_screen(struct vc_data *c)
* console initialization routines. * console initialization routines.
*/ */
vga_bootup_console = 1; vga_bootup_console = 1;
c->vc_x = screen_info.orig_x; c->state.x = screen_info.orig_x;
c->vc_y = screen_info.orig_y; c->state.y = screen_info.orig_y;
} }
/* We can't copy in more than the size of the video buffer, /* We can't copy in more than the size of the video buffer,

View File

@ -240,8 +240,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
int y = real_y(ops->p, vc->vc_y); int y = real_y(ops->p, vc->state.y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10); int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1; int err = 1;
char *src; char *src;
@ -286,10 +286,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
cursor.set |= FB_CUR_SETCMAP; cursor.set |= FB_CUR_SETCMAP;
} }
if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) || if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
(ops->cursor_state.image.dy != (vc->vc_font.height * y)) || (ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||
ops->cursor_reset) { ops->cursor_reset) {
ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x; ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
ops->cursor_state.image.dy = vc->vc_font.height * y; ops->cursor_state.image.dy = vc->vc_font.height * y;
cursor.set |= FB_CUR_SETPOS; cursor.set |= FB_CUR_SETPOS;
} }
@ -325,7 +325,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
ops->p->cursor_shape = vc->vc_cursor_type; ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE; cursor.set |= FB_CUR_SETSHAPE;
switch (ops->p->cursor_shape & CUR_HWMASK) { switch (CUR_SIZE(ops->p->cursor_shape)) {
case CUR_NONE: case CUR_NONE:
cur_height = 0; cur_height = 0;
break; break;

View File

@ -655,11 +655,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
} }
if (!save) { if (!save) {
int lines; int lines;
if (vc->vc_y + logo_lines >= rows) if (vc->state.y + logo_lines >= rows)
lines = rows - vc->vc_y - 1; lines = rows - vc->state.y - 1;
else else
lines = logo_lines; lines = logo_lines;
vc->vc_y += lines; vc->state.y += lines;
vc->vc_pos += lines * vc->vc_size_row; vc->vc_pos += lines * vc->vc_size_row;
} }
} }
@ -677,7 +677,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
vc->vc_size_row * vc->vc_size_row *
rows); rows);
scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2)); scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2));
vc->vc_y += logo_lines; vc->state.y += logo_lines;
vc->vc_pos += logo_lines * vc->vc_size_row; vc->vc_pos += logo_lines * vc->vc_size_row;
kfree(save); kfree(save);
} }
@ -1393,7 +1393,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
return; return;
if (vc->vc_cursor_type & 0x10) if (vc->vc_cursor_type & CUR_SW)
fbcon_del_cursor_timer(info); fbcon_del_cursor_timer(info);
else else
fbcon_add_cursor_timer(info); fbcon_add_cursor_timer(info);

View File

@ -225,8 +225,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c; int w = (vc->vc_font.height + 7) >> 3, c;
int y = real_y(ops->p, vc->vc_y); int y = real_y(ops->p, vc->state.y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10); int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p->scrollmode, info);
@ -284,7 +284,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
} }
dx = y * vc->vc_font.height; dx = y * vc->vc_font.height;
dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width); dy = vyres - ((vc->state.x + 1) * vc->vc_font.width);
if (ops->cursor_state.image.dx != dx || if (ops->cursor_state.image.dx != dx ||
ops->cursor_state.image.dy != dy || ops->cursor_state.image.dy != dy ||
@ -325,7 +325,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
ops->p->cursor_shape = vc->vc_cursor_type; ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE; cursor.set |= FB_CUR_SETSHAPE;
switch (ops->p->cursor_shape & CUR_HWMASK) { switch (CUR_SIZE(ops->p->cursor_shape)) {
case CUR_NONE: case CUR_NONE:
cur_height = 0; cur_height = 0;
break; break;

View File

@ -208,8 +208,8 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c; int w = (vc->vc_font.height + 7) >> 3, c;
int y = real_y(ops->p, vc->vc_y); int y = real_y(ops->p, vc->state.y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10); int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = GETVXRES(ops->p->scrollmode, info);
@ -267,7 +267,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
} }
dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height); dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height);
dy = vc->vc_x * vc->vc_font.width; dy = vc->state.x * vc->vc_font.width;
if (ops->cursor_state.image.dx != dx || if (ops->cursor_state.image.dx != dx ||
ops->cursor_state.image.dy != dy || ops->cursor_state.image.dy != dy ||
@ -308,7 +308,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
ops->p->cursor_shape = vc->vc_cursor_type; ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE; cursor.set |= FB_CUR_SETSHAPE;
switch (ops->p->cursor_shape & CUR_HWMASK) { switch (CUR_SIZE(ops->p->cursor_shape)) {
case CUR_NONE: case CUR_NONE:
cur_height = 0; cur_height = 0;
break; break;

View File

@ -255,8 +255,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c; int w = (vc->vc_font.width + 7) >> 3, c;
int y = real_y(ops->p, vc->vc_y); int y = real_y(ops->p, vc->state.y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10); int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = GETVYRES(ops->p->scrollmode, info);
@ -315,7 +315,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
} }
dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height); dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height);
dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width); dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width);
if (ops->cursor_state.image.dx != dx || if (ops->cursor_state.image.dx != dx ||
ops->cursor_state.image.dy != dy || ops->cursor_state.image.dy != dy ||
@ -348,7 +348,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
ops->p->cursor_shape = vc->vc_cursor_type; ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE; cursor.set |= FB_CUR_SETSHAPE;
switch (ops->p->cursor_shape & CUR_HWMASK) { switch (CUR_SIZE(ops->p->cursor_shape)) {
case CUR_NONE: case CUR_NONE:
cur_height = 0; cur_height = 0;
break; break;

View File

@ -83,10 +83,10 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int softback_lines, int fg, int bg) int softback_lines, int fg, int bg)
{ {
struct fb_tilecursor cursor; struct fb_tilecursor cursor;
int use_sw = (vc->vc_cursor_type & 0x10); int use_sw = vc->vc_cursor_type & CUR_SW;
cursor.sx = vc->vc_x; cursor.sx = vc->state.x;
cursor.sy = vc->vc_y; cursor.sy = vc->state.y;
cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1; cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
cursor.fg = fg; cursor.fg = fg;
cursor.bg = bg; cursor.bg = bg;

View File

@ -24,17 +24,13 @@ struct module;
struct tty_struct; struct tty_struct;
struct notifier_block; struct notifier_block;
/*
* this is what the terminal answers to a ESC-Z or csi0c query.
*/
#define VT100ID "\033[?1;2c"
#define VT102ID "\033[?6c"
enum con_scroll { enum con_scroll {
SM_UP, SM_UP,
SM_DOWN, SM_DOWN,
}; };
enum vc_intensity;
/** /**
* struct consw - callbacks for consoles * struct consw - callbacks for consoles
* *
@ -74,8 +70,9 @@ struct consw {
void (*con_scrolldelta)(struct vc_data *vc, int lines); void (*con_scrolldelta)(struct vc_data *vc, int lines);
int (*con_set_origin)(struct vc_data *vc); int (*con_set_origin)(struct vc_data *vc);
void (*con_save_screen)(struct vc_data *vc); void (*con_save_screen)(struct vc_data *vc);
u8 (*con_build_attr)(struct vc_data *vc, u8 color, u8 intensity, u8 (*con_build_attr)(struct vc_data *vc, u8 color,
u8 blink, u8 underline, u8 reverse, u8 italic); enum vc_intensity intensity,
bool blink, bool underline, bool reverse, bool italic);
void (*con_invert_region)(struct vc_data *vc, u16 *p, int count); void (*con_invert_region)(struct vc_data *vc, u16 *p, int count);
u16 *(*con_screen_pos)(struct vc_data *vc, int offset); u16 *(*con_screen_pos)(struct vc_data *vc, int offset);
unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position, unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position,

View File

@ -21,6 +21,43 @@ struct uni_pagedir;
struct uni_screen; struct uni_screen;
#define NPAR 16 #define NPAR 16
#define VC_TABSTOPS_COUNT 256U
enum vc_intensity {
VCI_HALF_BRIGHT,
VCI_NORMAL,
VCI_BOLD,
VCI_MASK = 0x3,
};
/**
* struct vc_state -- state of a VC
* @x: cursor's x-position
* @y: cursor's y-position
* @color: foreground & background colors
* @Gx_charset: what's G0/G1 slot set to (like GRAF_MAP, LAT1_MAP)
* @charset: what character set to use (0=G0 or 1=G1)
* @intensity: see enum vc_intensity for values
* @reverse: reversed foreground/background colors
*
* These members are defined separately from struct vc_data as we save &
* restore them at times.
*/
struct vc_state {
unsigned int x, y;
unsigned char color;
unsigned char Gx_charset[2];
unsigned int charset : 1;
/* attribute flags */
enum vc_intensity intensity;
bool italic;
bool underline;
bool blink;
bool reverse;
};
/* /*
* Example: vc_data of a console that was scrolled 3 lines down. * Example: vc_data of a console that was scrolled 3 lines down.
@ -57,6 +94,8 @@ struct uni_screen;
struct vc_data { struct vc_data {
struct tty_port port; /* Upper level data */ struct tty_port port; /* Upper level data */
struct vc_state state, saved_state;
unsigned short vc_num; /* Console number */ unsigned short vc_num; /* Console number */
unsigned int vc_cols; /* [#] Console size */ unsigned int vc_cols; /* [#] Console size */
unsigned int vc_rows; unsigned int vc_rows;
@ -73,8 +112,6 @@ struct vc_data {
/* attributes for all characters on screen */ /* attributes for all characters on screen */
unsigned char vc_attr; /* Current attributes */ unsigned char vc_attr; /* Current attributes */
unsigned char vc_def_color; /* Default colors */ unsigned char vc_def_color; /* Default colors */
unsigned char vc_color; /* Foreground & background */
unsigned char vc_s_color; /* Saved foreground & background */
unsigned char vc_ulcolor; /* Color for underline mode */ unsigned char vc_ulcolor; /* Color for underline mode */
unsigned char vc_itcolor; unsigned char vc_itcolor;
unsigned char vc_halfcolor; /* Color for half intensity mode */ unsigned char vc_halfcolor; /* Color for half intensity mode */
@ -82,8 +119,6 @@ struct vc_data {
unsigned int vc_cursor_type; unsigned int vc_cursor_type;
unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */ unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */
unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */ unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
unsigned int vc_x, vc_y; /* Cursor position */
unsigned int vc_saved_x, vc_saved_y;
unsigned long vc_pos; /* Cursor address */ unsigned long vc_pos; /* Cursor address */
/* fonts */ /* fonts */
unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */ unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
@ -98,8 +133,6 @@ struct vc_data {
int vt_newvt; int vt_newvt;
wait_queue_head_t paste_wait; wait_queue_head_t paste_wait;
/* mode flags */ /* mode flags */
unsigned int vc_charset : 1; /* Character set G0 / G1 */
unsigned int vc_s_charset : 1; /* Saved character set */
unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */ unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */
unsigned int vc_toggle_meta : 1; /* Toggle high bit? */ unsigned int vc_toggle_meta : 1; /* Toggle high bit? */
unsigned int vc_decscnm : 1; /* Screen Mode */ unsigned int vc_decscnm : 1; /* Screen Mode */
@ -107,17 +140,6 @@ struct vc_data {
unsigned int vc_decawm : 1; /* Autowrap Mode */ unsigned int vc_decawm : 1; /* Autowrap Mode */
unsigned int vc_deccm : 1; /* Cursor Visible */ unsigned int vc_deccm : 1; /* Cursor Visible */
unsigned int vc_decim : 1; /* Insert Mode */ unsigned int vc_decim : 1; /* Insert Mode */
/* attribute flags */
unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
unsigned int vc_italic:1;
unsigned int vc_underline : 1;
unsigned int vc_blink : 1;
unsigned int vc_reverse : 1;
unsigned int vc_s_intensity : 2; /* saved rendition */
unsigned int vc_s_italic:1;
unsigned int vc_s_underline : 1;
unsigned int vc_s_blink : 1;
unsigned int vc_s_reverse : 1;
/* misc */ /* misc */
unsigned int vc_priv : 3; unsigned int vc_priv : 3;
unsigned int vc_need_wrap : 1; unsigned int vc_need_wrap : 1;
@ -126,13 +148,9 @@ struct vc_data {
unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */ unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
unsigned char vc_utf_count; unsigned char vc_utf_count;
int vc_utf_char; int vc_utf_char;
unsigned int vc_tab_stop[8]; /* Tab stops. 256 columns. */ DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */
unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */
unsigned short * vc_translate; unsigned short * vc_translate;
unsigned char vc_G0_charset;
unsigned char vc_G1_charset;
unsigned char vc_saved_G0;
unsigned char vc_saved_G1;
unsigned int vc_resize_user; /* resize request from user */ unsigned int vc_resize_user; /* resize request from user */
unsigned int vc_bell_pitch; /* Console bell pitch */ unsigned int vc_bell_pitch; /* Console bell pitch */
unsigned int vc_bell_duration; /* Console bell duration */ unsigned int vc_bell_duration; /* Console bell duration */
@ -149,13 +167,15 @@ struct vc {
struct work_struct SAK_work; struct work_struct SAK_work;
/* might add scrmem, kbd at some time, /* might add scrmem, kbd at some time,
to have everything in one place - the disadvantage to have everything in one place */
would be that vc_cons etc can no longer be static */
}; };
extern struct vc vc_cons [MAX_NR_CONSOLES]; extern struct vc vc_cons [MAX_NR_CONSOLES];
extern void vc_SAK(struct work_struct *work); extern void vc_SAK(struct work_struct *work);
#define CUR_MAKE(size, change, set) ((size) | ((change) << 8) | \
((set) << 16))
#define CUR_SIZE(c) ((c) & 0x00000f)
# define CUR_DEF 0 # define CUR_DEF 0
# define CUR_NONE 1 # define CUR_NONE 1
# define CUR_UNDERLINE 2 # define CUR_UNDERLINE 2
@ -163,10 +183,13 @@ extern void vc_SAK(struct work_struct *work);
# define CUR_LOWER_HALF 4 # define CUR_LOWER_HALF 4
# define CUR_TWO_THIRDS 5 # define CUR_TWO_THIRDS 5
# define CUR_BLOCK 6 # define CUR_BLOCK 6
#define CUR_HWMASK 0x0f #define CUR_SW 0x000010
#define CUR_SWMASK 0xfff0 #define CUR_ALWAYS_BG 0x000020
#define CUR_INVERT_FG_BG 0x000040
#define CUR_DEFAULT CUR_UNDERLINE #define CUR_FG 0x000700
#define CUR_BG 0x007000
#define CUR_CHANGE(c) ((c) & 0x00ff00)
#define CUR_SET(c) (((c) & 0xff0000) >> 8)
bool con_is_visible(const struct vc_data *vc); bool con_is_visible(const struct vc_data *vc);

View File

@ -155,6 +155,8 @@ extern int early_serial_setup(struct uart_port *port);
extern int early_serial8250_setup(struct earlycon_device *device, extern int early_serial8250_setup(struct earlycon_device *device,
const char *options); const char *options);
extern void serial8250_update_uartclk(struct uart_port *port,
unsigned int uartclk);
extern void serial8250_do_set_termios(struct uart_port *port, extern void serial8250_do_set_termios(struct uart_port *port,
struct ktermios *termios, struct ktermios *old); struct ktermios *termios, struct ktermios *old);
extern void serial8250_do_set_ldisc(struct uart_port *port, extern void serial8250_do_set_ldisc(struct uart_port *port,

View File

@ -10,7 +10,6 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/circ_buf.h> #include <linux/circ_buf.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
@ -30,6 +29,7 @@
struct uart_port; struct uart_port;
struct serial_struct; struct serial_struct;
struct device; struct device;
struct gpio_desc;
/* /*
* This structure describes all the operations that can be done on the * This structure describes all the operations that can be done on the

View File

@ -74,8 +74,6 @@ int con_set_default_unimap(struct vc_data *vc);
void con_free_unimap(struct vc_data *vc); void con_free_unimap(struct vc_data *vc);
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \
((vc)->vc_toggle_meta ? 0x80 : 0)])
#else #else
static inline int con_set_trans_old(unsigned char __user *table) static inline int con_set_trans_old(unsigned char __user *table)
{ {
@ -124,7 +122,6 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
return 0; return 0;
} }
#define vc_translate(vc, c) (c)
#endif #endif
/* vt.c */ /* vt.c */

View File

@ -26,20 +26,6 @@
/* /*
* The type definitions. These are from Ted Ts'o's serial.h * The type definitions. These are from Ted Ts'o's serial.h
*/ */
#define PORT_UNKNOWN 0
#define PORT_8250 1
#define PORT_16450 2
#define PORT_16550 3
#define PORT_16550A 4
#define PORT_CIRRUS 5
#define PORT_16650 6
#define PORT_16650V2 7
#define PORT_16750 8
#define PORT_STARTECH 9
#define PORT_16C950 10
#define PORT_16654 11
#define PORT_16850 12
#define PORT_RSA 13
#define PORT_NS16550A 14 #define PORT_NS16550A 14
#define PORT_XSCALE 15 #define PORT_XSCALE 15
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */