diff options
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r-- | drivers/xen/gntdev.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 57390c7666e5..b0b02a501167 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -492,12 +492,19 @@ static bool in_range(struct gntdev_grant_map *map, | |||
492 | return true; | 492 | return true; |
493 | } | 493 | } |
494 | 494 | ||
495 | static void unmap_if_in_range(struct gntdev_grant_map *map, | 495 | static int unmap_if_in_range(struct gntdev_grant_map *map, |
496 | unsigned long start, unsigned long end) | 496 | unsigned long start, unsigned long end, |
497 | bool blockable) | ||
497 | { | 498 | { |
498 | unsigned long mstart, mend; | 499 | unsigned long mstart, mend; |
499 | int err; | 500 | int err; |
500 | 501 | ||
502 | if (!in_range(map, start, end)) | ||
503 | return 0; | ||
504 | |||
505 | if (!blockable) | ||
506 | return -EAGAIN; | ||
507 | |||
501 | mstart = max(start, map->vma->vm_start); | 508 | mstart = max(start, map->vma->vm_start); |
502 | mend = min(end, map->vma->vm_end); | 509 | mend = min(end, map->vma->vm_end); |
503 | pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", | 510 | pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", |
@@ -508,6 +515,8 @@ static void unmap_if_in_range(struct gntdev_grant_map *map, | |||
508 | (mstart - map->vma->vm_start) >> PAGE_SHIFT, | 515 | (mstart - map->vma->vm_start) >> PAGE_SHIFT, |
509 | (mend - mstart) >> PAGE_SHIFT); | 516 | (mend - mstart) >> PAGE_SHIFT); |
510 | WARN_ON(err); | 517 | WARN_ON(err); |
518 | |||
519 | return 0; | ||
511 | } | 520 | } |
512 | 521 | ||
513 | static int mn_invl_range_start(struct mmu_notifier *mn, | 522 | static int mn_invl_range_start(struct mmu_notifier *mn, |
@@ -519,25 +528,20 @@ static int mn_invl_range_start(struct mmu_notifier *mn, | |||
519 | struct gntdev_grant_map *map; | 528 | struct gntdev_grant_map *map; |
520 | int ret = 0; | 529 | int ret = 0; |
521 | 530 | ||
522 | /* TODO do we really need a mutex here? */ | ||
523 | if (blockable) | 531 | if (blockable) |
524 | mutex_lock(&priv->lock); | 532 | mutex_lock(&priv->lock); |
525 | else if (!mutex_trylock(&priv->lock)) | 533 | else if (!mutex_trylock(&priv->lock)) |
526 | return -EAGAIN; | 534 | return -EAGAIN; |
527 | 535 | ||
528 | list_for_each_entry(map, &priv->maps, next) { | 536 | list_for_each_entry(map, &priv->maps, next) { |
529 | if (in_range(map, start, end)) { | 537 | ret = unmap_if_in_range(map, start, end, blockable); |
530 | ret = -EAGAIN; | 538 | if (ret) |
531 | goto out_unlock; | 539 | goto out_unlock; |
532 | } | ||
533 | unmap_if_in_range(map, start, end); | ||
534 | } | 540 | } |
535 | list_for_each_entry(map, &priv->freeable_maps, next) { | 541 | list_for_each_entry(map, &priv->freeable_maps, next) { |
536 | if (in_range(map, start, end)) { | 542 | ret = unmap_if_in_range(map, start, end, blockable); |
537 | ret = -EAGAIN; | 543 | if (ret) |
538 | goto out_unlock; | 544 | goto out_unlock; |
539 | } | ||
540 | unmap_if_in_range(map, start, end); | ||
541 | } | 545 | } |
542 | 546 | ||
543 | out_unlock: | 547 | out_unlock: |