diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index ddabee714c47d9abda395daaa207f6925fa27c45..5960603cea21622d07be86dd266938e11e792ccf 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -438,7 +438,7 @@ static void hinic_destroy_num_qps(struct hinic_nic_dev *nic_dev) kfree(nic_dev->qps_irq_info); } -int hinic_poll(struct napi_struct *napi, int budget) +static int hinic_poll(struct napi_struct *napi, int budget) { int tx_pkts, rx_pkts; struct hinic_irq *irq_cfg = container_of(napi, struct hinic_irq, napi); @@ -451,6 +451,13 @@ int hinic_poll(struct napi_struct *napi, int budget) if (tx_pkts >= budget || rx_pkts >= budget) return budget; + set_bit(HINIC_RESEND_ON, &irq_cfg->intr_flag); + rx_pkts += hinic_rx_poll(irq_cfg->rxq, budget - rx_pkts); + if (rx_pkts >= budget) { + clear_bit(HINIC_RESEND_ON, &irq_cfg->intr_flag); + return budget; + } + napi_complete(napi); if (!test_and_set_bit(HINIC_INTR_ON, &irq_cfg->intr_flag)) { @@ -484,24 +491,33 @@ static irqreturn_t qp_irq(int irq, void *data) { struct hinic_irq *irq_cfg = (struct hinic_irq *)data; struct hinic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); + u16 msix_entry_idx = irq_cfg->msix_entry_idx; + + if (napi_schedule_prep(&irq_cfg->napi)) { + if (l2nic_interrupt_switch) { + /* Disable the interrupt until napi will be completed */ + if (!HINIC_FUNC_IS_VF(nic_dev->hwdev)) { + hinic_set_msix_state(nic_dev->hwdev, + msix_entry_idx, + HINIC_MSIX_DISABLE); + } else if (!nic_dev->in_vm) { + disable_irq_nosync(irq_cfg->irq_id); + } - if (l2nic_interrupt_switch) { - /* Disable the interrupt until napi will be completed */ - if (!HINIC_FUNC_IS_VF(nic_dev->hwdev)) - hinic_set_msix_state(nic_dev->hwdev, - irq_cfg->msix_entry_idx, - HINIC_MSIX_DISABLE); - else if (!nic_dev->in_vm) - disable_irq_nosync(irq_cfg->irq_id); + clear_bit(HINIC_INTR_ON, &irq_cfg->intr_flag); + } - clear_bit(HINIC_INTR_ON, &irq_cfg->intr_flag); - } + hinic_misx_intr_clear_resend_bit(nic_dev->hwdev, + msix_entry_idx, 1); + + clear_bit(HINIC_RESEND_ON, &irq_cfg->intr_flag); - /* 1 is resend_timer */ - hinic_misx_intr_clear_resend_bit(nic_dev->hwdev, - irq_cfg->msix_entry_idx, 1); + __napi_schedule(&irq_cfg->napi); + } else if (!test_bit(HINIC_RESEND_ON, &irq_cfg->intr_flag)) { + hinic_misx_intr_clear_resend_bit(nic_dev->hwdev, msix_entry_idx, + 1); + } - napi_schedule(&irq_cfg->napi); return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h index 3697aa4a47d2adcc4f6b6490d9b8a54f89f82949..c6879c431ff2ca0de4fa6c6982e247e0e4f3bea9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h @@ -104,6 +104,7 @@ struct hinic_dcb_config { enum hinic_intr_flags { HINIC_INTR_ON, + HINIC_RESEND_ON, }; struct hinic_irq {