| From foo@baz Sun Oct 12 20:11:55 CEST 2014 |
| From: KY Srinivasan <kys@microsoft.com> |
| Date: Sun, 5 Oct 2014 10:42:51 -0700 |
| Subject: hyperv: Fix a bug in netvsc_send() |
| |
| From: KY Srinivasan <kys@microsoft.com> |
| |
| [ Upstream commit 3a67c9ccad926a168d8b7891537a452018368a5b ] |
| |
| After the packet is successfully sent, we should not touch the packet |
| as it may have been freed. This patch is based on the work done by |
| Long Li <longli@microsoft.com>. |
| |
| David, please queue this up for stable. |
| |
| Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> |
| Reported-by: Sitsofe Wheeler <sitsofe@yahoo.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/hyperv/netvsc.c | 15 ++++++++------- |
| 1 file changed, 8 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/net/hyperv/netvsc.c |
| +++ b/drivers/net/hyperv/netvsc.c |
| @@ -708,6 +708,7 @@ int netvsc_send(struct hv_device *device |
| unsigned int section_index = NETVSC_INVALID_INDEX; |
| u32 msg_size = 0; |
| struct sk_buff *skb; |
| + u16 q_idx = packet->q_idx; |
| |
| |
| net_device = get_outbound_net_device(device); |
| @@ -772,24 +773,24 @@ int netvsc_send(struct hv_device *device |
| |
| if (ret == 0) { |
| atomic_inc(&net_device->num_outstanding_sends); |
| - atomic_inc(&net_device->queue_sends[packet->q_idx]); |
| + atomic_inc(&net_device->queue_sends[q_idx]); |
| |
| if (hv_ringbuf_avail_percent(&out_channel->outbound) < |
| RING_AVAIL_PERCENT_LOWATER) { |
| netif_tx_stop_queue(netdev_get_tx_queue( |
| - ndev, packet->q_idx)); |
| + ndev, q_idx)); |
| |
| if (atomic_read(&net_device-> |
| - queue_sends[packet->q_idx]) < 1) |
| + queue_sends[q_idx]) < 1) |
| netif_tx_wake_queue(netdev_get_tx_queue( |
| - ndev, packet->q_idx)); |
| + ndev, q_idx)); |
| } |
| } else if (ret == -EAGAIN) { |
| netif_tx_stop_queue(netdev_get_tx_queue( |
| - ndev, packet->q_idx)); |
| - if (atomic_read(&net_device->queue_sends[packet->q_idx]) < 1) { |
| + ndev, q_idx)); |
| + if (atomic_read(&net_device->queue_sends[q_idx]) < 1) { |
| netif_tx_wake_queue(netdev_get_tx_queue( |
| - ndev, packet->q_idx)); |
| + ndev, q_idx)); |
| ret = -ENOSPC; |
| } |
| } else { |