Tx transfer not triggering corresponding Rx interrupt
Date: Sun, 15 May 2022 02:41:57 UTC
Hi all, I am trying to understand why a USB Rx interrupt callback is not triggering. I am sending a USB Tx interrupt packet. The immediate next step is that the function will msleep(). The corresponding wakeup() occurs after an Rx interrupt. There is no explicit usbd_transfer_start() on the Rx interrupt. Elsewhere in the code there is an instance where an Tx interrupt should eventually result in a corresponding Rx interrupt that results in a wakeup(). That does not occurs here and I do not understand why not. ----------- Background: I am working on porting OpenBSD's athn(9) driver to FreeBSD. I loaded the firmware and I believe this is confirmed by sending a AR_HTC_MSG_READY message, which is https://github.com/khanzf/freebsd/blob/ 0ba9a9b92df496847058008598139e92f5e60850/sys/dev/athn/usb/if_athn_usb.c#L1009. There is an associated msleep() and wakeup() that suggest the firmware was successfully loaded. The wakeup occurs in the Rx interrupt handler. Then, there is a section where the driver sets up the Host Transport Communication (HTC) interface. The driver does a transfer of data of the Tx Interrupt, then immediately runs msleep(). The corresponding wakeup occurs when an Rx (not Tx) interrupt triggers and is processed. The code for this is located in athn_usb_htc_connect_svc(). My current implementation is here: https://github.com/khanzf/freebsd/blob/ 0ba9a9b92df496847058008598139e92f5e60850/sys/dev/athn/usb/if_athn_usb.c#L1293 The OpenBSD implementation is here: https://github.com/openbsd/src/blob/ 72a0854b669a0194895eeac5ffcdf5fc27bf2a30/sys/dev/usb/if_athn_usb.c#L809 Please note that in the OpenBSD implementation, the athn_usb_htc_msg() function calls usbd_setup_xfer/usbd_transfer, whereas my implementation calls usbd_transfer_start(). Also, OpenBSD opens the Rx Interrupt pipe with usbd_open_pipe_intr(), which gives the option for an interval. I suspect this is the same as the `interval` parameter in usb_config. I do not know if this is significant. ----------- Problem: The msleep() located on line 1314 fails with EWOULDBLOCK. This sleep seems to be the equivalent of the acknowledgement that the Tx interrupt packet was received. ----------- Expected: I expect this to somehow result in the Rx interrupt, which runs the corresponding handler athn_usb_intr(). This function contains the wakeup() line on line 2556 (the AR_HTC_MSG_CONN_SVC case). ----------- This happens elsewhere: In athn_usb_load_firmware(), line 1011, there is a usbd_do_request(), followed by an msleep(). The wait_msg_id is AR_HTC_MSG_READY. The wakeup for this occurs only after an Rx interrupt is called on line 2538. ----------- Question rephrased: Why is a USB transfer resulting in an Rx interrupt in one place, even though a usbd_transfer_start() is not called on the Rx interrupt, but not for athn_usb_htc_connect_svc()/athn_usb_htc_msg()? How do I make this Tx transfer result in an Rx interrupt without having to manually call usbd_transfer_start() (OpenBSD does not appear to do this?) I do not understand the differences between usbd_do_request, usb_transfer_start and usbd_setup_xfer/usbd_transfer that might be resulting in different behavior, so any light on that would also help. ----------- Been stuck for some time, so any assistance is appreciated. Thank you! - Farhan