0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/module.h>
0014 #include <linux/slab.h>
0015 #include <linux/sysctl.h>
0016 #include <linux/reboot.h>
0017 #include <linux/hyperv.h>
0018 #include <linux/clockchips.h>
0019 #include <linux/ptp_clock_kernel.h>
0020 #include <asm/mshyperv.h>
0021
0022 #include "hyperv_vmbus.h"
0023
0024 #define SD_MAJOR 3
0025 #define SD_MINOR 0
0026 #define SD_MINOR_1 1
0027 #define SD_MINOR_2 2
0028 #define SD_VERSION_3_1 (SD_MAJOR << 16 | SD_MINOR_1)
0029 #define SD_VERSION_3_2 (SD_MAJOR << 16 | SD_MINOR_2)
0030 #define SD_VERSION (SD_MAJOR << 16 | SD_MINOR)
0031
0032 #define SD_MAJOR_1 1
0033 #define SD_VERSION_1 (SD_MAJOR_1 << 16 | SD_MINOR)
0034
0035 #define TS_MAJOR 4
0036 #define TS_MINOR 0
0037 #define TS_VERSION (TS_MAJOR << 16 | TS_MINOR)
0038
0039 #define TS_MAJOR_1 1
0040 #define TS_VERSION_1 (TS_MAJOR_1 << 16 | TS_MINOR)
0041
0042 #define TS_MAJOR_3 3
0043 #define TS_VERSION_3 (TS_MAJOR_3 << 16 | TS_MINOR)
0044
0045 #define HB_MAJOR 3
0046 #define HB_MINOR 0
0047 #define HB_VERSION (HB_MAJOR << 16 | HB_MINOR)
0048
0049 #define HB_MAJOR_1 1
0050 #define HB_VERSION_1 (HB_MAJOR_1 << 16 | HB_MINOR)
0051
0052 static int sd_srv_version;
0053 static int ts_srv_version;
0054 static int hb_srv_version;
0055
0056 #define SD_VER_COUNT 4
0057 static const int sd_versions[] = {
0058 SD_VERSION_3_2,
0059 SD_VERSION_3_1,
0060 SD_VERSION,
0061 SD_VERSION_1
0062 };
0063
0064 #define TS_VER_COUNT 3
0065 static const int ts_versions[] = {
0066 TS_VERSION,
0067 TS_VERSION_3,
0068 TS_VERSION_1
0069 };
0070
0071 #define HB_VER_COUNT 2
0072 static const int hb_versions[] = {
0073 HB_VERSION,
0074 HB_VERSION_1
0075 };
0076
0077 #define FW_VER_COUNT 2
0078 static const int fw_versions[] = {
0079 UTIL_FW_VERSION,
0080 UTIL_WS2K8_FW_VERSION
0081 };
0082
0083
0084
0085
0086 struct hibernate_work_context {
0087 struct work_struct work;
0088 struct hv_device *dev;
0089 };
0090
0091 static struct hibernate_work_context hibernate_context;
0092 static bool hibernation_supported;
0093
0094 static void send_hibernate_uevent(struct work_struct *work)
0095 {
0096 char *uevent_env[2] = { "EVENT=hibernate", NULL };
0097 struct hibernate_work_context *ctx;
0098
0099 ctx = container_of(work, struct hibernate_work_context, work);
0100
0101 kobject_uevent_env(&ctx->dev->device.kobj, KOBJ_CHANGE, uevent_env);
0102
0103 pr_info("Sent hibernation uevent\n");
0104 }
0105
0106 static int hv_shutdown_init(struct hv_util_service *srv)
0107 {
0108 struct vmbus_channel *channel = srv->channel;
0109
0110 INIT_WORK(&hibernate_context.work, send_hibernate_uevent);
0111 hibernate_context.dev = channel->device_obj;
0112
0113 hibernation_supported = hv_is_hibernation_supported();
0114
0115 return 0;
0116 }
0117
0118 static void shutdown_onchannelcallback(void *context);
0119 static struct hv_util_service util_shutdown = {
0120 .util_cb = shutdown_onchannelcallback,
0121 .util_init = hv_shutdown_init,
0122 };
0123
0124 static int hv_timesync_init(struct hv_util_service *srv);
0125 static int hv_timesync_pre_suspend(void);
0126 static void hv_timesync_deinit(void);
0127
0128 static void timesync_onchannelcallback(void *context);
0129 static struct hv_util_service util_timesynch = {
0130 .util_cb = timesync_onchannelcallback,
0131 .util_init = hv_timesync_init,
0132 .util_pre_suspend = hv_timesync_pre_suspend,
0133 .util_deinit = hv_timesync_deinit,
0134 };
0135
0136 static void heartbeat_onchannelcallback(void *context);
0137 static struct hv_util_service util_heartbeat = {
0138 .util_cb = heartbeat_onchannelcallback,
0139 };
0140
0141 static struct hv_util_service util_kvp = {
0142 .util_cb = hv_kvp_onchannelcallback,
0143 .util_init = hv_kvp_init,
0144 .util_pre_suspend = hv_kvp_pre_suspend,
0145 .util_pre_resume = hv_kvp_pre_resume,
0146 .util_deinit = hv_kvp_deinit,
0147 };
0148
0149 static struct hv_util_service util_vss = {
0150 .util_cb = hv_vss_onchannelcallback,
0151 .util_init = hv_vss_init,
0152 .util_pre_suspend = hv_vss_pre_suspend,
0153 .util_pre_resume = hv_vss_pre_resume,
0154 .util_deinit = hv_vss_deinit,
0155 };
0156
0157 static struct hv_util_service util_fcopy = {
0158 .util_cb = hv_fcopy_onchannelcallback,
0159 .util_init = hv_fcopy_init,
0160 .util_pre_suspend = hv_fcopy_pre_suspend,
0161 .util_pre_resume = hv_fcopy_pre_resume,
0162 .util_deinit = hv_fcopy_deinit,
0163 };
0164
0165 static void perform_shutdown(struct work_struct *dummy)
0166 {
0167 orderly_poweroff(true);
0168 }
0169
0170 static void perform_restart(struct work_struct *dummy)
0171 {
0172 orderly_reboot();
0173 }
0174
0175
0176
0177
0178 static DECLARE_WORK(shutdown_work, perform_shutdown);
0179
0180
0181
0182
0183 static DECLARE_WORK(restart_work, perform_restart);
0184
0185 static void shutdown_onchannelcallback(void *context)
0186 {
0187 struct vmbus_channel *channel = context;
0188 struct work_struct *work = NULL;
0189 u32 recvlen;
0190 u64 requestid;
0191 u8 *shut_txf_buf = util_shutdown.recv_buffer;
0192
0193 struct shutdown_msg_data *shutdown_msg;
0194
0195 struct icmsg_hdr *icmsghdrp;
0196
0197 if (vmbus_recvpacket(channel, shut_txf_buf, HV_HYP_PAGE_SIZE, &recvlen, &requestid)) {
0198 pr_err_ratelimited("Shutdown request received. Could not read into shut txf buf\n");
0199 return;
0200 }
0201
0202 if (!recvlen)
0203 return;
0204
0205
0206 if (recvlen < ICMSG_HDR) {
0207 pr_err_ratelimited("Shutdown request received. Packet length too small: %d\n",
0208 recvlen);
0209 return;
0210 }
0211
0212 icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[sizeof(struct vmbuspipe_hdr)];
0213
0214 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
0215 if (vmbus_prep_negotiate_resp(icmsghdrp,
0216 shut_txf_buf, recvlen,
0217 fw_versions, FW_VER_COUNT,
0218 sd_versions, SD_VER_COUNT,
0219 NULL, &sd_srv_version)) {
0220 pr_info("Shutdown IC version %d.%d\n",
0221 sd_srv_version >> 16,
0222 sd_srv_version & 0xFFFF);
0223 }
0224 } else if (icmsghdrp->icmsgtype == ICMSGTYPE_SHUTDOWN) {
0225
0226 if (recvlen < ICMSG_HDR + sizeof(struct shutdown_msg_data)) {
0227 pr_err_ratelimited("Invalid shutdown msg data. Packet length too small: %u\n",
0228 recvlen);
0229 return;
0230 }
0231
0232 shutdown_msg = (struct shutdown_msg_data *)&shut_txf_buf[ICMSG_HDR];
0233
0234
0235
0236
0237
0238
0239
0240 switch (shutdown_msg->flags) {
0241 case 0:
0242 case 1:
0243 icmsghdrp->status = HV_S_OK;
0244 work = &shutdown_work;
0245 pr_info("Shutdown request received - graceful shutdown initiated\n");
0246 break;
0247 case 2:
0248 case 3:
0249 icmsghdrp->status = HV_S_OK;
0250 work = &restart_work;
0251 pr_info("Restart request received - graceful restart initiated\n");
0252 break;
0253 case 4:
0254 case 5:
0255 pr_info("Hibernation request received\n");
0256 icmsghdrp->status = hibernation_supported ?
0257 HV_S_OK : HV_E_FAIL;
0258 if (hibernation_supported)
0259 work = &hibernate_context.work;
0260 break;
0261 default:
0262 icmsghdrp->status = HV_E_FAIL;
0263 pr_info("Shutdown request received - Invalid request\n");
0264 break;
0265 }
0266 } else {
0267 icmsghdrp->status = HV_E_FAIL;
0268 pr_err_ratelimited("Shutdown request received. Invalid msg type: %d\n",
0269 icmsghdrp->icmsgtype);
0270 }
0271
0272 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
0273 | ICMSGHDRFLAG_RESPONSE;
0274
0275 vmbus_sendpacket(channel, shut_txf_buf,
0276 recvlen, requestid,
0277 VM_PKT_DATA_INBAND, 0);
0278
0279 if (work)
0280 schedule_work(work);
0281 }
0282
0283
0284
0285
0286 static struct work_struct adj_time_work;
0287
0288
0289
0290
0291
0292
0293 static struct {
0294 u64 host_time;
0295 u64 ref_time;
0296 spinlock_t lock;
0297 } host_ts;
0298
0299 static inline u64 reftime_to_ns(u64 reftime)
0300 {
0301 return (reftime - WLTIMEDELTA) * 100;
0302 }
0303
0304
0305
0306
0307 static const u64 HOST_TIMESYNC_DELAY_THRESH = 600 * (u64)NSEC_PER_SEC;
0308
0309 static int hv_get_adj_host_time(struct timespec64 *ts)
0310 {
0311 u64 newtime, reftime, timediff_adj;
0312 unsigned long flags;
0313 int ret = 0;
0314
0315 spin_lock_irqsave(&host_ts.lock, flags);
0316 reftime = hv_read_reference_counter();
0317
0318
0319
0320
0321
0322
0323
0324 timediff_adj = reftime - host_ts.ref_time;
0325 if (timediff_adj * 100 > HOST_TIMESYNC_DELAY_THRESH) {
0326 pr_warn_once("TIMESYNC IC: Stale time stamp, %llu nsecs old\n",
0327 (timediff_adj * 100));
0328 ret = -ESTALE;
0329 }
0330
0331 newtime = host_ts.host_time + timediff_adj;
0332 *ts = ns_to_timespec64(reftime_to_ns(newtime));
0333 spin_unlock_irqrestore(&host_ts.lock, flags);
0334
0335 return ret;
0336 }
0337
0338 static void hv_set_host_time(struct work_struct *work)
0339 {
0340
0341 struct timespec64 ts;
0342
0343 if (!hv_get_adj_host_time(&ts))
0344 do_settimeofday64(&ts);
0345 }
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360 static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags)
0361 {
0362 unsigned long flags;
0363 u64 cur_reftime;
0364
0365
0366
0367
0368
0369 spin_lock_irqsave(&host_ts.lock, flags);
0370
0371 cur_reftime = hv_read_reference_counter();
0372 host_ts.host_time = hosttime;
0373 host_ts.ref_time = cur_reftime;
0374
0375
0376
0377
0378
0379
0380
0381
0382 host_ts.host_time += (cur_reftime - reftime);
0383
0384 spin_unlock_irqrestore(&host_ts.lock, flags);
0385
0386
0387 if (adj_flags & ICTIMESYNCFLAG_SYNC)
0388 schedule_work(&adj_time_work);
0389 }
0390
0391
0392
0393
0394 static void timesync_onchannelcallback(void *context)
0395 {
0396 struct vmbus_channel *channel = context;
0397 u32 recvlen;
0398 u64 requestid;
0399 struct icmsg_hdr *icmsghdrp;
0400 struct ictimesync_data *timedatap;
0401 struct ictimesync_ref_data *refdata;
0402 u8 *time_txf_buf = util_timesynch.recv_buffer;
0403
0404
0405
0406
0407
0408 while (1) {
0409 int ret = vmbus_recvpacket(channel, time_txf_buf,
0410 HV_HYP_PAGE_SIZE, &recvlen,
0411 &requestid);
0412 if (ret) {
0413 pr_err_ratelimited("TimeSync IC pkt recv failed (Err: %d)\n",
0414 ret);
0415 break;
0416 }
0417
0418 if (!recvlen)
0419 break;
0420
0421
0422 if (recvlen < ICMSG_HDR) {
0423 pr_err_ratelimited("Timesync request received. Packet length too small: %d\n",
0424 recvlen);
0425 break;
0426 }
0427
0428 icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
0429 sizeof(struct vmbuspipe_hdr)];
0430
0431 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
0432 if (vmbus_prep_negotiate_resp(icmsghdrp,
0433 time_txf_buf, recvlen,
0434 fw_versions, FW_VER_COUNT,
0435 ts_versions, TS_VER_COUNT,
0436 NULL, &ts_srv_version)) {
0437 pr_info("TimeSync IC version %d.%d\n",
0438 ts_srv_version >> 16,
0439 ts_srv_version & 0xFFFF);
0440 }
0441 } else if (icmsghdrp->icmsgtype == ICMSGTYPE_TIMESYNC) {
0442 if (ts_srv_version > TS_VERSION_3) {
0443
0444 if (recvlen < ICMSG_HDR + sizeof(struct ictimesync_ref_data)) {
0445 pr_err_ratelimited("Invalid ictimesync ref data. Length too small: %u\n",
0446 recvlen);
0447 break;
0448 }
0449 refdata = (struct ictimesync_ref_data *)&time_txf_buf[ICMSG_HDR];
0450
0451 adj_guesttime(refdata->parenttime,
0452 refdata->vmreferencetime,
0453 refdata->flags);
0454 } else {
0455
0456 if (recvlen < ICMSG_HDR + sizeof(struct ictimesync_data)) {
0457 pr_err_ratelimited("Invalid ictimesync data. Length too small: %u\n",
0458 recvlen);
0459 break;
0460 }
0461 timedatap = (struct ictimesync_data *)&time_txf_buf[ICMSG_HDR];
0462
0463 adj_guesttime(timedatap->parenttime,
0464 hv_read_reference_counter(),
0465 timedatap->flags);
0466 }
0467 } else {
0468 icmsghdrp->status = HV_E_FAIL;
0469 pr_err_ratelimited("Timesync request received. Invalid msg type: %d\n",
0470 icmsghdrp->icmsgtype);
0471 }
0472
0473 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
0474 | ICMSGHDRFLAG_RESPONSE;
0475
0476 vmbus_sendpacket(channel, time_txf_buf,
0477 recvlen, requestid,
0478 VM_PKT_DATA_INBAND, 0);
0479 }
0480 }
0481
0482
0483
0484
0485
0486
0487 static void heartbeat_onchannelcallback(void *context)
0488 {
0489 struct vmbus_channel *channel = context;
0490 u32 recvlen;
0491 u64 requestid;
0492 struct icmsg_hdr *icmsghdrp;
0493 struct heartbeat_msg_data *heartbeat_msg;
0494 u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
0495
0496 while (1) {
0497
0498 if (vmbus_recvpacket(channel, hbeat_txf_buf, HV_HYP_PAGE_SIZE,
0499 &recvlen, &requestid)) {
0500 pr_err_ratelimited("Heartbeat request received. Could not read into hbeat txf buf\n");
0501 return;
0502 }
0503
0504 if (!recvlen)
0505 break;
0506
0507
0508 if (recvlen < ICMSG_HDR) {
0509 pr_err_ratelimited("Heartbeat request received. Packet length too small: %d\n",
0510 recvlen);
0511 break;
0512 }
0513
0514 icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
0515 sizeof(struct vmbuspipe_hdr)];
0516
0517 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
0518 if (vmbus_prep_negotiate_resp(icmsghdrp,
0519 hbeat_txf_buf, recvlen,
0520 fw_versions, FW_VER_COUNT,
0521 hb_versions, HB_VER_COUNT,
0522 NULL, &hb_srv_version)) {
0523
0524 pr_info("Heartbeat IC version %d.%d\n",
0525 hb_srv_version >> 16,
0526 hb_srv_version & 0xFFFF);
0527 }
0528 } else if (icmsghdrp->icmsgtype == ICMSGTYPE_HEARTBEAT) {
0529
0530
0531
0532
0533 if (recvlen < ICMSG_HDR + sizeof(u64)) {
0534 pr_err_ratelimited("Invalid heartbeat msg data. Length too small: %u\n",
0535 recvlen);
0536 break;
0537 }
0538 heartbeat_msg = (struct heartbeat_msg_data *)&hbeat_txf_buf[ICMSG_HDR];
0539
0540 heartbeat_msg->seq_num += 1;
0541 } else {
0542 icmsghdrp->status = HV_E_FAIL;
0543 pr_err_ratelimited("Heartbeat request received. Invalid msg type: %d\n",
0544 icmsghdrp->icmsgtype);
0545 }
0546
0547 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
0548 | ICMSGHDRFLAG_RESPONSE;
0549
0550 vmbus_sendpacket(channel, hbeat_txf_buf,
0551 recvlen, requestid,
0552 VM_PKT_DATA_INBAND, 0);
0553 }
0554 }
0555
0556 #define HV_UTIL_RING_SEND_SIZE VMBUS_RING_SIZE(3 * HV_HYP_PAGE_SIZE)
0557 #define HV_UTIL_RING_RECV_SIZE VMBUS_RING_SIZE(3 * HV_HYP_PAGE_SIZE)
0558
0559 static int util_probe(struct hv_device *dev,
0560 const struct hv_vmbus_device_id *dev_id)
0561 {
0562 struct hv_util_service *srv =
0563 (struct hv_util_service *)dev_id->driver_data;
0564 int ret;
0565
0566 srv->recv_buffer = kmalloc(HV_HYP_PAGE_SIZE * 4, GFP_KERNEL);
0567 if (!srv->recv_buffer)
0568 return -ENOMEM;
0569 srv->channel = dev->channel;
0570 if (srv->util_init) {
0571 ret = srv->util_init(srv);
0572 if (ret) {
0573 ret = -ENODEV;
0574 goto error1;
0575 }
0576 }
0577
0578
0579
0580
0581
0582
0583
0584
0585 set_channel_read_mode(dev->channel, HV_CALL_DIRECT);
0586
0587 hv_set_drvdata(dev, srv);
0588
0589 ret = vmbus_open(dev->channel, HV_UTIL_RING_SEND_SIZE,
0590 HV_UTIL_RING_RECV_SIZE, NULL, 0, srv->util_cb,
0591 dev->channel);
0592 if (ret)
0593 goto error;
0594
0595 return 0;
0596
0597 error:
0598 if (srv->util_deinit)
0599 srv->util_deinit();
0600 error1:
0601 kfree(srv->recv_buffer);
0602 return ret;
0603 }
0604
0605 static int util_remove(struct hv_device *dev)
0606 {
0607 struct hv_util_service *srv = hv_get_drvdata(dev);
0608
0609 if (srv->util_deinit)
0610 srv->util_deinit();
0611 vmbus_close(dev->channel);
0612 kfree(srv->recv_buffer);
0613
0614 return 0;
0615 }
0616
0617
0618
0619
0620
0621
0622 static int util_suspend(struct hv_device *dev)
0623 {
0624 struct hv_util_service *srv = hv_get_drvdata(dev);
0625 int ret = 0;
0626
0627 if (srv->util_pre_suspend) {
0628 ret = srv->util_pre_suspend();
0629 if (ret)
0630 return ret;
0631 }
0632
0633 vmbus_close(dev->channel);
0634
0635 return 0;
0636 }
0637
0638 static int util_resume(struct hv_device *dev)
0639 {
0640 struct hv_util_service *srv = hv_get_drvdata(dev);
0641 int ret = 0;
0642
0643 if (srv->util_pre_resume) {
0644 ret = srv->util_pre_resume();
0645 if (ret)
0646 return ret;
0647 }
0648
0649 ret = vmbus_open(dev->channel, HV_UTIL_RING_SEND_SIZE,
0650 HV_UTIL_RING_RECV_SIZE, NULL, 0, srv->util_cb,
0651 dev->channel);
0652 return ret;
0653 }
0654
0655 static const struct hv_vmbus_device_id id_table[] = {
0656
0657 { HV_SHUTDOWN_GUID,
0658 .driver_data = (unsigned long)&util_shutdown
0659 },
0660
0661 { HV_TS_GUID,
0662 .driver_data = (unsigned long)&util_timesynch
0663 },
0664
0665 { HV_HEART_BEAT_GUID,
0666 .driver_data = (unsigned long)&util_heartbeat
0667 },
0668
0669 { HV_KVP_GUID,
0670 .driver_data = (unsigned long)&util_kvp
0671 },
0672
0673 { HV_VSS_GUID,
0674 .driver_data = (unsigned long)&util_vss
0675 },
0676
0677 { HV_FCOPY_GUID,
0678 .driver_data = (unsigned long)&util_fcopy
0679 },
0680 { },
0681 };
0682
0683 MODULE_DEVICE_TABLE(vmbus, id_table);
0684
0685
0686 static struct hv_driver util_drv = {
0687 .name = "hv_utils",
0688 .id_table = id_table,
0689 .probe = util_probe,
0690 .remove = util_remove,
0691 .suspend = util_suspend,
0692 .resume = util_resume,
0693 .driver = {
0694 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0695 },
0696 };
0697
0698 static int hv_ptp_enable(struct ptp_clock_info *info,
0699 struct ptp_clock_request *request, int on)
0700 {
0701 return -EOPNOTSUPP;
0702 }
0703
0704 static int hv_ptp_settime(struct ptp_clock_info *p, const struct timespec64 *ts)
0705 {
0706 return -EOPNOTSUPP;
0707 }
0708
0709 static int hv_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
0710 {
0711 return -EOPNOTSUPP;
0712 }
0713 static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
0714 {
0715 return -EOPNOTSUPP;
0716 }
0717
0718 static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
0719 {
0720 return hv_get_adj_host_time(ts);
0721 }
0722
0723 static struct ptp_clock_info ptp_hyperv_info = {
0724 .name = "hyperv",
0725 .enable = hv_ptp_enable,
0726 .adjtime = hv_ptp_adjtime,
0727 .adjfreq = hv_ptp_adjfreq,
0728 .gettime64 = hv_ptp_gettime,
0729 .settime64 = hv_ptp_settime,
0730 .owner = THIS_MODULE,
0731 };
0732
0733 static struct ptp_clock *hv_ptp_clock;
0734
0735 static int hv_timesync_init(struct hv_util_service *srv)
0736 {
0737 spin_lock_init(&host_ts.lock);
0738
0739 INIT_WORK(&adj_time_work, hv_set_host_time);
0740
0741
0742
0743
0744
0745
0746 hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
0747 if (IS_ERR_OR_NULL(hv_ptp_clock)) {
0748 pr_err("cannot register PTP clock: %d\n",
0749 PTR_ERR_OR_ZERO(hv_ptp_clock));
0750 hv_ptp_clock = NULL;
0751 }
0752
0753 return 0;
0754 }
0755
0756 static void hv_timesync_cancel_work(void)
0757 {
0758 cancel_work_sync(&adj_time_work);
0759 }
0760
0761 static int hv_timesync_pre_suspend(void)
0762 {
0763 hv_timesync_cancel_work();
0764 return 0;
0765 }
0766
0767 static void hv_timesync_deinit(void)
0768 {
0769 if (hv_ptp_clock)
0770 ptp_clock_unregister(hv_ptp_clock);
0771
0772 hv_timesync_cancel_work();
0773 }
0774
0775 static int __init init_hyperv_utils(void)
0776 {
0777 pr_info("Registering HyperV Utility Driver\n");
0778
0779 return vmbus_driver_register(&util_drv);
0780 }
0781
0782 static void exit_hyperv_utils(void)
0783 {
0784 pr_info("De-Registered HyperV Utility Driver\n");
0785
0786 vmbus_driver_unregister(&util_drv);
0787 }
0788
0789 module_init(init_hyperv_utils);
0790 module_exit(exit_hyperv_utils);
0791
0792 MODULE_DESCRIPTION("Hyper-V Utilities");
0793 MODULE_LICENSE("GPL");