diff options
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns/hns_enet.c | 50 | ||||
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns/hns_enet.h | 2 |
2 files changed, 31 insertions, 21 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 73ec8c843920..5f67db2dc09c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -859,7 +859,7 @@ out: return recv_pkts; } -static void hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data) +static bool hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; int num = 0; @@ -873,22 +873,23 @@ static void hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data) ring_data->ring->q->handle->dev->ops->toggle_ring_irq( ring_data->ring, 1); - napi_schedule(&ring_data->napi); + return false; + } else { + return true; } } -static void hns_nic_rx_fini_pro_v2(struct hns_nic_ring_data *ring_data) +static bool hns_nic_rx_fini_pro_v2(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; - int num = 0; + int num; num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM); - if (num == 0) - ring_data->ring->q->handle->dev->ops->toggle_ring_irq( - ring, 0); + if (!num) + return true; else - napi_schedule(&ring_data->napi); + return false; } static inline void hns_nic_reclaim_one_desc(struct hnae_ring *ring, @@ -989,7 +990,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data, return 0; } -static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data) +static bool hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; int head; @@ -1002,20 +1003,21 @@ static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data) ring_data->ring->q->handle->dev->ops->toggle_ring_irq( ring_data->ring, 1); - napi_schedule(&ring_data->napi); + return false; + } else { + return true; } } -static void hns_nic_tx_fini_pro_v2(struct hns_nic_ring_data *ring_data) +static bool hns_nic_tx_fini_pro_v2(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; int head = readl_relaxed(ring->io_base + RCB_REG_HEAD); if (head == ring->next_to_clean) - ring_data->ring->q->handle->dev->ops->toggle_ring_irq( - ring, 0); + return true; else - napi_schedule(&ring_data->napi); + return false; } static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data) @@ -1042,15 +1044,23 @@ static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data) static int hns_nic_common_poll(struct napi_struct *napi, int budget) { + int clean_complete = 0; struct hns_nic_ring_data *ring_data = container_of(napi, struct hns_nic_ring_data, napi); - int clean_complete = ring_data->poll_one( - ring_data, budget, ring_data->ex_process); + struct hnae_ring *ring = ring_data->ring; - if (clean_complete >= 0 && clean_complete < budget) { - napi_complete(napi); - ring_data->fini_process(ring_data); - return 0; +try_again: + clean_complete += ring_data->poll_one( + ring_data, budget - clean_complete, + ring_data->ex_process); + + if (clean_complete < budget) { + if (ring_data->fini_process(ring_data)) { + napi_complete(napi); + ring->q->handle->dev->ops->toggle_ring_irq(ring, 0); + } else { + goto try_again; + } } return clean_complete; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h index fff8f8a21bd0..1b83232082b2 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h @@ -41,7 +41,7 @@ struct hns_nic_ring_data { int queue_index; int (*poll_one)(struct hns_nic_ring_data *, int, void *); void (*ex_process)(struct hns_nic_ring_data *, struct sk_buff *); - void (*fini_process)(struct hns_nic_ring_data *); + bool (*fini_process)(struct hns_nic_ring_data *); }; /* compatible the difference between two versions */ |