TTY/Serial driver updates for 5.8-rc1
Here is the tty and serial driver updates for 5.8-rc1 Nothing huge at all, just a lot of little serial driver fixes, updates for new devices and features, and other small things. Full details are in the shortlog. Note, you will get a conflict merging with your tree in the Documentation/devicetree/bindings/serial/rs485.yaml file, but it should be pretty obvious what to do. If not, I'm sure Rob will clean it all up afterwards :) All of these have been in linux-next with no issues for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXtzpCg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylRxACgjGtOKPjahONL4lWd0F8ZYEcyw7sAn34woBCO BDUV3kolrRQ4OYNJWsHP =TvqG -----END PGP SIGNATURE----- Merge tag 'tty-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial driver updates from Greg KH: "Here is the tty and serial driver updates for 5.8-rc1 Nothing huge at all, just a lot of little serial driver fixes, updates for new devices and features, and other small things. Full details are in the shortlog. All of these have been in linux-next with no issues for a while" * tag 'tty-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (67 commits) tty: serial: qcom_geni_serial: Add 51.2MHz frequency support tty: serial: imx: clear Ageing Timer Interrupt in handler serial: 8250_fintek: Add F81966 Support sc16is7xx: Add flag to activate IrDA mode dt-bindings: sc16is7xx: Add flag to activate IrDA mode serial: 8250: Support rs485 bus termination GPIO serial: 8520_port: Fix function param documentation dt-bindings: serial: Add binding for rs485 bus termination GPIO vt: keyboard: avoid signed integer overflow in k_ascii serial: 8250: Enable 16550A variants by default on non-x86 tty: hvc_console, fix crashes on parallel open/close serial: imx: Initialize lock for non-registered console sc16is7xx: Read the LSR register for basic device presence check sc16is7xx: Allow sharing the IRQ line sc16is7xx: Use threaded IRQ sc16is7xx: Always use falling edge IRQ tty: n_gsm: Fix bogus i++ in gsm_data_kick tty: n_gsm: Remove unnecessary test in gsm_print_packet() serial: stm32: add no_console_suspend support tty: serial: fsl_lpuart: Use __maybe_unused instead of #if CONFIG_PM_SLEEP ...
This commit is contained in:
commit
081096d98b
|
@ -231,13 +231,13 @@ prints help, and C) an action_msg string, that will print right before your
|
|||
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
|
||||
|
||||
After the ``sysrq_key_op`` is created, you can call the kernel function
|
||||
``register_sysrq_key(int key, struct sysrq_key_op *op_p);`` this will
|
||||
``register_sysrq_key(int key, const struct sysrq_key_op *op_p);`` this will
|
||||
register the operation pointed to by ``op_p`` at table key 'key',
|
||||
if that slot in the table is blank. At module unload time, you must call
|
||||
the function ``unregister_sysrq_key(int key, struct sysrq_key_op *op_p)``, which
|
||||
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
|
||||
it is currently registered in that slot. This is in case the slot has been
|
||||
overwritten since you registered it.
|
||||
the function ``unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)``,
|
||||
which will remove the key op pointed to by 'op_p' from the key 'key', if and
|
||||
only if it is currently registered in that slot. This is in case the slot has
|
||||
been overwritten since you registered it.
|
||||
|
||||
The Magic SysRQ system works by registering key operations against a key op
|
||||
lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
|
||||
|
|
|
@ -21,6 +21,8 @@ Optional properties:
|
|||
the second cell is used to specify the GPIO polarity:
|
||||
0 = active high,
|
||||
1 = active low.
|
||||
- irda-mode-ports: An array that lists the indices of the port that
|
||||
should operate in IrDA mode.
|
||||
|
||||
Example:
|
||||
sc16is750: sc16is750@51 {
|
||||
|
@ -55,6 +57,8 @@ Optional properties:
|
|||
the second cell is used to specify the GPIO polarity:
|
||||
0 = active high,
|
||||
1 = active low.
|
||||
- irda-mode-ports: An array that lists the indices of the port that
|
||||
should operate in IrDA mode.
|
||||
|
||||
Example:
|
||||
sc16is750: sc16is750@0 {
|
||||
|
|
|
@ -41,4 +41,8 @@ properties:
|
|||
rs485-rx-during-tx:
|
||||
description: enables the receiving of data even while sending data.
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
rs485-term-gpios:
|
||||
description: GPIO pin to enable RS485 bus termination.
|
||||
maxItems: 1
|
||||
...
|
||||
|
|
|
@ -29,6 +29,14 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reg-io-width:
|
||||
description: |
|
||||
The size (in bytes) of the IO accesses that should be performed
|
||||
on the device.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [ 1, 4 ]
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 5
|
||||
|
|
|
@ -48,6 +48,12 @@ properties:
|
|||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
cts-gpios:
|
||||
maxItems: 1
|
||||
|
||||
rts-gpios:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
rs485-rts-delay: true
|
||||
|
@ -55,6 +61,14 @@ properties:
|
|||
linux,rs485-enabled-at-boot-time: true
|
||||
rs485-rx-during-tx: true
|
||||
|
||||
if:
|
||||
required:
|
||||
- st,hw-flow-ctrl
|
||||
then:
|
||||
properties:
|
||||
cts-gpios: false
|
||||
rts-gpios: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -430,6 +430,15 @@ register_cpus(void)
|
|||
|
||||
arch_initcall(register_cpus);
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static const struct sysrq_key_op srm_sysrq_reboot_op = {
|
||||
.handler = machine_halt,
|
||||
.help_msg = "reboot(b)",
|
||||
.action_msg = "Resetting",
|
||||
.enable_mask = SYSRQ_ENABLE_BOOT,
|
||||
};
|
||||
#endif
|
||||
|
||||
void __init
|
||||
setup_arch(char **cmdline_p)
|
||||
{
|
||||
|
@ -550,8 +559,8 @@ setup_arch(char **cmdline_p)
|
|||
/* If we're using SRM, make sysrq-b halt back to the prom,
|
||||
not auto-reboot. */
|
||||
if (alpha_using_srm) {
|
||||
struct sysrq_key_op *op = __sysrq_get_key_op('b');
|
||||
op->handler = (void *) machine_halt;
|
||||
unregister_sysrq_key('b', __sysrq_reboot_op);
|
||||
register_sysrq_key('b', &srm_sysrq_reboot_op);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ static void sysrq_handle_tlbdump(int key)
|
|||
#endif
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_tlbdump_op = {
|
||||
static const struct sysrq_key_op sysrq_tlbdump_op = {
|
||||
.handler = sysrq_handle_tlbdump,
|
||||
.help_msg = "show-tlbs(x)",
|
||||
.action_msg = "Show TLB entries",
|
||||
|
|
|
@ -3919,7 +3919,7 @@ static void sysrq_handle_xmon(int key)
|
|||
xmon_init(0);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_xmon_op = {
|
||||
static const struct sysrq_key_op sysrq_xmon_op = {
|
||||
.handler = sysrq_handle_xmon,
|
||||
.help_msg = "xmon(x)",
|
||||
.action_msg = "Entering xmon",
|
||||
|
|
|
@ -313,7 +313,7 @@ static void sysrq_handle_globreg(int key)
|
|||
trigger_all_cpu_backtrace();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sparc_globalreg_op = {
|
||||
static const struct sysrq_key_op sparc_globalreg_op = {
|
||||
.handler = sysrq_handle_globreg,
|
||||
.help_msg = "global-regs(y)",
|
||||
.action_msg = "Show Global CPU Regs",
|
||||
|
@ -388,7 +388,7 @@ static void sysrq_handle_globpmu(int key)
|
|||
pmu_snapshot_all_cpus();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sparc_globalpmu_op = {
|
||||
static const struct sysrq_key_op sparc_globalpmu_op = {
|
||||
.handler = sysrq_handle_globpmu,
|
||||
.help_msg = "global-pmu(x)",
|
||||
.action_msg = "Show Global PMU Regs",
|
||||
|
|
|
@ -307,13 +307,13 @@ static void drm_fb_helper_sysrq(int dummy1)
|
|||
schedule_work(&drm_fb_helper_restore_work);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
|
||||
static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
|
||||
.handler = drm_fb_helper_sysrq,
|
||||
.help_msg = "force-fb(V)",
|
||||
.action_msg = "Restore framebuffer console",
|
||||
};
|
||||
#else
|
||||
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
|
||||
static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
|
||||
#endif
|
||||
|
||||
static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
|
||||
|
|
|
@ -371,15 +371,14 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
|
|||
* tty fields and return the kref reference.
|
||||
*/
|
||||
if (rc) {
|
||||
tty_port_tty_set(&hp->port, NULL);
|
||||
tty->driver_data = NULL;
|
||||
tty_port_put(&hp->port);
|
||||
printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
|
||||
} else
|
||||
} else {
|
||||
/* We are ready... raise DTR/RTS */
|
||||
if (C_BAUD(tty))
|
||||
if (hp->ops->dtr_rts)
|
||||
hp->ops->dtr_rts(hp, 1);
|
||||
tty_port_set_initialized(&hp->port, true);
|
||||
}
|
||||
|
||||
/* Force wakeup of the polling thread */
|
||||
hvc_kick();
|
||||
|
@ -389,22 +388,12 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
|
|||
|
||||
static void hvc_close(struct tty_struct *tty, struct file * filp)
|
||||
{
|
||||
struct hvc_struct *hp;
|
||||
struct hvc_struct *hp = tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
||||
if (tty_hung_up_p(filp))
|
||||
return;
|
||||
|
||||
/*
|
||||
* No driver_data means that this close was issued after a failed
|
||||
* hvc_open by the tty layer's release_dev() function and we can just
|
||||
* exit cleanly because the kref reference wasn't made.
|
||||
*/
|
||||
if (!tty->driver_data)
|
||||
return;
|
||||
|
||||
hp = tty->driver_data;
|
||||
|
||||
spin_lock_irqsave(&hp->port.lock, flags);
|
||||
|
||||
if (--hp->port.count == 0) {
|
||||
|
@ -412,6 +401,9 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
|
|||
/* We are done with the tty pointer now. */
|
||||
tty_port_tty_set(&hp->port, NULL);
|
||||
|
||||
if (!tty_port_initialized(&hp->port))
|
||||
return;
|
||||
|
||||
if (C_HUPCL(tty))
|
||||
if (hp->ops->dtr_rts)
|
||||
hp->ops->dtr_rts(hp, 0);
|
||||
|
@ -428,6 +420,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
|
|||
* waking periodically to check chars_in_buffer().
|
||||
*/
|
||||
tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
|
||||
tty_port_set_initialized(&hp->port, false);
|
||||
} else {
|
||||
if (hp->port.count < 0)
|
||||
printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
|
||||
|
|
|
@ -196,8 +196,6 @@ module_param(hvcs_parm_num_devs, int, 0);
|
|||
|
||||
static const char hvcs_driver_name[] = "hvcs";
|
||||
static const char hvcs_device_node[] = "hvcs";
|
||||
static const char hvcs_driver_string[]
|
||||
= "IBM hvcs (Hypervisor Virtual Console Server) Driver";
|
||||
|
||||
/* Status of partner info rescan triggered via sysfs. */
|
||||
static int hvcs_rescan_status;
|
||||
|
|
|
@ -638,16 +638,15 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd)
|
|||
* This routine is called to set the UART divisor registers to match
|
||||
* the specified baud rate for a serial port.
|
||||
*/
|
||||
static int mxser_change_speed(struct tty_struct *tty)
|
||||
static void mxser_change_speed(struct tty_struct *tty)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
unsigned cflag, cval, fcr;
|
||||
int ret = 0;
|
||||
unsigned char status;
|
||||
|
||||
cflag = tty->termios.c_cflag;
|
||||
if (!info->ioaddr)
|
||||
return ret;
|
||||
return;
|
||||
|
||||
if (mxser_set_baud_method[tty->index] == 0)
|
||||
mxser_set_baud(tty, tty_get_baud_rate(tty));
|
||||
|
@ -803,8 +802,6 @@ static int mxser_change_speed(struct tty_struct *tty)
|
|||
|
||||
outb(fcr, info->ioaddr + UART_FCR); /* set fcr */
|
||||
outb(cval, info->ioaddr + UART_LCR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mxser_check_modem_status(struct tty_struct *tty,
|
||||
|
|
|
@ -504,18 +504,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
|
|||
else
|
||||
pr_cont("(F)");
|
||||
|
||||
if (dlen) {
|
||||
int ct = 0;
|
||||
while (dlen--) {
|
||||
if (ct % 8 == 0) {
|
||||
pr_cont("\n");
|
||||
pr_debug(" ");
|
||||
}
|
||||
pr_cont("%02X ", *data++);
|
||||
ct++;
|
||||
}
|
||||
}
|
||||
pr_cont("\n");
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_NONE, data, dlen);
|
||||
}
|
||||
|
||||
|
||||
|
@ -673,11 +662,10 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
|
|||
* FIXME: lock against link layer control transmissions
|
||||
*/
|
||||
|
||||
static void gsm_data_kick(struct gsm_mux *gsm)
|
||||
static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci)
|
||||
{
|
||||
struct gsm_msg *msg, *nmsg;
|
||||
int len;
|
||||
int skip_sof = 0;
|
||||
|
||||
list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) {
|
||||
if (gsm->constipated && msg->addr)
|
||||
|
@ -699,18 +687,23 @@ static void gsm_data_kick(struct gsm_mux *gsm)
|
|||
print_hex_dump_bytes("gsm_data_kick: ",
|
||||
DUMP_PREFIX_OFFSET,
|
||||
gsm->txframe, len);
|
||||
|
||||
if (gsm->output(gsm, gsm->txframe + skip_sof,
|
||||
len - skip_sof) < 0)
|
||||
if (gsm->output(gsm, gsm->txframe, len) < 0)
|
||||
break;
|
||||
/* FIXME: Can eliminate one SOF in many more cases */
|
||||
gsm->tx_bytes -= msg->len;
|
||||
/* For a burst of frames skip the extra SOF within the
|
||||
burst */
|
||||
skip_sof = 1;
|
||||
|
||||
list_del(&msg->list);
|
||||
kfree(msg);
|
||||
|
||||
if (dlci) {
|
||||
tty_port_tty_wakeup(&dlci->port);
|
||||
} else {
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < NUM_DLCI; i++)
|
||||
if (gsm->dlci[i])
|
||||
tty_port_tty_wakeup(&gsm->dlci[i]->port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +755,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
|
|||
/* Add to the actual output queue */
|
||||
list_add_tail(&msg->list, &gsm->tx_list);
|
||||
gsm->tx_bytes += msg->len;
|
||||
gsm_data_kick(gsm);
|
||||
gsm_data_kick(gsm, dlci);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1223,7 +1216,7 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
|
|||
gsm_control_reply(gsm, CMD_FCON, NULL, 0);
|
||||
/* Kick the link in case it is idling */
|
||||
spin_lock_irqsave(&gsm->tx_lock, flags);
|
||||
gsm_data_kick(gsm);
|
||||
gsm_data_kick(gsm, NULL);
|
||||
spin_unlock_irqrestore(&gsm->tx_lock, flags);
|
||||
break;
|
||||
case CMD_FCOFF:
|
||||
|
@ -2545,7 +2538,7 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
|
|||
/* Queue poll */
|
||||
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||
spin_lock_irqsave(&gsm->tx_lock, flags);
|
||||
gsm_data_kick(gsm);
|
||||
gsm_data_kick(gsm, NULL);
|
||||
if (gsm->tx_bytes < TX_THRESH_LO) {
|
||||
gsm_dlci_data_sweep(gsm);
|
||||
}
|
||||
|
|
|
@ -1885,7 +1885,7 @@ static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
|
|||
*/
|
||||
static __init int register_PCI(int i, struct pci_dev *dev)
|
||||
{
|
||||
int num_aiops, aiop, max_num_aiops, num_chan, chan;
|
||||
int num_aiops, aiop, max_num_aiops, chan;
|
||||
unsigned int aiopio[MAX_AIOPS_PER_BOARD];
|
||||
CONTROLLER_t *ctlp;
|
||||
|
||||
|
@ -2157,8 +2157,7 @@ static __init int register_PCI(int i, struct pci_dev *dev)
|
|||
/* Reset the AIOPIC, init the serial ports */
|
||||
for (aiop = 0; aiop < num_aiops; aiop++) {
|
||||
sResetAiopByNum(ctlp, aiop);
|
||||
num_chan = ports_per_aiop;
|
||||
for (chan = 0; chan < num_chan; chan++)
|
||||
for (chan = 0; chan < ports_per_aiop; chan++)
|
||||
init_r_port(i, aiop, chan, dev);
|
||||
}
|
||||
|
||||
|
@ -2166,11 +2165,10 @@ static __init int register_PCI(int i, struct pci_dev *dev)
|
|||
if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
|
||||
(rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
|
||||
(rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
|
||||
num_chan = ports_per_aiop;
|
||||
for (chan = 0; chan < num_chan; chan++)
|
||||
for (chan = 0; chan < ports_per_aiop; chan++)
|
||||
sPCIModemReset(ctlp, chan, 1);
|
||||
msleep(500);
|
||||
for (chan = 0; chan < num_chan; chan++)
|
||||
for (chan = 0; chan < ports_per_aiop; chan++)
|
||||
sPCIModemReset(ctlp, chan, 0);
|
||||
msleep(500);
|
||||
rmSpeakerReset(ctlp, rocketModel[i].model);
|
||||
|
|
|
@ -1026,7 +1026,9 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|||
|
||||
if (up->port.dev) {
|
||||
uart->port.dev = up->port.dev;
|
||||
uart_get_rs485_mode(uart->port.dev, &uart->port.rs485);
|
||||
ret = uart_get_rs485_mode(&uart->port);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (up->port.flags & UPF_FIXED_TYPE)
|
||||
|
@ -1040,7 +1042,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|||
gpios = mctrl_gpio_init(&uart->port, 0);
|
||||
if (IS_ERR(gpios)) {
|
||||
ret = PTR_ERR(gpios);
|
||||
goto out_unlock;
|
||||
goto err;
|
||||
} else {
|
||||
uart->gpios = gpios;
|
||||
}
|
||||
|
@ -1089,8 +1091,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|||
serial8250_apply_quirks(uart);
|
||||
ret = uart_add_one_port(&serial8250_reg,
|
||||
&uart->port);
|
||||
if (ret == 0)
|
||||
ret = uart->port.line;
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = uart->port.line;
|
||||
} else {
|
||||
dev_info(uart->port.dev,
|
||||
"skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
|
||||
|
@ -1112,10 +1116,14 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&serial_mutex);
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
uart->port.dev = NULL;
|
||||
mutex_unlock(&serial_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(serial8250_register_8250_port);
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
|
||||
#include "8250.h"
|
||||
|
||||
#define PCI_DEVICE_ID_ACCES_COM_2S 0x1052
|
||||
#define PCI_DEVICE_ID_ACCES_COM_4S 0x105d
|
||||
#define PCI_DEVICE_ID_ACCES_COM_8S 0x106c
|
||||
#define PCI_DEVICE_ID_ACCES_COM232_8 0x10a8
|
||||
#define PCI_DEVICE_ID_ACCES_COM_2SM 0x10d2
|
||||
#define PCI_DEVICE_ID_ACCES_COM_4SM 0x10db
|
||||
#define PCI_DEVICE_ID_ACCES_COM_8SM 0x10ea
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_8S 0x106c
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM232_8 0x10a8
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_2SM 0x10d2
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_4SM 0x10db
|
||||
#define PCI_DEVICE_ID_ACCESSIO_COM_8SM 0x10ea
|
||||
|
||||
#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
|
||||
#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
|
||||
|
@ -755,9 +755,7 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
|
|||
(kernel_ulong_t)&bd \
|
||||
}
|
||||
|
||||
#define EXAR_DEVICE(vend, devid, bd) { \
|
||||
PCI_VDEVICE(vend, PCI_DEVICE_ID_##devid), (kernel_ulong_t)&bd \
|
||||
}
|
||||
#define EXAR_DEVICE(vend, devid, bd) { PCI_DEVICE_DATA(vend, devid, &bd) }
|
||||
|
||||
#define IBM_DEVICE(devid, sdevid, bd) { \
|
||||
PCI_DEVICE_SUB( \
|
||||
|
@ -769,14 +767,13 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
|
|||
}
|
||||
|
||||
static const struct pci_device_id exar_pci_tbl[] = {
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM_2S, acces_com_2x),
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM_4S, acces_com_4x),
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM_8S, acces_com_8x),
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM232_8, acces_com_8x),
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM_2SM, acces_com_2x),
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM_4SM, acces_com_4x),
|
||||
EXAR_DEVICE(ACCESSIO, ACCES_COM_8SM, acces_com_8x),
|
||||
|
||||
EXAR_DEVICE(ACCESSIO, COM_2S, acces_com_2x),
|
||||
EXAR_DEVICE(ACCESSIO, COM_4S, acces_com_4x),
|
||||
EXAR_DEVICE(ACCESSIO, COM_8S, acces_com_8x),
|
||||
EXAR_DEVICE(ACCESSIO, COM232_8, acces_com_8x),
|
||||
EXAR_DEVICE(ACCESSIO, COM_2SM, acces_com_2x),
|
||||
EXAR_DEVICE(ACCESSIO, COM_4SM, acces_com_4x),
|
||||
EXAR_DEVICE(ACCESSIO, COM_8SM, acces_com_8x),
|
||||
|
||||
CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
|
||||
CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),
|
||||
|
@ -794,24 +791,24 @@ static const struct pci_device_id exar_pci_tbl[] = {
|
|||
IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn),
|
||||
|
||||
/* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17C152, pbn_exar_XR17C15x),
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17C154, pbn_exar_XR17C15x),
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17C158, pbn_exar_XR17C15x),
|
||||
EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x),
|
||||
EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x),
|
||||
EXAR_DEVICE(EXAR, XR17C158, pbn_exar_XR17C15x),
|
||||
|
||||
/* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17V352, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17V354, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17V358, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17V4358, pbn_exar_XR17V4358),
|
||||
EXAR_DEVICE(EXAR, EXAR_XR17V8358, pbn_exar_XR17V8358),
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_4222PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_4224PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_4228PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, XR17V352, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, XR17V354, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, XR17V358, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, XR17V4358, pbn_exar_XR17V4358),
|
||||
EXAR_DEVICE(EXAR, XR17V8358, pbn_exar_XR17V8358),
|
||||
EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_exar_XR17V35x),
|
||||
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_4222PCI335, pbn_fastcom335_2),
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_4224PCI335, pbn_fastcom335_4),
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_2324PCI335, pbn_fastcom335_4),
|
||||
EXAR_DEVICE(COMMTECH, COMMTECH_2328PCI335, pbn_fastcom335_8),
|
||||
EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2),
|
||||
EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
|
||||
EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4),
|
||||
EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8),
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, exar_pci_tbl);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define CHIP_ID2 0x21
|
||||
#define CHIP_ID_F81865 0x0407
|
||||
#define CHIP_ID_F81866 0x1010
|
||||
#define CHIP_ID_F81966 0x0215
|
||||
#define CHIP_ID_F81216AD 0x1602
|
||||
#define CHIP_ID_F81216H 0x0501
|
||||
#define CHIP_ID_F81216 0x0802
|
||||
|
@ -62,9 +63,9 @@
|
|||
#define F81216_LDN_HIGH 0x4
|
||||
|
||||
/*
|
||||
* F81866 registers
|
||||
* F81866/966 registers
|
||||
*
|
||||
* The IRQ setting mode of F81866 is not the same with F81216 series.
|
||||
* The IRQ setting mode of F81866/966 is not the same with F81216 series.
|
||||
* Level/Low: IRQ_MODE0:0, IRQ_MODE1:0
|
||||
* Edge/High: IRQ_MODE0:1, IRQ_MODE1:0
|
||||
*
|
||||
|
@ -155,6 +156,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata)
|
|||
switch (chip) {
|
||||
case CHIP_ID_F81865:
|
||||
case CHIP_ID_F81866:
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81216AD:
|
||||
case CHIP_ID_F81216H:
|
||||
case CHIP_ID_F81216:
|
||||
|
@ -171,6 +173,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min,
|
|||
int *max)
|
||||
{
|
||||
switch (pdata->pid) {
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81865:
|
||||
case CHIP_ID_F81866:
|
||||
*min = F81866_LDN_LOW;
|
||||
|
@ -248,6 +251,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
|
|||
sio_write_reg(pdata, LDN, pdata->index);
|
||||
|
||||
switch (pdata->pid) {
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81866:
|
||||
sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1,
|
||||
0);
|
||||
|
@ -274,6 +278,7 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
|
|||
{
|
||||
switch (pdata->pid) {
|
||||
case CHIP_ID_F81216H: /* 128Bytes FIFO */
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81866:
|
||||
sio_write_mask_reg(pdata, FIFO_CTRL,
|
||||
FIFO_MODE_MASK | RXFTHR_MODE_MASK,
|
||||
|
@ -291,6 +296,7 @@ static void fintek_8250_goto_highspeed(struct uart_8250_port *uart,
|
|||
sio_write_reg(pdata, LDN, pdata->index);
|
||||
|
||||
switch (pdata->pid) {
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81866: /* set uart clock for high speed serial mode */
|
||||
sio_write_mask_reg(pdata, F81866_UART_CLK,
|
||||
F81866_UART_CLK_MASK,
|
||||
|
@ -327,6 +333,7 @@ static void fintek_8250_set_termios(struct uart_port *port,
|
|||
case CHIP_ID_F81216H:
|
||||
reg = RS485;
|
||||
break;
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81866:
|
||||
reg = F81866_UART_CLK;
|
||||
break;
|
||||
|
@ -373,6 +380,7 @@ static void fintek_8250_set_termios_handler(struct uart_8250_port *uart)
|
|||
|
||||
switch (pdata->pid) {
|
||||
case CHIP_ID_F81216H:
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81866:
|
||||
uart->port.set_termios = fintek_8250_set_termios;
|
||||
break;
|
||||
|
@ -443,6 +451,7 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart)
|
|||
switch (pdata->pid) {
|
||||
case CHIP_ID_F81216AD:
|
||||
case CHIP_ID_F81216H:
|
||||
case CHIP_ID_F81966:
|
||||
case CHIP_ID_F81866:
|
||||
case CHIP_ID_F81865:
|
||||
uart->port.rs485_config = fintek_8250_rs485_config;
|
||||
|
|
|
@ -681,6 +681,9 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485)
|
|||
memset(rs485->padding, 0, sizeof(rs485->padding));
|
||||
port->rs485 = *rs485;
|
||||
|
||||
gpiod_set_value(port->rs485_term_gpio,
|
||||
rs485->flags & SER_RS485_TERMINATE_BUS);
|
||||
|
||||
/*
|
||||
* Both serial8250_em485_init() and serial8250_em485_destroy()
|
||||
* are idempotent.
|
||||
|
@ -1432,7 +1435,7 @@ static void serial8250_stop_rx(struct uart_port *port)
|
|||
|
||||
/**
|
||||
* serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback
|
||||
* @up: uart 8250 port
|
||||
* @p: uart 8250 port
|
||||
*
|
||||
* Generic callback usable by 8250 uart drivers to stop rs485 transmission.
|
||||
*/
|
||||
|
@ -2615,6 +2618,8 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
|
|||
struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int tolerance = port->uartclk / 100;
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
* Allow 1% tolerance at the upper limit so uart clks marginally
|
||||
|
@ -2623,7 +2628,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
|
|||
*/
|
||||
return uart_get_baud_rate(port, termios, old,
|
||||
port->uartclk / 16 / UART_DIV_MAX,
|
||||
port->uartclk);
|
||||
(port->uartclk + tolerance) / 16);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -63,6 +63,7 @@ config SERIAL_8250_PNP
|
|||
config SERIAL_8250_16550A_VARIANTS
|
||||
bool "Support for variants of the 16550A serial port"
|
||||
depends on SERIAL_8250
|
||||
default !X86
|
||||
help
|
||||
The 8250 driver can probe for many variants of the venerable 16550A
|
||||
serial port. Doing so takes additional time at boot.
|
||||
|
|
|
@ -440,7 +440,7 @@ static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
|
|||
static int simple_config(struct pcmcia_device *link)
|
||||
{
|
||||
struct serial_info *info = link->priv;
|
||||
int i = -ENODEV, try;
|
||||
int ret, try;
|
||||
|
||||
/*
|
||||
* First pass: look for a config entry that looks normal.
|
||||
|
@ -472,8 +472,8 @@ static int simple_config(struct pcmcia_device *link)
|
|||
if (info->quirk && info->quirk->config)
|
||||
info->quirk->config(link);
|
||||
|
||||
i = pcmcia_enable_device(link);
|
||||
if (i != 0)
|
||||
ret = pcmcia_enable_device(link);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
return setup_serial(link, info, link->resource[0]->start, link->irq);
|
||||
}
|
||||
|
|
|
@ -1034,13 +1034,22 @@ config SERIAL_SIFIVE_CONSOLE
|
|||
boot time.)
|
||||
|
||||
config SERIAL_LANTIQ
|
||||
bool "Lantiq serial driver"
|
||||
depends on LANTIQ
|
||||
tristate "Lantiq serial driver"
|
||||
depends on (LANTIQ || X86) || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Support for UART on Lantiq and Intel SoCs.
|
||||
To compile this driver as a module, select M here. The
|
||||
module will be called lantiq.
|
||||
|
||||
config SERIAL_LANTIQ_CONSOLE
|
||||
bool "Console on Lantiq UART"
|
||||
depends on SERIAL_LANTIQ=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
Support for console and UART on Lantiq SoCs.
|
||||
Select this option if you would like to use a Lantiq UART as the
|
||||
system console.
|
||||
|
||||
config SERIAL_QE
|
||||
tristate "Freescale QUICC Engine serial port support"
|
||||
|
@ -1462,6 +1471,7 @@ config SERIAL_STM32
|
|||
tristate "STMicroelectronics STM32 serial port support"
|
||||
select SERIAL_CORE
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
help
|
||||
This driver is for the on-chip Serial Controller on
|
||||
STMicroelectronics STM32 MCUs.
|
||||
|
|
|
@ -2607,6 +2607,7 @@ 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.flags = UPF_BOOT_AUTOCONF;
|
||||
uap->port.line = index;
|
||||
spin_lock_init(&uap->port.lock);
|
||||
|
||||
amba_ports[index] = uap;
|
||||
|
||||
|
|
|
@ -766,8 +766,6 @@ static int ar933x_uart_probe(struct platform_device *pdev)
|
|||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
uart_get_rs485_mode(&pdev->dev, &port->rs485);
|
||||
|
||||
port->mapbase = mem_res->start;
|
||||
port->line = id;
|
||||
port->irq = irq_res->start;
|
||||
|
@ -786,6 +784,10 @@ static int ar933x_uart_probe(struct platform_device *pdev)
|
|||
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
|
||||
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
|
||||
|
||||
ret = uart_get_rs485_mode(port);
|
||||
if (ret)
|
||||
goto err_disable_clk;
|
||||
|
||||
up->gpios = mctrl_gpio_init(port, 0);
|
||||
if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS)
|
||||
return PTR_ERR(up->gpios);
|
||||
|
|
|
@ -2491,8 +2491,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
|
|||
atmel_init_property(atmel_port, pdev);
|
||||
atmel_set_ops(port);
|
||||
|
||||
uart_get_rs485_mode(&mpdev->dev, &port->rs485);
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||
port->ops = &atmel_pops;
|
||||
|
@ -2506,6 +2504,10 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
|
|||
|
||||
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
|
||||
|
||||
ret = uart_get_rs485_mode(port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* for console, the clock could already be configured */
|
||||
if (!atmel_port->clk) {
|
||||
atmel_port->clk = clk_get(&mpdev->dev, "usart");
|
||||
|
|
|
@ -1231,9 +1231,7 @@ static void lpuart_dma_rx_free(struct uart_port *port)
|
|||
struct lpuart_port, port);
|
||||
struct dma_chan *chan = sport->dma_rx_chan;
|
||||
|
||||
if (chan)
|
||||
dmaengine_terminate_all(chan);
|
||||
|
||||
dmaengine_terminate_all(chan);
|
||||
dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
|
||||
kfree(sport->rx_ring.buf);
|
||||
sport->rx_ring.tail = 0;
|
||||
|
@ -1514,17 +1512,17 @@ static void lpuart_request_dma(struct lpuart_port *sport)
|
|||
{
|
||||
sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx");
|
||||
if (IS_ERR(sport->dma_tx_chan)) {
|
||||
dev_info_once(sport->port.dev,
|
||||
"DMA tx channel request failed, operating without tx DMA (%ld)\n",
|
||||
PTR_ERR(sport->dma_tx_chan));
|
||||
dev_dbg_once(sport->port.dev,
|
||||
"DMA tx channel request failed, operating without tx DMA (%ld)\n",
|
||||
PTR_ERR(sport->dma_tx_chan));
|
||||
sport->dma_tx_chan = NULL;
|
||||
}
|
||||
|
||||
sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx");
|
||||
if (IS_ERR(sport->dma_rx_chan)) {
|
||||
dev_info_once(sport->port.dev,
|
||||
"DMA rx channel request failed, operating without rx DMA (%ld)\n",
|
||||
PTR_ERR(sport->dma_rx_chan));
|
||||
dev_dbg_once(sport->port.dev,
|
||||
"DMA rx channel request failed, operating without rx DMA (%ld)\n",
|
||||
PTR_ERR(sport->dma_rx_chan));
|
||||
sport->dma_rx_chan = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2621,7 +2619,9 @@ static int lpuart_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto failed_attach_port;
|
||||
|
||||
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
|
||||
ret = uart_get_rs485_mode(&sport->port);
|
||||
if (ret)
|
||||
goto failed_get_rs485;
|
||||
|
||||
if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)
|
||||
dev_err(&pdev->dev, "driver doesn't support RX during TX\n");
|
||||
|
@ -2634,6 +2634,7 @@ static int lpuart_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
failed_get_rs485:
|
||||
failed_attach_port:
|
||||
failed_irq_request:
|
||||
lpuart_disable_clks(sport);
|
||||
|
@ -2664,8 +2665,7 @@ static int lpuart_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int lpuart_suspend(struct device *dev)
|
||||
static int __maybe_unused lpuart_suspend(struct device *dev)
|
||||
{
|
||||
struct lpuart_port *sport = dev_get_drvdata(dev);
|
||||
unsigned long temp;
|
||||
|
@ -2723,7 +2723,7 @@ static int lpuart_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart_resume(struct device *dev)
|
||||
static int __maybe_unused lpuart_resume(struct device *dev)
|
||||
{
|
||||
struct lpuart_port *sport = dev_get_drvdata(dev);
|
||||
bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
|
||||
|
@ -2754,7 +2754,6 @@ static int lpuart_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume);
|
||||
|
||||
|
|
|
@ -909,6 +909,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
|
|||
usr2 &= ~USR2_ORE;
|
||||
|
||||
if (usr1 & (USR1_RRDY | USR1_AGTIM)) {
|
||||
imx_uart_writel(sport, USR1_AGTIM, USR1);
|
||||
|
||||
__imx_uart_rxint(irq, dev_id);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
@ -2252,6 +2254,8 @@ static int imx_uart_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(base);
|
||||
|
||||
rxirq = platform_get_irq(pdev, 0);
|
||||
if (rxirq < 0)
|
||||
return rxirq;
|
||||
txirq = platform_get_irq_optional(pdev, 1);
|
||||
rtsirq = platform_get_irq_optional(pdev, 2);
|
||||
|
||||
|
@ -2302,7 +2306,11 @@ static int imx_uart_probe(struct platform_device *pdev)
|
|||
sport->ucr4 = readl(sport->port.membase + UCR4);
|
||||
sport->ufcr = readl(sport->port.membase + UFCR);
|
||||
|
||||
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
|
||||
ret = uart_get_rs485_mode(&sport->port);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sport->port.rs485.flags & SER_RS485_ENABLED &&
|
||||
(!sport->have_rtscts && !sport->have_rtsgpio))
|
||||
|
@ -2398,6 +2406,9 @@ 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;
|
||||
|
||||
platform_set_drvdata(pdev, sport);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/lantiq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
@ -597,6 +598,7 @@ static const struct uart_ops lqasc_pops = {
|
|||
.verify_port = lqasc_verify_port,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_LANTIQ_CONSOLE
|
||||
static void
|
||||
lqasc_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
|
@ -705,6 +707,14 @@ lqasc_serial_early_console_setup(struct earlycon_device *device,
|
|||
OF_EARLYCON_DECLARE(lantiq, "lantiq,asc", lqasc_serial_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(lantiq, "intel,lgm-asc", lqasc_serial_early_console_setup);
|
||||
|
||||
#define LANTIQ_SERIAL_CONSOLE (&lqasc_console)
|
||||
|
||||
#else
|
||||
|
||||
#define LANTIQ_SERIAL_CONSOLE NULL
|
||||
|
||||
#endif /* CONFIG_SERIAL_LANTIQ_CONSOLE */
|
||||
|
||||
static struct uart_driver lqasc_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = DRVNAME,
|
||||
|
@ -712,7 +722,7 @@ static struct uart_driver lqasc_reg = {
|
|||
.major = 0,
|
||||
.minor = 0,
|
||||
.nr = MAXPORTS,
|
||||
.cons = &lqasc_console,
|
||||
.cons = LANTIQ_SERIAL_CONSOLE,
|
||||
};
|
||||
|
||||
static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port)
|
||||
|
@ -814,8 +824,7 @@ static void free_irq_intel(struct uart_port *port)
|
|||
free_irq(ltq_port->common_irq, port);
|
||||
}
|
||||
|
||||
static int __init
|
||||
lqasc_probe(struct platform_device *pdev)
|
||||
static int lqasc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct ltq_uart_port *ltq_port;
|
||||
|
@ -899,6 +908,13 @@ lqasc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lqasc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
|
||||
return uart_remove_one_port(&lqasc_reg, port);
|
||||
}
|
||||
|
||||
static const struct ltq_soc_data soc_data_lantiq = {
|
||||
.fetch_irq = fetch_irq_lantiq,
|
||||
.request_irq = request_irq_lantiq,
|
||||
|
@ -916,8 +932,11 @@ static const struct of_device_id ltq_asc_match[] = {
|
|||
{ .compatible = "intel,lgm-asc", .data = &soc_data_intel },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ltq_asc_match);
|
||||
|
||||
static struct platform_driver lqasc_driver = {
|
||||
.probe = lqasc_probe,
|
||||
.remove = lqasc_remove,
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.of_match_table = ltq_asc_match,
|
||||
|
@ -933,10 +952,21 @@ init_lqasc(void)
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
|
||||
ret = platform_driver_register(&lqasc_driver);
|
||||
if (ret != 0)
|
||||
uart_unregister_driver(&lqasc_reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
device_initcall(init_lqasc);
|
||||
|
||||
static void __exit exit_lqasc(void)
|
||||
{
|
||||
platform_driver_unregister(&lqasc_driver);
|
||||
uart_unregister_driver(&lqasc_reg);
|
||||
}
|
||||
|
||||
module_init(init_lqasc);
|
||||
module_exit(exit_lqasc);
|
||||
|
||||
MODULE_DESCRIPTION("Serial driver for Lantiq & Intel gateway SoCs");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/nmi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/soc/nxp/lpc32xx-misc.h>
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/platform_data/serial-omap.h>
|
||||
|
||||
#define OMAP_MAX_HSUART_PORTS 10
|
||||
|
@ -153,7 +152,7 @@ struct uart_omap_port {
|
|||
u32 errata;
|
||||
u32 features;
|
||||
|
||||
int rts_gpio;
|
||||
struct gpio_desc *rts_gpiod;
|
||||
|
||||
struct pm_qos_request pm_qos_request;
|
||||
u32 latency;
|
||||
|
@ -303,11 +302,11 @@ static void serial_omap_stop_tx(struct uart_port *port)
|
|||
serial_out(up, UART_OMAP_SCR, up->scr);
|
||||
res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ?
|
||||
1 : 0;
|
||||
if (gpio_get_value(up->rts_gpio) != res) {
|
||||
if (gpiod_get_value(up->rts_gpiod) != res) {
|
||||
if (port->rs485.delay_rts_after_send > 0)
|
||||
mdelay(
|
||||
port->rs485.delay_rts_after_send);
|
||||
gpio_set_value(up->rts_gpio, res);
|
||||
gpiod_set_value(up->rts_gpiod, res);
|
||||
}
|
||||
} else {
|
||||
/* We're asked to stop, but there's still stuff in the
|
||||
|
@ -412,8 +411,8 @@ static void serial_omap_start_tx(struct uart_port *port)
|
|||
|
||||
/* if rts not already enabled */
|
||||
res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
|
||||
if (gpio_get_value(up->rts_gpio) != res) {
|
||||
gpio_set_value(up->rts_gpio, res);
|
||||
if (gpiod_get_value(up->rts_gpiod) != res) {
|
||||
gpiod_set_value(up->rts_gpiod, res);
|
||||
if (port->rs485.delay_rts_before_send > 0)
|
||||
mdelay(port->rs485.delay_rts_before_send);
|
||||
}
|
||||
|
@ -1414,12 +1413,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
|
|||
* Just as a precaution, only allow rs485
|
||||
* to be enabled if the gpio pin is valid
|
||||
*/
|
||||
if (gpio_is_valid(up->rts_gpio)) {
|
||||
if (up->rts_gpiod) {
|
||||
/* enable / disable rts */
|
||||
val = (port->rs485.flags & SER_RS485_ENABLED) ?
|
||||
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
|
||||
val = (port->rs485.flags & val) ? 1 : 0;
|
||||
gpio_set_value(up->rts_gpio, val);
|
||||
gpiod_set_value(up->rts_gpiod, val);
|
||||
} else
|
||||
port->rs485.flags &= ~SER_RS485_ENABLED;
|
||||
|
||||
|
@ -1596,18 +1595,22 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
|
|||
}
|
||||
|
||||
static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
||||
struct device_node *np)
|
||||
struct device *dev)
|
||||
{
|
||||
struct serial_rs485 *rs485conf = &up->port.rs485;
|
||||
struct device_node *np = dev->of_node;
|
||||
enum gpiod_flags gflags;
|
||||
int ret;
|
||||
|
||||
rs485conf->flags = 0;
|
||||
up->rts_gpio = -EINVAL;
|
||||
up->rts_gpiod = NULL;
|
||||
|
||||
if (!np)
|
||||
return 0;
|
||||
|
||||
uart_get_rs485_mode(up->dev, rs485conf);
|
||||
ret = uart_get_rs485_mode(&up->port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (of_property_read_bool(np, "rs485-rts-active-high")) {
|
||||
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
|
||||
|
@ -1618,19 +1621,20 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
|
|||
}
|
||||
|
||||
/* check for tx enable gpio */
|
||||
up->rts_gpio = of_get_named_gpio(np, "rts-gpio", 0);
|
||||
if (gpio_is_valid(up->rts_gpio)) {
|
||||
ret = devm_gpio_request(up->dev, up->rts_gpio, "omap-serial");
|
||||
if (ret < 0)
|
||||
gflags = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ?
|
||||
GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
|
||||
up->rts_gpiod = devm_gpiod_get_optional(dev, "rts", gflags);
|
||||
if (IS_ERR(up->rts_gpiod)) {
|
||||
ret = PTR_ERR(up->rts_gpiod);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
ret = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? 1 : 0;
|
||||
ret = gpio_direction_output(up->rts_gpio, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (up->rts_gpio == -EPROBE_DEFER) {
|
||||
return -EPROBE_DEFER;
|
||||
/*
|
||||
* FIXME: the code historically ignored any other error than
|
||||
* -EPROBE_DEFER and just went on without GPIO.
|
||||
*/
|
||||
up->rts_gpiod = NULL;
|
||||
} else {
|
||||
up->rts_gpio = -EINVAL;
|
||||
gpiod_set_consumer_name(up->rts_gpiod, "omap-serial");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1703,7 +1707,7 @@ static int serial_omap_probe(struct platform_device *pdev)
|
|||
dev_info(up->port.dev, "no wakeirq for uart%d\n",
|
||||
up->port.line);
|
||||
|
||||
ret = serial_omap_probe_rs485(up, pdev->dev.of_node);
|
||||
ret = serial_omap_probe_rs485(up, &pdev->dev);
|
||||
if (ret < 0)
|
||||
goto err_rs485;
|
||||
|
||||
|
|
|
@ -141,9 +141,10 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport);
|
|||
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
|
||||
|
||||
static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
|
||||
32000000, 48000000, 64000000, 80000000,
|
||||
96000000, 100000000, 102400000,
|
||||
112000000, 120000000, 128000000};
|
||||
32000000, 48000000, 51200000, 64000000,
|
||||
80000000, 96000000, 100000000,
|
||||
102400000, 112000000, 120000000,
|
||||
128000000};
|
||||
|
||||
#define to_dev_port(ptr, member) \
|
||||
container_of(ptr, struct qcom_geni_serial_port, member)
|
||||
|
|
|
@ -154,10 +154,33 @@ struct s3c24xx_uart_port {
|
|||
#define portaddrl(port, reg) \
|
||||
((unsigned long *)(unsigned long)((port)->membase + (reg)))
|
||||
|
||||
#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg)))
|
||||
static u32 rd_reg(struct uart_port *port, u32 reg)
|
||||
{
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
return readb_relaxed(portaddr(port, reg));
|
||||
case UPIO_MEM32:
|
||||
return readl_relaxed(portaddr(port, reg));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
|
||||
|
||||
#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg))
|
||||
static void wr_reg(struct uart_port *port, u32 reg, u32 val)
|
||||
{
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
writeb_relaxed(val, portaddr(port, reg));
|
||||
break;
|
||||
case UPIO_MEM32:
|
||||
writel_relaxed(val, portaddr(port, reg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
|
||||
|
||||
/* Byte-order aware bit setting/clearing functions. */
|
||||
|
@ -714,7 +737,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
|
|||
fifocnt--;
|
||||
|
||||
uerstat = rd_regl(port, S3C2410_UERSTAT);
|
||||
ch = rd_regb(port, S3C2410_URXH);
|
||||
ch = rd_reg(port, S3C2410_URXH);
|
||||
|
||||
if (port->flags & UPF_CONS_FLOW) {
|
||||
int txe = s3c24xx_serial_txempty_nofifo(port);
|
||||
|
@ -826,7 +849,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||
}
|
||||
|
||||
if (port->x_char) {
|
||||
wr_regb(port, S3C2410_UTXH, port->x_char);
|
||||
wr_reg(port, S3C2410_UTXH, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
goto out;
|
||||
|
@ -852,7 +875,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
|
||||
break;
|
||||
|
||||
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
|
||||
wr_reg(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
count--;
|
||||
|
@ -916,7 +939,7 @@ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
|
|||
/* no modem control lines */
|
||||
static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int umstat = rd_regb(port, S3C2410_UMSTAT);
|
||||
unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
|
||||
|
||||
if (umstat & S3C2410_UMSTAT_CTS)
|
||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
|
@ -1281,14 +1304,14 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
|
|||
struct s3c24xx_uart_info *info = ourport->info;
|
||||
struct clk *clk;
|
||||
unsigned long rate;
|
||||
unsigned int cnt, baud, quot, clk_sel, best_quot = 0;
|
||||
unsigned int cnt, baud, quot, best_quot = 0;
|
||||
char clkname[MAX_CLK_NAME_LENGTH];
|
||||
int calc_deviation, deviation = (1 << 30) - 1;
|
||||
|
||||
clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
|
||||
ourport->info->def_clk_sel;
|
||||
for (cnt = 0; cnt < info->num_clks; cnt++) {
|
||||
if (!(clk_sel & (1 << cnt)))
|
||||
/* Keep selected clock if provided */
|
||||
if (ourport->cfg->clk_sel &&
|
||||
!(ourport->cfg->clk_sel & (1 << cnt)))
|
||||
continue;
|
||||
|
||||
sprintf(clkname, "clk_uart_baud%d", cnt);
|
||||
|
@ -1974,7 +1997,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||
struct device_node *np = pdev->dev.of_node;
|
||||
struct s3c24xx_uart_port *ourport;
|
||||
int index = probe_index;
|
||||
int ret;
|
||||
int ret, prop = 0;
|
||||
|
||||
if (np) {
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
|
@ -2000,10 +2023,27 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|||
dev_get_platdata(&pdev->dev) :
|
||||
ourport->drv_data->def_cfg;
|
||||
|
||||
if (np)
|
||||
if (np) {
|
||||
of_property_read_u32(np,
|
||||
"samsung,uart-fifosize", &ourport->port.fifosize);
|
||||
|
||||
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
|
||||
switch (prop) {
|
||||
case 1:
|
||||
ourport->port.iotype = UPIO_MEM;
|
||||
break;
|
||||
case 4:
|
||||
ourport->port.iotype = UPIO_MEM32;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
|
||||
prop);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ourport->drv_data->fifosize[index])
|
||||
ourport->port.fifosize = ourport->drv_data->fifosize[index];
|
||||
else if (ourport->info->fifosize)
|
||||
|
@ -2185,7 +2225,7 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
|
|||
if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
return rd_regb(port, S3C2410_URXH);
|
||||
return rd_reg(port, S3C2410_URXH);
|
||||
}
|
||||
|
||||
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
|
||||
|
@ -2200,7 +2240,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
|
|||
|
||||
while (!s3c24xx_serial_console_txrdy(port, ufcon))
|
||||
cpu_relax();
|
||||
wr_regb(port, S3C2410_UTXH, c);
|
||||
wr_reg(port, S3C2410_UTXH, c);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
|
@ -2212,7 +2252,7 @@ s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
|
|||
|
||||
while (!s3c24xx_serial_console_txrdy(port, ufcon))
|
||||
cpu_relax();
|
||||
wr_regb(port, S3C2410_UTXH, ch);
|
||||
wr_reg(port, S3C2410_UTXH, ch);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2587,6 +2627,18 @@ module_platform_driver(samsung_serial_driver);
|
|||
* Early console.
|
||||
*/
|
||||
|
||||
static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val)
|
||||
{
|
||||
switch (port->iotype) {
|
||||
case UPIO_MEM:
|
||||
writeb(val, portaddr(port, reg));
|
||||
break;
|
||||
case UPIO_MEM32:
|
||||
writel(val, portaddr(port, reg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct samsung_early_console_data {
|
||||
u32 txfull_mask;
|
||||
};
|
||||
|
@ -2612,7 +2664,7 @@ static void samsung_early_putc(struct uart_port *port, int c)
|
|||
else
|
||||
samsung_early_busyuart(port);
|
||||
|
||||
writeb(c, port->membase + S3C2410_UTXH);
|
||||
wr_reg_barrier(port, S3C2410_UTXH, c);
|
||||
}
|
||||
|
||||
static void samsung_early_write(struct console *con, const char *s,
|
||||
|
|
|
@ -315,6 +315,7 @@ struct sc16is7xx_one {
|
|||
struct kthread_work tx_work;
|
||||
struct kthread_work reg_work;
|
||||
struct sc16is7xx_one_config config;
|
||||
bool irda_mode;
|
||||
};
|
||||
|
||||
struct sc16is7xx_port {
|
||||
|
@ -327,7 +328,6 @@ struct sc16is7xx_port {
|
|||
unsigned char buf[SC16IS7XX_FIFO_SIZE];
|
||||
struct kthread_worker kworker;
|
||||
struct task_struct *kworker_task;
|
||||
struct kthread_work irq_work;
|
||||
struct mutex efr_lock;
|
||||
struct sc16is7xx_one p[];
|
||||
};
|
||||
|
@ -710,9 +710,9 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void sc16is7xx_ist(struct kthread_work *ws)
|
||||
static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
|
||||
struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
|
||||
|
||||
mutex_lock(&s->efr_lock);
|
||||
|
||||
|
@ -727,13 +727,6 @@ static void sc16is7xx_ist(struct kthread_work *ws)
|
|||
}
|
||||
|
||||
mutex_unlock(&s->efr_lock);
|
||||
}
|
||||
|
||||
static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
|
||||
|
||||
kthread_queue_work(&s->kworker, &s->irq_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -994,6 +987,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
|
|||
|
||||
static int sc16is7xx_startup(struct uart_port *port)
|
||||
{
|
||||
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
|
||||
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
|
||||
unsigned int val;
|
||||
|
||||
|
@ -1032,6 +1026,13 @@ static int sc16is7xx_startup(struct uart_port *port)
|
|||
/* Now, initialize the UART */
|
||||
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);
|
||||
|
||||
/* Enable IrDA mode if requested in DT */
|
||||
/* This bit must be written with LCR[7] = 0 */
|
||||
sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
|
||||
SC16IS7XX_MCR_IRDA_BIT,
|
||||
one->irda_mode ?
|
||||
SC16IS7XX_MCR_IRDA_BIT : 0);
|
||||
|
||||
/* Enable the Rx and Tx FIFO */
|
||||
sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
|
||||
SC16IS7XX_EFCR_RXDISABLE_BIT |
|
||||
|
@ -1176,10 +1177,11 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
|
|||
|
||||
static int sc16is7xx_probe(struct device *dev,
|
||||
const struct sc16is7xx_devtype *devtype,
|
||||
struct regmap *regmap, int irq, unsigned long flags)
|
||||
struct regmap *regmap, int irq)
|
||||
{
|
||||
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
|
||||
unsigned long freq = 0, *pfreq = dev_get_platdata(dev);
|
||||
unsigned int val;
|
||||
u32 uartclk = 0;
|
||||
int i, ret;
|
||||
struct sc16is7xx_port *s;
|
||||
|
@ -1187,6 +1189,16 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
/*
|
||||
* This device does not have an identification register that would
|
||||
* tell us if we are really connected to the correct device.
|
||||
* The best we can do is to check if communication is at all possible.
|
||||
*/
|
||||
ret = regmap_read(regmap,
|
||||
SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Alloc port structure */
|
||||
s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL);
|
||||
if (!s) {
|
||||
|
@ -1221,7 +1233,6 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
mutex_init(&s->efr_lock);
|
||||
|
||||
kthread_init_worker(&s->kworker);
|
||||
kthread_init_work(&s->irq_work, sc16is7xx_ist);
|
||||
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
|
||||
"sc16is7xx");
|
||||
if (IS_ERR(s->kworker_task)) {
|
||||
|
@ -1302,9 +1313,33 @@ static int sc16is7xx_probe(struct device *dev,
|
|||
sc16is7xx_power(&s->p[i].port, 0);
|
||||
}
|
||||
|
||||
/* Setup interrupt */
|
||||
ret = devm_request_irq(dev, irq, sc16is7xx_irq,
|
||||
flags, dev_name(dev), s);
|
||||
if (dev->of_node) {
|
||||
struct property *prop;
|
||||
const __be32 *p;
|
||||
u32 u;
|
||||
|
||||
of_property_for_each_u32(dev->of_node, "irda-mode-ports",
|
||||
prop, p, u)
|
||||
if (u < devtype->nr_uart)
|
||||
s->p[u].irda_mode = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup interrupt. We first try to acquire the IRQ line as level IRQ.
|
||||
* If that succeeds, we can allow sharing the interrupt as well.
|
||||
* In case the interrupt controller doesn't support that, we fall
|
||||
* back to a non-shared falling-edge trigger.
|
||||
*/
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq,
|
||||
IRQF_TRIGGER_LOW | IRQF_SHARED |
|
||||
IRQF_ONESHOT,
|
||||
dev_name(dev), s);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
dev_name(dev), s);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
|
@ -1378,7 +1413,6 @@ static struct regmap_config regcfg = {
|
|||
static int sc16is7xx_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct sc16is7xx_devtype *devtype;
|
||||
unsigned long flags = 0;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
|
@ -1399,14 +1433,13 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
|
|||
const struct spi_device_id *id_entry = spi_get_device_id(spi);
|
||||
|
||||
devtype = (struct sc16is7xx_devtype *)id_entry->driver_data;
|
||||
flags = IRQF_TRIGGER_FALLING;
|
||||
}
|
||||
|
||||
regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
|
||||
(devtype->nr_uart - 1);
|
||||
regmap = devm_regmap_init_spi(spi, ®cfg);
|
||||
|
||||
return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq, flags);
|
||||
return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq);
|
||||
}
|
||||
|
||||
static int sc16is7xx_spi_remove(struct spi_device *spi)
|
||||
|
@ -1445,7 +1478,6 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct sc16is7xx_devtype *devtype;
|
||||
unsigned long flags = 0;
|
||||
struct regmap *regmap;
|
||||
|
||||
if (i2c->dev.of_node) {
|
||||
|
@ -1454,14 +1486,13 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
|
|||
return -ENODEV;
|
||||
} else {
|
||||
devtype = (struct sc16is7xx_devtype *)id->driver_data;
|
||||
flags = IRQF_TRIGGER_FALLING;
|
||||
}
|
||||
|
||||
regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
|
||||
(devtype->nr_uart - 1);
|
||||
regmap = devm_regmap_init_i2c(i2c, ®cfg);
|
||||
|
||||
return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq, flags);
|
||||
return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq);
|
||||
}
|
||||
|
||||
static int sc16is7xx_i2c_remove(struct i2c_client *client)
|
||||
|
|
|
@ -3295,8 +3295,10 @@ EXPORT_SYMBOL(uart_remove_one_port);
|
|||
* This function implements the device tree binding described in
|
||||
* Documentation/devicetree/bindings/serial/rs485.txt.
|
||||
*/
|
||||
void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
|
||||
int uart_get_rs485_mode(struct uart_port *port)
|
||||
{
|
||||
struct serial_rs485 *rs485conf = &port->rs485;
|
||||
struct device *dev = port->dev;
|
||||
u32 rs485_delay[2];
|
||||
int ret;
|
||||
|
||||
|
@ -3315,6 +3317,7 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
|
|||
* to get to a defined state with the following properties:
|
||||
*/
|
||||
rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED |
|
||||
SER_RS485_TERMINATE_BUS |
|
||||
SER_RS485_RTS_AFTER_SEND);
|
||||
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
|
||||
|
||||
|
@ -3328,6 +3331,23 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
|
|||
rs485conf->flags &= ~SER_RS485_RTS_ON_SEND;
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disabling termination by default is the safe choice: Else if many
|
||||
* bus participants enable it, no communication is possible at all.
|
||||
* Works fine for short cables and users may enable for longer cables.
|
||||
*/
|
||||
port->rs485_term_gpio = devm_gpiod_get_optional(dev, "rs485-term",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(port->rs485_term_gpio)) {
|
||||
ret = PTR_ERR(port->rs485_term_gpio);
|
||||
port->rs485_term_gpio = NULL;
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Cannot get rs485-term-gpios\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(uart_get_rs485_mode);
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#define SCI_MAJOR 204
|
||||
#define SCI_MINOR_START 8
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/tty_flip.h>
|
||||
#include <linux/tty.h>
|
||||
|
||||
#include "serial_mctrl_gpio.h"
|
||||
#include "stm32-usart.h"
|
||||
|
||||
static void stm32_stop_tx(struct uart_port *port);
|
||||
|
@ -158,9 +159,7 @@ static int stm32_init_rs485(struct uart_port *port,
|
|||
if (!pdev->dev.of_node)
|
||||
return -ENODEV;
|
||||
|
||||
uart_get_rs485_mode(&pdev->dev, rs485conf);
|
||||
|
||||
return 0;
|
||||
return uart_get_rs485_mode(port);
|
||||
}
|
||||
|
||||
static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res,
|
||||
|
@ -510,12 +509,29 @@ static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
stm32_set_bits(port, ofs->cr3, USART_CR3_RTSE);
|
||||
else
|
||||
stm32_clr_bits(port, ofs->cr3, USART_CR3_RTSE);
|
||||
|
||||
mctrl_gpio_set(stm32_port->gpios, mctrl);
|
||||
}
|
||||
|
||||
static unsigned int stm32_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
unsigned int ret;
|
||||
|
||||
/* This routine is used to get signals of: DCD, DSR, RI, and CTS */
|
||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
|
||||
return mctrl_gpio_get(stm32_port->gpios, &ret);
|
||||
}
|
||||
|
||||
static void stm32_enable_ms(struct uart_port *port)
|
||||
{
|
||||
mctrl_gpio_enable_ms(to_stm32_port(port)->gpios);
|
||||
}
|
||||
|
||||
static void stm32_disable_ms(struct uart_port *port)
|
||||
{
|
||||
mctrl_gpio_disable_ms(to_stm32_port(port)->gpios);
|
||||
}
|
||||
|
||||
/* Transmit stop */
|
||||
|
@ -626,6 +642,9 @@ static void stm32_shutdown(struct uart_port *port)
|
|||
u32 val, isr;
|
||||
int ret;
|
||||
|
||||
/* Disable modem control interrupts */
|
||||
stm32_disable_ms(port);
|
||||
|
||||
val = USART_CR1_TXEIE | USART_CR1_TE;
|
||||
val |= stm32_port->cr1_irq | USART_CR1_RE;
|
||||
val |= BIT(cfg->uart_enable_bit);
|
||||
|
@ -764,6 +783,12 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
|
||||
}
|
||||
|
||||
/* Handle modem control interrupts */
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
stm32_enable_ms(port);
|
||||
else
|
||||
stm32_disable_ms(port);
|
||||
|
||||
usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
|
||||
|
||||
/*
|
||||
|
@ -898,6 +923,7 @@ static const struct uart_ops stm32_uart_ops = {
|
|||
.throttle = stm32_throttle,
|
||||
.unthrottle = stm32_unthrottle,
|
||||
.stop_rx = stm32_stop_rx,
|
||||
.enable_ms = stm32_enable_ms,
|
||||
.break_ctl = stm32_break_ctl,
|
||||
.startup = stm32_startup,
|
||||
.shutdown = stm32_shutdown,
|
||||
|
@ -931,7 +957,9 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
|||
|
||||
port->rs485_config = stm32_config_rs485;
|
||||
|
||||
stm32_init_rs485(port, pdev);
|
||||
ret = stm32_init_rs485(port, pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (stm32port->info->cfg.has_wakeup) {
|
||||
stm32port->wakeirq = platform_get_irq(pdev, 1);
|
||||
|
@ -960,10 +988,31 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
|||
|
||||
stm32port->port.uartclk = clk_get_rate(stm32port->clk);
|
||||
if (!stm32port->port.uartclk) {
|
||||
clk_disable_unprepare(stm32port->clk);
|
||||
ret = -EINVAL;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0);
|
||||
if (IS_ERR(stm32port->gpios)) {
|
||||
ret = PTR_ERR(stm32port->gpios);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
/* Both CTS/RTS gpios and "st,hw-flow-ctrl" should not be specified */
|
||||
if (stm32port->hw_flow_control) {
|
||||
if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) ||
|
||||
mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) {
|
||||
dev_err(&pdev->dev, "Conflicting RTS/CTS config\n");
|
||||
ret = -EINVAL;
|
||||
goto err_clk;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(stm32port->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1375,7 +1424,18 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev)
|
|||
else
|
||||
stm32_serial_enable_wakeup(port, false);
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
/*
|
||||
* When "no_console_suspend" is enabled, keep the pinctrl default state
|
||||
* and rely on bootloader stage to restore this state upon resume.
|
||||
* Otherwise, apply the idle or sleep states depending on wakeup
|
||||
* capabilities.
|
||||
*/
|
||||
if (console_suspend_enabled || !uart_console(port)) {
|
||||
if (device_may_wakeup(dev))
|
||||
pinctrl_pm_select_idle_state(dev);
|
||||
else
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -274,6 +274,7 @@ struct stm32_port {
|
|||
bool fifoen;
|
||||
int wakeirq;
|
||||
int rdr_mask; /* receive data register mask */
|
||||
struct mctrl_gpios *gpios; /* modem control gpios */
|
||||
};
|
||||
|
||||
static struct stm32_port stm32_ports[STM32_MAX_PORTS];
|
||||
|
|
|
@ -1235,9 +1235,7 @@ static void cdns_uart_console_write(struct console *co, const char *s,
|
|||
writel(ctrl, port->membase + CDNS_UART_CR);
|
||||
|
||||
uart_console_write(port, s, count, cdns_uart_console_putchar);
|
||||
while ((readl(port->membase + CDNS_UART_SR) &
|
||||
(CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE)) !=
|
||||
CDNS_UART_SR_TXEMPTY)
|
||||
while (cdns_uart_tx_empty(port) != TIOCSER_TEMT)
|
||||
cpu_relax();
|
||||
|
||||
/* restore interrupt state */
|
||||
|
@ -1262,6 +1260,7 @@ static int cdns_uart_console_setup(struct console *co, char *options)
|
|||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
unsigned long time_out;
|
||||
|
||||
if (!port->membase) {
|
||||
pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
|
||||
|
@ -1272,6 +1271,13 @@ static int cdns_uart_console_setup(struct console *co, char *options)
|
|||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
/* Wait for tx_empty before setting up the console */
|
||||
time_out = jiffies + usecs_to_jiffies(TX_TIMEOUT);
|
||||
|
||||
while (time_before(jiffies, time_out) &&
|
||||
cdns_uart_tx_empty(port) != TIOCSER_TEMT)
|
||||
cpu_relax();
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ static void sysrq_handle_loglevel(int key)
|
|||
pr_info("Loglevel set to %d\n", i);
|
||||
console_loglevel = i;
|
||||
}
|
||||
static struct sysrq_key_op sysrq_loglevel_op = {
|
||||
static const struct sysrq_key_op sysrq_loglevel_op = {
|
||||
.handler = sysrq_handle_loglevel,
|
||||
.help_msg = "loglevel(0-9)",
|
||||
.action_msg = "Changing Loglevel",
|
||||
|
@ -119,14 +119,14 @@ static void sysrq_handle_SAK(int key)
|
|||
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
|
||||
schedule_work(SAK_work);
|
||||
}
|
||||
static struct sysrq_key_op sysrq_SAK_op = {
|
||||
static const struct sysrq_key_op sysrq_SAK_op = {
|
||||
.handler = sysrq_handle_SAK,
|
||||
.help_msg = "sak(k)",
|
||||
.action_msg = "SAK",
|
||||
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
|
||||
};
|
||||
#else
|
||||
#define sysrq_SAK_op (*(struct sysrq_key_op *)NULL)
|
||||
#define sysrq_SAK_op (*(const struct sysrq_key_op *)NULL)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VT
|
||||
|
@ -135,14 +135,14 @@ static void sysrq_handle_unraw(int key)
|
|||
vt_reset_unicode(fg_console);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_unraw_op = {
|
||||
static const struct sysrq_key_op sysrq_unraw_op = {
|
||||
.handler = sysrq_handle_unraw,
|
||||
.help_msg = "unraw(r)",
|
||||
.action_msg = "Keyboard mode set to system default",
|
||||
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
|
||||
};
|
||||
#else
|
||||
#define sysrq_unraw_op (*(struct sysrq_key_op *)NULL)
|
||||
#define sysrq_unraw_op (*(const struct sysrq_key_op *)NULL)
|
||||
#endif /* CONFIG_VT */
|
||||
|
||||
static void sysrq_handle_crash(int key)
|
||||
|
@ -152,7 +152,7 @@ static void sysrq_handle_crash(int key)
|
|||
|
||||
panic("sysrq triggered crash\n");
|
||||
}
|
||||
static struct sysrq_key_op sysrq_crash_op = {
|
||||
static const struct sysrq_key_op sysrq_crash_op = {
|
||||
.handler = sysrq_handle_crash,
|
||||
.help_msg = "crash(c)",
|
||||
.action_msg = "Trigger a crash",
|
||||
|
@ -165,18 +165,20 @@ static void sysrq_handle_reboot(int key)
|
|||
local_irq_enable();
|
||||
emergency_restart();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_reboot_op = {
|
||||
static const struct sysrq_key_op sysrq_reboot_op = {
|
||||
.handler = sysrq_handle_reboot,
|
||||
.help_msg = "reboot(b)",
|
||||
.action_msg = "Resetting",
|
||||
.enable_mask = SYSRQ_ENABLE_BOOT,
|
||||
};
|
||||
|
||||
const struct sysrq_key_op *__sysrq_reboot_op = &sysrq_reboot_op;
|
||||
|
||||
static void sysrq_handle_sync(int key)
|
||||
{
|
||||
emergency_sync();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_sync_op = {
|
||||
static const struct sysrq_key_op sysrq_sync_op = {
|
||||
.handler = sysrq_handle_sync,
|
||||
.help_msg = "sync(s)",
|
||||
.action_msg = "Emergency Sync",
|
||||
|
@ -188,7 +190,7 @@ static void sysrq_handle_show_timers(int key)
|
|||
sysrq_timer_list_show();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_show_timers_op = {
|
||||
static const struct sysrq_key_op sysrq_show_timers_op = {
|
||||
.handler = sysrq_handle_show_timers,
|
||||
.help_msg = "show-all-timers(q)",
|
||||
.action_msg = "Show clockevent devices & pending hrtimers (no others)",
|
||||
|
@ -198,7 +200,7 @@ static void sysrq_handle_mountro(int key)
|
|||
{
|
||||
emergency_remount();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_mountro_op = {
|
||||
static const struct sysrq_key_op sysrq_mountro_op = {
|
||||
.handler = sysrq_handle_mountro,
|
||||
.help_msg = "unmount(u)",
|
||||
.action_msg = "Emergency Remount R/O",
|
||||
|
@ -211,13 +213,13 @@ static void sysrq_handle_showlocks(int key)
|
|||
debug_show_all_locks();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_showlocks_op = {
|
||||
static const struct sysrq_key_op sysrq_showlocks_op = {
|
||||
.handler = sysrq_handle_showlocks,
|
||||
.help_msg = "show-all-locks(d)",
|
||||
.action_msg = "Show Locks Held",
|
||||
};
|
||||
#else
|
||||
#define sysrq_showlocks_op (*(struct sysrq_key_op *)NULL)
|
||||
#define sysrq_showlocks_op (*(const struct sysrq_key_op *)NULL)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -264,7 +266,7 @@ static void sysrq_handle_showallcpus(int key)
|
|||
}
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_showallcpus_op = {
|
||||
static const struct sysrq_key_op sysrq_showallcpus_op = {
|
||||
.handler = sysrq_handle_showallcpus,
|
||||
.help_msg = "show-backtrace-all-active-cpus(l)",
|
||||
.action_msg = "Show backtrace of all active CPUs",
|
||||
|
@ -282,7 +284,7 @@ static void sysrq_handle_showregs(int key)
|
|||
show_regs(regs);
|
||||
perf_event_print_debug();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_showregs_op = {
|
||||
static const struct sysrq_key_op sysrq_showregs_op = {
|
||||
.handler = sysrq_handle_showregs,
|
||||
.help_msg = "show-registers(p)",
|
||||
.action_msg = "Show Regs",
|
||||
|
@ -294,7 +296,7 @@ static void sysrq_handle_showstate(int key)
|
|||
show_state();
|
||||
show_workqueue_state();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_showstate_op = {
|
||||
static const struct sysrq_key_op sysrq_showstate_op = {
|
||||
.handler = sysrq_handle_showstate,
|
||||
.help_msg = "show-task-states(t)",
|
||||
.action_msg = "Show State",
|
||||
|
@ -305,7 +307,7 @@ static void sysrq_handle_showstate_blocked(int key)
|
|||
{
|
||||
show_state_filter(TASK_UNINTERRUPTIBLE);
|
||||
}
|
||||
static struct sysrq_key_op sysrq_showstate_blocked_op = {
|
||||
static const struct sysrq_key_op sysrq_showstate_blocked_op = {
|
||||
.handler = sysrq_handle_showstate_blocked,
|
||||
.help_msg = "show-blocked-tasks(w)",
|
||||
.action_msg = "Show Blocked State",
|
||||
|
@ -319,21 +321,21 @@ static void sysrq_ftrace_dump(int key)
|
|||
{
|
||||
ftrace_dump(DUMP_ALL);
|
||||
}
|
||||
static struct sysrq_key_op sysrq_ftrace_dump_op = {
|
||||
static const struct sysrq_key_op sysrq_ftrace_dump_op = {
|
||||
.handler = sysrq_ftrace_dump,
|
||||
.help_msg = "dump-ftrace-buffer(z)",
|
||||
.action_msg = "Dump ftrace buffer",
|
||||
.enable_mask = SYSRQ_ENABLE_DUMP,
|
||||
};
|
||||
#else
|
||||
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL)
|
||||
#define sysrq_ftrace_dump_op (*(const struct sysrq_key_op *)NULL)
|
||||
#endif
|
||||
|
||||
static void sysrq_handle_showmem(int key)
|
||||
{
|
||||
show_mem(0, NULL);
|
||||
}
|
||||
static struct sysrq_key_op sysrq_showmem_op = {
|
||||
static const struct sysrq_key_op sysrq_showmem_op = {
|
||||
.handler = sysrq_handle_showmem,
|
||||
.help_msg = "show-memory-usage(m)",
|
||||
.action_msg = "Show Memory",
|
||||
|
@ -364,7 +366,7 @@ static void sysrq_handle_term(int key)
|
|||
send_sig_all(SIGTERM);
|
||||
console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
|
||||
}
|
||||
static struct sysrq_key_op sysrq_term_op = {
|
||||
static const struct sysrq_key_op sysrq_term_op = {
|
||||
.handler = sysrq_handle_term,
|
||||
.help_msg = "terminate-all-tasks(e)",
|
||||
.action_msg = "Terminate All Tasks",
|
||||
|
@ -394,7 +396,7 @@ static void sysrq_handle_moom(int key)
|
|||
{
|
||||
schedule_work(&moom_work);
|
||||
}
|
||||
static struct sysrq_key_op sysrq_moom_op = {
|
||||
static const struct sysrq_key_op sysrq_moom_op = {
|
||||
.handler = sysrq_handle_moom,
|
||||
.help_msg = "memory-full-oom-kill(f)",
|
||||
.action_msg = "Manual OOM execution",
|
||||
|
@ -406,7 +408,7 @@ static void sysrq_handle_thaw(int key)
|
|||
{
|
||||
emergency_thaw_all();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_thaw_op = {
|
||||
static const struct sysrq_key_op sysrq_thaw_op = {
|
||||
.handler = sysrq_handle_thaw,
|
||||
.help_msg = "thaw-filesystems(j)",
|
||||
.action_msg = "Emergency Thaw of all frozen filesystems",
|
||||
|
@ -419,7 +421,7 @@ static void sysrq_handle_kill(int key)
|
|||
send_sig_all(SIGKILL);
|
||||
console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
|
||||
}
|
||||
static struct sysrq_key_op sysrq_kill_op = {
|
||||
static const struct sysrq_key_op sysrq_kill_op = {
|
||||
.handler = sysrq_handle_kill,
|
||||
.help_msg = "kill-all-tasks(i)",
|
||||
.action_msg = "Kill All Tasks",
|
||||
|
@ -430,7 +432,7 @@ static void sysrq_handle_unrt(int key)
|
|||
{
|
||||
normalize_rt_tasks();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_unrt_op = {
|
||||
static const struct sysrq_key_op sysrq_unrt_op = {
|
||||
.handler = sysrq_handle_unrt,
|
||||
.help_msg = "nice-all-RT-tasks(n)",
|
||||
.action_msg = "Nice All RT Tasks",
|
||||
|
@ -440,7 +442,7 @@ static struct sysrq_key_op sysrq_unrt_op = {
|
|||
/* Key Operations table and lock */
|
||||
static DEFINE_SPINLOCK(sysrq_key_table_lock);
|
||||
|
||||
static struct sysrq_key_op *sysrq_key_table[36] = {
|
||||
static const struct sysrq_key_op *sysrq_key_table[36] = {
|
||||
&sysrq_loglevel_op, /* 0 */
|
||||
&sysrq_loglevel_op, /* 1 */
|
||||
&sysrq_loglevel_op, /* 2 */
|
||||
|
@ -516,9 +518,9 @@ static int sysrq_key_table_key2index(int key)
|
|||
/*
|
||||
* get and put functions for the table, exposed to modules.
|
||||
*/
|
||||
struct sysrq_key_op *__sysrq_get_key_op(int key)
|
||||
static const struct sysrq_key_op *__sysrq_get_key_op(int key)
|
||||
{
|
||||
struct sysrq_key_op *op_p = NULL;
|
||||
const struct sysrq_key_op *op_p = NULL;
|
||||
int i;
|
||||
|
||||
i = sysrq_key_table_key2index(key);
|
||||
|
@ -528,7 +530,7 @@ struct sysrq_key_op *__sysrq_get_key_op(int key)
|
|||
return op_p;
|
||||
}
|
||||
|
||||
static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
|
||||
static void __sysrq_put_key_op(int key, const struct sysrq_key_op *op_p)
|
||||
{
|
||||
int i = sysrq_key_table_key2index(key);
|
||||
|
||||
|
@ -538,7 +540,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
|
|||
|
||||
void __handle_sysrq(int key, bool check_mask)
|
||||
{
|
||||
struct sysrq_key_op *op_p;
|
||||
const struct sysrq_key_op *op_p;
|
||||
int orig_log_level;
|
||||
int orig_suppress_printk;
|
||||
int i;
|
||||
|
@ -1061,8 +1063,8 @@ int sysrq_toggle_support(int enable_mask)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sysrq_toggle_support);
|
||||
|
||||
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
|
||||
struct sysrq_key_op *remove_op_p)
|
||||
static int __sysrq_swap_key_ops(int key, const struct sysrq_key_op *insert_op_p,
|
||||
const struct sysrq_key_op *remove_op_p)
|
||||
{
|
||||
int retval;
|
||||
|
||||
|
@ -1085,13 +1087,13 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
|
|||
return retval;
|
||||
}
|
||||
|
||||
int register_sysrq_key(int key, struct sysrq_key_op *op_p)
|
||||
int register_sysrq_key(int key, const struct sysrq_key_op *op_p)
|
||||
{
|
||||
return __sysrq_swap_key_ops(key, op_p, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(register_sysrq_key);
|
||||
|
||||
int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
|
||||
int unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)
|
||||
{
|
||||
return __sysrq_swap_key_ops(key, NULL, op_p);
|
||||
}
|
||||
|
|
|
@ -605,6 +605,7 @@ static int vcc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|||
port->index = vcc_table_add(port);
|
||||
if (port->index == -1) {
|
||||
pr_err("VCC: no more TTY indices left for allocation\n");
|
||||
rv = -ENOMEM;
|
||||
goto free_ldc;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,11 @@ static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf' and friends */
|
|||
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
|
||||
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
|
||||
static bool dead_key_next;
|
||||
static int npadch = -1; /* -1 or number assembled on pad */
|
||||
|
||||
/* Handles a number being assembled on the number pad */
|
||||
static bool npadch_active;
|
||||
static unsigned int npadch_value;
|
||||
|
||||
static unsigned int diacr;
|
||||
static char rep; /* flag telling character repeat */
|
||||
|
||||
|
@ -845,12 +849,12 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
|
|||
shift_state &= ~(1 << value);
|
||||
|
||||
/* kludge */
|
||||
if (up_flag && shift_state != old_state && npadch != -1) {
|
||||
if (up_flag && shift_state != old_state && npadch_active) {
|
||||
if (kbd->kbdmode == VC_UNICODE)
|
||||
to_utf8(vc, npadch);
|
||||
to_utf8(vc, npadch_value);
|
||||
else
|
||||
put_queue(vc, npadch & 0xff);
|
||||
npadch = -1;
|
||||
put_queue(vc, npadch_value & 0xff);
|
||||
npadch_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -868,7 +872,7 @@ static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
|
|||
|
||||
static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
|
||||
{
|
||||
int base;
|
||||
unsigned int base;
|
||||
|
||||
if (up_flag)
|
||||
return;
|
||||
|
@ -882,10 +886,12 @@ static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
|
|||
base = 16;
|
||||
}
|
||||
|
||||
if (npadch == -1)
|
||||
npadch = value;
|
||||
else
|
||||
npadch = npadch * base + value;
|
||||
if (!npadch_active) {
|
||||
npadch_value = 0;
|
||||
npadch_active = true;
|
||||
}
|
||||
|
||||
npadch_value = npadch_value * base + value;
|
||||
}
|
||||
|
||||
static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
|
||||
|
|
|
@ -185,47 +185,54 @@ int set_selection_user(const struct tiocl_selection __user *sel,
|
|||
return set_selection_kernel(&v, tty);
|
||||
}
|
||||
|
||||
static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
|
||||
static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
|
||||
{
|
||||
struct vc_data *vc = vc_cons[fg_console].d;
|
||||
int new_sel_start, new_sel_end, spc;
|
||||
char *bp, *obp;
|
||||
int i, ps, pe;
|
||||
u32 c;
|
||||
int ret = 0;
|
||||
bool unicode;
|
||||
unsigned int i;
|
||||
|
||||
poke_blanked_console();
|
||||
|
||||
v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
|
||||
v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
|
||||
v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
|
||||
v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
|
||||
ps = v->ys * vc->vc_size_row + (v->xs << 1);
|
||||
pe = v->ye * vc->vc_size_row + (v->xe << 1);
|
||||
|
||||
if (v->sel_mode == TIOCL_SELCLEAR) {
|
||||
/* useful for screendump without selection highlights */
|
||||
/* Allocate a new buffer before freeing the old one ... */
|
||||
/* chars can take up to 4 bytes with unicode */
|
||||
bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
|
||||
GFP_KERNEL);
|
||||
if (!bp) {
|
||||
printk(KERN_WARNING "selection: kmalloc() failed\n");
|
||||
clear_selection();
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
kfree(vc_sel.buffer);
|
||||
vc_sel.buffer = bp;
|
||||
|
||||
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
|
||||
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
|
||||
v->ys);
|
||||
return 0;
|
||||
obp = bp;
|
||||
for (i = vc_sel.start; i <= vc_sel.end; i += 2) {
|
||||
u32 c = sel_pos(i, unicode);
|
||||
if (unicode)
|
||||
bp += store_utf8(c, bp);
|
||||
else
|
||||
*bp++ = c;
|
||||
if (!isspace(c))
|
||||
obp = bp;
|
||||
if (!((i + 2) % vc->vc_size_row)) {
|
||||
/* strip trailing blanks from line and add newline,
|
||||
unless non-space at end of line. */
|
||||
if (obp != bp) {
|
||||
bp = obp;
|
||||
*bp++ = '\r';
|
||||
}
|
||||
obp = bp;
|
||||
}
|
||||
}
|
||||
vc_sel.buf_len = bp - vc_sel.buffer;
|
||||
|
||||
if (ps > pe) /* make vc_sel.start <= vc_sel.end */
|
||||
swap(ps, pe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vc_sel.cons != vc_cons[fg_console].d) {
|
||||
clear_selection();
|
||||
vc_sel.cons = vc_cons[fg_console].d;
|
||||
}
|
||||
unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE;
|
||||
static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps,
|
||||
int pe)
|
||||
{
|
||||
int new_sel_start, new_sel_end, spc;
|
||||
bool unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE;
|
||||
|
||||
switch (v->sel_mode) {
|
||||
switch (mode) {
|
||||
case TIOCL_SELCHAR: /* character-by-character selection */
|
||||
new_sel_start = ps;
|
||||
new_sel_end = pe;
|
||||
|
@ -303,40 +310,44 @@ static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *
|
|||
vc_sel.start = new_sel_start;
|
||||
vc_sel.end = new_sel_end;
|
||||
|
||||
/* Allocate a new buffer before freeing the old one ... */
|
||||
/* chars can take up to 4 bytes with unicode */
|
||||
bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
|
||||
GFP_KERNEL);
|
||||
if (!bp) {
|
||||
printk(KERN_WARNING "selection: kmalloc() failed\n");
|
||||
return vc_selection_store_chars(vc, unicode);
|
||||
}
|
||||
|
||||
static int vc_selection(struct vc_data *vc, struct tiocl_selection *v,
|
||||
struct tty_struct *tty)
|
||||
{
|
||||
int ps, pe;
|
||||
|
||||
poke_blanked_console();
|
||||
|
||||
if (v->sel_mode == TIOCL_SELCLEAR) {
|
||||
/* useful for screendump without selection highlights */
|
||||
clear_selection();
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
kfree(vc_sel.buffer);
|
||||
vc_sel.buffer = bp;
|
||||
|
||||
obp = bp;
|
||||
for (i = vc_sel.start; i <= vc_sel.end; i += 2) {
|
||||
c = sel_pos(i, unicode);
|
||||
if (unicode)
|
||||
bp += store_utf8(c, bp);
|
||||
else
|
||||
*bp++ = c;
|
||||
if (!isspace(c))
|
||||
obp = bp;
|
||||
if (! ((i + 2) % vc->vc_size_row)) {
|
||||
/* strip trailing blanks from line and add newline,
|
||||
unless non-space at end of line. */
|
||||
if (obp != bp) {
|
||||
bp = obp;
|
||||
*bp++ = '\r';
|
||||
}
|
||||
obp = bp;
|
||||
}
|
||||
v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
|
||||
v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
|
||||
v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
|
||||
v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
|
||||
|
||||
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
|
||||
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
|
||||
v->ys);
|
||||
return 0;
|
||||
}
|
||||
vc_sel.buf_len = bp - vc_sel.buffer;
|
||||
|
||||
return ret;
|
||||
ps = v->ys * vc->vc_size_row + (v->xs << 1);
|
||||
pe = v->ye * vc->vc_size_row + (v->xe << 1);
|
||||
if (ps > pe) /* make vc_sel.start <= vc_sel.end */
|
||||
swap(ps, pe);
|
||||
|
||||
if (vc_sel.cons != vc) {
|
||||
clear_selection();
|
||||
vc_sel.cons = vc;
|
||||
}
|
||||
|
||||
return vc_do_selection(vc, v->sel_mode, ps, pe);
|
||||
}
|
||||
|
||||
int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
|
||||
|
@ -345,7 +356,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
|
|||
|
||||
mutex_lock(&vc_sel.lock);
|
||||
console_lock();
|
||||
ret = __set_selection_kernel(v, tty);
|
||||
ret = vc_selection(vc_cons[fg_console].d, v, tty);
|
||||
console_unlock();
|
||||
mutex_unlock(&vc_sel.lock);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -251,6 +252,7 @@ struct uart_port {
|
|||
struct attribute_group *attr_group; /* port specific attributes */
|
||||
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
|
||||
struct serial_rs485 rs485;
|
||||
struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */
|
||||
struct serial_iso7816 iso7816;
|
||||
void *private_data; /* generic platform data pointer */
|
||||
};
|
||||
|
@ -472,5 +474,5 @@ extern int uart_handle_break(struct uart_port *port);
|
|||
(cflag) & CRTSCTS || \
|
||||
!((cflag) & CLOCAL))
|
||||
|
||||
void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf);
|
||||
int uart_get_rs485_mode(struct uart_port *port);
|
||||
#endif /* LINUX_SERIAL_CORE_H */
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
#define SYSRQ_ENABLE_RTNICE 0x0100
|
||||
|
||||
struct sysrq_key_op {
|
||||
void (*handler)(int);
|
||||
char *help_msg;
|
||||
char *action_msg;
|
||||
int enable_mask;
|
||||
void (* const handler)(int);
|
||||
const char * const help_msg;
|
||||
const char * const action_msg;
|
||||
const int enable_mask;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
|
@ -45,9 +45,9 @@ struct sysrq_key_op {
|
|||
|
||||
void handle_sysrq(int key);
|
||||
void __handle_sysrq(int key, bool check_mask);
|
||||
int register_sysrq_key(int key, struct sysrq_key_op *op);
|
||||
int unregister_sysrq_key(int key, struct sysrq_key_op *op);
|
||||
struct sysrq_key_op *__sysrq_get_key_op(int key);
|
||||
int register_sysrq_key(int key, const struct sysrq_key_op *op);
|
||||
int unregister_sysrq_key(int key, const struct sysrq_key_op *op);
|
||||
extern const struct sysrq_key_op *__sysrq_reboot_op;
|
||||
|
||||
int sysrq_toggle_support(int enable_mask);
|
||||
int sysrq_mask(void);
|
||||
|
@ -62,12 +62,12 @@ static inline void __handle_sysrq(int key, bool check_mask)
|
|||
{
|
||||
}
|
||||
|
||||
static inline int register_sysrq_key(int key, struct sysrq_key_op *op)
|
||||
static inline int register_sysrq_key(int key, const struct sysrq_key_op *op)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int unregister_sysrq_key(int key, struct sysrq_key_op *op)
|
||||
static inline int unregister_sysrq_key(int key, const struct sysrq_key_op *op)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -935,7 +935,7 @@ static void sysrq_handle_dbg(int key)
|
|||
kgdb_breakpoint();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_dbg_op = {
|
||||
static const struct sysrq_key_op sysrq_dbg_op = {
|
||||
.handler = sysrq_handle_dbg,
|
||||
.help_msg = "debug(g)",
|
||||
.action_msg = "DEBUG",
|
||||
|
|
|
@ -29,7 +29,7 @@ static void handle_poweroff(int key)
|
|||
schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_poweroff_op = {
|
||||
static const struct sysrq_key_op sysrq_poweroff_op = {
|
||||
.handler = handle_poweroff,
|
||||
.help_msg = "poweroff(o)",
|
||||
.action_msg = "Power Off",
|
||||
|
|
|
@ -807,7 +807,7 @@ static void sysrq_show_rcu(int key)
|
|||
show_rcu_gp_kthreads();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_rcudump_op = {
|
||||
static const struct sysrq_key_op sysrq_rcudump_op = {
|
||||
.handler = sysrq_show_rcu,
|
||||
.help_msg = "show-rcu(y)",
|
||||
.action_msg = "Show RCU tree",
|
||||
|
|
Loading…
Reference in New Issue
Block a user