@@ -290,6 +290,7 @@ static void i40e_stat_update_48(struct i40e_hw *hw,
uint64_t *stat);
static void i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue);
static void i40e_dev_interrupt_handler(void *param);
+static void i40e_dev_alarm_handler(void *param);
static int i40e_res_pool_init(struct i40e_res_pool_info *pool,
uint32_t base, uint32_t num);
static void i40e_res_pool_destroy(struct i40e_res_pool_info *pool);
@@ -1189,6 +1190,8 @@ i40e_aq_debug_write_global_register(struct i40e_hw *hw,
return i40e_aq_debug_write_register(hw, reg_addr, reg_val, cmd_details);
}
+#define I40E_ALARM_INTERVAL 50000 /* us */
+
static int
eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
{
@@ -1450,16 +1453,20 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
/* initialize pf host driver to setup SRIOV resource if applicable */
i40e_pf_host_init(dev);
- /* register callback func to eal lib */
- rte_intr_callback_register(intr_handle,
- i40e_dev_interrupt_handler, dev);
-
/* configure and enable device interrupt */
i40e_pf_config_irq0(hw, TRUE);
i40e_pf_enable_irq0(hw);
- /* enable uio intr after callback register */
- rte_intr_enable(intr_handle);
+ if (!pf->support_multi_driver) {
+ /* register callback func to eal lib */
+ rte_intr_callback_register(intr_handle,
+ i40e_dev_interrupt_handler, dev);
+ /* enable uio intr after callback register */
+ rte_intr_enable(intr_handle);
+ } else {
+ rte_eal_alarm_set(I40E_ALARM_INTERVAL,
+ i40e_dev_alarm_handler, dev);
+ }
/* By default disable flexible payload in global configuration */
if (!pf->support_multi_driver)
@@ -1654,23 +1661,27 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
rte_free(dev->data->mac_addrs);
dev->data->mac_addrs = NULL;
- /* disable uio intr before callback unregister */
- rte_intr_disable(intr_handle);
-
- /* unregister callback func to eal lib */
- do {
- ret = rte_intr_callback_unregister(intr_handle,
- i40e_dev_interrupt_handler, dev);
- if (ret >= 0) {
- break;
- } else if (ret != -EAGAIN) {
- PMD_INIT_LOG(ERR,
- "intr callback unregister failed: %d",
- ret);
- return ret;
- }
- i40e_msec_delay(500);
- } while (retries++ < 5);
+ if (!pf->support_multi_driver) {
+ /* disable uio intr before callback unregister */
+ rte_intr_disable(intr_handle);
+
+ /* unregister callback func to eal lib */
+ do {
+ ret = rte_intr_callback_unregister(intr_handle,
+ i40e_dev_interrupt_handler, dev);
+ if (ret >= 0) {
+ break;
+ } else if (ret != -EAGAIN) {
+ PMD_INIT_LOG(ERR,
+ "intr callback unregister failed: %d",
+ ret);
+ return ret;
+ }
+ i40e_msec_delay(500);
+ } while (retries++ < 5);
+ } else {
+ rte_eal_alarm_cancel(i40e_dev_alarm_handler, dev);
+ }
i40e_rm_ethtype_filter_list(pf);
i40e_rm_tunnel_filter_list(pf);
@@ -2161,7 +2172,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
return -EINVAL;
}
- rte_intr_disable(intr_handle);
+ if (!pf->support_multi_driver || dev->data->dev_conf.intr_conf.rxq != 0)
+ rte_intr_disable(intr_handle);
if ((rte_intr_cap_multiple(intr_handle) ||
!RTE_ETH_DEV_SRIOV(dev).active) &&
@@ -2259,9 +2271,12 @@ i40e_dev_start(struct rte_eth_dev *dev)
}
if (!rte_intr_allow_others(intr_handle)) {
- rte_intr_callback_unregister(intr_handle,
- i40e_dev_interrupt_handler,
- (void *)dev);
+ if (!pf->support_multi_driver)
+ rte_intr_callback_unregister(intr_handle,
+ i40e_dev_interrupt_handler,
+ (void *)dev);
+ else
+ rte_eal_alarm_cancel(i40e_dev_alarm_handler, dev);
/* configure and enable device interrupt */
i40e_pf_config_irq0(hw, FALSE);
i40e_pf_enable_irq0(hw);
@@ -2282,7 +2297,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
}
/* enable uio intr after callback register */
- rte_intr_enable(intr_handle);
+ if (!pf->support_multi_driver || dev->data->dev_conf.intr_conf.rxq != 0)
+ rte_intr_enable(intr_handle);
i40e_filter_restore(pf);
@@ -2334,7 +2350,7 @@ i40e_dev_stop(struct rte_eth_dev *dev)
/* Set link down */
i40e_dev_set_link_down(dev);
- if (!rte_intr_allow_others(intr_handle))
+ if (!pf->support_multi_driver && !rte_intr_allow_others(intr_handle))
/* resume to the default handler */
rte_intr_callback_register(intr_handle,
i40e_dev_interrupt_handler,
@@ -2392,7 +2408,8 @@ i40e_dev_close(struct rte_eth_dev *dev)
/* Disable interrupt */
i40e_pf_disable_irq0(hw);
- rte_intr_disable(intr_handle);
+ if (!pf->support_multi_driver || dev->data->dev_conf.intr_conf.rxq != 0)
+ rte_intr_disable(intr_handle);
i40e_fdir_teardown(pf);
@@ -6535,6 +6552,55 @@ i40e_dev_interrupt_handler(void *param)
rte_intr_enable(dev->intr_handle);
}
+static void
+i40e_dev_alarm_handler(void *param)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t icr0;
+
+ /* Disable interrupt */
+ i40e_pf_disable_irq0(hw);
+
+ /* read out interrupt causes */
+ icr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0);
+
+ /* No interrupt event indicated */
+ if (!(icr0 & I40E_PFINT_ICR0_INTEVENT_MASK)) {
+ PMD_DRV_LOG(INFO, "No interrupt event");
+ goto done;
+ }
+ if (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK)
+ PMD_DRV_LOG(ERR, "ICR0: unrecoverable ECC error");
+ if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK)
+ PMD_DRV_LOG(ERR, "ICR0: malicious programming detected");
+ if (icr0 & I40E_PFINT_ICR0_GRST_MASK)
+ PMD_DRV_LOG(INFO, "ICR0: global reset requested");
+ if (icr0 & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK)
+ PMD_DRV_LOG(INFO, "ICR0: PCI exception activated");
+ if (icr0 & I40E_PFINT_ICR0_STORM_DETECT_MASK)
+ PMD_DRV_LOG(INFO, "ICR0: a change in the storm control state");
+ if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK)
+ PMD_DRV_LOG(ERR, "ICR0: HMC error");
+ if (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK)
+ PMD_DRV_LOG(ERR, "ICR0: protocol engine critical error");
+
+ if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
+ PMD_DRV_LOG(INFO, "ICR0: VF reset detected");
+ i40e_dev_handle_vfr_event(dev);
+ }
+ if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
+ PMD_DRV_LOG(INFO, "ICR0: adminq event");
+ i40e_dev_handle_aq_msg(dev);
+ }
+
+done:
+ /* Enable interrupt */
+ i40e_pf_enable_irq0(hw);
+ rte_eal_alarm_set(I40E_ALARM_INTERVAL,
+ i40e_dev_alarm_handler, dev);
+}
+
int
i40e_add_macvlan_filters(struct i40e_vsi *vsi,
struct i40e_macvlan_filter *filter,
@@ -11402,6 +11468,7 @@ i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
uint16_t msix_intr;
msix_intr = intr_handle->intr_vec[queue_id];
@@ -11419,7 +11486,8 @@ i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
I40E_PFINT_DYN_CTLN_ITR_INDX_MASK);
I40E_WRITE_FLUSH(hw);
- rte_intr_enable(&pci_dev->intr_handle);
+ if (!pf->support_multi_driver)
+ rte_intr_enable(&pci_dev->intr_handle);
return 0;
}