summaryrefslogtreecommitdiff
path: root/drivers/edgetpu/edgetpu-device-group.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edgetpu/edgetpu-device-group.c')
-rw-r--r--drivers/edgetpu/edgetpu-device-group.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/drivers/edgetpu/edgetpu-device-group.c b/drivers/edgetpu/edgetpu-device-group.c
index fd0c410..1b668f5 100644
--- a/drivers/edgetpu/edgetpu-device-group.c
+++ b/drivers/edgetpu/edgetpu-device-group.c
@@ -142,16 +142,11 @@ static int edgetpu_group_activate(struct edgetpu_device_group *group)
static void edgetpu_group_deactivate(struct edgetpu_device_group *group)
{
u8 mailbox_id;
- int ret;
if (edgetpu_group_mailbox_detached_locked(group))
return;
mailbox_id = edgetpu_group_context_id_locked(group);
- ret = edgetpu_mailbox_deactivate(group->etdev, mailbox_id);
- if (ret)
- etdev_err(group->etdev, "deactivate mailbox for VCID %d failed with %d",
- group->vcid, ret);
- return;
+ edgetpu_mailbox_deactivate(group->etdev, mailbox_id);
}
/*
@@ -1141,6 +1136,7 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
int i;
int ret;
struct vm_area_struct *vma;
+ struct vm_area_struct **vmas;
unsigned int foll_flags = FOLL_LONGTERM | FOLL_WRITE;
if (size == 0)
@@ -1161,11 +1157,10 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
*/
pages = kvmalloc((num_pages * sizeof(*pages)), GFP_KERNEL | __GFP_NOWARN);
if (!pages) {
- etdev_dbg(etdev, "%s: kvmalloc failed (%lu bytes)\n", __func__,
- (num_pages * sizeof(*pages)));
+ etdev_dbg(etdev, "%s: kvmalloc pages failed (%lu bytes)\n",
+ __func__, (num_pages * sizeof(*pages)));
return ERR_PTR(-ENOMEM);
}
-
/*
* The host pages might be read-only and could fail if we attempt to pin
* it with FOLL_WRITE.
@@ -1179,10 +1174,43 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
*preadonly = false;
}
+ /* Try fast call first, in case it's actually faster. */
ret = pin_user_pages_fast(host_addr & PAGE_MASK, num_pages, foll_flags,
pages);
+ if (ret == num_pages) {
+ *pnum_pages = num_pages;
+ return pages;
+ }
if (ret < 0) {
- etdev_dbg(etdev, "get user pages failed %u:%pK-%u: %d",
+ etdev_dbg(etdev, "pin_user_pages failed %u:%pK-%u: %d",
+ group->workload_id, (void *)host_addr, num_pages,
+ ret);
+ if (ret != -ENOMEM) {
+ num_pages = 0;
+ goto error;
+ }
+ }
+ etdev_dbg(etdev,
+ "pin_user_pages_fast error %u:%pK npages=%u ret=%d",
+ group->workload_id, (void *)host_addr, num_pages,
+ ret);
+ /* Unpin any partial mapping and start over again. */
+ for (i = 0; i < ret; i++)
+ unpin_user_page(pages[i]);
+
+ /* Allocate our own vmas array non-contiguous. */
+ vmas = kvmalloc((num_pages * sizeof(*vmas)), GFP_KERNEL | __GFP_NOWARN);
+ if (!vmas) {
+ etdev_dbg(etdev, "%s: kvmalloc vmas failed (%lu bytes)\n",
+ __func__, (num_pages * sizeof(*pages)));
+ kvfree(pages);
+ return ERR_PTR(-ENOMEM);
+ }
+ ret = pin_user_pages(host_addr & PAGE_MASK, num_pages, foll_flags,
+ pages, vmas);
+ kvfree(vmas);
+ if (ret < 0) {
+ etdev_dbg(etdev, "pin_user_pages failed %u:%pK-%u: %d",
group->workload_id, (void *)host_addr, num_pages,
ret);
num_pages = 0;
@@ -1190,7 +1218,7 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
}
if (ret < num_pages) {
etdev_dbg(etdev,
- "get user pages partial %u:%pK npages=%u pinned=%d",
+ "pin_user_pages partial %u:%pK npages=%u pinned=%d",
group->workload_id, (void *)host_addr, num_pages,
ret);
num_pages = ret;
@@ -1199,7 +1227,6 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
}
*pnum_pages = num_pages;
-
return pages;
error: