- Added better handling of long TTY packets
authorTom Knot <tomasknot@gmail.com>
Mon, 25 Jun 2018 12:20:41 +0000 (14:20 +0200)
committerTom Knot <tomasknot@gmail.com>
Mon, 25 Jun 2018 12:20:41 +0000 (14:20 +0200)
- SYSFS register access improved and expanded

modules/unipi/Makefile
modules/unipi/src/unipi_common.h
modules/unipi/src/unipi_sysfs.c
modules/unipi/src/unipi_uart.c
modules/unipi/src/unipi_uart.h
version.txt

index c1e73567930bc7acf65bca61df35efda3c2a9f7b..39886dfe774f1359784016bd77754c66e29aa0ce 100644 (file)
@@ -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
 
index a98a24635ebc69070c66514b5b592738b5dce440..2ee40c7b7a30cb771272f11631eede2503d49ca8 100644 (file)
@@ -51,7 +51,7 @@
 #if NEURONSPI_SCHED_REQUIRED > 0
        #include <uapi/linux/sched/types.h>
 #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;
 };
index 1562db9f6c604d6d1205ca3f1dc98f6db8f6b64a..d3ba7a29b1a4526df4d2894456a403b22848c119 100644 (file)
@@ -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,
 };
 
index 85cd04bf0fe1ccaa89eebcf405021b7bdcc25259..3417fb38a5813b811785fcda88f4d1c51b71b752 100644 (file)
@@ -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);
 }
 
index 147864c22195fb6c11bfce37a7af684f292b9306..db0ac06b5335c0a744d128157b68c93c49f77903 100644 (file)
@@ -30,6 +30,8 @@
 #define NEURONSPI_UART_LDISC_REGISTER  503
 #define NEURONSPI_UART_TIMEOUT_REGISTER 504
 
+#define NEURONSPI_MAX_TX_WORK  16
+
 /*************************
  * Function Declarations *
  *************************/
index 4745628ccc948a58a775e9535ca755e0f6db74a5..c3e89467e8cbd8eca6e290a1c3b47160fb26e44a 100644 (file)
@@ -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