On Thu, May 05, 2022 at 01:19:08PM -0400, Farhan Khan wrote:
> Hi all,
> 
> Summary Question:
> 
> Broadly, I am trying to understand where a interrupt callback is specified if 
> not already specified by usbd_open_pipe_intr(9). Specifically, for the 
> athn(4) 
> driver, I am trying to understand if/how athn_usb_intr() is executed for Tx 
> interrupts. This seems necessary yet I do not see a callback specified by 
> usbd_setup_xfer(9) or by usbd_open_pipe_intr(9).
> 
> All code is located in sys/dev/usb/if_athn_usb.c.
> 
> Question Walk-through:
> 
> >From reading the code, it seems that the athn_usb_intr() function is called 
> whenever a Tx interrupt is triggered. The reason I think this is because 
> there 
> is a tsleep_nsec(9) for a Tx interrupt that awaits for a wakeup(9) that only 
> happens in athn_usb_intr().
> 
> The 3 relevant steps are listed below in athn_usb_htc_setup() under the 
> comment "Set credits for WLAN Tx pipe":
> 
> 1. athn_usb_htc_msg(), which runs usbd_setup_xfer(9) and usbd_transfer(9) for 
> a Tx interrupt. The callback is set to NULL.
> 2. usc->wait_msg_id is set to AR_HTC_MSG_CONF_PIPE_RSP.
> 3. A tsleep_nsec() on &usc->wait_msg_id
> 
> The only place I see a wakeup(9) on &usc->wait_msg_id is within 
> athn_usb_intr(), on condition that usc->wait_msg_id is set to 
> AR_HTC_MSG_CONF_PIPE_RSP. Seems like a perfect match. Additionally, I do not 
> see an Rx interrupt anywhere else. But even if it does happen somewhere and I 
> am just missing it, the only place AR_HTC_MSG_CONF_PIPE_RSP is used is step 2.
> 
> Rx interrupt callbacks to athn_usb_intr() are specified by the 
> usbd_open_pipe_intr(9) call in athn_usb_open_pipes(). That seems explicit. 
> But 
> for the Tx interrupt, I do not see where the mapping to athn_usb_intr() is.
> 
> Please assist, thank you.

Everything related to Tx is happening in athn_usb_tx() and athn_usb_txoef().

usbd_setup_xfer() gets a function pointer to call when the USB transfer
has completed. This function pointer is athn_usb_txeof():

        usbd_setup_xfer(data->xfer, usc->tx_data_pipe, data, data->buf,
            xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, ATHN_USB_TX_TIMEOUT,
            athn_usb_txeof);

athn_usb_txeof() puts the buffer associated with the Tx attempt back onto
the list of free buffers, and schedules more Tx attempts if needed by
calling if_start().

The associated mbuf is freed quite early, before the Tx attempt is even made,
because the entire packet gets copied into the Tx command sent to the device:

        /* Copy payload. */
        m_copydata(m, 0, m->m_pkthdr.len, frm);
        frm += m->m_pkthdr.len;
        m_freem(m);

Reply via email to