diff --git a/include/osi_dma.h b/include/osi_dma.h index d365946..62668ee 100644 --- a/include/osi_dma.h +++ b/include/osi_dma.h @@ -182,6 +182,19 @@ /** @} */ +/** + * @addtogroup OSI-INTR OSI DMA interrupt handling macros. + * + * @brief Macros to pass osi_handle_dma_intr() API to handle + * the interrupts between OSI and OSD. + * @{ + */ +#define OSI_DMA_CH_TX_INTR 0U +#define OSI_DMA_CH_RX_INTR 1U +#define OSI_DMA_INTR_DISABLE 0U +#define OSI_DMA_INTR_ENABLE 1U +/** @} */ + /** * @brief OSI packet error stats */ @@ -1201,6 +1214,49 @@ nve32_t osi_dma_get_systime_from_mac(struct osi_dma_priv_data *const osi_dma, */ nveu32_t osi_is_mac_enabled(struct osi_dma_priv_data *const osi_dma); +/** + * @brief osi_handle_dma_intr - Handles DMA interrupts. + * + * @note + * Algorithm: + * - Enables/Disables DMA CH TX/RX/VM inetrrupts. + * + * @param[in] osi_dma: OSI DMA private data. + * @param[in] chan: DMA Rx channel number. Max OSI_EQOS_MAX_NUM_CHANS. + * @param[in] tx_rx: Indicates whether DMA channel is Tx or Rx. + * OSI_DMA_CH_TX_INTR for Tx interrupt. + * OSI_DMA_CH_RX_INTR for Rx interrupt. + * @param[in] en_dis: Enable/Disable DMA channel interrupts. + * OSI_DMA_INTR_DISABLE for disabling the interrupt. + * OSI_DMA_INTR_ENABLE for enabling the interrupt. + * + * @pre + * - MAC needs to be out of reset and proper clocks need to be configured. + * - DMA HW init need to be completed successfully, see osi_hw_dma_init + * - Mapping of physical IRQ line to DMA channel need to be maintained at + * OS Dependent layer and pass corresponding channel number. + * + * @note + * Traceability Details: TBD + * + * @note + * Classification: + * - Interrupt: Yes + * - Signal handler: Yes + * - Thread safe: No + * - Required Privileges: None + * + * @note + * API Group: + * - Initialization: Yes + * - Run time: Yes + * - De-initialization: No + * + * @retval 0 on success + * @retval -1 on failure. + */ +nve32_t osi_handle_dma_intr(struct osi_dma_priv_data *osi_dma, + nveu32_t chan, nveu32_t tx_rx, nveu32_t en_dis); #ifndef OSI_STRIPPED_LIB /** * @brief - Read-validate HW registers for func safety. diff --git a/osi/dma/dma_local.h b/osi/dma/dma_local.h index 4e301fb..5351157 100644 --- a/osi/dma/dma_local.h +++ b/osi/dma/dma_local.h @@ -93,6 +93,10 @@ struct dma_local { struct dma_chan_ops ops; /** Flag to represent OSI DMA software init done */ unsigned int init_done; + /** Holds the MAC version of MAC controller */ + nveu32_t mac_ver; + /** Represents whether DMA interrupts are VM or Non-VM */ + nveu32_t vm_intr; }; void eqos_init_dma_chan_ops(struct dma_chan_ops *ops); diff --git a/osi/dma/eqos_dma.c b/osi/dma/eqos_dma.c index 1ef19ae..53b4581 100644 --- a/osi/dma/eqos_dma.c +++ b/osi/dma/eqos_dma.c @@ -966,6 +966,8 @@ static void eqos_clear_vm_tx_intr(void *addr, nveu32_t chan) (nveu8_t *)addr + EQOS_DMA_CHX_STATUS(chan)); osi_writel(EQOS_VIRT_INTR_CHX_STATUS_TX, (nveu8_t *)addr + EQOS_VIRT_INTR_CHX_STATUS(chan)); + + eqos_disable_chan_tx_intr(addr, chan); } /** @@ -990,6 +992,8 @@ static void eqos_clear_vm_rx_intr(void *addr, nveu32_t chan) (nveu8_t *)addr + EQOS_DMA_CHX_STATUS(chan)); osi_writel(EQOS_VIRT_INTR_CHX_STATUS_RX, (nveu8_t *)addr + EQOS_VIRT_INTR_CHX_STATUS(chan)); + + eqos_disable_chan_rx_intr(addr, chan); } /** diff --git a/osi/dma/osi_dma.c b/osi/dma/osi_dma.c index 282c78c..3bc2f44 100644 --- a/osi/dma/osi_dma.c +++ b/osi/dma/osi_dma.c @@ -23,6 +23,7 @@ #include "dma_local.h" #include #include "hw_desc.h" +#include "../osi/common/common.h" /** * @brief g_dma - DMA local data variable @@ -227,6 +228,19 @@ nve32_t osi_hw_dma_init(struct osi_dma_priv_data *osi_dma) return ret; } + g_dma.mac_ver = osi_readl((unsigned char *)osi_dma->base + MAC_VERSION) & + MAC_VERSION_SNVER_MASK; + if (is_valid_mac_version(g_dma.mac_ver) == 0) { + OSI_DMA_ERR(OSI_NULL, OSI_LOG_ARG_INVALID, + "Invalid MAC version\n", (nveu64_t)g_dma.mac_ver); + return -1; + } + + if ((g_dma.mac_ver != OSI_EQOS_MAC_4_10) && + (g_dma.mac_ver != OSI_EQOS_MAC_5_00)) { + g_dma.vm_intr = OSI_ENABLE; + } + /* Enable channel interrupts at wrapper level and start DMA */ for (i = 0; i < osi_dma->num_dma_chans; i++) { chan = osi_dma->dma_chans[i]; @@ -371,6 +385,37 @@ nveu32_t osi_get_global_dma_status(struct osi_dma_priv_data *osi_dma) return ops_p->get_global_dma_status(osi_dma->base); } +nve32_t osi_handle_dma_intr(struct osi_dma_priv_data *osi_dma, + nveu32_t chan, + nveu32_t tx_rx, + nveu32_t en_dis) +{ + typedef void (*dma_intr_fn)(void *, nveu32_t); + dma_intr_fn fn[2][2][2] = { + { { ops_p->disable_chan_tx_intr, ops_p->enable_chan_tx_intr }, + { ops_p->disable_chan_rx_intr, ops_p->enable_chan_rx_intr } }, + { { ops_p->clear_vm_tx_intr, ops_p->enable_chan_tx_intr }, + { ops_p->clear_vm_rx_intr, ops_p->enable_chan_rx_intr } } + }; + + if (validate_args(osi_dma) < 0) { + return -1; + } + + if (validate_dma_chan_num(osi_dma, chan) < 0) { + return -1; + } + + if ((tx_rx > OSI_DMA_CH_RX_INTR) || + (en_dis > OSI_DMA_INTR_ENABLE)) { + return -1; + } + + fn[g_dma.vm_intr][tx_rx][en_dis](osi_dma->base, chan); + + return 0; +} + nve32_t osi_start_dma(struct osi_dma_priv_data *osi_dma, nveu32_t chan) {