diff options
author | David S. Miller <davem@davemloft.net> | 2014-03-14 22:53:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-14 22:53:35 -0400 |
commit | e7ef085d0a9dc1cc72e7d8108ed3b4e1a5e8d938 (patch) | |
tree | f8ae35945d4100401117f32d27d776c16c0cd086 | |
parent | 1c79a5a8f4faec88f9f4632d0ef9b0365bff8e28 (diff) | |
parent | 75363a4676cdb046242d06dca6e8a9c0a20d6c4a (diff) |
Merge branch 'napi_budget_zero'
Eric W. Biederman says:
====================
Don't receive packets when the napi budget == 0
After reading through all 120 drivers supporting netpoll I have found 16
more that process at least received packet when the napi budget == 0.
Processing more packets than your budget has always been a bug but
we haven't cared before so it looks like these drivers slipped through,
and need fixes.
As netpoll will shortly be using a budget of 0 to get the tx queue
processing with the rx queue processing we now care.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/amd/amd8111e.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_main.c | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/ibmveth.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/marvell/sky2.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/neterion/s2io.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/neterion/vxge/vxge-main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ef10.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/farch.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/tile/tilegx.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/tile/tilepro.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/toshiba/tc35815.c | 3 |
17 files changed, 53 insertions, 12 deletions
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index 2061b471fd16..26efaaa5e73f 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c | |||
@@ -720,6 +720,9 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) | |||
720 | int rx_pkt_limit = budget; | 720 | int rx_pkt_limit = budget; |
721 | unsigned long flags; | 721 | unsigned long flags; |
722 | 722 | ||
723 | if (rx_pkt_limit <= 0) | ||
724 | goto rx_not_empty; | ||
725 | |||
723 | do{ | 726 | do{ |
724 | /* process receive packets until we use the quota*/ | 727 | /* process receive packets until we use the quota*/ |
725 | /* If we own the next entry, it's a new packet. Send it up. */ | 728 | /* If we own the next entry, it's a new packet. Send it up. */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 117b5c7f8ac9..acd494647f25 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -872,6 +872,8 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) | |||
872 | if (unlikely(bp->panic)) | 872 | if (unlikely(bp->panic)) |
873 | return 0; | 873 | return 0; |
874 | #endif | 874 | #endif |
875 | if (budget <= 0) | ||
876 | return rx_pkt; | ||
875 | 877 | ||
876 | bd_cons = fp->rx_bd_cons; | 878 | bd_cons = fp->rx_bd_cons; |
877 | bd_prod = fp->rx_bd_prod; | 879 | bd_prod = fp->rx_bd_prod; |
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index dcd58f23834a..4c35fc8fad99 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c | |||
@@ -1086,14 +1086,15 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1086 | unsigned int intr = enic_legacy_io_intr(); | 1086 | unsigned int intr = enic_legacy_io_intr(); |
1087 | unsigned int rq_work_to_do = budget; | 1087 | unsigned int rq_work_to_do = budget; |
1088 | unsigned int wq_work_to_do = -1; /* no limit */ | 1088 | unsigned int wq_work_to_do = -1; /* no limit */ |
1089 | unsigned int work_done, rq_work_done, wq_work_done; | 1089 | unsigned int work_done, rq_work_done = 0, wq_work_done; |
1090 | int err; | 1090 | int err; |
1091 | 1091 | ||
1092 | /* Service RQ (first) and WQ | 1092 | /* Service RQ (first) and WQ |
1093 | */ | 1093 | */ |
1094 | 1094 | ||
1095 | rq_work_done = vnic_cq_service(&enic->cq[cq_rq], | 1095 | if (budget > 0) |
1096 | rq_work_to_do, enic_rq_service, NULL); | 1096 | rq_work_done = vnic_cq_service(&enic->cq[cq_rq], |
1097 | rq_work_to_do, enic_rq_service, NULL); | ||
1097 | 1098 | ||
1098 | wq_work_done = vnic_cq_service(&enic->cq[cq_wq], | 1099 | wq_work_done = vnic_cq_service(&enic->cq[cq_wq], |
1099 | wq_work_to_do, enic_wq_service, NULL); | 1100 | wq_work_to_do, enic_wq_service, NULL); |
@@ -1141,14 +1142,15 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1141 | unsigned int cq = enic_cq_rq(enic, rq); | 1142 | unsigned int cq = enic_cq_rq(enic, rq); |
1142 | unsigned int intr = enic_msix_rq_intr(enic, rq); | 1143 | unsigned int intr = enic_msix_rq_intr(enic, rq); |
1143 | unsigned int work_to_do = budget; | 1144 | unsigned int work_to_do = budget; |
1144 | unsigned int work_done; | 1145 | unsigned int work_done = 0; |
1145 | int err; | 1146 | int err; |
1146 | 1147 | ||
1147 | /* Service RQ | 1148 | /* Service RQ |
1148 | */ | 1149 | */ |
1149 | 1150 | ||
1150 | work_done = vnic_cq_service(&enic->cq[cq], | 1151 | if (budget > 0) |
1151 | work_to_do, enic_rq_service, NULL); | 1152 | work_done = vnic_cq_service(&enic->cq[cq], |
1153 | work_to_do, enic_rq_service, NULL); | ||
1152 | 1154 | ||
1153 | /* Return intr event credits for this polling | 1155 | /* Return intr event credits for this polling |
1154 | * cycle. An intr event is the completion of a | 1156 | * cycle. An intr event is the completion of a |
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 62f042d4aaa9..dc80db41d6b3 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | |||
@@ -91,6 +91,9 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) | |||
91 | u16 pkt_len, sc; | 91 | u16 pkt_len, sc; |
92 | int curidx; | 92 | int curidx; |
93 | 93 | ||
94 | if (budget <= 0) | ||
95 | return received; | ||
96 | |||
94 | /* | 97 | /* |
95 | * First, grab all of the stats for the incoming packet. | 98 | * First, grab all of the stats for the incoming packet. |
96 | * These get messed up if we get called due to a busy condition. | 99 | * These get messed up if we get called due to a busy condition. |
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 1fc8334fc181..e75bdfcd1374 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c | |||
@@ -1072,7 +1072,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) | |||
1072 | unsigned long lpar_rc; | 1072 | unsigned long lpar_rc; |
1073 | 1073 | ||
1074 | restart_poll: | 1074 | restart_poll: |
1075 | do { | 1075 | while (frames_processed < budget) { |
1076 | if (!ibmveth_rxq_pending_buffer(adapter)) | 1076 | if (!ibmveth_rxq_pending_buffer(adapter)) |
1077 | break; | 1077 | break; |
1078 | 1078 | ||
@@ -1121,7 +1121,7 @@ restart_poll: | |||
1121 | netdev->stats.rx_bytes += length; | 1121 | netdev->stats.rx_bytes += length; |
1122 | frames_processed++; | 1122 | frames_processed++; |
1123 | } | 1123 | } |
1124 | } while (frames_processed < budget); | 1124 | } |
1125 | 1125 | ||
1126 | ibmveth_replenish_task(adapter); | 1126 | ibmveth_replenish_task(adapter); |
1127 | 1127 | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index daa3b295ff3d..88666adb0743 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c | |||
@@ -1302,6 +1302,9 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) | |||
1302 | u8 rx_ptype; | 1302 | u8 rx_ptype; |
1303 | u64 qword; | 1303 | u64 qword; |
1304 | 1304 | ||
1305 | if (budget <= 0) | ||
1306 | return 0; | ||
1307 | |||
1305 | rx_desc = I40E_RX_DESC(rx_ring, i); | 1308 | rx_desc = I40E_RX_DESC(rx_ring, i); |
1306 | qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); | 1309 | qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); |
1307 | rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> | 1310 | rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index f81d87cfcc8d..d6b11522fed7 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -6946,7 +6946,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) | |||
6946 | unsigned int total_bytes = 0, total_packets = 0; | 6946 | unsigned int total_bytes = 0, total_packets = 0; |
6947 | u16 cleaned_count = igb_desc_unused(rx_ring); | 6947 | u16 cleaned_count = igb_desc_unused(rx_ring); |
6948 | 6948 | ||
6949 | do { | 6949 | while (likely(total_packets < budget)) { |
6950 | union e1000_adv_rx_desc *rx_desc; | 6950 | union e1000_adv_rx_desc *rx_desc; |
6951 | 6951 | ||
6952 | /* return some buffers to hardware, one at a time is too slow */ | 6952 | /* return some buffers to hardware, one at a time is too slow */ |
@@ -6998,7 +6998,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) | |||
6998 | 6998 | ||
6999 | /* update budget accounting */ | 6999 | /* update budget accounting */ |
7000 | total_packets++; | 7000 | total_packets++; |
7001 | } while (likely(total_packets < budget)); | 7001 | } |
7002 | 7002 | ||
7003 | /* place incomplete frames back on ring for completion */ | 7003 | /* place incomplete frames back on ring for completion */ |
7004 | rx_ring->skb = skb; | 7004 | rx_ring->skb = skb; |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5d314fe873bb..18cd8ca319ea 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -2076,7 +2076,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, | |||
2076 | #endif /* IXGBE_FCOE */ | 2076 | #endif /* IXGBE_FCOE */ |
2077 | u16 cleaned_count = ixgbe_desc_unused(rx_ring); | 2077 | u16 cleaned_count = ixgbe_desc_unused(rx_ring); |
2078 | 2078 | ||
2079 | do { | 2079 | while (likely(total_rx_packets < budget)) { |
2080 | union ixgbe_adv_rx_desc *rx_desc; | 2080 | union ixgbe_adv_rx_desc *rx_desc; |
2081 | struct sk_buff *skb; | 2081 | struct sk_buff *skb; |
2082 | 2082 | ||
@@ -2151,7 +2151,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, | |||
2151 | 2151 | ||
2152 | /* update budget accounting */ | 2152 | /* update budget accounting */ |
2153 | total_rx_packets++; | 2153 | total_rx_packets++; |
2154 | } while (likely(total_rx_packets < budget)); | 2154 | } |
2155 | 2155 | ||
2156 | u64_stats_update_begin(&rx_ring->syncp); | 2156 | u64_stats_update_begin(&rx_ring->syncp); |
2157 | rx_ring->stats.packets += total_rx_packets; | 2157 | rx_ring->stats.packets += total_rx_packets; |
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 5a5b23741179..d524676fdff4 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c | |||
@@ -2735,6 +2735,9 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) | |||
2735 | unsigned int total_bytes[2] = { 0 }; | 2735 | unsigned int total_bytes[2] = { 0 }; |
2736 | unsigned int total_packets[2] = { 0 }; | 2736 | unsigned int total_packets[2] = { 0 }; |
2737 | 2737 | ||
2738 | if (to_do <= 0) | ||
2739 | return work_done; | ||
2740 | |||
2738 | rmb(); | 2741 | rmb(); |
2739 | do { | 2742 | do { |
2740 | struct sky2_port *sky2; | 2743 | struct sky2_port *sky2; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 8afb72ec957d..ba049ae88749 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c | |||
@@ -661,6 +661,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud | |||
661 | if (!priv->port_up) | 661 | if (!priv->port_up) |
662 | return 0; | 662 | return 0; |
663 | 663 | ||
664 | if (budget <= 0) | ||
665 | return polled; | ||
666 | |||
664 | /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx | 667 | /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx |
665 | * descriptor offset can be deduced from the CQE index instead of | 668 | * descriptor offset can be deduced from the CQE index instead of |
666 | * reading 'cqe->index' */ | 669 | * reading 'cqe->index' */ |
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 56e3a9d42bb2..d44fdb91808e 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c | |||
@@ -2914,6 +2914,9 @@ static int rx_intr_handler(struct ring_info *ring_data, int budget) | |||
2914 | struct RxD1 *rxdp1; | 2914 | struct RxD1 *rxdp1; |
2915 | struct RxD3 *rxdp3; | 2915 | struct RxD3 *rxdp3; |
2916 | 2916 | ||
2917 | if (budget <= 0) | ||
2918 | return napi_pkts; | ||
2919 | |||
2917 | get_info = ring_data->rx_curr_get_info; | 2920 | get_info = ring_data->rx_curr_get_info; |
2918 | get_block = get_info.block_index; | 2921 | get_block = get_info.block_index; |
2919 | memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info)); | 2922 | memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info)); |
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index c5bb1ace4a74..11adc89959c1 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c | |||
@@ -368,6 +368,9 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, | |||
368 | vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", | 368 | vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d", |
369 | ring->ndev->name, __func__, __LINE__); | 369 | ring->ndev->name, __func__, __LINE__); |
370 | 370 | ||
371 | if (ring->budget <= 0) | ||
372 | goto out; | ||
373 | |||
371 | do { | 374 | do { |
372 | prefetch((char *)dtr + L1_CACHE_BYTES); | 375 | prefetch((char *)dtr + L1_CACHE_BYTES); |
373 | rx_priv = vxge_hw_ring_rxd_private_get(dtr); | 376 | rx_priv = vxge_hw_ring_rxd_private_get(dtr); |
@@ -525,6 +528,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, | |||
525 | if (first_dtr) | 528 | if (first_dtr) |
526 | vxge_hw_ring_rxd_post_post_wmb(ringh, first_dtr); | 529 | vxge_hw_ring_rxd_post_post_wmb(ringh, first_dtr); |
527 | 530 | ||
531 | out: | ||
528 | vxge_debug_entryexit(VXGE_TRACE, | 532 | vxge_debug_entryexit(VXGE_TRACE, |
529 | "%s:%d Exiting...", | 533 | "%s:%d Exiting...", |
530 | __func__, __LINE__); | 534 | __func__, __LINE__); |
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index eb75675f6e32..651626e133f9 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c | |||
@@ -1955,6 +1955,9 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota) | |||
1955 | int tx_descs = 0; | 1955 | int tx_descs = 0; |
1956 | int spent = 0; | 1956 | int spent = 0; |
1957 | 1957 | ||
1958 | if (quota <= 0) | ||
1959 | return spent; | ||
1960 | |||
1958 | read_ptr = channel->eventq_read_ptr; | 1961 | read_ptr = channel->eventq_read_ptr; |
1959 | 1962 | ||
1960 | for (;;) { | 1963 | for (;;) { |
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index aa1b169f45ec..a08761360cdf 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c | |||
@@ -1248,6 +1248,9 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget) | |||
1248 | int tx_packets = 0; | 1248 | int tx_packets = 0; |
1249 | int spent = 0; | 1249 | int spent = 0; |
1250 | 1250 | ||
1251 | if (budget <= 0) | ||
1252 | return spent; | ||
1253 | |||
1251 | read_ptr = channel->eventq_read_ptr; | 1254 | read_ptr = channel->eventq_read_ptr; |
1252 | 1255 | ||
1253 | for (;;) { | 1256 | for (;;) { |
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 17503da9f7a5..b43f1b3b9632 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c | |||
@@ -659,6 +659,9 @@ static int tile_net_poll(struct napi_struct *napi, int budget) | |||
659 | struct info_mpipe *info_mpipe = | 659 | struct info_mpipe *info_mpipe = |
660 | container_of(napi, struct info_mpipe, napi); | 660 | container_of(napi, struct info_mpipe, napi); |
661 | 661 | ||
662 | if (budget <= 0) | ||
663 | goto done; | ||
664 | |||
662 | instance = info_mpipe->instance; | 665 | instance = info_mpipe->instance; |
663 | while ((n = gxio_mpipe_iqueue_try_peek( | 666 | while ((n = gxio_mpipe_iqueue_try_peek( |
664 | &info_mpipe->iqueue, | 667 | &info_mpipe->iqueue, |
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 7e33973487ee..b94449b4bd34 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c | |||
@@ -831,6 +831,9 @@ static int tile_net_poll(struct napi_struct *napi, int budget) | |||
831 | 831 | ||
832 | unsigned int work = 0; | 832 | unsigned int work = 0; |
833 | 833 | ||
834 | if (budget <= 0) | ||
835 | goto done; | ||
836 | |||
834 | while (priv->active) { | 837 | while (priv->active) { |
835 | int index = qup->__packet_receive_read; | 838 | int index = qup->__packet_receive_read; |
836 | if (index == qsp->__packet_receive_queue.__packet_write) | 839 | if (index == qsp->__packet_receive_queue.__packet_write) |
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index 88e9c73cebc0..fef5573dbfca 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c | |||
@@ -1645,6 +1645,9 @@ static int tc35815_poll(struct napi_struct *napi, int budget) | |||
1645 | int received = 0, handled; | 1645 | int received = 0, handled; |
1646 | u32 status; | 1646 | u32 status; |
1647 | 1647 | ||
1648 | if (budget <= 0) | ||
1649 | return received; | ||
1650 | |||
1648 | spin_lock(&lp->rx_lock); | 1651 | spin_lock(&lp->rx_lock); |
1649 | status = tc_readl(&tr->Int_Src); | 1652 | status = tc_readl(&tr->Int_Src); |
1650 | do { | 1653 | do { |