diff options
author | Vitaly Kuznetsov <vkuznets@redhat.com> | 2015-04-11 21:07:52 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-24 15:17:41 -0400 |
commit | 6472f80a2eeb34b442542bccd4d600e9251d9c36 (patch) | |
tree | afab8c5e127db58891ccba29c50e6a98533a7325 /drivers/hv | |
parent | 14b50f80c32dd4e84b6baeaa8bf4049cc5ecf56d (diff) |
Drivers: hv: vss: convert to hv_utils_transport
Convert to hv_utils_transport to support both netlink and /dev/vmbus/hv_vss communication methods.
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Tested-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/hv_snapshot.c | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index ddb1cda4b2fc..2c8c246d09eb 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/hyperv.h> | 25 | #include <linux/hyperv.h> |
26 | 26 | ||
27 | #include "hyperv_vmbus.h" | 27 | #include "hyperv_vmbus.h" |
28 | #include "hv_utils_transport.h" | ||
28 | 29 | ||
29 | #define VSS_MAJOR 5 | 30 | #define VSS_MAJOR 5 |
30 | #define VSS_MINOR 0 | 31 | #define VSS_MINOR 0 |
@@ -58,9 +59,9 @@ static struct { | |||
58 | 59 | ||
59 | static void vss_respond_to_host(int error); | 60 | static void vss_respond_to_host(int error); |
60 | 61 | ||
61 | static struct cb_id vss_id = { CN_VSS_IDX, CN_VSS_VAL }; | 62 | static const char vss_devname[] = "vmbus/hv_vss"; |
62 | static const char vss_name[] = "vss_kernel_module"; | ||
63 | static __u8 *recv_buffer; | 63 | static __u8 *recv_buffer; |
64 | static struct hvutil_transport *hvt; | ||
64 | 65 | ||
65 | static void vss_send_op(struct work_struct *dummy); | 66 | static void vss_send_op(struct work_struct *dummy); |
66 | static void vss_timeout_func(struct work_struct *dummy); | 67 | static void vss_timeout_func(struct work_struct *dummy); |
@@ -88,12 +89,12 @@ static void vss_timeout_func(struct work_struct *dummy) | |||
88 | hv_vss_onchannelcallback); | 89 | hv_vss_onchannelcallback); |
89 | } | 90 | } |
90 | 91 | ||
91 | static void | 92 | static int vss_on_msg(void *msg, int len) |
92 | vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | ||
93 | { | 93 | { |
94 | struct hv_vss_msg *vss_msg; | 94 | struct hv_vss_msg *vss_msg = (struct hv_vss_msg *)msg; |
95 | 95 | ||
96 | vss_msg = (struct hv_vss_msg *)msg->data; | 96 | if (len != sizeof(*vss_msg)) |
97 | return -EINVAL; | ||
97 | 98 | ||
98 | /* | 99 | /* |
99 | * Don't process registration messages if we're in the middle of | 100 | * Don't process registration messages if we're in the middle of |
@@ -101,7 +102,7 @@ vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
101 | */ | 102 | */ |
102 | if (vss_transaction.state > HVUTIL_READY && | 103 | if (vss_transaction.state > HVUTIL_READY && |
103 | vss_msg->vss_hdr.operation == VSS_OP_REGISTER) | 104 | vss_msg->vss_hdr.operation == VSS_OP_REGISTER) |
104 | return; | 105 | return -EINVAL; |
105 | 106 | ||
106 | if (vss_transaction.state == HVUTIL_DEVICE_INIT && | 107 | if (vss_transaction.state == HVUTIL_DEVICE_INIT && |
107 | vss_msg->vss_hdr.operation == VSS_OP_REGISTER) { | 108 | vss_msg->vss_hdr.operation == VSS_OP_REGISTER) { |
@@ -119,8 +120,9 @@ vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
119 | } else { | 120 | } else { |
120 | /* This is a spurious call! */ | 121 | /* This is a spurious call! */ |
121 | pr_warn("VSS: Transaction not active\n"); | 122 | pr_warn("VSS: Transaction not active\n"); |
122 | return; | 123 | return -EINVAL; |
123 | } | 124 | } |
125 | return 0; | ||
124 | } | 126 | } |
125 | 127 | ||
126 | 128 | ||
@@ -128,27 +130,20 @@ static void vss_send_op(struct work_struct *dummy) | |||
128 | { | 130 | { |
129 | int op = vss_transaction.msg->vss_hdr.operation; | 131 | int op = vss_transaction.msg->vss_hdr.operation; |
130 | int rc; | 132 | int rc; |
131 | struct cn_msg *msg; | ||
132 | struct hv_vss_msg *vss_msg; | 133 | struct hv_vss_msg *vss_msg; |
133 | 134 | ||
134 | /* The transaction state is wrong. */ | 135 | /* The transaction state is wrong. */ |
135 | if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED) | 136 | if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED) |
136 | return; | 137 | return; |
137 | 138 | ||
138 | msg = kzalloc(sizeof(*msg) + sizeof(*vss_msg), GFP_ATOMIC); | 139 | vss_msg = kzalloc(sizeof(*vss_msg), GFP_KERNEL); |
139 | if (!msg) | 140 | if (!vss_msg) |
140 | return; | 141 | return; |
141 | 142 | ||
142 | vss_msg = (struct hv_vss_msg *)msg->data; | ||
143 | |||
144 | msg->id.idx = CN_VSS_IDX; | ||
145 | msg->id.val = CN_VSS_VAL; | ||
146 | |||
147 | vss_msg->vss_hdr.operation = op; | 143 | vss_msg->vss_hdr.operation = op; |
148 | msg->len = sizeof(struct hv_vss_msg); | ||
149 | 144 | ||
150 | vss_transaction.state = HVUTIL_USERSPACE_REQ; | 145 | vss_transaction.state = HVUTIL_USERSPACE_REQ; |
151 | rc = cn_netlink_send(msg, 0, 0, GFP_ATOMIC); | 146 | rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg)); |
152 | if (rc) { | 147 | if (rc) { |
153 | pr_warn("VSS: failed to communicate to the daemon: %d\n", rc); | 148 | pr_warn("VSS: failed to communicate to the daemon: %d\n", rc); |
154 | if (cancel_delayed_work_sync(&vss_timeout_work)) { | 149 | if (cancel_delayed_work_sync(&vss_timeout_work)) { |
@@ -157,7 +152,7 @@ static void vss_send_op(struct work_struct *dummy) | |||
157 | } | 152 | } |
158 | } | 153 | } |
159 | 154 | ||
160 | kfree(msg); | 155 | kfree(vss_msg); |
161 | 156 | ||
162 | return; | 157 | return; |
163 | } | 158 | } |
@@ -308,14 +303,16 @@ void hv_vss_onchannelcallback(void *context) | |||
308 | 303 | ||
309 | } | 304 | } |
310 | 305 | ||
306 | static void vss_on_reset(void) | ||
307 | { | ||
308 | if (cancel_delayed_work_sync(&vss_timeout_work)) | ||
309 | vss_respond_to_host(HV_E_FAIL); | ||
310 | vss_transaction.state = HVUTIL_DEVICE_INIT; | ||
311 | } | ||
312 | |||
311 | int | 313 | int |
312 | hv_vss_init(struct hv_util_service *srv) | 314 | hv_vss_init(struct hv_util_service *srv) |
313 | { | 315 | { |
314 | int err; | ||
315 | |||
316 | err = cn_add_callback(&vss_id, vss_name, vss_cn_callback); | ||
317 | if (err) | ||
318 | return err; | ||
319 | recv_buffer = srv->recv_buffer; | 316 | recv_buffer = srv->recv_buffer; |
320 | 317 | ||
321 | /* | 318 | /* |
@@ -326,13 +323,18 @@ hv_vss_init(struct hv_util_service *srv) | |||
326 | */ | 323 | */ |
327 | vss_transaction.state = HVUTIL_DEVICE_INIT; | 324 | vss_transaction.state = HVUTIL_DEVICE_INIT; |
328 | 325 | ||
326 | hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL, | ||
327 | vss_on_msg, vss_on_reset); | ||
328 | if (!hvt) | ||
329 | return -EFAULT; | ||
330 | |||
329 | return 0; | 331 | return 0; |
330 | } | 332 | } |
331 | 333 | ||
332 | void hv_vss_deinit(void) | 334 | void hv_vss_deinit(void) |
333 | { | 335 | { |
334 | vss_transaction.state = HVUTIL_DEVICE_DYING; | 336 | vss_transaction.state = HVUTIL_DEVICE_DYING; |
335 | cn_del_callback(&vss_id); | ||
336 | cancel_delayed_work_sync(&vss_timeout_work); | 337 | cancel_delayed_work_sync(&vss_timeout_work); |
337 | cancel_work_sync(&vss_send_op_work); | 338 | cancel_work_sync(&vss_send_op_work); |
339 | hvutil_transport_destroy(hvt); | ||
338 | } | 340 | } |