|
@@ -1128,6 +1128,39 @@ static inline void netvsc_receive_inband(struct hv_device *hdev,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void netvsc_process_raw_pkt(struct hv_device *device,
|
|
|
+ struct vmbus_channel *channel,
|
|
|
+ struct netvsc_device *net_device,
|
|
|
+ struct net_device *ndev,
|
|
|
+ u64 request_id,
|
|
|
+ struct vmpacket_descriptor *desc)
|
|
|
+{
|
|
|
+ struct nvsp_message *nvmsg;
|
|
|
+
|
|
|
+ nvmsg = (struct nvsp_message *)((unsigned long)
|
|
|
+ desc + (desc->offset8 << 3));
|
|
|
+
|
|
|
+ switch (desc->type) {
|
|
|
+ case VM_PKT_COMP:
|
|
|
+ netvsc_send_completion(net_device, channel, device, desc);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case VM_PKT_DATA_USING_XFER_PAGES:
|
|
|
+ netvsc_receive(net_device, channel, device, desc);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case VM_PKT_DATA_INBAND:
|
|
|
+ netvsc_receive_inband(device, net_device, nvmsg);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ netdev_err(ndev, "unhandled packet type %d, tid %llx\n",
|
|
|
+ desc->type, request_id);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void netvsc_channel_cb(void *context)
|
|
|
{
|
|
|
int ret;
|
|
@@ -1140,7 +1173,7 @@ void netvsc_channel_cb(void *context)
|
|
|
unsigned char *buffer;
|
|
|
int bufferlen = NETVSC_PACKET_SIZE;
|
|
|
struct net_device *ndev;
|
|
|
- struct nvsp_message *nvmsg;
|
|
|
+ bool need_to_commit = false;
|
|
|
|
|
|
if (channel->primary_channel != NULL)
|
|
|
device = channel->primary_channel->device_obj;
|
|
@@ -1154,39 +1187,36 @@ void netvsc_channel_cb(void *context)
|
|
|
buffer = get_per_channel_state(channel);
|
|
|
|
|
|
do {
|
|
|
+ desc = get_next_pkt_raw(channel);
|
|
|
+ if (desc != NULL) {
|
|
|
+ netvsc_process_raw_pkt(device,
|
|
|
+ channel,
|
|
|
+ net_device,
|
|
|
+ ndev,
|
|
|
+ desc->trans_id,
|
|
|
+ desc);
|
|
|
+
|
|
|
+ put_pkt_raw(channel, desc);
|
|
|
+ need_to_commit = true;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (need_to_commit) {
|
|
|
+ need_to_commit = false;
|
|
|
+ commit_rd_index(channel);
|
|
|
+ }
|
|
|
+
|
|
|
ret = vmbus_recvpacket_raw(channel, buffer, bufferlen,
|
|
|
&bytes_recvd, &request_id);
|
|
|
if (ret == 0) {
|
|
|
if (bytes_recvd > 0) {
|
|
|
desc = (struct vmpacket_descriptor *)buffer;
|
|
|
- nvmsg = (struct nvsp_message *)((unsigned long)
|
|
|
- desc + (desc->offset8 << 3));
|
|
|
- switch (desc->type) {
|
|
|
- case VM_PKT_COMP:
|
|
|
- netvsc_send_completion(net_device,
|
|
|
- channel,
|
|
|
- device, desc);
|
|
|
- break;
|
|
|
-
|
|
|
- case VM_PKT_DATA_USING_XFER_PAGES:
|
|
|
- netvsc_receive(net_device, channel,
|
|
|
- device, desc);
|
|
|
- break;
|
|
|
-
|
|
|
- case VM_PKT_DATA_INBAND:
|
|
|
- netvsc_receive_inband(device,
|
|
|
- net_device,
|
|
|
- nvmsg);
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- netdev_err(ndev,
|
|
|
- "unhandled packet type %d, "
|
|
|
- "tid %llx len %d\n",
|
|
|
- desc->type, request_id,
|
|
|
- bytes_recvd);
|
|
|
- break;
|
|
|
- }
|
|
|
+ netvsc_process_raw_pkt(device,
|
|
|
+ channel,
|
|
|
+ net_device,
|
|
|
+ ndev,
|
|
|
+ request_id,
|
|
|
+ desc);
|
|
|
+
|
|
|
|
|
|
} else {
|
|
|
/*
|