From bcf119c9e64d25b36e309e8f158ba4e932e41dfd Mon Sep 17 00:00:00 2001 From: Tom Knot Date: Mon, 25 Jun 2018 14:20:41 +0200 Subject: [PATCH] - Added better handling of long TTY packets - SYSFS register access improved and expanded --- modules/unipi/Makefile | 2 +- modules/unipi/src/unipi_common.h | 6 +- modules/unipi/src/unipi_sysfs.c | 96 +++++++++++++++++++++++++++++++- modules/unipi/src/unipi_uart.c | 63 +++++++++++++++++++-- modules/unipi/src/unipi_uart.h | 2 + version.txt | 2 +- 6 files changed, 161 insertions(+), 10 deletions(-) diff --git a/modules/unipi/Makefile b/modules/unipi/Makefile index c1e7356..39886df 100644 --- a/modules/unipi/Makefile +++ b/modules/unipi/Makefile @@ -3,7 +3,7 @@ # if necessary. SYMLINK_DIR_PATH = /run/kernel/neuron_spi -LINUX_DIR_PATH = /root/linux/4_14_34/ +LINUX_DIR_PATH = /root/linux/4_9_14/linux/ SRC_DIR_PATH = $(PWD)/src BIN_DIR_PATH = $(PWD)/bin diff --git a/modules/unipi/src/unipi_common.h b/modules/unipi/src/unipi_common.h index a98a246..2ee40c7 100644 --- a/modules/unipi/src/unipi_common.h +++ b/modules/unipi/src/unipi_common.h @@ -51,7 +51,7 @@ #if NEURONSPI_SCHED_REQUIRED > 0 #include #endif -#define NEURONSPI_MAJOR_VERSIONSTRING "Development Beta Version 0.12:14:06:2018" +#define NEURONSPI_MAJOR_VERSIONSTRING "Development Beta Version 0.12:25:06:2018" #define NEURONSPI_MAX_DEVS 3 #define NEURONSPI_MAX_UART 128 @@ -66,6 +66,7 @@ #define NEURONSPI_MAX_TX 62 #define NEURONSPI_MAX_BAUD 115200 #define NEURONSPI_FIFO_SIZE 256 +#define NEURONSPI_FIFO_MIN_CONTINUOUS 50 #define NEURONSPI_DETAILED_DEBUG 0 #define NEURONSPI_LAST_TRANSFER_DELAY 40 @@ -119,6 +120,8 @@ struct neuronspi_port struct kthread_work tx_work; struct kthread_work rx_work; struct kthread_work irq_work; + struct spinlock tx_lock; + u8 tx_work_count; u32 flags; u8 ier_clear; u8 buf[NEURONSPI_FIFO_SIZE]; @@ -191,6 +194,7 @@ struct neuronspi_driver_data u8 combination_id; s32 neuron_index; u16 sysfs_regmap_target; + u16 sysfs_register_target; u16 sysfs_counter_target; u32 ideal_frequency; }; diff --git a/modules/unipi/src/unipi_sysfs.c b/modules/unipi/src/unipi_sysfs.c index 1562db9..d3ba7a2 100644 --- a/modules/unipi/src/unipi_sysfs.c +++ b/modules/unipi/src/unipi_sysfs.c @@ -205,7 +205,7 @@ static ssize_t neuronspi_spi_show_uart_timeout(struct device *dev, struct device if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) { read_length = neuronspi_spi_compose_single_register_read(504, &inp_buf, &outp_buf); neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 25, 1, 0); - val = outp_buf[10 + 1]; + val = outp_buf[11]; memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16)); kfree(inp_buf); kfree(outp_buf); @@ -706,13 +706,81 @@ err_end: return count; } + +static ssize_t neuronspi_spi_show_register(struct device *dev, struct device_attribute *attr, char *buf) +{ + u8 *inp_buf, *outp_buf; + int read_length; + ssize_t ret = 0; + u16 val = 0; + struct neuronspi_driver_data *n_spi; + struct spi_device *spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + spi = neuronspi_s_dev[n_spi->neuron_index]; + if (n_spi && n_spi->reg_map) { + spin_lock(&n_spi->sysfs_regmap_lock); + read_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf); + spin_unlock(&n_spi->sysfs_regmap_lock); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 125, 1, 0); + memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16)); + ret = scnprintf(buf, 255, "%x\n", (u32)val); + } + return ret; +} + +static ssize_t neuronspi_spi_store_register(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->reg_map && val < 65536) { + spin_lock(&n_spi->sysfs_regmap_lock); + n_spi->sysfs_register_target = val; + spin_unlock(&n_spi->sysfs_regmap_lock); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_store_register_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + u8 *inp_buf, *outp_buf; + int write_length; + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct spi_device *spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + spi = neuronspi_s_dev[n_spi->neuron_index]; + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->reg_map && val < 65536) { + spin_lock(&n_spi->sysfs_regmap_lock); + write_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf); + spin_unlock(&n_spi->sysfs_regmap_lock); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0); + } +err_end: + return count; +} + + + static ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret = 0; u32 val = 0; struct neuronspi_driver_data *n_spi; + struct spi_device *spi; struct platform_device *plat = to_platform_device(dev); n_spi = platform_get_drvdata(plat); + spi = neuronspi_s_dev[n_spi->neuron_index]; if (n_spi && n_spi->reg_map) { spin_lock(&n_spi->sysfs_regmap_lock); regmap_read(n_spi->reg_map, n_spi->sysfs_regmap_target, &val); @@ -740,6 +808,24 @@ err_end: return count; } +static ssize_t neuronspi_store_regmap_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->reg_map && val < 65536) { + spin_lock(&n_spi->sysfs_regmap_lock); + regmap_write(n_spi->reg_map, n_spi->sysfs_regmap_target, val); + spin_unlock(&n_spi->sysfs_regmap_lock); + } +err_end: + return count; +} + static ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret = 0; @@ -1030,7 +1116,10 @@ static DEVICE_ATTR(model_name, 0440, neuronspi_show_model, NULL); static DEVICE_ATTR(sys_reading_freq, 0660, neuronspi_show_sysfs_speed, neuronspi_store_sysfs_speed); static DEVICE_ATTR(sys_eeprom_name, 0440, neuronspi_show_eeprom, NULL); static DEVICE_ATTR(driver_version, 0440, neuronspi_show_driver_version, NULL); -static DEVICE_ATTR(register_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap); +static DEVICE_ATTR(register_read, 0660, neuronspi_spi_show_register, neuronspi_spi_store_register); +static DEVICE_ATTR(register_set, 0220, NULL, neuronspi_spi_store_register_value); +static DEVICE_ATTR(regmap_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap); +static DEVICE_ATTR(regmap_set, 0220, NULL, neuronspi_store_regmap_value); static DEVICE_ATTR(sys_board_serial, 0440, neuronspi_spi_show_serial, NULL); static DEVICE_ATTR(sys_board_name, 0440, neuronspi_spi_show_board, NULL); static DEVICE_ATTR(sys_primary_major_id, 0440, neuronspi_spi_show_lboard_id, NULL); @@ -1090,6 +1179,9 @@ static struct attribute *neuron_board_attrs[] = { &dev_attr_uart_config.attr, &dev_attr_uart_timeout.attr, &dev_attr_register_read.attr, + &dev_attr_register_set.attr, + &dev_attr_regmap_read.attr, + &dev_attr_regmap_set.attr, NULL, }; diff --git a/modules/unipi/src/unipi_uart.c b/modules/unipi/src/unipi_uart.c index 85cd04b..3417fb3 100644 --- a/modules/unipi/src/unipi_uart.c +++ b/modules/unipi/src/unipi_uart.c @@ -77,7 +77,6 @@ void neuronspi_uart_tx_proc(struct kthread_work *ws) (port->port.rs485.delay_rts_before_send > 0)) { msleep(port->port.rs485.delay_rts_before_send); } - neuronspi_uart_handle_tx(port); } @@ -212,6 +211,24 @@ void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen) } } +int static neuronspi_uart_get_charcount(struct neuronspi_port *port) { + u8 *inp_buf, *outp_buf; + int read_length; + struct spi_device *spi; + struct neuronspi_driver_data *n_spi; + int ret = 0; + spi = neuronspi_s_dev[port->dev_index]; + n_spi = spi_get_drvdata(spi); + if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) { + read_length = neuronspi_spi_compose_single_register_read(n_spi->regstart_table->uart_queue_reg, &inp_buf, &outp_buf); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 35, 1, 0); + ret = outp_buf[MODBUS_FIRST_DATA_BYTE + 1]; + kfree(inp_buf); + kfree(outp_buf); + } + return ret; +} + void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send) { s32 i; @@ -223,6 +240,9 @@ void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send) printk(KERN_INFO "NEURONSPI: UART Char Send: %x\n", port->buf[i]); #endif } + while(neuronspi_uart_get_charcount(port) > 50) { + msleep(1); + } neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port); } @@ -267,7 +287,7 @@ void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir) void neuronspi_uart_handle_tx(struct neuronspi_port *port) { - u32 txlen, to_send, i; + u32 max_txlen, to_send, i; struct spi_device *spi; struct neuronspi_driver_data *d_data; struct circ_buf *xmit; @@ -280,19 +300,39 @@ void neuronspi_uart_handle_tx(struct neuronspi_port *port) neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port); port->port.icount.tx++; port->port.x_char = 0; + spin_lock(&port->tx_lock); + port->tx_work_count--; + spin_unlock(&port->tx_lock); return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) { + spin_lock(&port->tx_lock); + port->tx_work_count--; + spin_unlock(&port->tx_lock); return; } /* Get length of data pending in circular buffer */ to_send = uart_circ_chars_pending(xmit); if (likely(to_send)) { - /* Limit to size of TX FIFO */ - txlen = NEURONSPI_FIFO_SIZE; - to_send = (to_send > txlen) ? txlen : to_send; + /* Limit to size of (TX FIFO / 2) */ + max_txlen = NEURONSPI_FIFO_SIZE >> 1; + while (to_send > max_txlen) { + to_send = (to_send > max_txlen) ? max_txlen : to_send; + + /* Add data to send */ + port->port.icount.tx += to_send; + + /* Convert to linear buffer */ + for (i = 0; i < to_send; ++i) { + port->buf[i] = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } + + neuronspi_uart_fifo_write(port, to_send); + } + to_send = (to_send > NEURONSPI_FIFO_SIZE - NEURONSPI_FIFO_MIN_CONTINUOUS) ? NEURONSPI_FIFO_SIZE - NEURONSPI_FIFO_MIN_CONTINUOUS : to_send; /* Add data to send */ port->port.icount.tx += to_send; @@ -304,7 +344,11 @@ void neuronspi_uart_handle_tx(struct neuronspi_port *port) } neuronspi_uart_fifo_write(port, to_send); + } + spin_lock(&port->tx_lock); + port->tx_work_count--; + spin_unlock(&port->tx_lock); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { uart_write_wakeup(&port->port); @@ -386,6 +430,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index) uart_data->p[i].port.rs485_config = neuronspi_uart_config_rs485; uart_data->p[i].port.ops = &neuronspi_uart_ops; uart_data->p[i].port.line = neuronspi_uart_alloc_line(); + spin_lock_init(&uart_data->p[i].tx_lock); spin_lock_init(&uart_data->p[i].port.lock); if (uart_data->p[i].port.line >= NEURONSPI_MAX_DEVS) { ret = -ENOMEM; @@ -520,6 +565,14 @@ void neuronspi_uart_start_tx(struct uart_port *port) #if NEURONSPI_DETAILED_DEBUG > 0 printk(KERN_INFO "NEURONSPI: Start TX\n"); #endif + spin_lock(&n_port->tx_lock); + if (n_port->tx_work_count > NEURONSPI_MAX_TX_WORK) { + spin_unlock(&n_port->tx_lock); + return; + } else { + n_port->tx_work_count++; + } + spin_unlock(&n_port->tx_lock); kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work); } diff --git a/modules/unipi/src/unipi_uart.h b/modules/unipi/src/unipi_uart.h index 147864c..db0ac06 100644 --- a/modules/unipi/src/unipi_uart.h +++ b/modules/unipi/src/unipi_uart.h @@ -30,6 +30,8 @@ #define NEURONSPI_UART_LDISC_REGISTER 503 #define NEURONSPI_UART_TIMEOUT_REGISTER 504 +#define NEURONSPI_MAX_TX_WORK 16 + /************************* * Function Declarations * *************************/ diff --git a/version.txt b/version.txt index 4745628..c3e8946 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -Repository:neuron-kernel ActiveBranch:[uart_timeout] PrecedingRelease:v.0.12 PrecedingRevision:48(7b58ef1) LatestCommit:Thu Jun 14 16:09:24 CEST 2018 +Repository:neuron-kernel ActiveBranch:[uart_timeout] PrecedingRelease:v.0.12 PrecedingRevision:49(e00d27d) LatestCommit:Mon Jun 25 14:20:41 CEST 2018 -- 2.34.1