aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/pvcalls-front.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/pvcalls-front.c')
-rw-r--r--drivers/xen/pvcalls-front.c104
1 files changed, 75 insertions, 29 deletions
diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c
index 77224d8f3e6f..8a249c95c193 100644
--- a/drivers/xen/pvcalls-front.c
+++ b/drivers/xen/pvcalls-front.c
@@ -31,6 +31,12 @@
31#define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE) 31#define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE)
32#define PVCALLS_FRONT_MAX_SPIN 5000 32#define PVCALLS_FRONT_MAX_SPIN 5000
33 33
34static struct proto pvcalls_proto = {
35 .name = "PVCalls",
36 .owner = THIS_MODULE,
37 .obj_size = sizeof(struct sock),
38};
39
34struct pvcalls_bedata { 40struct pvcalls_bedata {
35 struct xen_pvcalls_front_ring ring; 41 struct xen_pvcalls_front_ring ring;
36 grant_ref_t ref; 42 grant_ref_t ref;
@@ -335,6 +341,42 @@ int pvcalls_front_socket(struct socket *sock)
335 return ret; 341 return ret;
336} 342}
337 343
344static void free_active_ring(struct sock_mapping *map)
345{
346 if (!map->active.ring)
347 return;
348
349 free_pages((unsigned long)map->active.data.in,
350 map->active.ring->ring_order);
351 free_page((unsigned long)map->active.ring);
352}
353
354static int alloc_active_ring(struct sock_mapping *map)
355{
356 void *bytes;
357
358 map->active.ring = (struct pvcalls_data_intf *)
359 get_zeroed_page(GFP_KERNEL);
360 if (!map->active.ring)
361 goto out;
362
363 map->active.ring->ring_order = PVCALLS_RING_ORDER;
364 bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
365 PVCALLS_RING_ORDER);
366 if (!bytes)
367 goto out;
368
369 map->active.data.in = bytes;
370 map->active.data.out = bytes +
371 XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
372
373 return 0;
374
375out:
376 free_active_ring(map);
377 return -ENOMEM;
378}
379
338static int create_active(struct sock_mapping *map, int *evtchn) 380static int create_active(struct sock_mapping *map, int *evtchn)
339{ 381{
340 void *bytes; 382 void *bytes;
@@ -343,15 +385,7 @@ static int create_active(struct sock_mapping *map, int *evtchn)
343 *evtchn = -1; 385 *evtchn = -1;
344 init_waitqueue_head(&map->active.inflight_conn_req); 386 init_waitqueue_head(&map->active.inflight_conn_req);
345 387
346 map->active.ring = (struct pvcalls_data_intf *) 388 bytes = map->active.data.in;
347 __get_free_page(GFP_KERNEL | __GFP_ZERO);
348 if (map->active.ring == NULL)
349 goto out_error;
350 map->active.ring->ring_order = PVCALLS_RING_ORDER;
351 bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
352 PVCALLS_RING_ORDER);
353 if (bytes == NULL)
354 goto out_error;
355 for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) 389 for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
356 map->active.ring->ref[i] = gnttab_grant_foreign_access( 390 map->active.ring->ref[i] = gnttab_grant_foreign_access(
357 pvcalls_front_dev->otherend_id, 391 pvcalls_front_dev->otherend_id,
@@ -361,10 +395,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
361 pvcalls_front_dev->otherend_id, 395 pvcalls_front_dev->otherend_id,
362 pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0); 396 pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0);
363 397
364 map->active.data.in = bytes;
365 map->active.data.out = bytes +
366 XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
367
368 ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn); 398 ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn);
369 if (ret) 399 if (ret)
370 goto out_error; 400 goto out_error;
@@ -385,8 +415,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
385out_error: 415out_error:
386 if (*evtchn >= 0) 416 if (*evtchn >= 0)
387 xenbus_free_evtchn(pvcalls_front_dev, *evtchn); 417 xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
388 free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
389 free_page((unsigned long)map->active.ring);
390 return ret; 418 return ret;
391} 419}
392 420
@@ -406,17 +434,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
406 return PTR_ERR(map); 434 return PTR_ERR(map);
407 435
408 bedata = dev_get_drvdata(&pvcalls_front_dev->dev); 436 bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
437 ret = alloc_active_ring(map);
438 if (ret < 0) {
439 pvcalls_exit_sock(sock);
440 return ret;
441 }
409 442
410 spin_lock(&bedata->socket_lock); 443 spin_lock(&bedata->socket_lock);
411 ret = get_request(bedata, &req_id); 444 ret = get_request(bedata, &req_id);
412 if (ret < 0) { 445 if (ret < 0) {
413 spin_unlock(&bedata->socket_lock); 446 spin_unlock(&bedata->socket_lock);
447 free_active_ring(map);
414 pvcalls_exit_sock(sock); 448 pvcalls_exit_sock(sock);
415 return ret; 449 return ret;
416 } 450 }
417 ret = create_active(map, &evtchn); 451 ret = create_active(map, &evtchn);
418 if (ret < 0) { 452 if (ret < 0) {
419 spin_unlock(&bedata->socket_lock); 453 spin_unlock(&bedata->socket_lock);
454 free_active_ring(map);
420 pvcalls_exit_sock(sock); 455 pvcalls_exit_sock(sock);
421 return ret; 456 return ret;
422 } 457 }
@@ -469,8 +504,10 @@ static int __write_ring(struct pvcalls_data_intf *intf,
469 virt_mb(); 504 virt_mb();
470 505
471 size = pvcalls_queued(prod, cons, array_size); 506 size = pvcalls_queued(prod, cons, array_size);
472 if (size >= array_size) 507 if (size > array_size)
473 return -EINVAL; 508 return -EINVAL;
509 if (size == array_size)
510 return 0;
474 if (len > array_size - size) 511 if (len > array_size - size)
475 len = array_size - size; 512 len = array_size - size;
476 513
@@ -560,15 +597,13 @@ static int __read_ring(struct pvcalls_data_intf *intf,
560 error = intf->in_error; 597 error = intf->in_error;
561 /* get pointers before reading from the ring */ 598 /* get pointers before reading from the ring */
562 virt_rmb(); 599 virt_rmb();
563 if (error < 0)
564 return error;
565 600
566 size = pvcalls_queued(prod, cons, array_size); 601 size = pvcalls_queued(prod, cons, array_size);
567 masked_prod = pvcalls_mask(prod, array_size); 602 masked_prod = pvcalls_mask(prod, array_size);
568 masked_cons = pvcalls_mask(cons, array_size); 603 masked_cons = pvcalls_mask(cons, array_size);
569 604
570 if (size == 0) 605 if (size == 0)
571 return 0; 606 return error ?: size;
572 607
573 if (len > size) 608 if (len > size)
574 len = size; 609 len = size;
@@ -780,25 +815,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
780 } 815 }
781 } 816 }
782 817
783 spin_lock(&bedata->socket_lock); 818 map2 = kzalloc(sizeof(*map2), GFP_KERNEL);
784 ret = get_request(bedata, &req_id); 819 if (map2 == NULL) {
785 if (ret < 0) {
786 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, 820 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
787 (void *)&map->passive.flags); 821 (void *)&map->passive.flags);
788 spin_unlock(&bedata->socket_lock); 822 pvcalls_exit_sock(sock);
823 return -ENOMEM;
824 }
825 ret = alloc_active_ring(map2);
826 if (ret < 0) {
827 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
828 (void *)&map->passive.flags);
829 kfree(map2);
789 pvcalls_exit_sock(sock); 830 pvcalls_exit_sock(sock);
790 return ret; 831 return ret;
791 } 832 }
792 map2 = kzalloc(sizeof(*map2), GFP_ATOMIC); 833 spin_lock(&bedata->socket_lock);
793 if (map2 == NULL) { 834 ret = get_request(bedata, &req_id);
835 if (ret < 0) {
794 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, 836 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
795 (void *)&map->passive.flags); 837 (void *)&map->passive.flags);
796 spin_unlock(&bedata->socket_lock); 838 spin_unlock(&bedata->socket_lock);
839 free_active_ring(map2);
840 kfree(map2);
797 pvcalls_exit_sock(sock); 841 pvcalls_exit_sock(sock);
798 return -ENOMEM; 842 return ret;
799 } 843 }
844
800 ret = create_active(map2, &evtchn); 845 ret = create_active(map2, &evtchn);
801 if (ret < 0) { 846 if (ret < 0) {
847 free_active_ring(map2);
802 kfree(map2); 848 kfree(map2);
803 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, 849 clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
804 (void *)&map->passive.flags); 850 (void *)&map->passive.flags);
@@ -839,7 +885,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
839 885
840received: 886received:
841 map2->sock = newsock; 887 map2->sock = newsock;
842 newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL); 888 newsock->sk = sk_alloc(sock_net(sock->sk), PF_INET, GFP_KERNEL, &pvcalls_proto, false);
843 if (!newsock->sk) { 889 if (!newsock->sk) {
844 bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID; 890 bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
845 map->passive.inflight_req_id = PVCALLS_INVALID_ID; 891 map->passive.inflight_req_id = PVCALLS_INVALID_ID;
@@ -1032,8 +1078,8 @@ int pvcalls_front_release(struct socket *sock)
1032 spin_lock(&bedata->socket_lock); 1078 spin_lock(&bedata->socket_lock);
1033 list_del(&map->list); 1079 list_del(&map->list);
1034 spin_unlock(&bedata->socket_lock); 1080 spin_unlock(&bedata->socket_lock);
1035 if (READ_ONCE(map->passive.inflight_req_id) != 1081 if (READ_ONCE(map->passive.inflight_req_id) != PVCALLS_INVALID_ID &&
1036 PVCALLS_INVALID_ID) { 1082 READ_ONCE(map->passive.inflight_req_id) != 0) {
1037 pvcalls_front_free_map(bedata, 1083 pvcalls_front_free_map(bedata,
1038 map->passive.accept_map); 1084 map->passive.accept_map);
1039 } 1085 }