Thread (1 message) 1 message, 1 author, 2000-01-25
DORMANTno replies

[PATCH] Re: UART driver problem

From: Marcus Sundberg <hidden>
Date: 2000-01-25 13:27:52

"Ralf HECKHAUSEN" [off-list ref] writes:
I have a strange problem with the uart driver. The 8xx_write in uart.c
always fails because copy_from_user returns 0 instead of the requested
number of bytes. When I ignore the comparison with the requested
number of bytes everything works ok, the correct bytes are transmitted
and 8xx_write returns something >0.
I noted that as well the other day, together with another problem,
when starting to use sysvinit instead of a simple bash script.

The above problem is solved by this patch:

diff -u -u -r1.4 -r1.5
--- uart.c      2000/01/17 17:20:57     1.4
+++ uart.c      2000/01/24 18:02:19     1.5
@@ -976,8 +976,7 @@
                }

                if (from_user) {
-                       if (c !=
-                           copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+                       if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
                                if (!ret)
                                        ret = -EFAULT;
                                break;
Strangely enough drivers/char/serial.c is broken as well in standard
kernels. The only difference is that there the copy_from_user() will
appear to always succeed instead of always failing...

The other problem got triggered by init doing open(); write(); close();
cycles on the serial console. Without this patch the write() output
gets aborted before finishing:

diff -u -u -r1.4 -r1.5
--- uart.c      2000/01/17 17:20:57     1.4
+++ uart.c      2000/01/24 18:02:19     1.5
@@ -1692,6 +1691,13 @@
         * be at least two characters waiting to be sent after the buffers
         * are empty.
         */
+       bdp = info->tx_cur;
+       /* We want to wait for the last buffer, not the first. */
+       if (bdp == info->tx_bd_base) {
+               bdp += (TX_NUM_FIFO-1);
+       } else {
+               bdp--;
+       }
        do {
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
                printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
@@ -1703,7 +1709,6 @@
                        break;
                if (timeout && ((orig_jiffies + timeout) < jiffies))
                        break;
-               bdp = info->tx_cur;
        } while (bdp->cbd_sc & BD_SC_READY);
        current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT

//Marcus
--
Signature under construction, please come back later.

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help