After submitting a print job and then turning on my USB printer I got:

ulpt0 at uhub0 port 1 configuration 1 interface 0 "Hewlett-Packard HP LaserJet 
1020" rev 2.00/1.00 addr 2
ulpt0: using bi-directional mode
ulpt0: ucode upload error=IOERROR!
ulpt0: could not load firmware 'ulpt-hp1020'
uvm_fault(0xf388ac04, 0x0, 0, 1) -> e
kernel: page fault trap, code=0
Stopped at      usbd_transfer+0x13:     movl    0x4(%edi),%eax
ddb> trace
usbd_transfer(d56362a0,0,0,f39ef000,d) at usbd_transfer+0x13
ulpt_do_write(d150e600,f39e7e9c,1,d03ff869,f39e7d2c) at ulpt_do_write+0xd6
ulptwrite(4000,f39e7e9c,1,d04f2dbb,f37d7b7c) at ulptwrite+0x5d
spec_write(f39e7dc8,f38b71bc,f39e7ddc,d03ff869,f39e7dcc) at spec_write+0xad
VOP_WRITE(f37d6838,f39e7e9c,1,f3909664,f388ac08) at VOP_WRITE+0x42
vn_write(d561b834,d561b850,f39e7e9c,f3909664,4faf4658) at vn_write+0x92
dofilewritev(d5488b98,5,d561b834,f39e7f04,1) at dofilewritev+0x194
sys_write(d5488b98,f39e7f60,f39e7f80,d056d895,d5488b98) at sys_write+0xa5
syscall() at syscall+0x24d
--- syscall (number -809625138) ---
0x2:
ddb> 

With the following diff firmware load errors (which I triggered on
purpose both by pulling the USB cable at the right time, and also
by renaming the firmware file) are handled more gracefully:

$ lpq
waiting for lp to become ready (offline ?)
Rank   Owner      Job  Files                                 Total Size
1st    stsp       143  (standard input)                      3 bytes
$ tail /var/log/messages  
Oct 19 16:02:13 dougal /bsd: ulpt0: failed loadfirmware of file ulpt-hp1020 
(error 2)
Oct 19 16:02:13 dougal /bsd: ulpt0: could not load firmware 'ulpt-hp1020'
Oct 19 16:02:29 dougal /bsd: ulpt0: failed loadfirmware of file ulpt-hp1020 
(error 2)
Oct 19 16:02:29 dougal /bsd: ulpt0: could not load firmware 'ulpt-hp1020'
Oct 19 16:03:01 dougal /bsd: ulpt0: failed loadfirmware of file ulpt-hp1020 
(error 2)
Oct 19 16:03:01 dougal /bsd: ulpt0: could not load firmware 'ulpt-hp1020'
Oct 19 16:03:33 dougal /bsd: ulpt0: failed loadfirmware of file ulpt-hp1020 
(error 2)
Oct 19 16:03:33 dougal /bsd: ulpt0: could not load firmware 'ulpt-hp1020'
Oct 19 16:04:06 dougal /bsd: ulpt0: failed loadfirmware of file ulpt-hp1020 
(error 2)
Oct 19 16:04:06 dougal /bsd: ulpt0: could not load firmware 'ulpt-hp1020'

In my testing the printer recovers automatically once the firmware
file is put in place. There is no need to re-plug it.

ok?

Index: ulpt.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ulpt.c,v
retrieving revision 1.47
diff -u -p -r1.47 ulpt.c
--- ulpt.c      12 Jul 2014 20:26:33 -0000      1.47
+++ ulpt.c      19 Oct 2014 13:41:00 -0000
@@ -100,6 +100,7 @@ struct ulpt_softc {
 #define        ULPT_INIT       0x04    /* waiting to initialize for open */
        u_char sc_flags;
 #define        ULPT_NOPRIME    0x40    /* don't prime on open */
+#define        ULPT_EFIRMWARE  0x80    /* error loading firmware */
        u_char sc_laststatus;
 
        int sc_refcnt;
@@ -193,9 +194,12 @@ ulpt_load_firmware(void *arg)
        usbd_status err;
 
        err = (sc->sc_fwdev->ucode_loader)(sc);
-       if (err != USBD_NORMAL_COMPLETION)
+       if (err != USBD_NORMAL_COMPLETION) {
+               sc->sc_flags |= ULPT_EFIRMWARE;
                printf("%s: could not load firmware '%s'\n",
                    sc->sc_dev.dv_xname, sc->sc_fwdev->ucode_name);
+       } else
+               sc->sc_flags &= ~ULPT_EFIRMWARE;
 }
 
 #define ulpt_lookup(v, p) \
@@ -469,6 +473,13 @@ ulptopen(dev_t dev, int flag, int mode, 
        if (sc->sc_state)
                return (EBUSY);
 
+       /* If a previous attempt to load firmware failed, retry. */
+       if (sc->sc_flags & ULPT_EFIRMWARE) {
+               ulpt_load_firmware(sc);
+               if (sc->sc_flags & ULPT_EFIRMWARE)
+                       return (EIO);
+       }
+
        sc->sc_state = ULPT_INIT;
        sc->sc_flags = flags;
        DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags));
@@ -640,7 +651,7 @@ ulptwrite(dev_t dev, struct uio *uio, in
 
        sc = ulpt_cd.cd_devs[ULPTUNIT(dev)];
 
-       if (usbd_is_dying(sc->sc_udev))
+       if (usbd_is_dying(sc->sc_udev) || (sc->sc_flags & ULPT_EFIRMWARE))
                return (EIO);
 
        sc->sc_refcnt++;

Reply via email to