From e2e773d883ed282ff9d18c6a9dfe8a7d02ccccc0 Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Tue, 5 Dec 2017 13:06:39 +0900 Subject: [PATCH] HFI: fix tidinfo and length calculation in program_rcvarray() --- kernel/user_exp_rcv.c | 64 ++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/kernel/user_exp_rcv.c b/kernel/user_exp_rcv.c index b0582327..a1047649 100644 --- a/kernel/user_exp_rcv.c +++ b/kernel/user_exp_rcv.c @@ -60,10 +60,10 @@ #define dkprintf(...) do { if(0) kprintf(__VA_ARGS__); } while (0) #endif -static int program_rcvarray(struct hfi1_filedata *, uintptr_t, size_t, u32 *); -static int set_rcvarray_entry(struct hfi1_filedata *, uintptr_t, - u32, struct tid_group *, - u16); +static int program_rcvarray(struct hfi1_filedata *, unsigned long, uintptr_t, + size_t, u32 *); +static int set_rcvarray_entry(struct hfi1_filedata *, unsigned long, uintptr_t, + u32, struct tid_group *, int, u32); static int unprogram_rcvarray(struct hfi1_filedata *, u32, struct tid_group **); static void clear_tid_node(struct hfi1_filedata *, struct tid_rb_node *); @@ -170,7 +170,7 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd, struct hfi1_tid_info *tinf len = MAX_EXPECTED_BUFFER; } - ret = program_rcvarray(fd, phys, len, tidlist + tididx); + ret = program_rcvarray(fd, vaddr, phys, len, tidlist + tididx); if (ret <= 0) { kprintf("Failed to program RcvArray entries: %d\n", ret); @@ -240,23 +240,32 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd, struct hfi1_tid_info *tinf break; } } + + kprintf("%s: 0x%llx:%lu -> %d TIDs unprogrammed\n", + __FUNCTION__, tinfo->vaddr, tinfo->length, tinfo->tidcnt); + + spin_lock(&fd->tid_lock); fd->tid_used -= tididx; + spin_unlock(&fd->tid_lock); + tinfo->tidcnt = tididx; done: kfree(tidinfo); return ret; } + /** * program_rcvarray() - program an RcvArray group with receive buffers */ -static int program_rcvarray(struct hfi1_filedata *fd, uintptr_t phys, +static int program_rcvarray(struct hfi1_filedata *fd, + unsigned long vaddr, + uintptr_t phys, size_t len, u32 *ptid) { struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_devdata *dd = uctxt->dd; u16 idx = 0; - s16 order; u32 tidinfo = 0, rcventry; int ret = -ENOMEM, count = 0; struct tid_group *grp = NULL; @@ -264,6 +273,9 @@ static int program_rcvarray(struct hfi1_filedata *fd, uintptr_t phys, /* lock is taken at loop edges */ spin_lock(&fd->tid_lock); while (len > 0) { + size_t tid_len; + size_t tid_npages; + if (!grp) { if (!uctxt->tid_used_list.count) { if (!uctxt->tid_group_list.count) { @@ -286,26 +298,23 @@ static int program_rcvarray(struct hfi1_filedata *fd, uintptr_t phys, } spin_unlock(&fd->tid_lock); - - /* order is power of two of 4k (2^12) pages */ - order = fls(len) - 13; - if (order < 0) - order = 0; - dkprintf("len %u, order %u\n", len, order); + tid_len = (len > MAX_EXPECTED_BUFFER) ? MAX_EXPECTED_BUFFER : + (1 << (fls(len) - 1)); + tid_npages = (tid_len > PAGE_SIZE) ? tid_len >> PAGE_SHIFT : 1; rcventry = grp->base + idx; rcv_array_wc_fill(dd, rcventry); - ret = set_rcvarray_entry(fd, phys, rcventry, grp, - order); + tidinfo = rcventry2tidinfo(rcventry - uctxt->expected_base) | + EXP_TID_SET(LEN, tid_npages); + ret = set_rcvarray_entry(fd, vaddr, phys, rcventry, + grp, tid_npages, tidinfo); if (ret) return ret; - tidinfo = rcventry2tidinfo(rcventry - uctxt->expected_base) | - EXP_TID_SET(LEN, 1 << order); ptid[count++] = tidinfo; - len -= 1 << (order + 12); - phys += 1 << (order + 12); - + len -= tid_len; + vaddr += tid_len; + phys += tid_len; spin_lock(&fd->tid_lock); grp->used++; @@ -327,10 +336,10 @@ static int program_rcvarray(struct hfi1_filedata *fd, uintptr_t phys, return count; } - -static int set_rcvarray_entry(struct hfi1_filedata *fd, uintptr_t phys, - u32 rcventry, struct tid_group *grp, - u16 order) +static int set_rcvarray_entry(struct hfi1_filedata *fd, + unsigned long vaddr, uintptr_t phys, + u32 rcventry, struct tid_group *grp, + int npages, u32 tidinfo) { struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_devdata *dd = uctxt->dd; @@ -346,18 +355,17 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd, uintptr_t phys, return -ENOMEM; dkprintf("Registering rcventry %d, phys 0x%p, len %u\n", rcventry, - phys, 1 << (order+12)); + phys, npages << PAGE_SHIFT); node->phys = phys; - node->len = 1 << (order+12); + node->len = npages << PAGE_SHIFT; node->rcventry = rcventry; node->grp = grp; // TODO: check node->rcventry - uctxt->expected_base is within // [0; uctxt->expected_count[ ? fd->entry_to_rb[node->rcventry - uctxt->expected_base] = node; - - hfi1_put_tid(dd, rcventry, PT_EXPECTED, phys, order+1); + hfi1_put_tid(dd, rcventry, PT_EXPECTED, phys, fls(npages)); #if 0 trace_hfi1_exp_tid_reg(uctxt->ctxt, fd->subctxt, rcventry, npages, node->mmu.addr, node->phys, phys);