hyperv: Report actual status in receive completion packet

The existing code always reports NVSP_STAT_SUCCESS. This patch adds the
mechanism to report failure when it happens.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d9c4c03..1cd7748 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -558,7 +558,7 @@
 }
 
 static void netvsc_send_recv_completion(struct hv_device *device,
-					u64 transaction_id)
+					u64 transaction_id, u32 status)
 {
 	struct nvsp_message recvcompMessage;
 	int retries = 0;
@@ -571,9 +571,7 @@
 	recvcompMessage.hdr.msg_type =
 				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
 
-	/* FIXME: Pass in the status */
-	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
-		NVSP_STAT_SUCCESS;
+	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
 
 retry_send_cmplt:
 	/* Send the completion */
@@ -613,6 +611,7 @@
 	bool fsend_receive_comp = false;
 	unsigned long flags;
 	struct net_device *ndev;
+	u32 status = NVSP_STAT_NONE;
 
 	/*
 	 * Even though it seems logical to do a GetOutboundNetDevice() here to
@@ -627,6 +626,9 @@
 	/* Overloading use of the lock. */
 	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
 
+	if (packet->status != NVSP_STAT_SUCCESS)
+		packet->xfer_page_pkt->status = NVSP_STAT_FAIL;
+
 	packet->xfer_page_pkt->count--;
 
 	/*
@@ -636,6 +638,7 @@
 	if (packet->xfer_page_pkt->count == 0) {
 		fsend_receive_comp = true;
 		transaction_id = packet->completion.recv.recv_completion_tid;
+		status = packet->xfer_page_pkt->status;
 		list_add_tail(&packet->xfer_page_pkt->list_ent,
 			      &net_device->recv_pkt_list);
 
@@ -647,7 +650,7 @@
 
 	/* Send a receive completion for the xfer page packet */
 	if (fsend_receive_comp)
-		netvsc_send_recv_completion(device, transaction_id);
+		netvsc_send_recv_completion(device, transaction_id, status);
 
 }
 
@@ -736,7 +739,8 @@
 				       flags);
 
 		netvsc_send_recv_completion(device,
-					    vmxferpage_packet->d.trans_id);
+					    vmxferpage_packet->d.trans_id,
+					    NVSP_STAT_FAIL);
 
 		return;
 	}
@@ -744,6 +748,7 @@
 	/* Remove the 1st packet to represent the xfer page packet itself */
 	xferpage_packet = (struct xferpage_packet *)listHead.next;
 	list_del(&xferpage_packet->list_ent);
+	xferpage_packet->status = NVSP_STAT_SUCCESS;
 
 	/* This is how much we can satisfy */
 	xferpage_packet->count = count - 1;
@@ -760,6 +765,7 @@
 		list_del(&netvsc_packet->list_ent);
 
 		/* Initialize the netvsc packet */
+		netvsc_packet->status = NVSP_STAT_SUCCESS;
 		netvsc_packet->xfer_page_pkt = xferpage_packet;
 		netvsc_packet->completion.recv.recv_completion =
 					netvsc_receive_completion;