101325476SK. Y. Srinivasan /* 201325476SK. Y. Srinivasan * An implementation of file copy service. 301325476SK. Y. Srinivasan * 401325476SK. Y. Srinivasan * Copyright (C) 2014, Microsoft, Inc. 501325476SK. Y. Srinivasan * 601325476SK. Y. Srinivasan * Author : K. Y. Srinivasan <ksrinivasan@novell.com> 701325476SK. Y. Srinivasan * 801325476SK. Y. Srinivasan * This program is free software; you can redistribute it and/or modify it 901325476SK. Y. Srinivasan * under the terms of the GNU General Public License version 2 as published 1001325476SK. Y. Srinivasan * by the Free Software Foundation. 1101325476SK. Y. Srinivasan * 1201325476SK. Y. Srinivasan * This program is distributed in the hope that it will be useful, but 1301325476SK. Y. Srinivasan * WITHOUT ANY WARRANTY; without even the implied warranty of 1401325476SK. Y. Srinivasan * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 1501325476SK. Y. Srinivasan * NON INFRINGEMENT. See the GNU General Public License for more 1601325476SK. Y. Srinivasan * details. 1701325476SK. Y. Srinivasan * 1801325476SK. Y. Srinivasan */ 1901325476SK. Y. Srinivasan 2001325476SK. Y. Srinivasan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2101325476SK. Y. Srinivasan 2201325476SK. Y. Srinivasan #include <linux/semaphore.h> 2301325476SK. Y. Srinivasan #include <linux/fs.h> 2401325476SK. Y. Srinivasan #include <linux/nls.h> 2501325476SK. Y. Srinivasan #include <linux/workqueue.h> 2601325476SK. Y. Srinivasan #include <linux/cdev.h> 2701325476SK. Y. Srinivasan #include <linux/hyperv.h> 2801325476SK. Y. Srinivasan #include <linux/sched.h> 2901325476SK. Y. Srinivasan #include <linux/uaccess.h> 3001325476SK. Y. Srinivasan #include <linux/miscdevice.h> 3101325476SK. Y. Srinivasan 3201325476SK. Y. Srinivasan #include "hyperv_vmbus.h" 3301325476SK. Y. Srinivasan 3401325476SK. Y. Srinivasan #define WIN8_SRV_MAJOR 1 3501325476SK. Y. Srinivasan #define WIN8_SRV_MINOR 1 3601325476SK. Y. Srinivasan #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) 3701325476SK. Y. Srinivasan 3801325476SK. Y. Srinivasan /* 3901325476SK. Y. Srinivasan * Global state maintained for transaction that is being processed. 4001325476SK. Y. Srinivasan * For a class of integration services, including the "file copy service", 4101325476SK. Y. Srinivasan * the specified protocol is a "request/response" protocol which means that 4201325476SK. Y. Srinivasan * there can only be single outstanding transaction from the host at any 4301325476SK. Y. Srinivasan * given point in time. We use this to simplify memory management in this 4401325476SK. Y. Srinivasan * driver - we cache and process only one message at a time. 4501325476SK. Y. Srinivasan * 4601325476SK. Y. Srinivasan * While the request/response protocol is guaranteed by the host, we further 4701325476SK. Y. Srinivasan * ensure this by serializing packet processing in this driver - we do not 4801325476SK. Y. Srinivasan * read additional packets from the VMBUs until the current packet is fully 4901325476SK. Y. Srinivasan * handled. 5001325476SK. Y. Srinivasan * 5101325476SK. Y. Srinivasan * The transaction "active" state is set when we receive a request from the 5201325476SK. Y. Srinivasan * host and we cleanup this state when the transaction is completed - when we 5301325476SK. Y. Srinivasan * respond to the host with our response. When the transaction active state is 5401325476SK. Y. Srinivasan * set, we defer handling incoming packets. 5501325476SK. Y. Srinivasan */ 5601325476SK. Y. Srinivasan 5701325476SK. Y. Srinivasan static struct { 5801325476SK. Y. Srinivasan bool active; /* transaction status - active or not */ 5901325476SK. Y. Srinivasan int recv_len; /* number of bytes received. */ 6001325476SK. Y. Srinivasan struct hv_fcopy_hdr *fcopy_msg; /* current message */ 6101325476SK. Y. Srinivasan struct hv_start_fcopy message; /* sent to daemon */ 6201325476SK. Y. Srinivasan struct vmbus_channel *recv_channel; /* chn we got the request */ 6301325476SK. Y. Srinivasan u64 recv_req_id; /* request ID. */ 6401325476SK. Y. Srinivasan void *fcopy_context; /* for the channel callback */ 6501325476SK. Y. Srinivasan struct semaphore read_sema; 6601325476SK. Y. Srinivasan } fcopy_transaction; 6701325476SK. Y. Srinivasan 6801325476SK. Y. Srinivasan static bool opened; /* currently device opened */ 6901325476SK. Y. Srinivasan 7001325476SK. Y. Srinivasan /* 7101325476SK. Y. Srinivasan * Before we can accept copy messages from the host, we need 7201325476SK. Y. Srinivasan * to handshake with the user level daemon. This state tracks 7301325476SK. Y. Srinivasan * if we are in the handshake phase. 7401325476SK. Y. Srinivasan */ 7501325476SK. Y. Srinivasan static bool in_hand_shake = true; 7601325476SK. Y. Srinivasan static void fcopy_send_data(void); 7701325476SK. Y. Srinivasan static void fcopy_respond_to_host(int error); 7801325476SK. Y. Srinivasan static void fcopy_work_func(struct work_struct *dummy); 7901325476SK. Y. Srinivasan static DECLARE_DELAYED_WORK(fcopy_work, fcopy_work_func); 8001325476SK. Y. Srinivasan static u8 *recv_buffer; 8101325476SK. Y. Srinivasan 8201325476SK. Y. Srinivasan static void fcopy_work_func(struct work_struct *dummy) 8301325476SK. Y. Srinivasan { 8401325476SK. Y. Srinivasan /* 8501325476SK. Y. Srinivasan * If the timer fires, the user-mode component has not responded; 8601325476SK. Y. Srinivasan * process the pending transaction. 8701325476SK. Y. Srinivasan */ 8801325476SK. Y. Srinivasan fcopy_respond_to_host(HV_E_FAIL); 8901325476SK. Y. Srinivasan } 9001325476SK. Y. Srinivasan 9101325476SK. Y. Srinivasan static int fcopy_handle_handshake(u32 version) 9201325476SK. Y. Srinivasan { 9301325476SK. Y. Srinivasan switch (version) { 9401325476SK. Y. Srinivasan case FCOPY_CURRENT_VERSION: 9501325476SK. Y. Srinivasan break; 9601325476SK. Y. Srinivasan default: 9701325476SK. Y. Srinivasan /* 9801325476SK. Y. Srinivasan * For now we will fail the registration. 9901325476SK. Y. Srinivasan * If and when we have multiple versions to 10001325476SK. Y. Srinivasan * deal with, we will be backward compatible. 10101325476SK. Y. Srinivasan * We will add this code when needed. 10201325476SK. Y. Srinivasan */ 10301325476SK. Y. Srinivasan return -EINVAL; 10401325476SK. Y. Srinivasan } 10501325476SK. Y. Srinivasan pr_info("FCP: user-mode registering done. Daemon version: %d\n", 10601325476SK. Y. Srinivasan version); 10701325476SK. Y. Srinivasan fcopy_transaction.active = false; 10801325476SK. Y. Srinivasan if (fcopy_transaction.fcopy_context) 10901325476SK. Y. Srinivasan hv_fcopy_onchannelcallback(fcopy_transaction.fcopy_context); 11001325476SK. Y. Srinivasan in_hand_shake = false; 11101325476SK. Y. Srinivasan return 0; 11201325476SK. Y. Srinivasan } 11301325476SK. Y. Srinivasan 11401325476SK. Y. Srinivasan static void fcopy_send_data(void) 11501325476SK. Y. Srinivasan { 11601325476SK. Y. Srinivasan struct hv_start_fcopy *smsg_out = &fcopy_transaction.message; 11701325476SK. Y. Srinivasan int operation = fcopy_transaction.fcopy_msg->operation; 11801325476SK. Y. Srinivasan struct hv_start_fcopy *smsg_in; 11901325476SK. Y. Srinivasan 12001325476SK. Y. Srinivasan /* 12101325476SK. Y. Srinivasan * The strings sent from the host are encoded in 12201325476SK. Y. Srinivasan * in utf16; convert it to utf8 strings. 12301325476SK. Y. Srinivasan * The host assures us that the utf16 strings will not exceed 12401325476SK. Y. Srinivasan * the max lengths specified. We will however, reserve room 12501325476SK. Y. Srinivasan * for the string terminating character - in the utf16s_utf8s() 12601325476SK. Y. Srinivasan * function we limit the size of the buffer where the converted 12701325476SK. Y. Srinivasan * string is placed to W_MAX_PATH -1 to guarantee 12801325476SK. Y. Srinivasan * that the strings can be properly terminated! 12901325476SK. Y. Srinivasan */ 13001325476SK. Y. Srinivasan 13101325476SK. Y. Srinivasan switch (operation) { 13201325476SK. Y. Srinivasan case START_FILE_COPY: 13301325476SK. Y. Srinivasan memset(smsg_out, 0, sizeof(struct hv_start_fcopy)); 13401325476SK. Y. Srinivasan smsg_out->hdr.operation = operation; 13501325476SK. Y. Srinivasan smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg; 13601325476SK. Y. Srinivasan 13701325476SK. Y. Srinivasan utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH, 13801325476SK. Y. Srinivasan UTF16_LITTLE_ENDIAN, 13901325476SK. Y. Srinivasan (__u8 *)smsg_out->file_name, W_MAX_PATH - 1); 14001325476SK. Y. Srinivasan 14101325476SK. Y. Srinivasan utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH, 14201325476SK. Y. Srinivasan UTF16_LITTLE_ENDIAN, 14301325476SK. Y. Srinivasan (__u8 *)smsg_out->path_name, W_MAX_PATH - 1); 14401325476SK. Y. Srinivasan 14501325476SK. Y. Srinivasan smsg_out->copy_flags = smsg_in->copy_flags; 14601325476SK. Y. Srinivasan smsg_out->file_size = smsg_in->file_size; 14701325476SK. Y. Srinivasan break; 14801325476SK. Y. Srinivasan 14901325476SK. Y. Srinivasan default: 15001325476SK. Y. Srinivasan break; 15101325476SK. Y. Srinivasan } 15201325476SK. Y. Srinivasan up(&fcopy_transaction.read_sema); 15301325476SK. Y. Srinivasan return; 15401325476SK. Y. Srinivasan } 15501325476SK. Y. Srinivasan 15601325476SK. Y. Srinivasan /* 15701325476SK. Y. Srinivasan * Send a response back to the host. 15801325476SK. Y. Srinivasan */ 15901325476SK. Y. Srinivasan 16001325476SK. Y. Srinivasan static void 16101325476SK. Y. Srinivasan fcopy_respond_to_host(int error) 16201325476SK. Y. Srinivasan { 16301325476SK. Y. Srinivasan struct icmsg_hdr *icmsghdr; 16401325476SK. Y. Srinivasan u32 buf_len; 16501325476SK. Y. Srinivasan struct vmbus_channel *channel; 16601325476SK. Y. Srinivasan u64 req_id; 16701325476SK. Y. Srinivasan 16801325476SK. Y. Srinivasan /* 16901325476SK. Y. Srinivasan * Copy the global state for completing the transaction. Note that 17001325476SK. Y. Srinivasan * only one transaction can be active at a time. This is guaranteed 17101325476SK. Y. Srinivasan * by the file copy protocol implemented by the host. Furthermore, 17201325476SK. Y. Srinivasan * the "transaction active" state we maintain ensures that there can 17301325476SK. Y. Srinivasan * only be one active transaction at a time. 17401325476SK. Y. Srinivasan */ 17501325476SK. Y. Srinivasan 17601325476SK. Y. Srinivasan buf_len = fcopy_transaction.recv_len; 17701325476SK. Y. Srinivasan channel = fcopy_transaction.recv_channel; 17801325476SK. Y. Srinivasan req_id = fcopy_transaction.recv_req_id; 17901325476SK. Y. Srinivasan 18001325476SK. Y. Srinivasan fcopy_transaction.active = false; 18101325476SK. Y. Srinivasan 18201325476SK. Y. Srinivasan icmsghdr = (struct icmsg_hdr *) 18301325476SK. Y. Srinivasan &recv_buffer[sizeof(struct vmbuspipe_hdr)]; 18401325476SK. Y. Srinivasan 18501325476SK. Y. Srinivasan if (channel->onchannel_callback == NULL) 18601325476SK. Y. Srinivasan /* 18701325476SK. Y. Srinivasan * We have raced with util driver being unloaded; 18801325476SK. Y. Srinivasan * silently return. 18901325476SK. Y. Srinivasan */ 19001325476SK. Y. Srinivasan return; 19101325476SK. Y. Srinivasan 19201325476SK. Y. Srinivasan icmsghdr->status = error; 19301325476SK. Y. Srinivasan icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 19401325476SK. Y. Srinivasan vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, 19501325476SK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 19601325476SK. Y. Srinivasan } 19701325476SK. Y. Srinivasan 19801325476SK. Y. Srinivasan void hv_fcopy_onchannelcallback(void *context) 19901325476SK. Y. Srinivasan { 20001325476SK. Y. Srinivasan struct vmbus_channel *channel = context; 20101325476SK. Y. Srinivasan u32 recvlen; 20201325476SK. Y. Srinivasan u64 requestid; 20301325476SK. Y. Srinivasan struct hv_fcopy_hdr *fcopy_msg; 20401325476SK. Y. Srinivasan struct icmsg_hdr *icmsghdr; 20501325476SK. Y. Srinivasan struct icmsg_negotiate *negop = NULL; 20601325476SK. Y. Srinivasan int util_fw_version; 20701325476SK. Y. Srinivasan int fcopy_srv_version; 20801325476SK. Y. Srinivasan 20901325476SK. Y. Srinivasan if (fcopy_transaction.active) { 21001325476SK. Y. Srinivasan /* 21101325476SK. Y. Srinivasan * We will defer processing this callback once 21201325476SK. Y. Srinivasan * the current transaction is complete. 21301325476SK. Y. Srinivasan */ 21401325476SK. Y. Srinivasan fcopy_transaction.fcopy_context = context; 21501325476SK. Y. Srinivasan return; 21601325476SK. Y. Srinivasan } 21701325476SK. Y. Srinivasan 21801325476SK. Y. Srinivasan vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, 21901325476SK. Y. Srinivasan &requestid); 22001325476SK. Y. Srinivasan if (recvlen <= 0) 22101325476SK. Y. Srinivasan return; 22201325476SK. Y. Srinivasan 22301325476SK. Y. Srinivasan icmsghdr = (struct icmsg_hdr *)&recv_buffer[ 22401325476SK. Y. Srinivasan sizeof(struct vmbuspipe_hdr)]; 22501325476SK. Y. Srinivasan if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) { 22601325476SK. Y. Srinivasan util_fw_version = UTIL_FW_VERSION; 22701325476SK. Y. Srinivasan fcopy_srv_version = WIN8_SRV_VERSION; 22801325476SK. Y. Srinivasan vmbus_prep_negotiate_resp(icmsghdr, negop, recv_buffer, 22901325476SK. Y. Srinivasan util_fw_version, fcopy_srv_version); 23001325476SK. Y. Srinivasan } else { 23101325476SK. Y. Srinivasan fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ 23201325476SK. Y. Srinivasan sizeof(struct vmbuspipe_hdr) + 23301325476SK. Y. Srinivasan sizeof(struct icmsg_hdr)]; 23401325476SK. Y. Srinivasan 23501325476SK. Y. Srinivasan /* 23601325476SK. Y. Srinivasan * Stash away this global state for completing the 23701325476SK. Y. Srinivasan * transaction; note transactions are serialized. 23801325476SK. Y. Srinivasan */ 23901325476SK. Y. Srinivasan 24001325476SK. Y. Srinivasan fcopy_transaction.active = true; 24101325476SK. Y. Srinivasan fcopy_transaction.recv_len = recvlen; 24201325476SK. Y. Srinivasan fcopy_transaction.recv_channel = channel; 24301325476SK. Y. Srinivasan fcopy_transaction.recv_req_id = requestid; 24401325476SK. Y. Srinivasan fcopy_transaction.fcopy_msg = fcopy_msg; 24501325476SK. Y. Srinivasan 24601325476SK. Y. Srinivasan /* 24701325476SK. Y. Srinivasan * Send the information to the user-level daemon. 24801325476SK. Y. Srinivasan */ 24901325476SK. Y. Srinivasan schedule_delayed_work(&fcopy_work, 5*HZ); 2502ef82d24SDexuan Cui fcopy_send_data(); 25101325476SK. Y. Srinivasan return; 25201325476SK. Y. Srinivasan } 25301325476SK. Y. Srinivasan icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; 25401325476SK. Y. Srinivasan vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, 25501325476SK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 25601325476SK. Y. Srinivasan } 25701325476SK. Y. Srinivasan 25801325476SK. Y. Srinivasan /* 25901325476SK. Y. Srinivasan * Create a char device that can support read/write for passing 26001325476SK. Y. Srinivasan * the payload. 26101325476SK. Y. Srinivasan */ 26201325476SK. Y. Srinivasan 26301325476SK. Y. Srinivasan static ssize_t fcopy_read(struct file *file, char __user *buf, 26401325476SK. Y. Srinivasan size_t count, loff_t *ppos) 26501325476SK. Y. Srinivasan { 26601325476SK. Y. Srinivasan void *src; 26701325476SK. Y. Srinivasan size_t copy_size; 26801325476SK. Y. Srinivasan int operation; 26901325476SK. Y. Srinivasan 27001325476SK. Y. Srinivasan /* 27101325476SK. Y. Srinivasan * Wait until there is something to be read. 27201325476SK. Y. Srinivasan */ 27301325476SK. Y. Srinivasan if (down_interruptible(&fcopy_transaction.read_sema)) 27401325476SK. Y. Srinivasan return -EINTR; 27501325476SK. Y. Srinivasan 27601325476SK. Y. Srinivasan /* 27701325476SK. Y. Srinivasan * The channel may be rescinded and in this case, we will wakeup the 27801325476SK. Y. Srinivasan * the thread blocked on the semaphore and we will use the opened 27901325476SK. Y. Srinivasan * state to correctly handle this case. 28001325476SK. Y. Srinivasan */ 28101325476SK. Y. Srinivasan if (!opened) 28201325476SK. Y. Srinivasan return -ENODEV; 28301325476SK. Y. Srinivasan 28401325476SK. Y. Srinivasan operation = fcopy_transaction.fcopy_msg->operation; 28501325476SK. Y. Srinivasan 28601325476SK. Y. Srinivasan if (operation == START_FILE_COPY) { 28701325476SK. Y. Srinivasan src = &fcopy_transaction.message; 28801325476SK. Y. Srinivasan copy_size = sizeof(struct hv_start_fcopy); 28901325476SK. Y. Srinivasan if (count < copy_size) 29001325476SK. Y. Srinivasan return 0; 29101325476SK. Y. Srinivasan } else { 29201325476SK. Y. Srinivasan src = fcopy_transaction.fcopy_msg; 29301325476SK. Y. Srinivasan copy_size = sizeof(struct hv_do_fcopy); 29401325476SK. Y. Srinivasan if (count < copy_size) 29501325476SK. Y. Srinivasan return 0; 29601325476SK. Y. Srinivasan } 29701325476SK. Y. Srinivasan if (copy_to_user(buf, src, copy_size)) 29801325476SK. Y. Srinivasan return -EFAULT; 29901325476SK. Y. Srinivasan 30001325476SK. Y. Srinivasan return copy_size; 30101325476SK. Y. Srinivasan } 30201325476SK. Y. Srinivasan 30301325476SK. Y. Srinivasan static ssize_t fcopy_write(struct file *file, const char __user *buf, 30401325476SK. Y. Srinivasan size_t count, loff_t *ppos) 30501325476SK. Y. Srinivasan { 30601325476SK. Y. Srinivasan int response = 0; 30701325476SK. Y. Srinivasan 30801325476SK. Y. Srinivasan if (count != sizeof(int)) 30901325476SK. Y. Srinivasan return -EINVAL; 31001325476SK. Y. Srinivasan 31101325476SK. Y. Srinivasan if (copy_from_user(&response, buf, sizeof(int))) 31201325476SK. Y. Srinivasan return -EFAULT; 31301325476SK. Y. Srinivasan 31401325476SK. Y. Srinivasan if (in_hand_shake) { 31501325476SK. Y. Srinivasan if (fcopy_handle_handshake(response)) 31601325476SK. Y. Srinivasan return -EINVAL; 31701325476SK. Y. Srinivasan return sizeof(int); 31801325476SK. Y. Srinivasan } 31901325476SK. Y. Srinivasan 32001325476SK. Y. Srinivasan /* 32101325476SK. Y. Srinivasan * Complete the transaction by forwarding the result 32201325476SK. Y. Srinivasan * to the host. But first, cancel the timeout. 32301325476SK. Y. Srinivasan */ 32401325476SK. Y. Srinivasan if (cancel_delayed_work_sync(&fcopy_work)) 32501325476SK. Y. Srinivasan fcopy_respond_to_host(response); 32601325476SK. Y. Srinivasan 32701325476SK. Y. Srinivasan return sizeof(int); 32801325476SK. Y. Srinivasan } 32901325476SK. Y. Srinivasan 330c765a6dfSFengguang Wu static int fcopy_open(struct inode *inode, struct file *f) 33101325476SK. Y. Srinivasan { 33201325476SK. Y. Srinivasan /* 33301325476SK. Y. Srinivasan * The user level daemon that will open this device is 33401325476SK. Y. Srinivasan * really an extension of this driver. We can have only 33501325476SK. Y. Srinivasan * active open at a time. 33601325476SK. Y. Srinivasan */ 33701325476SK. Y. Srinivasan if (opened) 33801325476SK. Y. Srinivasan return -EBUSY; 33901325476SK. Y. Srinivasan 34001325476SK. Y. Srinivasan /* 34101325476SK. Y. Srinivasan * The daemon is alive; setup the state. 34201325476SK. Y. Srinivasan */ 34301325476SK. Y. Srinivasan opened = true; 34401325476SK. Y. Srinivasan return 0; 34501325476SK. Y. Srinivasan } 34601325476SK. Y. Srinivasan 347c765a6dfSFengguang Wu static int fcopy_release(struct inode *inode, struct file *f) 34801325476SK. Y. Srinivasan { 34901325476SK. Y. Srinivasan /* 35001325476SK. Y. Srinivasan * The daemon has exited; reset the state. 35101325476SK. Y. Srinivasan */ 35201325476SK. Y. Srinivasan in_hand_shake = true; 35301325476SK. Y. Srinivasan opened = false; 35401325476SK. Y. Srinivasan return 0; 35501325476SK. Y. Srinivasan } 35601325476SK. Y. Srinivasan 35701325476SK. Y. Srinivasan 35801325476SK. Y. Srinivasan static const struct file_operations fcopy_fops = { 35901325476SK. Y. Srinivasan .read = fcopy_read, 36001325476SK. Y. Srinivasan .write = fcopy_write, 36101325476SK. Y. Srinivasan .release = fcopy_release, 36201325476SK. Y. Srinivasan .open = fcopy_open, 36301325476SK. Y. Srinivasan }; 36401325476SK. Y. Srinivasan 36501325476SK. Y. Srinivasan static struct miscdevice fcopy_misc = { 36601325476SK. Y. Srinivasan .minor = MISC_DYNAMIC_MINOR, 36701325476SK. Y. Srinivasan .name = "vmbus/hv_fcopy", 36801325476SK. Y. Srinivasan .fops = &fcopy_fops, 36901325476SK. Y. Srinivasan }; 37001325476SK. Y. Srinivasan 37101325476SK. Y. Srinivasan static int fcopy_dev_init(void) 37201325476SK. Y. Srinivasan { 37301325476SK. Y. Srinivasan return misc_register(&fcopy_misc); 37401325476SK. Y. Srinivasan } 37501325476SK. Y. Srinivasan 37601325476SK. Y. Srinivasan static void fcopy_dev_deinit(void) 37701325476SK. Y. Srinivasan { 37801325476SK. Y. Srinivasan 37901325476SK. Y. Srinivasan /* 38001325476SK. Y. Srinivasan * The device is going away - perhaps because the 38101325476SK. Y. Srinivasan * host has rescinded the channel. Setup state so that 38201325476SK. Y. Srinivasan * user level daemon can gracefully exit if it is blocked 38301325476SK. Y. Srinivasan * on the read semaphore. 38401325476SK. Y. Srinivasan */ 38501325476SK. Y. Srinivasan opened = false; 38601325476SK. Y. Srinivasan /* 38701325476SK. Y. Srinivasan * Signal the semaphore as the device is 38801325476SK. Y. Srinivasan * going away. 38901325476SK. Y. Srinivasan */ 39001325476SK. Y. Srinivasan up(&fcopy_transaction.read_sema); 39101325476SK. Y. Srinivasan misc_deregister(&fcopy_misc); 39201325476SK. Y. Srinivasan } 39301325476SK. Y. Srinivasan 39401325476SK. Y. Srinivasan int hv_fcopy_init(struct hv_util_service *srv) 39501325476SK. Y. Srinivasan { 39601325476SK. Y. Srinivasan recv_buffer = srv->recv_buffer; 39701325476SK. Y. Srinivasan 39801325476SK. Y. Srinivasan /* 39901325476SK. Y. Srinivasan * When this driver loads, the user level daemon that 40001325476SK. Y. Srinivasan * processes the host requests may not yet be running. 40101325476SK. Y. Srinivasan * Defer processing channel callbacks until the daemon 40201325476SK. Y. Srinivasan * has registered. 40301325476SK. Y. Srinivasan */ 40401325476SK. Y. Srinivasan fcopy_transaction.active = true; 40501325476SK. Y. Srinivasan sema_init(&fcopy_transaction.read_sema, 0); 40601325476SK. Y. Srinivasan 40701325476SK. Y. Srinivasan return fcopy_dev_init(); 40801325476SK. Y. Srinivasan } 40901325476SK. Y. Srinivasan 41001325476SK. Y. Srinivasan void hv_fcopy_deinit(void) 41101325476SK. Y. Srinivasan { 41201325476SK. Y. Srinivasan cancel_delayed_work_sync(&fcopy_work); 41301325476SK. Y. Srinivasan fcopy_dev_deinit(); 41401325476SK. Y. Srinivasan } 415