| From foo@baz Tue Aug 8 16:51:58 PDT 2017 |
| From: Wei Liu <wei.liu2@citrix.com> |
| Date: Wed, 21 Jun 2017 10:21:22 +0100 |
| Subject: xen-netback: correctly schedule rate-limited queues |
| |
| From: Wei Liu <wei.liu2@citrix.com> |
| |
| |
| [ Upstream commit dfa523ae9f2542bee4cddaea37b3be3e157f6e6b ] |
| |
| Add a flag to indicate if a queue is rate-limited. Test the flag in |
| NAPI poll handler and avoid rescheduling the queue if true, otherwise |
| we risk locking up the host. The rescheduling will be done in the |
| timer callback function. |
| |
| Reported-by: Jean-Louis Dupond <jean-louis@dupond.be> |
| Signed-off-by: Wei Liu <wei.liu2@citrix.com> |
| Tested-by: Jean-Louis Dupond <jean-louis@dupond.be> |
| Reviewed-by: Paul Durrant <paul.durrant@citrix.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/xen-netback/common.h | 1 + |
| drivers/net/xen-netback/interface.c | 6 +++++- |
| drivers/net/xen-netback/netback.c | 6 +++++- |
| 3 files changed, 11 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/xen-netback/common.h |
| +++ b/drivers/net/xen-netback/common.h |
| @@ -201,6 +201,7 @@ struct xenvif_queue { /* Per-queue data |
| unsigned long remaining_credit; |
| struct timer_list credit_timeout; |
| u64 credit_window_start; |
| + bool rate_limited; |
| |
| /* Statistics */ |
| struct xenvif_stats stats; |
| --- a/drivers/net/xen-netback/interface.c |
| +++ b/drivers/net/xen-netback/interface.c |
| @@ -105,7 +105,11 @@ static int xenvif_poll(struct napi_struc |
| |
| if (work_done < budget) { |
| napi_complete(napi); |
| - xenvif_napi_schedule_or_enable_events(queue); |
| + /* If the queue is rate-limited, it shall be |
| + * rescheduled in the timer callback. |
| + */ |
| + if (likely(!queue->rate_limited)) |
| + xenvif_napi_schedule_or_enable_events(queue); |
| } |
| |
| return work_done; |
| --- a/drivers/net/xen-netback/netback.c |
| +++ b/drivers/net/xen-netback/netback.c |
| @@ -687,6 +687,7 @@ static void tx_add_credit(struct xenvif_ |
| max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */ |
| |
| queue->remaining_credit = min(max_credit, max_burst); |
| + queue->rate_limited = false; |
| } |
| |
| void xenvif_tx_credit_callback(unsigned long data) |
| @@ -1184,8 +1185,10 @@ static bool tx_credit_exceeded(struct xe |
| msecs_to_jiffies(queue->credit_usec / 1000); |
| |
| /* Timer could already be pending in rare cases. */ |
| - if (timer_pending(&queue->credit_timeout)) |
| + if (timer_pending(&queue->credit_timeout)) { |
| + queue->rate_limited = true; |
| return true; |
| + } |
| |
| /* Passed the point where we can replenish credit? */ |
| if (time_after_eq64(now, next_credit)) { |
| @@ -1200,6 +1203,7 @@ static bool tx_credit_exceeded(struct xe |
| mod_timer(&queue->credit_timeout, |
| next_credit); |
| queue->credit_window_start = next_credit; |
| + queue->rate_limited = true; |
| |
| return true; |
| } |