From 40ac32acdae89383ae44f32e612bf37fa0493631 Mon Sep 17 00:00:00 2001 From: norly Date: Fri, 31 May 2019 01:20:17 +0200 Subject: [PATCH] Separate buffers from struct elm This avoids trouble with CPU caches racing DMA accesses on ARM. --- module/elmcan.c | 36 +++++++++++++++++++++++++++--------- readme.rst | 3 --- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/module/elmcan.c b/module/elmcan.c index ba4ef0d..7ac1f54 100644 --- a/module/elmcan.c +++ b/module/elmcan.c @@ -60,6 +60,9 @@ MODULE_PARM_DESC(accept_flaky_uart, "Don't bail at the first invalid character. #define N_ELMCAN 29 #endif +#define ELM327_SIZE_RXBUF 256 +#define ELM327_SIZE_TXBUF 32 + #define ELM327_CAN_CONFIG_SEND_SFF 0x8000 #define ELM327_CAN_CONFIG_VARIABLE_DLC 0x4000 #define ELM327_CAN_CONFIG_RECV_BOTH_SFF_EFF 0x2000 @@ -111,12 +114,12 @@ struct elmcan { /* TTY TX helpers */ struct work_struct tx_work; /* Flushes TTY TX buffer */ - unsigned char txbuf[32]; + unsigned char *txbuf; unsigned char *txhead; /* Pointer to next TX byte */ int txleft; /* Bytes left to TX */ /* TTY RX helpers */ - unsigned char rxbuf[256]; + unsigned char *rxbuf; int rxfill; /* State machine */ @@ -687,7 +690,7 @@ static bool elm327_is_ready_char(char c) static void elm327_drop_bytes(struct elmcan *elm, int i) { - memmove(&elm->rxbuf[0], &elm->rxbuf[i], sizeof(elm->rxbuf) - i); + memmove(&elm->rxbuf[0], &elm->rxbuf[i], ELM327_SIZE_RXBUF - i); elm->rxfill -= i; } @@ -739,7 +742,7 @@ static void elm327_parse_rxbuf(struct elmcan *elm) /* empty loop */ } - if (len == sizeof(elm->rxbuf)) { + if (len == ELM327_SIZE_RXBUF) { /* Line exceeds buffer. It's probably all garbage. * Did we even connect at the right baud rate? */ @@ -984,7 +987,7 @@ static void elmcan_ldisc_rx(struct tty_struct *tty, goto out; } - while (count-- && elm->rxfill < sizeof(elm->rxbuf)) { + while (count-- && elm->rxfill < ELM327_SIZE_RXBUF) { if (fp && *fp++) { netdev_err(elm->dev, "Error in received character stream. Check your wiring."); @@ -1137,6 +1140,13 @@ static int elmcan_ldisc_open(struct tty_struct *tty) return -ENFILE; elm = netdev_priv(dev); + elm->rxbuf = kmalloc(ELM327_SIZE_RXBUF, GFP_KERNEL); + elm->txbuf = kmalloc(ELM327_SIZE_TXBUF, GFP_KERNEL); + if (!elm->rxbuf || !elm->txbuf) { + err = -ENOMEM; + goto out_err; + } + /* Configure TTY interface */ tty->receive_room = 65536; /* We don't flow control */ elm->txleft = 0; /* Clear TTY TX buffer */ @@ -1163,14 +1173,20 @@ static int elmcan_ldisc_open(struct tty_struct *tty) /* Let 'er rip */ err = register_candev(elm->dev); - if (err) { - free_candev(elm->dev); - return err; - } + if (err) + goto out_err; netdev_info(elm->dev, "elmcan on %s.\n", tty->name); return 0; + +out_err: + if (elm->txbuf) + kfree(elm->txbuf); + if (elm->rxbuf) + kfree(elm->rxbuf); + free_candev(elm->dev); + return err; } /* Close down an elmcan channel. @@ -1212,6 +1228,8 @@ static void elmcan_ldisc_close(struct tty_struct *tty) netdev_info(elm->dev, "elmcan off %s.\n", tty->name); + kfree(elm->txbuf); + kfree(elm->rxbuf); free_candev(elm->dev); } diff --git a/readme.rst b/readme.rst index 9924167..a283e0a 100644 --- a/readme.rst +++ b/readme.rst @@ -341,8 +341,5 @@ termination resistors on its PCB and try removing them. To Do list for future development ---------------------------------- -- DMA capable rx/tx buffers - (is this relevant for this driver?) - - flushing of ``tx_work`` is too late in ``ldisc_close()`` (is this still the case?) -- 2.30.2