// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * hcd_intr.c - DesignWare HS OTG Controller host-mode interrupt handling * * Copyright (C) 2004-2013 Synopsys, Inc. */ /* * This file contains the interrupt handlers for Host mode */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/usb/ch11.h> #include "core.h" #include "hcd.h" /* * If we get this many NAKs on a split transaction we'll slow down * retransmission. A 1 here means delay after the first NAK. */ #define DWC2_NAKS_BEFORE_DELAY … /* This function is for debug only */ static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) { … } static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd) { … } /* * Handles the start-of-frame interrupt in host mode. Non-periodic * transactions may be queued to the DWC_otg controller for the current * (micro)frame. Periodic transactions may be queued to the controller * for the next (micro)frame. */ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg) { … } /* * Handles the Rx FIFO Level Interrupt, which indicates that there is * at least one packet in the Rx FIFO. The packets are moved from the FIFO to * memory if the DWC_otg controller is operating in Slave mode. */ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) { … } /* * This interrupt occurs when the non-periodic Tx FIFO is half-empty. More * data packets may be written to the FIFO for OUT transfers. More requests * may be written to the non-periodic request queue for IN transfers. This * interrupt is enabled only in Slave mode. */ static void dwc2_np_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg) { … } /* * This interrupt occurs when the periodic Tx FIFO is half-empty. More data * packets may be written to the FIFO for OUT transfers. More requests may be * written to the periodic request queue for IN transfers. This interrupt is * enabled only in Slave mode. */ static void dwc2_perio_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg) { … } static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, u32 *hprt0_modify) { … } /* * There are multiple conditions that can cause a port interrupt. This function * determines which interrupt conditions have occurred and handles them * appropriately. */ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) { … } /* * Gets the actual length of a transfer after the transfer halts. halt_status * holds the reason for the halt. * * For IN transfers where halt_status is DWC2_HC_XFER_COMPLETE, *short_read * is set to 1 upon return if less than the requested number of bytes were * transferred. short_read may also be NULL on entry, in which case it remains * unchanged. */ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status, int *short_read) { … } /** * dwc2_update_urb_state() - Updates the state of the URB after a Transfer * Complete interrupt on the host channel. Updates the actual_length field * of the URB based on the number of bytes transferred via the host channel. * Sets the URB status if the data transfer is finished. * * @hsotg: Programming view of the DWC_otg controller * @chan: Programming view of host channel * @chnum: Channel number * @urb: Processing URB * @qtd: Queue transfer descriptor * * Return: 1 if the data transfer specified by the URB is completely finished, * 0 otherwise */ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_hcd_urb *urb, struct dwc2_qtd *qtd) { … } /* * Save the starting data toggle for the next transfer. The data toggle is * saved in the QH for non-control transfers and it's saved in the QTD for * control transfers. */ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /** * dwc2_update_isoc_urb_state() - Updates the state of an Isochronous URB when * the transfer is stopped for any reason. The fields of the current entry in * the frame descriptor array are set based on the transfer state and the input * halt_status. Completes the Isochronous URB if all the URB frames have been * completed. * * @hsotg: Programming view of the DWC_otg controller * @chan: Programming view of host channel * @chnum: Channel number * @halt_status: Reason for halting a host channel * @qtd: Queue transfer descriptor * * Return: DWC2_HC_XFER_COMPLETE if there are more frames remaining to be * transferred in the URB. Otherwise return DWC2_HC_XFER_URB_COMPLETE. */ static enum dwc2_halt_status dwc2_update_isoc_urb_state( struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { … } /* * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic * QHs, removes the QH from the active non-periodic schedule. If any QTDs are * still linked to the QH, the QH is added to the end of the inactive * non-periodic schedule. For periodic QHs, removes the QH from the periodic * schedule if no more QTDs are linked to the QH. */ static void dwc2_deactivate_qh(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, int free_qtd) { … } /** * dwc2_release_channel() - Releases a host channel for use by other transfers * * @hsotg: The HCD state structure * @chan: The host channel to release * @qtd: The QTD associated with the host channel. This QTD may be * freed if the transfer is complete or an error has occurred. * @halt_status: Reason the channel is being released. This status * determines the actions taken by this function. * * Also attempts to select and queue more transactions since at least one host * channel is available. */ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { … } /* * Halts a host channel. If the channel cannot be halted immediately because * the request queue is full, this function ensures that the FIFO empty * interrupt for the appropriate queue is enabled so that the halt request can * be queued when there is space in the request queue. * * This function may also be called in DMA mode. In that case, the channel is * simply released since the core always halts the channel automatically in * DMA mode. */ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { … } /* * Performs common cleanup for non-periodic transfers after a Transfer * Complete interrupt. This function should be called after any endpoint type * specific handling is finished to release the host channel. */ static void dwc2_complete_non_periodic_xfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { … } /* * Performs common cleanup for periodic transfers after a Transfer Complete * interrupt. This function should be called after any endpoint type specific * handling is finished to release the host channel. */ static void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { … } static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel Transfer Complete interrupt. This handler may be * called in either DMA mode or Slave mode. */ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel STALL interrupt. This handler may be called in * either DMA mode or Slave mode. */ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Updates the state of the URB when a transfer has been stopped due to an * abnormal condition before the transfer completes. Modifies the * actual_length field of the URB to reflect the number of bytes that have * actually been transferred via the host channel. */ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_hcd_urb *urb, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { … } /* * Handles a host channel NAK interrupt. This handler may be called in either * DMA mode or Slave mode. */ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel ACK interrupt. This interrupt is enabled when * performing the PING protocol in Slave mode, when errors occur during * either Slave mode or DMA mode, and during Start Split transactions. */ static void dwc2_hc_ack_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel NYET interrupt. This interrupt should only occur on * Bulk and Control OUT endpoints and for complete split transactions. If a * NYET occurs at the same time as a Transfer Complete interrupt, it is * handled in the xfercomp interrupt handler, not here. This handler may be * called in either DMA mode or Slave mode. */ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel babble interrupt. This handler may be called in * either DMA mode or Slave mode. */ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel AHB error interrupt. This handler is only called in * DMA mode. */ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel transaction error interrupt. This handler may be * called in either DMA mode or Slave mode. */ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel frame overrun interrupt. This handler may be called * in either DMA mode or Slave mode. */ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel data toggle error interrupt. This handler may be * called in either DMA mode or Slave mode. */ static void dwc2_hc_datatglerr_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * For debug only. It checks that a valid halt status is set and that * HCCHARn.chdis is clear. If there's a problem, corrective action is * taken and a warning is issued. * * Return: true if halt status is ok, false otherwise */ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host Channel Halted interrupt in DMA mode. This handler * determines the reason the channel halted and proceeds accordingly. */ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Handles a host channel Channel Halted interrupt * * In slave mode, this handler is called only when the driver specifically * requests a halt. This occurs during handling other host channel interrupts * (e.g. nak, xacterr, stall, nyet, etc.). * * In DMA mode, this is the interrupt that occurs when the core has finished * processing a transfer on a channel. Other host channel interrupts (except * ahberr) are disabled in DMA mode. */ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { … } /* * Check if the given qtd is still the top of the list (and thus valid). * * If dwc2_hcd_qtd_unlink_and_free() has been called since we grabbed * the qtd from the top of the list, this will return false (otherwise true). */ static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh) { … } /* Handles interrupt for a specific Host Channel */ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) { … } /* * This interrupt indicates that one or more host channels has a pending * interrupt. There are multiple conditions that can cause each host channel * interrupt. This function determines which conditions have occurred for each * host channel interrupt and handles them appropriately. */ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg) { … } /* This function handles interrupts for the HCD */ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg) { … }