Re: Trouble loading firmware to USB device

From: Hans Petter Selasky <hps_at_selasky.org>
Date: Mon, 18 Apr 2022 18:57:15 UTC
On 4/13/22 00:10, Farhan Khan wrote:
> Hi all,
> 
> I am trying to load the copy the OpenBSD athn code. Currently I am
> trying to load the firmware of the device but running an issue where
> the interrupt RX callback is getting an USB_ERR_CANCELLED event.
> 
> Based on my reading of the OpenBSD code, it appears that the OpenBSD
> driver will load the firmware in chunks, then submit a NULL (size 0)
> usbd_do_request to indicate completion of the firmware. At this, the
> driver will tsleep() for 1 second. If it breaks with a return value of
> 0, the driver will continue successfully. My understanding is that this
> should trigger an Rx Interrupt, which should run the wakup() that the
> tsleep() is looking for.
> 
> However, in my case the USB_ST_SETUP condition is run, but it seems to
> block indefinitely. Meanwhile, the tsleep() expires, returns a
> EWOULDBLOCK and eventually runs the detach handler. As a result, the
> blocking callback receives a USB_ST_ERROR with the value
> USB_ERR_CANCELLED.
> 
> What might be causing the blocking of the callback? Am I loading the
> firmware incorrectly?
> 
> My firmware code is here:
> https://github.com/khanzf/freebsd/blob/ar9271-check/sys/dev/athn/usb/if_athn_usb.c#L934
> The interrupt handler, athn_usb_intr, is line 2405.
> 
> The OpenBSD equivalent of the firmware loader is this:
> https://github.com/openbsd/src/blob/master/sys/dev/usb/if_athn_usb.c#L642
> The interrupt handler is also athn_usb_intr online 1874.
> 
> Any assistance would be great, been stuck for a few weeks :/
> 

Hi,

error = tsleep(&usc->wait_msg_id, 0, "athnfw", 5);

This means wait 5 ticks which is typically 5ms before timing out, which 
is probably too short!

This code is wrong for FreeBSD.

The lock should cover the whole section and you should use msleep instead.

     ATHN_LOCK(sc);
     error = usbd_do_request(usc->sc_udev, &sc->sc_mtx, &req, NULL);
     if (error == 0 && usc->wait_msg_id != 0) {
         printf("Error is %d\n", error);
         error = msleep(&usc->wait_msg_id, 0, "athnfw", hz); /* wait 1 
second at most */
         if (error) {
             ATHN_UNLOCK(sc);
             printf("Exiting condition %d\n", error);
             return error;
         }
     }
     ATHN_UNLOCK(sc);

--HPS