Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 63f6921d authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller
Browse files

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: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6562640b
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ struct hv_netvsc_packet;
/* Represent the xfer page packet which contains 1 or more netvsc packet */
/* Represent the xfer page packet which contains 1 or more netvsc packet */
struct xferpage_packet {
struct xferpage_packet {
	struct list_head list_ent;
	struct list_head list_ent;
	u32 status;


	/* # of netvsc packets this xfer packet contains */
	/* # of netvsc packets this xfer packet contains */
	u32 count;
	u32 count;
@@ -47,6 +48,7 @@ struct xferpage_packet {
struct hv_netvsc_packet {
struct hv_netvsc_packet {
	/* Bookkeeping stuff */
	/* Bookkeeping stuff */
	struct list_head list_ent;
	struct list_head list_ent;
	u32 status;


	struct hv_device *device;
	struct hv_device *device;
	bool is_data_pkt;
	bool is_data_pkt;
+12 −6
Original line number Original line Diff line number Diff line
@@ -558,7 +558,7 @@ int netvsc_send(struct hv_device *device,
}
}


static void netvsc_send_recv_completion(struct hv_device *device,
static void netvsc_send_recv_completion(struct hv_device *device,
					u64 transaction_id)
					u64 transaction_id, u32 status)
{
{
	struct nvsp_message recvcompMessage;
	struct nvsp_message recvcompMessage;
	int retries = 0;
	int retries = 0;
@@ -571,9 +571,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
	recvcompMessage.hdr.msg_type =
	recvcompMessage.hdr.msg_type =
				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;


	/* FIXME: Pass in the status */
	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
		NVSP_STAT_SUCCESS;


retry_send_cmplt:
retry_send_cmplt:
	/* Send the completion */
	/* Send the completion */
@@ -613,6 +611,7 @@ static void netvsc_receive_completion(void *context)
	bool fsend_receive_comp = false;
	bool fsend_receive_comp = false;
	unsigned long flags;
	unsigned long flags;
	struct net_device *ndev;
	struct net_device *ndev;
	u32 status = NVSP_STAT_NONE;


	/*
	/*
	 * Even though it seems logical to do a GetOutboundNetDevice() here to
	 * Even though it seems logical to do a GetOutboundNetDevice() here to
@@ -627,6 +626,9 @@ static void netvsc_receive_completion(void *context)
	/* Overloading use of the lock. */
	/* Overloading use of the lock. */
	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
	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--;
	packet->xfer_page_pkt->count--;


	/*
	/*
@@ -636,6 +638,7 @@ static void netvsc_receive_completion(void *context)
	if (packet->xfer_page_pkt->count == 0) {
	if (packet->xfer_page_pkt->count == 0) {
		fsend_receive_comp = true;
		fsend_receive_comp = true;
		transaction_id = packet->completion.recv.recv_completion_tid;
		transaction_id = packet->completion.recv.recv_completion_tid;
		status = packet->xfer_page_pkt->status;
		list_add_tail(&packet->xfer_page_pkt->list_ent,
		list_add_tail(&packet->xfer_page_pkt->list_ent,
			      &net_device->recv_pkt_list);
			      &net_device->recv_pkt_list);


@@ -647,7 +650,7 @@ static void netvsc_receive_completion(void *context)


	/* Send a receive completion for the xfer page packet */
	/* Send a receive completion for the xfer page packet */
	if (fsend_receive_comp)
	if (fsend_receive_comp)
		netvsc_send_recv_completion(device, transaction_id);
		netvsc_send_recv_completion(device, transaction_id, status);


}
}


@@ -736,7 +739,8 @@ static void netvsc_receive(struct hv_device *device,
				       flags);
				       flags);


		netvsc_send_recv_completion(device,
		netvsc_send_recv_completion(device,
					    vmxferpage_packet->d.trans_id);
					    vmxferpage_packet->d.trans_id,
					    NVSP_STAT_FAIL);


		return;
		return;
	}
	}
@@ -744,6 +748,7 @@ static void netvsc_receive(struct hv_device *device,
	/* Remove the 1st packet to represent the xfer page packet itself */
	/* Remove the 1st packet to represent the xfer page packet itself */
	xferpage_packet = (struct xferpage_packet *)listHead.next;
	xferpage_packet = (struct xferpage_packet *)listHead.next;
	list_del(&xferpage_packet->list_ent);
	list_del(&xferpage_packet->list_ent);
	xferpage_packet->status = NVSP_STAT_SUCCESS;


	/* This is how much we can satisfy */
	/* This is how much we can satisfy */
	xferpage_packet->count = count - 1;
	xferpage_packet->count = count - 1;
@@ -760,6 +765,7 @@ static void netvsc_receive(struct hv_device *device,
		list_del(&netvsc_packet->list_ent);
		list_del(&netvsc_packet->list_ent);


		/* Initialize the netvsc packet */
		/* Initialize the netvsc packet */
		netvsc_packet->status = NVSP_STAT_SUCCESS;
		netvsc_packet->xfer_page_pkt = xferpage_packet;
		netvsc_packet->xfer_page_pkt = xferpage_packet;
		netvsc_packet->completion.recv.recv_completion =
		netvsc_packet->completion.recv.recv_completion =
					netvsc_receive_completion;
					netvsc_receive_completion;
+2 −0
Original line number Original line Diff line number Diff line
@@ -265,6 +265,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
	if (!net) {
	if (!net) {
		netdev_err(net, "got receive callback but net device"
		netdev_err(net, "got receive callback but net device"
			" not initialized yet\n");
			" not initialized yet\n");
		packet->status = NVSP_STAT_FAIL;
		return 0;
		return 0;
	}
	}


@@ -272,6 +273,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
	skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
	skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
	if (unlikely(!skb)) {
	if (unlikely(!skb)) {
		++net->stats.rx_dropped;
		++net->stats.rx_dropped;
		packet->status = NVSP_STAT_FAIL;
		return 0;
		return 0;
	}
	}


+14 −5
Original line number Original line Diff line number Diff line
@@ -411,9 +411,12 @@ int rndis_filter_receive(struct hv_device *dev,
	struct rndis_device *rndis_dev;
	struct rndis_device *rndis_dev;
	struct rndis_message *rndis_msg;
	struct rndis_message *rndis_msg;
	struct net_device *ndev;
	struct net_device *ndev;
	int ret = 0;


	if (!net_dev)
	if (!net_dev) {
		return -EINVAL;
		ret = -EINVAL;
		goto exit;
	}


	ndev = net_dev->ndev;
	ndev = net_dev->ndev;


@@ -421,14 +424,16 @@ int rndis_filter_receive(struct hv_device *dev,
	if (!net_dev->extension) {
	if (!net_dev->extension) {
		netdev_err(ndev, "got rndis message but no rndis device - "
		netdev_err(ndev, "got rndis message but no rndis device - "
			  "dropping this message!\n");
			  "dropping this message!\n");
		return -ENODEV;
		ret = -ENODEV;
		goto exit;
	}
	}


	rndis_dev = (struct rndis_device *)net_dev->extension;
	rndis_dev = (struct rndis_device *)net_dev->extension;
	if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
	if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
		netdev_err(ndev, "got rndis message but rndis device "
		netdev_err(ndev, "got rndis message but rndis device "
			   "uninitialized...dropping this message!\n");
			   "uninitialized...dropping this message!\n");
		return -ENODEV;
		ret = -ENODEV;
		goto exit;
	}
	}


	rndis_msg = pkt->data;
	rndis_msg = pkt->data;
@@ -460,7 +465,11 @@ int rndis_filter_receive(struct hv_device *dev,
		break;
		break;
	}
	}


	return 0;
exit:
	if (ret != 0)
		pkt->status = NVSP_STAT_FAIL;

	return ret;
}
}


static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,