+/* Enable IRQ0 */
+static void
+ice_pf_enable_irq0(struct ice_hw *hw)
+{
+ /* reset the registers */
+ ICE_WRITE_REG(hw, PFINT_OICR_ENA, 0);
+ ICE_READ_REG(hw, PFINT_OICR);
+
+#ifdef ICE_LSE_SPT
+ ICE_WRITE_REG(hw, PFINT_OICR_ENA,
+ (uint32_t)(PFINT_OICR_ENA_INT_ENA_M &
+ (~PFINT_OICR_LINK_STAT_CHANGE_M)));
+
+ ICE_WRITE_REG(hw, PFINT_OICR_CTL,
+ (0 & PFINT_OICR_CTL_MSIX_INDX_M) |
+ ((0 << PFINT_OICR_CTL_ITR_INDX_S) &
+ PFINT_OICR_CTL_ITR_INDX_M) |
+ PFINT_OICR_CTL_CAUSE_ENA_M);
+
+ ICE_WRITE_REG(hw, PFINT_FW_CTL,
+ (0 & PFINT_FW_CTL_MSIX_INDX_M) |
+ ((0 << PFINT_FW_CTL_ITR_INDX_S) &
+ PFINT_FW_CTL_ITR_INDX_M) |
+ PFINT_FW_CTL_CAUSE_ENA_M);
+#else
+ ICE_WRITE_REG(hw, PFINT_OICR_ENA, PFINT_OICR_ENA_INT_ENA_M);
+#endif
+
+ ICE_WRITE_REG(hw, GLINT_DYN_CTL(0),
+ GLINT_DYN_CTL_INTENA_M |
+ GLINT_DYN_CTL_CLEARPBA_M |
+ GLINT_DYN_CTL_ITR_INDX_M);
+
+ ice_flush(hw);
+}
+
+/* Disable IRQ0 */
+static void
+ice_pf_disable_irq0(struct ice_hw *hw)
+{
+ /* Disable all interrupt types */
+ ICE_WRITE_REG(hw, GLINT_DYN_CTL(0), GLINT_DYN_CTL_WB_ON_ITR_M);
+ ice_flush(hw);
+}
+
+#ifdef ICE_LSE_SPT
+static void
+ice_handle_aq_msg(struct rte_eth_dev *dev)
+{
+ struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct ice_ctl_q_info *cq = &hw->adminq;
+ struct ice_rq_event_info event;
+ uint16_t pending, opcode;
+ int ret;
+
+ event.buf_len = ICE_AQ_MAX_BUF_LEN;
+ event.msg_buf = rte_zmalloc(NULL, event.buf_len, 0);
+ if (!event.msg_buf) {
+ PMD_DRV_LOG(ERR, "Failed to allocate mem");
+ return;
+ }
+
+ pending = 1;
+ while (pending) {
+ ret = ice_clean_rq_elem(hw, cq, &event, &pending);
+
+ if (ret != ICE_SUCCESS) {
+ PMD_DRV_LOG(INFO,
+ "Failed to read msg from AdminQ, "
+ "adminq_err: %u",
+ hw->adminq.sq_last_status);
+ break;
+ }
+ opcode = rte_le_to_cpu_16(event.desc.opcode);
+
+ switch (opcode) {
+ case ice_aqc_opc_get_link_status:
+ ret = ice_link_update(dev, 0);
+ if (!ret)
+ _rte_eth_dev_callback_process
+ (dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+ break;
+ default:
+ PMD_DRV_LOG(DEBUG, "Request %u is not supported yet",
+ opcode);
+ break;
+ }
+ }
+ rte_free(event.msg_buf);
+}
+#endif
+
+/**
+ * Interrupt handler triggered by NIC for handling
+ * specific interrupt.
+ *
+ * @param handle
+ * Pointer to interrupt handle.
+ * @param param
+ * The address of parameter (struct rte_eth_dev *) regsitered before.
+ *
+ * @return
+ * void
+ */
+static void
+ice_interrupt_handler(void *param)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+ struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t oicr;
+ uint32_t reg;
+ uint8_t pf_num;
+ uint8_t event;
+ uint16_t queue;
+#ifdef ICE_LSE_SPT
+ uint32_t int_fw_ctl;
+#endif
+
+ /* Disable interrupt */
+ ice_pf_disable_irq0(hw);
+
+ /* read out interrupt causes */
+ oicr = ICE_READ_REG(hw, PFINT_OICR);
+#ifdef ICE_LSE_SPT
+ int_fw_ctl = ICE_READ_REG(hw, PFINT_FW_CTL);
+#endif
+
+ /* No interrupt event indicated */
+ if (!(oicr & PFINT_OICR_INTEVENT_M)) {
+ PMD_DRV_LOG(INFO, "No interrupt event");
+ goto done;
+ }
+
+#ifdef ICE_LSE_SPT
+ if (int_fw_ctl & PFINT_FW_CTL_INTEVENT_M) {
+ PMD_DRV_LOG(INFO, "FW_CTL: link state change event");
+ ice_handle_aq_msg(dev);
+ }
+#else
+ if (oicr & PFINT_OICR_LINK_STAT_CHANGE_M) {
+ PMD_DRV_LOG(INFO, "OICR: link state change event");
+ ice_link_update(dev, 0);
+ }
+#endif
+
+ if (oicr & PFINT_OICR_MAL_DETECT_M) {
+ PMD_DRV_LOG(WARNING, "OICR: MDD event");
+ reg = ICE_READ_REG(hw, GL_MDET_TX_PQM);
+ if (reg & GL_MDET_TX_PQM_VALID_M) {
+ pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >>
+ GL_MDET_TX_PQM_PF_NUM_S;
+ event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >>
+ GL_MDET_TX_PQM_MAL_TYPE_S;
+ queue = (reg & GL_MDET_TX_PQM_QNUM_M) >>
+ GL_MDET_TX_PQM_QNUM_S;
+
+ PMD_DRV_LOG(WARNING, "Malicious Driver Detection event "
+ "%d by PQM on TX queue %d PF# %d",
+ event, queue, pf_num);
+ }
+
+ reg = ICE_READ_REG(hw, GL_MDET_TX_TCLAN);
+ if (reg & GL_MDET_TX_TCLAN_VALID_M) {
+ pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >>
+ GL_MDET_TX_TCLAN_PF_NUM_S;
+ event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >>
+ GL_MDET_TX_TCLAN_MAL_TYPE_S;
+ queue = (reg & GL_MDET_TX_TCLAN_QNUM_M) >>
+ GL_MDET_TX_TCLAN_QNUM_S;
+
+ PMD_DRV_LOG(WARNING, "Malicious Driver Detection event "
+ "%d by TCLAN on TX queue %d PF# %d",
+ event, queue, pf_num);
+ }
+ }
+done:
+ /* Enable interrupt */
+ ice_pf_enable_irq0(hw);
+ rte_intr_enable(dev->intr_handle);
+}
+