aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv/netvsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hyperv/netvsc.c')
-rw-r--r--drivers/net/hyperv/netvsc.c88
1 files changed, 59 insertions, 29 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 6909c322de4e..20e09174ff62 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1128,6 +1128,39 @@ static inline void netvsc_receive_inband(struct hv_device *hdev,
1128 } 1128 }
1129} 1129}
1130 1130
1131static void netvsc_process_raw_pkt(struct hv_device *device,
1132 struct vmbus_channel *channel,
1133 struct netvsc_device *net_device,
1134 struct net_device *ndev,
1135 u64 request_id,
1136 struct vmpacket_descriptor *desc)
1137{
1138 struct nvsp_message *nvmsg;
1139
1140 nvmsg = (struct nvsp_message *)((unsigned long)
1141 desc + (desc->offset8 << 3));
1142
1143 switch (desc->type) {
1144 case VM_PKT_COMP:
1145 netvsc_send_completion(net_device, channel, device, desc);
1146 break;
1147
1148 case VM_PKT_DATA_USING_XFER_PAGES:
1149 netvsc_receive(net_device, channel, device, desc);
1150 break;
1151
1152 case VM_PKT_DATA_INBAND:
1153 netvsc_receive_inband(device, net_device, nvmsg);
1154 break;
1155
1156 default:
1157 netdev_err(ndev, "unhandled packet type %d, tid %llx\n",
1158 desc->type, request_id);
1159 break;
1160 }
1161}
1162
1163
1131void netvsc_channel_cb(void *context) 1164void netvsc_channel_cb(void *context)
1132{ 1165{
1133 int ret; 1166 int ret;
@@ -1140,7 +1173,7 @@ void netvsc_channel_cb(void *context)
1140 unsigned char *buffer; 1173 unsigned char *buffer;
1141 int bufferlen = NETVSC_PACKET_SIZE; 1174 int bufferlen = NETVSC_PACKET_SIZE;
1142 struct net_device *ndev; 1175 struct net_device *ndev;
1143 struct nvsp_message *nvmsg; 1176 bool need_to_commit = false;
1144 1177
1145 if (channel->primary_channel != NULL) 1178 if (channel->primary_channel != NULL)
1146 device = channel->primary_channel->device_obj; 1179 device = channel->primary_channel->device_obj;
@@ -1154,39 +1187,36 @@ void netvsc_channel_cb(void *context)
1154 buffer = get_per_channel_state(channel); 1187 buffer = get_per_channel_state(channel);
1155 1188
1156 do { 1189 do {
1190 desc = get_next_pkt_raw(channel);
1191 if (desc != NULL) {
1192 netvsc_process_raw_pkt(device,
1193 channel,
1194 net_device,
1195 ndev,
1196 desc->trans_id,
1197 desc);
1198
1199 put_pkt_raw(channel, desc);
1200 need_to_commit = true;
1201 continue;
1202 }
1203 if (need_to_commit) {
1204 need_to_commit = false;
1205 commit_rd_index(channel);
1206 }
1207
1157 ret = vmbus_recvpacket_raw(channel, buffer, bufferlen, 1208 ret = vmbus_recvpacket_raw(channel, buffer, bufferlen,
1158 &bytes_recvd, &request_id); 1209 &bytes_recvd, &request_id);
1159 if (ret == 0) { 1210 if (ret == 0) {
1160 if (bytes_recvd > 0) { 1211 if (bytes_recvd > 0) {
1161 desc = (struct vmpacket_descriptor *)buffer; 1212 desc = (struct vmpacket_descriptor *)buffer;
1162 nvmsg = (struct nvsp_message *)((unsigned long) 1213 netvsc_process_raw_pkt(device,
1163 desc + (desc->offset8 << 3)); 1214 channel,
1164 switch (desc->type) { 1215 net_device,
1165 case VM_PKT_COMP: 1216 ndev,
1166 netvsc_send_completion(net_device, 1217 request_id,
1167 channel, 1218 desc);
1168 device, desc); 1219
1169 break;
1170
1171 case VM_PKT_DATA_USING_XFER_PAGES:
1172 netvsc_receive(net_device, channel,
1173 device, desc);
1174 break;
1175
1176 case VM_PKT_DATA_INBAND:
1177 netvsc_receive_inband(device,
1178 net_device,
1179 nvmsg);
1180 break;
1181
1182 default:
1183 netdev_err(ndev,
1184 "unhandled packet type %d, "
1185 "tid %llx len %d\n",
1186 desc->type, request_id,
1187 bytes_recvd);
1188 break;
1189 }
1190 1220
1191 } else { 1221 } else {
1192 /* 1222 /*