diff options
| author | Haiyang Zhang <haiyangz@microsoft.com> | 2012-10-02 01:30:23 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-10-02 14:39:31 -0400 |
| commit | 63f6921d300c6fbdca3d0e73dcc24b4e5e4dced2 (patch) | |
| tree | 5cd2560e12959f51574e0235bc1d9bdb81b30b98 /drivers | |
| parent | 6562640bd3b368a7ffb1caa61c82abe6e9d54b3b (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>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 2 | ||||
| -rw-r--r-- | drivers/net/hyperv/netvsc.c | 18 | ||||
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 2 | ||||
| -rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 19 |
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 */ |
| 36 | struct xferpage_packet { | 36 | struct 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 { | |||
| 47 | struct hv_netvsc_packet { | 48 | struct 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 | ||
| 560 | static void netvsc_send_recv_completion(struct hv_device *device, | 560 | static 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 | ||
| 578 | retry_send_cmplt: | 576 | retry_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; | 468 | exit: |
| 469 | if (ret != 0) | ||
| 470 | pkt->status = NVSP_STAT_FAIL; | ||
| 471 | |||
| 472 | return ret; | ||
| 464 | } | 473 | } |
| 465 | 474 | ||
| 466 | static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, | 475 | static int rndis_filter_query_device(struct rndis_device *dev, u32 oid, |
