hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/uio/uio_hv_generic.c
....@@ -17,7 +17,6 @@
1717 * # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \
1818 * > /sys/bus/vmbus/drivers/uio_hv_generic/bind
1919 */
20
-#define DEBUG 1
2120 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2221
2322 #include <linux/device.h>
....@@ -33,13 +32,13 @@
3332
3433 #include "../hv/hyperv_vmbus.h"
3534
36
-#define DRIVER_VERSION "0.02.0"
35
+#define DRIVER_VERSION "0.02.1"
3736 #define DRIVER_AUTHOR "Stephen Hemminger <sthemmin at microsoft.com>"
3837 #define DRIVER_DESC "Generic UIO driver for VMBus devices"
3938
4039 #define HV_RING_SIZE 512 /* pages */
41
-#define SEND_BUFFER_SIZE (15 * 1024 * 1024)
42
-#define RECV_BUFFER_SIZE (15 * 1024 * 1024)
40
+#define SEND_BUFFER_SIZE (16 * 1024 * 1024)
41
+#define RECV_BUFFER_SIZE (31 * 1024 * 1024)
4342
4443 /*
4544 * List of resources to be mapped to user space
....@@ -56,6 +55,7 @@
5655 struct hv_uio_private_data {
5756 struct uio_info info;
5857 struct hv_device *device;
58
+ atomic_t refcnt;
5959
6060 void *recv_buf;
6161 u32 recv_gpadl;
....@@ -129,12 +129,10 @@
129129 {
130130 struct vmbus_channel *channel
131131 = container_of(kobj, struct vmbus_channel, kobj);
132
- struct hv_device *dev = channel->primary_channel->device_obj;
133
- u16 q_idx = channel->offermsg.offer.sub_channel_index;
134132 void *ring_buffer = page_address(channel->ringbuffer_page);
135133
136
- dev_dbg(&dev->device, "mmap channel %u pages %#lx at %#lx\n",
137
- q_idx, vma_pages(vma), vma->vm_pgoff);
134
+ if (channel->state != CHANNEL_OPENED_STATE)
135
+ return -ENODEV;
138136
139137 return vm_iomap_memory(vma, virt_to_phys(ring_buffer),
140138 channel->ringbuffer_pagecount << PAGE_SHIFT);
....@@ -177,58 +175,106 @@
177175 }
178176 }
179177
178
+/* free the reserved buffers for send and receive */
180179 static void
181180 hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
182181 {
183
- if (pdata->send_gpadl)
182
+ if (pdata->send_gpadl) {
184183 vmbus_teardown_gpadl(dev->channel, pdata->send_gpadl);
185
- vfree(pdata->send_buf);
184
+ pdata->send_gpadl = 0;
185
+ vfree(pdata->send_buf);
186
+ }
186187
187
- if (pdata->recv_gpadl)
188
+ if (pdata->recv_gpadl) {
188189 vmbus_teardown_gpadl(dev->channel, pdata->recv_gpadl);
189
- vfree(pdata->recv_buf);
190
+ pdata->recv_gpadl = 0;
191
+ vfree(pdata->recv_buf);
192
+ }
193
+}
194
+
195
+/* VMBus primary channel is opened on first use */
196
+static int
197
+hv_uio_open(struct uio_info *info, struct inode *inode)
198
+{
199
+ struct hv_uio_private_data *pdata
200
+ = container_of(info, struct hv_uio_private_data, info);
201
+ struct hv_device *dev = pdata->device;
202
+ int ret;
203
+
204
+ if (atomic_inc_return(&pdata->refcnt) != 1)
205
+ return 0;
206
+
207
+ vmbus_set_chn_rescind_callback(dev->channel, hv_uio_rescind);
208
+ vmbus_set_sc_create_callback(dev->channel, hv_uio_new_channel);
209
+
210
+ ret = vmbus_connect_ring(dev->channel,
211
+ hv_uio_channel_cb, dev->channel);
212
+ if (ret == 0)
213
+ dev->channel->inbound.ring_buffer->interrupt_mask = 1;
214
+ else
215
+ atomic_dec(&pdata->refcnt);
216
+
217
+ return ret;
218
+}
219
+
220
+/* VMBus primary channel is closed on last close */
221
+static int
222
+hv_uio_release(struct uio_info *info, struct inode *inode)
223
+{
224
+ struct hv_uio_private_data *pdata
225
+ = container_of(info, struct hv_uio_private_data, info);
226
+ struct hv_device *dev = pdata->device;
227
+ int ret = 0;
228
+
229
+ if (atomic_dec_and_test(&pdata->refcnt))
230
+ ret = vmbus_disconnect_ring(dev->channel);
231
+
232
+ return ret;
190233 }
191234
192235 static int
193236 hv_uio_probe(struct hv_device *dev,
194237 const struct hv_vmbus_device_id *dev_id)
195238 {
239
+ struct vmbus_channel *channel = dev->channel;
196240 struct hv_uio_private_data *pdata;
241
+ void *ring_buffer;
197242 int ret;
243
+
244
+ /* Communicating with host has to be via shared memory not hypercall */
245
+ if (!channel->offermsg.monitor_allocated) {
246
+ dev_err(&dev->device, "vmbus channel requires hypercall\n");
247
+ return -ENOTSUPP;
248
+ }
198249
199250 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
200251 if (!pdata)
201252 return -ENOMEM;
202253
203
- ret = vmbus_open(dev->channel, HV_RING_SIZE * PAGE_SIZE,
204
- HV_RING_SIZE * PAGE_SIZE, NULL, 0,
205
- hv_uio_channel_cb, dev->channel);
254
+ ret = vmbus_alloc_ring(channel, HV_RING_SIZE * PAGE_SIZE,
255
+ HV_RING_SIZE * PAGE_SIZE);
206256 if (ret)
207257 goto fail;
208258
209
- /* Communicating with host has to be via shared memory not hypercall */
210
- if (!dev->channel->offermsg.monitor_allocated) {
211
- dev_err(&dev->device, "vmbus channel requires hypercall\n");
212
- ret = -ENOTSUPP;
213
- goto fail_close;
214
- }
215
-
216
- dev->channel->inbound.ring_buffer->interrupt_mask = 1;
217
- set_channel_read_mode(dev->channel, HV_CALL_ISR);
259
+ set_channel_read_mode(channel, HV_CALL_ISR);
218260
219261 /* Fill general uio info */
220262 pdata->info.name = "uio_hv_generic";
221263 pdata->info.version = DRIVER_VERSION;
222264 pdata->info.irqcontrol = hv_uio_irqcontrol;
265
+ pdata->info.open = hv_uio_open;
266
+ pdata->info.release = hv_uio_release;
223267 pdata->info.irq = UIO_IRQ_CUSTOM;
268
+ atomic_set(&pdata->refcnt, 0);
224269
225270 /* mem resources */
226271 pdata->info.mem[TXRX_RING_MAP].name = "txrx_rings";
272
+ ring_buffer = page_address(channel->ringbuffer_page);
227273 pdata->info.mem[TXRX_RING_MAP].addr
228
- = (uintptr_t)page_address(dev->channel->ringbuffer_page);
274
+ = (uintptr_t)virt_to_phys(ring_buffer);
229275 pdata->info.mem[TXRX_RING_MAP].size
230
- = dev->channel->ringbuffer_pagecount << PAGE_SHIFT;
231
- pdata->info.mem[TXRX_RING_MAP].memtype = UIO_MEM_LOGICAL;
276
+ = channel->ringbuffer_pagecount << PAGE_SHIFT;
277
+ pdata->info.mem[TXRX_RING_MAP].memtype = UIO_MEM_IOVA;
232278
233279 pdata->info.mem[INT_PAGE_MAP].name = "int_page";
234280 pdata->info.mem[INT_PAGE_MAP].addr
....@@ -248,10 +294,12 @@
248294 goto fail_close;
249295 }
250296
251
- ret = vmbus_establish_gpadl(dev->channel, pdata->recv_buf,
297
+ ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
252298 RECV_BUFFER_SIZE, &pdata->recv_gpadl);
253
- if (ret)
299
+ if (ret) {
300
+ vfree(pdata->recv_buf);
254301 goto fail_close;
302
+ }
255303
256304 /* put Global Physical Address Label in name */
257305 snprintf(pdata->recv_name, sizeof(pdata->recv_name),
....@@ -262,17 +310,18 @@
262310 pdata->info.mem[RECV_BUF_MAP].size = RECV_BUFFER_SIZE;
263311 pdata->info.mem[RECV_BUF_MAP].memtype = UIO_MEM_VIRTUAL;
264312
265
-
266313 pdata->send_buf = vzalloc(SEND_BUFFER_SIZE);
267314 if (pdata->send_buf == NULL) {
268315 ret = -ENOMEM;
269316 goto fail_close;
270317 }
271318
272
- ret = vmbus_establish_gpadl(dev->channel, pdata->send_buf,
319
+ ret = vmbus_establish_gpadl(channel, pdata->send_buf,
273320 SEND_BUFFER_SIZE, &pdata->send_gpadl);
274
- if (ret)
321
+ if (ret) {
322
+ vfree(pdata->send_buf);
275323 goto fail_close;
324
+ }
276325
277326 snprintf(pdata->send_name, sizeof(pdata->send_name),
278327 "send:%u", pdata->send_gpadl);
....@@ -291,10 +340,7 @@
291340 goto fail_close;
292341 }
293342
294
- vmbus_set_chn_rescind_callback(dev->channel, hv_uio_rescind);
295
- vmbus_set_sc_create_callback(dev->channel, hv_uio_new_channel);
296
-
297
- ret = sysfs_create_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr);
343
+ ret = sysfs_create_bin_file(&channel->kobj, &ring_buffer_bin_attr);
298344 if (ret)
299345 dev_notice(&dev->device,
300346 "sysfs create ring bin file failed; %d\n", ret);
....@@ -305,7 +351,6 @@
305351
306352 fail_close:
307353 hv_uio_cleanup(dev, pdata);
308
- vmbus_close(dev->channel);
309354 fail:
310355 kfree(pdata);
311356
....@@ -320,10 +365,12 @@
320365 if (!pdata)
321366 return 0;
322367
368
+ sysfs_remove_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr);
323369 uio_unregister_device(&pdata->info);
324370 hv_uio_cleanup(dev, pdata);
325371 hv_set_drvdata(dev, NULL);
326
- vmbus_close(dev->channel);
372
+
373
+ vmbus_free_ring(dev->channel);
327374 kfree(pdata);
328375 return 0;
329376 }