Hopefully I have at last foudn the right place to post this...
I have an HP1100 printer and since I upgraded to a faster CPU the
printer has started hanging. The problem persisteed across 2.0 2.2 and
2.4 kernel versions. I am running Red Hat Linux 8.0 on a Compaq Armada E500.
The problem occurs intermittently. The symptom is that the 'buffer
contains data' light stays on on the printer, but data transfer stops.
I traced the problem to drivers/parport/ieee1284_ops.c function
parport_ieee1284_write_compat. The problem occurs when the parallel port
is not using interrupts. If the printer takes a while to respond the
routine parport_wait_event gets called, if count == 0. However this
routine generally waits almost no time, as shown in my traces, if the
port does not have interrupts enabled. Looking at that code, it seems
that parport_wait_event is only meant to be called when interrupts are
available on the port.
Anyway, if 32 repeats of this occur e.g. for a complex document where
the printer is slow, 'wait' ends up as a negative number from repeated
doublings due to the way twos complement arithmetic works in C. In this
case the routine never returns, or at least waits for a very long time
i.e. hours. So no more data gets sent to the printer.
Originally I fixed the problem by adding code to ensure that 'wait'
never got set to anything above 10 seconds (10 * HZ). However the patch
I have sent you does something different, it just ensures that
parport_wait_event never gets called for printer without interrupt. I
have tested this on documents which reproduce the problem and the hangs
go away.
Clearly I am not an expert on the parport code, so my patch may be
incorrect. I have traces using extra printks I put in the code, showing
the wait variable being doubled to negative value, available on request.
Definitely my patch does fix a real problem on my system.
As far as I can tell from browsing the patches since 2.4.18, there has
not been any other fix for this problem to date.
Regards,
Tim Josling
--- ChangeLog.original 2003-03-16 09:18:07.000000000 +1100
+++ ChangeLog 2003-03-16 09:20:35.000000000 +1100
@@ -1,3 +1,9 @@
+2003-03-16 Tim Josling <tej@melbpc.org.au>
+
+ * ieee1284_ops.c (parport_ieee1284_write_compat): Avoid calling
+ parport_wait_event if interrupts are not enabled for device, avoid
+ output hang.
+
2002-04-25 Tim Waugh <twaugh@redhat.com>
* parport_serial.c, parport_pc.c: Move some SIIG cards around.
--- ieee1284_ops.c.original 2003-03-16 08:27:33.000000000 +1100
+++ ieee1284_ops.c 2003-03-16 09:17:23.000000000 +1100
@@ -93,7 +93,7 @@
first time around the loop, don't let go of
the port. This way, we find out if we have
our interrupt handler called. */
- if (count && no_irq) {
+ if (count || no_irq) {
parport_release (dev);
__set_current_state (TASK_INTERRUPTIBLE);
schedule_timeout (wait);
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2b29 : Thu Mar 20 2003 - 14:51:13 EST