diff options
Diffstat (limited to 'drivers/pci/p2pdma.c')
-rw-r--r-- | drivers/pci/p2pdma.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 7abd4f546d3c..19214ec81fbb 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -140,13 +140,22 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj, rcu_read_unlock(); for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) { - ret = vm_insert_page(vma, vaddr, virt_to_page(kaddr)); + struct page *page = virt_to_page(kaddr); + + /* + * Initialise the refcount for the freshly allocated page. As + * we have just allocated the page no one else should be + * using it. + */ + VM_WARN_ON_ONCE_PAGE(!page_ref_count(page), page); + set_page_count(page, 1); + ret = vm_insert_page(vma, vaddr, page); if (ret) { gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len); return ret; } percpu_ref_get(ref); - put_page(virt_to_page(kaddr)); + put_page(page); kaddr += PAGE_SIZE; len -= PAGE_SIZE; } @@ -161,7 +170,7 @@ out: return ret; } -static struct bin_attribute p2pmem_alloc_attr = { +static const struct bin_attribute p2pmem_alloc_attr = { .attr = { .name = "allocate", .mode = 0660 }, .mmap = p2pmem_alloc_mmap, /* @@ -180,20 +189,20 @@ static struct attribute *p2pmem_attrs[] = { NULL, }; -static struct bin_attribute *p2pmem_bin_attrs[] = { +static const struct bin_attribute *const p2pmem_bin_attrs[] = { &p2pmem_alloc_attr, NULL, }; static const struct attribute_group p2pmem_group = { .attrs = p2pmem_attrs, - .bin_attrs = p2pmem_bin_attrs, + .bin_attrs_new = p2pmem_bin_attrs, .name = "p2pmem", }; static void p2pdma_page_free(struct page *page) { - struct pci_p2pdma_pagemap *pgmap = to_p2p_pgmap(page->pgmap); + struct pci_p2pdma_pagemap *pgmap = to_p2p_pgmap(page_pgmap(page)); /* safe to dereference while a reference is held to the percpu ref */ struct pci_p2pdma *p2pdma = rcu_dereference_protected(pgmap->provider->p2pdma, 1); @@ -1016,8 +1025,8 @@ enum pci_p2pdma_map_type pci_p2pdma_map_segment(struct pci_p2pdma_map_state *state, struct device *dev, struct scatterlist *sg) { - if (state->pgmap != sg_page(sg)->pgmap) { - state->pgmap = sg_page(sg)->pgmap; + if (state->pgmap != page_pgmap(sg_page(sg))) { + state->pgmap = page_pgmap(sg_page(sg)); state->map = pci_p2pdma_map_type(state->pgmap, dev); state->bus_off = to_p2p_pgmap(state->pgmap)->bus_offset; } |