static void mousevsc_on_channel_callback(void *context) { const int packet_size = 0x100; int ret; struct hv_device *device = context; u32 bytes_recvd; u64 req_id; struct vmpacket_descriptor *desc; unsigned char *buffer; int bufferlen = packet_size; buffer = kmalloc(bufferlen, GFP_ATOMIC); if (!buffer) return; do { ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, &bytes_recvd, &req_id); switch (ret) { case 0: if (bytes_recvd <= 0) { kfree(buffer); return; } desc = (struct vmpacket_descriptor *)buffer; switch (desc->type) { case VM_PKT_COMP: break; case VM_PKT_DATA_INBAND: mousevsc_on_receive(device, desc); break; default: pr_err("unhandled packet type %d, tid %llx len %d\n", desc->type, req_id, bytes_recvd); break; } break; case -ENOBUFS: kfree(buffer); /* Handle large packet */ bufferlen = bytes_recvd; buffer = kmalloc(bytes_recvd, GFP_ATOMIC); if (!buffer) return; break; } } while (1); }
static void hv_kbd_on_channel_callback(void *context) { struct hv_device *hv_dev = context; void *buffer; int bufferlen = 0x100; /* Start with sensible size */ u32 bytes_recvd; u64 req_id; int error; buffer = kmalloc(bufferlen, GFP_ATOMIC); if (!buffer) return; while (1) { error = vmbus_recvpacket_raw(hv_dev->channel, buffer, bufferlen, &bytes_recvd, &req_id); switch (error) { case 0: if (bytes_recvd == 0) { kfree(buffer); return; } hv_kbd_handle_received_packet(hv_dev, buffer, bytes_recvd, req_id); break; case -ENOBUFS: kfree(buffer); /* Handle large packet */ bufferlen = bytes_recvd; buffer = kmalloc(bytes_recvd, GFP_ATOMIC); if (!buffer) return; break; } } }
void netvsc_channel_cb(void *context) { int ret; struct vmbus_channel *channel = (struct vmbus_channel *)context; struct hv_device *device; struct netvsc_device *net_device; u32 bytes_recvd; u64 request_id; struct vmpacket_descriptor *desc; unsigned char *buffer; int bufferlen = NETVSC_PACKET_SIZE; struct net_device *ndev; struct nvsp_message *nvmsg; if (channel->primary_channel != NULL) device = channel->primary_channel->device_obj; else device = channel->device_obj; net_device = get_inbound_net_device(device); if (!net_device) return; ndev = net_device->ndev; buffer = get_per_channel_state(channel); do { 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, 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; } } else { /* * We are done for this pass. */ break; } } else if (ret == -ENOBUFS) { if (bufferlen > NETVSC_PACKET_SIZE) kfree(buffer); /* Handle large packet */ buffer = kmalloc(bytes_recvd, GFP_ATOMIC); if (buffer == NULL) { /* Try again next time around */ netdev_err(ndev, "unable to allocate buffer of size " "(%d)!!\n", bytes_recvd); break; } bufferlen = bytes_recvd; } } while (1); if (bufferlen > NETVSC_PACKET_SIZE) kfree(buffer); return; }