[PATCH] Re: UART driver problem

Marcus Sundberg erammsu at kieraypc01.p.y.ki.era.ericsson.se
Wed Jan 26 00:27:52 EST 2000


"Ralf HECKHAUSEN" <RHeckhau at frequentis.com> 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/





More information about the Linuxppc-embedded mailing list