0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011
0012 #include <linux/nls.h>
0013 #include <linux/workqueue.h>
0014 #include <linux/hyperv.h>
0015 #include <linux/sched.h>
0016 #include <asm/hyperv-tlfs.h>
0017
0018 #include "hyperv_vmbus.h"
0019 #include "hv_utils_transport.h"
0020
0021 #define WIN8_SRV_MAJOR 1
0022 #define WIN8_SRV_MINOR 1
0023 #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
0024
0025 #define FCOPY_VER_COUNT 1
0026 static const int fcopy_versions[] = {
0027 WIN8_SRV_VERSION
0028 };
0029
0030 #define FW_VER_COUNT 1
0031 static const int fw_versions[] = {
0032 UTIL_FW_VERSION
0033 };
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 static struct {
0050 int state;
0051 int recv_len;
0052 struct hv_fcopy_hdr *fcopy_msg;
0053 struct vmbus_channel *recv_channel;
0054 u64 recv_req_id;
0055 } fcopy_transaction;
0056
0057 static void fcopy_respond_to_host(int error);
0058 static void fcopy_send_data(struct work_struct *dummy);
0059 static void fcopy_timeout_func(struct work_struct *dummy);
0060 static DECLARE_DELAYED_WORK(fcopy_timeout_work, fcopy_timeout_func);
0061 static DECLARE_WORK(fcopy_send_work, fcopy_send_data);
0062 static const char fcopy_devname[] = "vmbus/hv_fcopy";
0063 static u8 *recv_buffer;
0064 static struct hvutil_transport *hvt;
0065
0066
0067
0068 static int dm_reg_value;
0069
0070 static void fcopy_poll_wrapper(void *channel)
0071 {
0072
0073 fcopy_transaction.state = HVUTIL_READY;
0074 tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
0075 }
0076
0077 static void fcopy_timeout_func(struct work_struct *dummy)
0078 {
0079
0080
0081
0082
0083 fcopy_respond_to_host(HV_E_FAIL);
0084 hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
0085 }
0086
0087 static void fcopy_register_done(void)
0088 {
0089 pr_debug("FCP: userspace daemon registered\n");
0090 hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
0091 }
0092
0093 static int fcopy_handle_handshake(u32 version)
0094 {
0095 u32 our_ver = FCOPY_CURRENT_VERSION;
0096
0097 switch (version) {
0098 case FCOPY_VERSION_0:
0099
0100 dm_reg_value = version;
0101 break;
0102 case FCOPY_VERSION_1:
0103
0104 if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver),
0105 fcopy_register_done))
0106 return -EFAULT;
0107 dm_reg_value = version;
0108 break;
0109 default:
0110
0111
0112
0113
0114
0115
0116 return -EINVAL;
0117 }
0118 pr_debug("FCP: userspace daemon ver. %d connected\n", version);
0119 return 0;
0120 }
0121
0122 static void fcopy_send_data(struct work_struct *dummy)
0123 {
0124 struct hv_start_fcopy *smsg_out = NULL;
0125 int operation = fcopy_transaction.fcopy_msg->operation;
0126 struct hv_start_fcopy *smsg_in;
0127 void *out_src;
0128 int rc, out_len;
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 switch (operation) {
0142 case START_FILE_COPY:
0143 out_len = sizeof(struct hv_start_fcopy);
0144 smsg_out = kzalloc(sizeof(*smsg_out), GFP_KERNEL);
0145 if (!smsg_out)
0146 return;
0147
0148 smsg_out->hdr.operation = operation;
0149 smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg;
0150
0151 utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH,
0152 UTF16_LITTLE_ENDIAN,
0153 (__u8 *)&smsg_out->file_name, W_MAX_PATH - 1);
0154
0155 utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH,
0156 UTF16_LITTLE_ENDIAN,
0157 (__u8 *)&smsg_out->path_name, W_MAX_PATH - 1);
0158
0159 smsg_out->copy_flags = smsg_in->copy_flags;
0160 smsg_out->file_size = smsg_in->file_size;
0161 out_src = smsg_out;
0162 break;
0163
0164 case WRITE_TO_FILE:
0165 out_src = fcopy_transaction.fcopy_msg;
0166 out_len = sizeof(struct hv_do_fcopy);
0167 break;
0168 default:
0169 out_src = fcopy_transaction.fcopy_msg;
0170 out_len = fcopy_transaction.recv_len;
0171 break;
0172 }
0173
0174 fcopy_transaction.state = HVUTIL_USERSPACE_REQ;
0175 rc = hvutil_transport_send(hvt, out_src, out_len, NULL);
0176 if (rc) {
0177 pr_debug("FCP: failed to communicate to the daemon: %d\n", rc);
0178 if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
0179 fcopy_respond_to_host(HV_E_FAIL);
0180 fcopy_transaction.state = HVUTIL_READY;
0181 }
0182 }
0183 kfree(smsg_out);
0184 }
0185
0186
0187
0188
0189
0190 static void
0191 fcopy_respond_to_host(int error)
0192 {
0193 struct icmsg_hdr *icmsghdr;
0194 u32 buf_len;
0195 struct vmbus_channel *channel;
0196 u64 req_id;
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 buf_len = fcopy_transaction.recv_len;
0207 channel = fcopy_transaction.recv_channel;
0208 req_id = fcopy_transaction.recv_req_id;
0209
0210 icmsghdr = (struct icmsg_hdr *)
0211 &recv_buffer[sizeof(struct vmbuspipe_hdr)];
0212
0213 if (channel->onchannel_callback == NULL)
0214
0215
0216
0217
0218 return;
0219
0220 icmsghdr->status = error;
0221 icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
0222 vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
0223 VM_PKT_DATA_INBAND, 0);
0224 }
0225
0226 void hv_fcopy_onchannelcallback(void *context)
0227 {
0228 struct vmbus_channel *channel = context;
0229 u32 recvlen;
0230 u64 requestid;
0231 struct hv_fcopy_hdr *fcopy_msg;
0232 struct icmsg_hdr *icmsghdr;
0233 int fcopy_srv_version;
0234
0235 if (fcopy_transaction.state > HVUTIL_READY)
0236 return;
0237
0238 if (vmbus_recvpacket(channel, recv_buffer, HV_HYP_PAGE_SIZE * 2, &recvlen, &requestid)) {
0239 pr_err_ratelimited("Fcopy request received. Could not read into recv buf\n");
0240 return;
0241 }
0242
0243 if (!recvlen)
0244 return;
0245
0246
0247 if (recvlen < ICMSG_HDR) {
0248 pr_err_ratelimited("Fcopy request received. Packet length too small: %d\n",
0249 recvlen);
0250 return;
0251 }
0252
0253 icmsghdr = (struct icmsg_hdr *)&recv_buffer[
0254 sizeof(struct vmbuspipe_hdr)];
0255
0256 if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) {
0257 if (vmbus_prep_negotiate_resp(icmsghdr,
0258 recv_buffer, recvlen,
0259 fw_versions, FW_VER_COUNT,
0260 fcopy_versions, FCOPY_VER_COUNT,
0261 NULL, &fcopy_srv_version)) {
0262
0263 pr_info("FCopy IC version %d.%d\n",
0264 fcopy_srv_version >> 16,
0265 fcopy_srv_version & 0xFFFF);
0266 }
0267 } else if (icmsghdr->icmsgtype == ICMSGTYPE_FCOPY) {
0268
0269 if (recvlen < ICMSG_HDR + sizeof(struct hv_fcopy_hdr)) {
0270 pr_err_ratelimited("Invalid Fcopy hdr. Packet length too small: %u\n",
0271 recvlen);
0272 return;
0273 }
0274 fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ICMSG_HDR];
0275
0276
0277
0278
0279
0280
0281 fcopy_transaction.recv_len = recvlen;
0282 fcopy_transaction.recv_req_id = requestid;
0283 fcopy_transaction.fcopy_msg = fcopy_msg;
0284
0285 if (fcopy_transaction.state < HVUTIL_READY) {
0286
0287 fcopy_respond_to_host(HV_E_FAIL);
0288 return;
0289 }
0290 fcopy_transaction.state = HVUTIL_HOSTMSG_RECEIVED;
0291
0292
0293
0294
0295 schedule_work(&fcopy_send_work);
0296 schedule_delayed_work(&fcopy_timeout_work,
0297 HV_UTIL_TIMEOUT * HZ);
0298 return;
0299 } else {
0300 pr_err_ratelimited("Fcopy request received. Invalid msg type: %d\n",
0301 icmsghdr->icmsgtype);
0302 return;
0303 }
0304 icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
0305 vmbus_sendpacket(channel, recv_buffer, recvlen, requestid,
0306 VM_PKT_DATA_INBAND, 0);
0307 }
0308
0309
0310 static int fcopy_on_msg(void *msg, int len)
0311 {
0312 int *val = (int *)msg;
0313
0314 if (len != sizeof(int))
0315 return -EINVAL;
0316
0317 if (fcopy_transaction.state == HVUTIL_DEVICE_INIT)
0318 return fcopy_handle_handshake(*val);
0319
0320 if (fcopy_transaction.state != HVUTIL_USERSPACE_REQ)
0321 return -EINVAL;
0322
0323
0324
0325
0326
0327 if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
0328 fcopy_transaction.state = HVUTIL_USERSPACE_RECV;
0329 fcopy_respond_to_host(*val);
0330 hv_poll_channel(fcopy_transaction.recv_channel,
0331 fcopy_poll_wrapper);
0332 }
0333
0334 return 0;
0335 }
0336
0337 static void fcopy_on_reset(void)
0338 {
0339
0340
0341
0342 fcopy_transaction.state = HVUTIL_DEVICE_INIT;
0343
0344 if (cancel_delayed_work_sync(&fcopy_timeout_work))
0345 fcopy_respond_to_host(HV_E_FAIL);
0346 }
0347
0348 int hv_fcopy_init(struct hv_util_service *srv)
0349 {
0350 recv_buffer = srv->recv_buffer;
0351 fcopy_transaction.recv_channel = srv->channel;
0352 fcopy_transaction.recv_channel->max_pkt_size = HV_HYP_PAGE_SIZE * 2;
0353
0354
0355
0356
0357
0358
0359
0360 fcopy_transaction.state = HVUTIL_DEVICE_INIT;
0361
0362 hvt = hvutil_transport_init(fcopy_devname, 0, 0,
0363 fcopy_on_msg, fcopy_on_reset);
0364 if (!hvt)
0365 return -EFAULT;
0366
0367 return 0;
0368 }
0369
0370 static void hv_fcopy_cancel_work(void)
0371 {
0372 cancel_delayed_work_sync(&fcopy_timeout_work);
0373 cancel_work_sync(&fcopy_send_work);
0374 }
0375
0376 int hv_fcopy_pre_suspend(void)
0377 {
0378 struct vmbus_channel *channel = fcopy_transaction.recv_channel;
0379 struct hv_fcopy_hdr *fcopy_msg;
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390 fcopy_msg = kzalloc(sizeof(*fcopy_msg), GFP_KERNEL);
0391 if (!fcopy_msg)
0392 return -ENOMEM;
0393
0394 tasklet_disable(&channel->callback_event);
0395
0396 fcopy_msg->operation = CANCEL_FCOPY;
0397
0398 hv_fcopy_cancel_work();
0399
0400
0401 hvutil_transport_send(hvt, fcopy_msg, sizeof(*fcopy_msg), NULL);
0402
0403 kfree(fcopy_msg);
0404
0405 fcopy_transaction.state = HVUTIL_READY;
0406
0407
0408 return 0;
0409 }
0410
0411 int hv_fcopy_pre_resume(void)
0412 {
0413 struct vmbus_channel *channel = fcopy_transaction.recv_channel;
0414
0415 tasklet_enable(&channel->callback_event);
0416
0417 return 0;
0418 }
0419
0420 void hv_fcopy_deinit(void)
0421 {
0422 fcopy_transaction.state = HVUTIL_DEVICE_DYING;
0423
0424 hv_fcopy_cancel_work();
0425
0426 hvutil_transport_destroy(hvt);
0427 }