kernel.io_delay_type = 1
时间: 2024-04-19 09:25:13 浏览: 151
在Linux内核中,`kernel.io_delay_type` 是一个内核参数,用于控制延迟函数的实现方式。该参数的可选值有以下几种:
- `0`:使用忙等待(busy-waiting)方式实现延迟函数。
- `1`:使用I/O等待(I/O-waiting)方式实现延迟函数。
- `2`:使用混合延迟(hybrid-waiting)方式实现延迟函数。
这些不同的实现方式涉及到内核中的延迟函数,用于在代码中引入一定的延迟,以便处理器可以执行其他任务或等待I/O操作完成。选择不同的延迟函数实现方式可能会对系统性能产生一定的影响。
对于大多数情况来说,使用默认值 `1`(I/O等待方式)是合适的,因为它在等待期间不会占用过多的CPU资源,允许其他进程获得更多的CPU时间。
请注意,修改内核参数需要具有超级用户权限,并且不正确的参数设置可能导致系统不稳定或性能下降。如果您不确定如何正确配置该参数,请谨慎操作或咨询专业人士的建议。
相关问题
请提供Linux kernel 4.14 AXI UART 16550 driver完整源代码
以下是 Linux kernel 4.14 中 AXI UART 16550 驱动程序的完整源代码,供参考:
```c
/*
* AXI 16550 UART driver
*/
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/serial_core.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/tty_port.h>
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define XUARTPS_CR_STOPBRK 0x00000001 /* Stop transmitter break */
#define XUARTPS_CR_STARTBRK 0x00000002 /* Start transmitter break */
#define XUARTPS_CR_TORST 0x00000008 /* Transmit out-of-band reset */
#define XUARTPS_CR_TX_DIS 0x00000010 /* Transmit disable */
#define XUARTPS_CR_TX_EN 0x00000020 /* Transmit enable */
#define XUARTPS_CR_RX_DIS 0x00000040 /* Receive disable */
#define XUARTPS_CR_RX_EN 0x00000080 /* Receive enable */
/* RS485 support */
#define AXI_RS485_ENABLED (1 << 0)
#define AXI_RS485_RTS_ACTIVE_HIGH (1 << 1)
#define AXI_RS485_RX_DURING_TX (1 << 2)
/* AXI UART 16550 registers */
struct axi_uart16550 {
u32 rxfifo;
u32 txdata;
u32 ctrl;
u32 intr_enable;
u32 intr_status;
u32 baud_rate_gen;
u32 rcv_timeout;
u32 flow_ctrl;
u32 mode;
};
/* AXI UART 16550 driver data */
struct axi_uart16550_data {
struct uart_port port;
struct clk *clk;
void __iomem *regs;
struct tty_port tty_port;
unsigned int ns16550_irq;
spinlock_t lock;
u32 ctrl_reg;
unsigned int rs485_flags;
};
/* AXI UART 16550 driver functions */
static void axi_uart16550_set_mctrl(struct uart_port *port, u_int mctrl)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
if (mctrl & TIOCM_RTS) {
if (data->rs485_flags & AXI_RS485_ENABLED) {
if (data->rs485_flags & AXI_RS485_RTS_ACTIVE_HIGH)
data->ctrl_reg |= XUARTPS_CR_TX_EN;
else
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
} else {
data->ctrl_reg |= XUARTPS_CR_TX_EN;
}
} else {
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
}
if (mctrl & TIOCM_DTR) {
data->ctrl_reg |= XUARTPS_CR_RX_EN;
} else {
data->ctrl_reg &= ~XUARTPS_CR_RX_EN;
}
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static u_int axi_uart16550_get_mctrl(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
u_int status = 0;
spin_lock_irqsave(&data->lock, flags);
if (data->ctrl_reg & XUARTPS_CR_TX_EN)
status |= TIOCM_RTS;
if (data->ctrl_reg & XUARTPS_CR_RX_EN)
status |= TIOCM_DTR;
spin_unlock_irqrestore(&data->lock, flags);
return status;
}
static void axi_uart16550_stop_tx(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static void axi_uart16550_start_tx(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
if (data->rs485_flags & AXI_RS485_ENABLED) {
if (data->rs485_flags & AXI_RS485_RX_DURING_TX)
data->ctrl_reg |= XUARTPS_CR_RX_EN;
else
data->ctrl_reg &= ~XUARTPS_CR_RX_EN;
if (data->rs485_flags & AXI_RS485_RTS_ACTIVE_HIGH)
data->ctrl_reg |= XUARTPS_CR_TX_EN;
else
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
} else {
data->ctrl_reg |= XUARTPS_CR_TX_EN;
data->ctrl_reg |= XUARTPS_CR_RX_EN;
}
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static void axi_uart16550_stop_rx(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
data->ctrl_reg &= ~XUARTPS_CR_RX_EN;
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static void axi_uart16550_enable_ms(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
data->ctrl_reg |= XUARTPS_CR_RX_EN | XUARTPS_CR_TX_EN;
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
}
static void axi_uart16550_break_ctl(struct uart_port *port, int break_state)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
if (break_state == -1) {
data->ctrl_reg &= ~XUARTPS_CR_STARTBRK;
data->ctrl_reg |= XUARTPS_CR_STOPBRK;
} else if (break_state == 1) {
data->ctrl_reg |= XUARTPS_CR_STARTBRK;
data->ctrl_reg &= ~XUARTPS_CR_STOPBRK;
}
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
}
static int axi_uart16550_startup(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
int ret;
/* Enable clock */
ret = clk_prepare_enable(data->clk);
if (ret < 0) {
dev_err(port->dev, "failed to enable clock: %d\n", ret);
return ret;
}
/* Initialize port */
uart_port_set_ops(port, &serial8250_ops);
port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
port->iotype = UPIO_MEM;
port->regshift = 2;
port->mapbase = (unsigned long)data->regs;
port->type = PORT_16550A;
port->irq = data->ns16550_irq;
spin_lock_init(&data->lock);
tty_port_init(&data->tty_port);
port->private_data = &data->tty_port;
/* Register port */
ret = uart_add_one_port(&serial8250_reg, port);
if (ret < 0) {
dev_err(port->dev, "failed to register port: %d\n", ret);
clk_disable_unprepare(data->clk);
return ret;
}
/* Enable IRQ */
writel(0xff, data->regs + offsetof(struct axi_uart16550, intr_enable));
return 0;
}
static void axi_uart16550_shutdown(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
/* Disable IRQ */
writel(0x00, data->regs + offsetof(struct axi_uart16550, intr_enable));
/* Unregister port */
uart_remove_one_port(&serial8250_reg, port);
/* Free resources */
clk_disable_unprepare(data->clk);
}
static int axi_uart16550_request_port(struct uart_port *port)
{
return 0;
}
static void axi_uart16550_config_port(struct uart_port *port, int flags)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long baud_divisor;
u32 mode_reg = 0;
/* Set baud rate */
baud_divisor = uart_get_baud_rate(port, flags, port->uartclk, 115200, 4000000);
uart_update_timeout(port, baud_divisor, 115200);
writel(baud_divisor, data->regs + offsetof(struct axi_uart16550, baud_rate_gen));
/* Set data format */
mode_reg |= (3 << 0); /* 8 data bits */
mode_reg |= (0 << 3); /* 1 stop bit */
mode_reg |= (0 << 4); /* no parity */
mode_reg |= (0 << 6); /* no break */
writel(mode_reg, data->regs + offsetof(struct axi_uart16550, mode));
}
static void axi_uart16550_release_port(struct uart_port *port)
{
/* Do nothing */
}
static const struct uart_ops axi_uart16550_ops = {
.tx_empty = serial8250_tx_empty,
.set_mctrl = axi_uart16550_set_mctrl,
.get_mctrl = axi_uart16550_get_mctrl,
.stop_tx = axi_uart16550_stop_tx,
.start_tx = axi_uart16550_start_tx,
.stop_rx = axi_uart16550_stop_rx,
.enable_ms = axi_uart16550_enable_ms,
.break_ctl = axi_uart16550_break_ctl,
.startup = axi_uart16550_startup,
.shutdown = axi_uart16550_shutdown,
.flush_buffer = serial8250_clear_and_reinit_fifos,
.set_termios = serial8250_set_termios,
.type = serial8250_type,
.release_port = axi_uart16550_release_port,
.request_port = axi_uart16550_request_port,
.config_port = axi_uart16550_config_port,
};
/* AXI UART 16550 driver initialization */
static int axi_uart16550_probe(struct platform_device *pdev)
{
struct
阅读全文