Re: parport driver broken in 2.1.127-pre7?

Andrea Arcangeli (andrea@e-mind.com)
Thu, 5 Nov 1998 15:11:58 +0100 (CET)


On Thu, 5 Nov 1998, Andrea Arcangeli wrote:

>On Thu, 5 Nov 1998, Andrea Arcangeli wrote:
>
>>I' ll send to you a patch ASAP that should fix your problem (I just know
>
>Here the patch that should fix your problem:

I implemented the trustirq ioctl now.

This minimal proggy allow me to set/unset the trustirq flag at runtime.

#define LPTRUSTIRQ 0x060f

main(int argc, char **argv)
{
int fd = open("/dev/lp0");
ioctl(fd, LPTRUSTIRQ, argc - 1);
}

And here the patch that implement the ioctl (against pre-2.1.127-6):

Index: linux/drivers/char/lp.c
diff -u linux/drivers/char/lp.c:1.1.1.4 linux/drivers/char/lp.c:1.1.1.1.12.7
--- linux/drivers/char/lp.c:1.1.1.4 Wed Nov 4 13:06:06 1998
+++ linux/drivers/char/lp.c Thu Nov 5 14:52:13 1998
@@ -21,7 +21,8 @@
* Full efficient handling of printer with buggy irq handshake (now I have
* understood the meaning of the strange handshake). This is done sending new
* characters if the interrupt is just happened, even if the printer say to
- * be still BUSY. This is needed at least with Epson Stylus Color.
+ * be still BUSY. This is needed at least with Epson Stylus Color but
+ * to be safe you must enable this _needed_ feature via ioctl.
* I also fixed the irq on the rising edge of the strobe problem.
* Andrea Arcangeli, 15 Oct 1998
*/
@@ -225,25 +226,36 @@
lp_yield(minor);

status = r_str(minor);
- /*
- * On Epson Stylus Color we must continue even if LP_READY()
- * is false to be efficient. This way is backwards
- * compatible with old not-buggy printers. -arca
- */
- if (LP_NO_ERROR(status) &&
- ((lp_table[minor].irq_detected && LP_NO_ACKING(status)) ||
- LP_READY(status)))
- break;
- /*
- * To have a chance to sleep on the interrupt we should break
- * the polling loop ASAP. Unfortunately there seems to be
- * some hardware that underperform so we leave this
- * configurable at runtime. So when printing with irqs
- * `tunelp /dev/lp0 -c 1' is a must to take the full
- * advantage of the irq. -arca
- */
- if (++count == LP_CHAR(minor))
- return 0;
+ if (lp_table[minor].trustirq)
+ {
+ /*
+ * On Epson Stylus Color we must continue even if
+ * LP_READY() is false to be efficient. This way
+ * _should_ be backwards compatible with old
+ * not-buggy printers but it isn' t. -arca
+ */
+ if (LP_NO_ERROR(status) &&
+ ((lp_table[minor].irq_detected &&
+ LP_NO_ACKING(status)) ||
+ LP_READY(status)))
+ break;
+ if (!LP_POLLED(minor) || ++count == LP_CHAR(minor))
+ return 0;
+ } else {
+ if (LP_NO_ERROR(status) && LP_READY(status))
+ break;
+ /*
+ * To have a chance to sleep on the interrupt we
+ * should break the polling loop ASAP. Unfortunately
+ * there seems to be some hardware that underperform
+ * so we leave this configurable at runtime. So when
+ * printing with irqs `tunelp /dev/lp0 -c 1' should
+ * be a must to take the full advantage of the
+ * irq. -arca
+ */
+ if (++count == LP_CHAR(minor))
+ return 0;
+ }
}

w_dtr(minor, lpchar);
@@ -731,12 +743,17 @@
if (copy_to_user((int *) arg, &status, sizeof(int)))
return -EFAULT;
break;
+ case LPTRUSTIRQ:
+ if (arg)
+ lp_table[minor].trustirq = 1;
+ else
+ lp_table[minor].trustirq = 0;
+ break;
default:
retval = -EINVAL;
}
return retval;
}
-

static struct file_operations lp_fops = {
lp_lseek,
Index: linux/include/linux/lp.h
diff -u linux/include/linux/lp.h:1.1.1.4 linux/include/linux/lp.h:1.1.1.1.12.3
--- linux/include/linux/lp.h:1.1.1.4 Wed Nov 4 13:09:24 1998
+++ linux/include/linux/lp.h Thu Nov 5 14:48:29 1998
@@ -67,7 +67,7 @@
or 0 for polling (no IRQ) */
#define LPGETIRQ 0x0606 /* get the current IRQ number */
#define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */
-#ifdef LP_NEED_CAREFUL
+#if 0
#define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off-
line, and error indicators good on all writes,
FALSE to ignore them. Default is ignore. */
@@ -80,6 +80,9 @@
#define LPGETSTATS 0x060d /* get statistics (struct lp_stats) */
#endif
#define LPGETFLAGS 0x060e /* get status flags */
+#define LPTRUSTIRQ 0x060f /* cause lp to trust or not the irq, this is needed
+ * to give a sense to the irq printing at least
+ * for Epson Stylus Color */

/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
This is also used for re-checking error conditions if LP_ABORT is
@@ -126,9 +129,10 @@
#endif
struct wait_queue *wait_q;
unsigned int last_error;
- volatile unsigned int irq_detected:1;
- volatile unsigned int irq_missed:1;
+ unsigned int irq_detected:1;
+ unsigned int irq_missed:1;
unsigned int polled:1;
+ unsigned int trustirq:1;
};

/*

I' ll try to explain why Epson Stylus Color need to trust the irq.

____
BUSY
_________________ ____________________
___ | |
ACK ----------
____________________ _______________________
| |
---
---
| |
*polling loop time*

The problem is that the printer generate the ACK (and so the irq) very
very soon. Once the irq is been generated lp doesn' t sleep on the irq
anymore and continue to poll the BUSY flag because it knows that the
printer will be ready very very soon. The problem is that polling so fast
(in the *polling loop time*), causes lp to _overload_ the machine (this
doesn' t harm because lp always schedule if need_resched is set, but it' s
really stupid).

>From pratical experience all Epson Stylus Color are just ready after the
irq (if LP_NO_ACKING() is true) and so, on such printers, we can send the
next char a bit after the irq avoiding such stupid polling loop.

Not buggy printers should handle that `trustirq' feature fine too because
the specs say that after ACK is removed BUSY should be sure just removed
from ages too. Unfortunately that' s not true as Peter pointed out ;-). So
we need an ioctl that allow the admin to select on which printer trust the
irq (and handle the full advantage of the irq). The overloading of the
machine in system time change from 80/90% to 20/30% here, so if you don'
t use trustirq, on some printers it' s better that you use polling...

It would be nice if somebody would update tunelp to the new lp (note also
that LP_CAREFUL is been removed from the kernel, because checking for the
careful flag is slower than being careful all the time). I can do that
myself if nobody else is interested to do that.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/