aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2012-10-02 01:30:23 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-02 14:39:31 -0400
commit63f6921d300c6fbdca3d0e73dcc24b4e5e4dced2 (patch)
tree5cd2560e12959f51574e0235bc1d9bdb81b30b98
parent6562640bd3b368a7ffb1caa61c82abe6e9d54b3b (diff)
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>
-rw-r--r--drivers/net/hyperv/hyperv_net.h2
-rw-r--r--drivers/net/hyperv/netvsc.c18
-rw-r--r--drivers/net/hyperv/netvsc_drv.c2
-rw-r--r--drivers/net/hyperv/rndis_filter.c19
4 files changed, 30 insertions, 11 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index d58f28c46386..5fd6f4674326 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -35,6 +35,7 @@ struct hv_netvsc_packet;
35/* Represent the xfer page packet which contains 1 or more netvsc packet */ 35/* Represent the xfer page packet which contains 1 or more netvsc packet */
36struct xferpage_packet { 36struct xferpage_packet {
37 struct list_head list_ent; 37 struct list_head list_ent;
38 u32 status;
38 39
39 /* # of netvsc packets this xfer packet contains */ 40 /* # of netvsc packets this xfer packet contains */
40 u32 count; 41 u32 count;
@@ -47,6 +48,7 @@ struct xferpage_packet {
47struct hv_netvsc_packet { 48struct hv_netvsc_packet {
48 /* Bookkeeping stuff */ 49 /* Bookkeeping stuff */
49 struct list_head list_ent; 50 struct list_head list_ent;
51 u32 status;
50 52
51 struct hv_device *device; 53 struct hv_device *device;
52 bool is_data_pkt; 54 bool is_data_pkt;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d9c4c0399c88..1cd77483da50 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -558,7 +558,7 @@ int netvsc_send(struct hv_device *device,
558} 558}
559 559
560static void netvsc_send_recv_completion(struct hv_device *device, 560static void netvsc_send_recv_completion(struct hv_device *device,
561 u64 transaction_id) 561 u64 transaction_id, u32 status)
562{ 562{
563 struct nvsp_message recvcompMessage; 563 struct nvsp_message recvcompMessage;
564 int retries = 0; 564 int retries = 0;
@@ -571,9 +571,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
571 recvcompMessage.hdr.msg_type = 571 recvcompMessage.hdr.msg_type =
572 NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; 572 NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
573 573
574 /* FIXME: Pass in the status */ 574 recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
575 recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
576 NVSP_STAT_SUCCESS;
577 575
578retry_send_cmplt: 576retry_send_cmplt:
579 /* Send the completion */ 577 /* Send the completion */
@@ -613,6 +611,7 @@ static void netvsc_receive_completion(void *context)
613 bool fsend_receive_comp = false; 611 bool fsend_receive_comp = false;
614 unsigned long flags; 612 unsigned long flags;
615 struct net_device *ndev; 613 struct net_device *ndev;
614 u32 status = NVSP_STAT_NONE;
616 615
617 /* 616 /*
618 * Even though it seems logical to do a GetOutboundNetDevice() here to 617 * Even though it seems logical to do a GetOutboundNetDevice() here to
@@ -627,6 +626,9 @@ static void netvsc_receive_completion(void *context)
627 /* Overloading use of the lock. */ 626 /* Overloading use of the lock. */
628 spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); 627 spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
629 628
629 if (packet->status != NVSP_STAT_SUCCESS)
630 packet->xfer_page_pkt->status = NVSP_STAT_FAIL;
631
630 packet->xfer_page_pkt->count--; 632 packet->xfer_page_pkt->count--;
631 633
632 /* 634 /*
@@ -636,6 +638,7 @@ static void netvsc_receive_completion(void *context)
636 if (packet->xfer_page_pkt->count == 0) { 638 if (packet->xfer_page_pkt->count == 0) {
637 fsend_receive_comp = true; 639 fsend_receive_comp = true;
638 transaction_id = packet->completion.recv.recv_completion_tid; 640 transaction_id = packet->completion.recv.recv_completion_tid;
641 status = packet->xfer_page_pkt->status;
639 list_add_tail(&packet->xfer_page_pkt->list_ent, 642 list_add_tail(&packet->xfer_page_pkt->list_ent,
640 &net_device->recv_pkt_list); 643 &net_device->recv_pkt_list);
641 644
@@ -647,7 +650,7 @@ static void netvsc_receive_completion(void *context)
647 650
648 /* Send a receive completion for the xfer page packet */ 651 /* Send a receive completion for the xfer page packet */
649 if (fsend_receive_comp) 652 if (fsend_receive_comp)
650 netvsc_send_recv_completion(device, transaction_id); 653 netvsc_send_recv_completion(device, transaction_id, status);
651 654
652} 655}
653 656
@@ -736,7 +739,8 @@ static void netvsc_receive(struct hv_device *device,
736 flags); 739 flags);
737 740
738 netvsc_send_recv_completion(device, 741 netvsc_send_recv_completion(device,
739 vmxferpage_packet->d.trans_id); 742 vmxferpage_packet->d.trans_id,
743 NVSP_STAT_FAIL);
740 744
741 return; 745 return;
742 } 746 }
@@ -744,6 +748,7 @@ static void netvsc_receive(struct hv_device *device,
744 /* Remove the 1st packet to represent the xfer page packet itself */ 748 /* Remove the 1st packet to represent the xfer page packet itself */
745 xferpage_packet = (struct xferpage_packet *)listHead.next; 749 xferpage_packet = (struct xferpage_packet *)listHead.next;
746 list_del(&xferpage_packet->list_ent); 750 list_del(&xferpage_packet->list_ent);
751 xferpage_packet->status = NVSP_STAT_SUCCESS;
747 752
748 /* This is how much we can satisfy */ 753 /* This is how much we can satisfy */
749 xferpage_packet->count = count - 1; 754 xferpage_packet->count = count - 1;
@@ -760,6 +765,7 @@ static void netvsc_receive(struct hv_device *device,
760 list_del(&netvsc_packet->list_ent); 765 list_del(&netvsc_packet->list_ent);
761 766
762 /* Initialize the netvsc packet */ 767 /* Initialize the netvsc packet */
768 netvsc_packet->status = NVSP_STAT_SUCCESS;
763 netvsc_packet->xfer_page_pkt = xferpage_packet; 769 netvsc_packet->xfer_page_pkt = xferpage_packet;
764 netvsc_packet->completion.recv.recv_completion = 770 netvsc_packet->completion.recv.recv_completion =
765 netvsc_receive_completion; 771 netvsc_receive_completion;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index e91111a656f7..f825a629a699 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -265,6 +265,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
265 if (!net) { 265 if (!net) {
266 netdev_err(net, "got receive callback but net device" 266 netdev_err(net, "got receive callback but net device"
267 " not initialized yet\n"); 267 " not initialized yet\n");
268 packet->status = NVSP_STAT_FAIL;
268 return 0; 269 return 0;
269 } 270 }
270 271
@@ -272,6 +273,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
272 skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); 273 skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
273 if (unlikely(!skb)) { 274 if (unlikely(!skb)) {
274 ++net->stats.rx_dropped; 275 ++net->stats.rx_dropped;
276 packet->status = NVSP_STAT_FAIL;
275 return 0; 277 return 0;
276 } 278 }
277 279
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index f25f41e1fdb7..e7e12cfbbf37 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -411,9 +411,12 @@ int rndis_filter_receive(struct hv_device *dev,
411 struct rndis_device *rndis_dev; 411 struct rndis_device *rndis_dev;
412 struct rndis_message *rndis_msg; 412 struct rndis_message *rndis_msg;
413 struct net_device *ndev; 413 struct net_device *ndev;
414 int ret = 0;
414 415
415 if (!net_dev) 416 if (!net_dev) {
416 return -EINVAL; 417 ret = -EINVAL;
418 goto exit;
419 }
417 420
418 ndev = net_dev->ndev; 421 ndev = net_dev->ndev;
419 422
@@ -421,14 +424,16 @@ int rndis_filter_receive(struct hv_device *dev,
421 if (!net_dev->extension) { 424 if (!net_dev->extension) {
422 netdev_err(ndev, "got rndis message but no rndis device - " 425 netdev_err(ndev, "got rndis message but no rndis device - "
423 "dropping this message!\n"); 426 "dropping this message!\n");
424 return -ENODEV; 427 ret = -ENODEV;
428 goto exit;
425 } 429 }
426 430
427 rndis_dev = (struct rndis_device *)net_dev->extension; 431 rndis_dev = (struct rndis_device *)net_dev->extension;
428 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { 432 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
429 netdev_err(ndev, "got rndis message but rndis device " 433 netdev_err(ndev, "got rndis message but rndis device "
430 "uninitialized...dropping this message!\n"); 434 "uninitialized...dropping this message!\n");
431 return -ENODEV; 435 ret = -ENODEV;
436 goto exit;
432 } 437 }
433 438
434 rndis_msg = pkt->data; 439 rndis_msg = pkt->data;
@@ -460,7 +465,11 @@ int rndis_filter_receive(struct hv_device *dev,
460 break; 465 break;
461 } 466 }
462 467
463 return 0; 468exit:
469 if (ret != 0)
470 pkt->status = NVSP_STAT_FAIL;
471
472 return ret;
464} 473}
465 474
466static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, 475static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,