diff options
| author | Mark Brown <broonie@kernel.org> | 2026-07-23 13:42:58 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-07-23 13:43:02 +0100 |
| commit | cdae9963d80ffb6351ae94b866d6c05ff456952c (patch) | |
| tree | 655f312daba7c56c037ce5013ad0816a112b6ce4 /drivers | |
| parent | b60d1fe05289a42ca691c26825503cc3d31305e2 (diff) | |
| parent | 71a7a58818a33631c9518f944cef5ca55aba6537 (diff) | |
| download | linux-next-cdae9963d80ffb6351ae94b866d6c05ff456952c.tar.gz linux-next-cdae9963d80ffb6351ae94b866d6c05ff456952c.zip | |
Merge branch 'mm-unstable' of https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Diffstat (limited to 'drivers')
38 files changed, 502 insertions, 294 deletions
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 4b3a62aa8798..0a0ff9a10946 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -1047,7 +1047,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo) bool found; int ret; - timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); again: found = false; down_write(&xdna->notifier_lock); @@ -1072,24 +1072,9 @@ again: return -EFAULT; } - mapp->range.notifier_seq = mmu_interval_read_begin(&mapp->notifier); - mmap_read_lock(mm); - ret = hmm_range_fault(&mapp->range); - mmap_read_unlock(mm); - if (ret) { - if (time_after(jiffies, timeout)) { - ret = -ETIME; - goto put_mm; - } - - if (ret == -EBUSY) { - amdxdna_umap_put(mapp); - mmput(mm); - goto again; - } - + ret = hmm_range_fault_unlocked_timeout(&mapp->range, timeout); + if (ret) goto put_mm; - } down_write(&xdna->notifier_lock); if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) { @@ -1107,7 +1092,7 @@ again: put_mm: amdxdna_umap_put(mapp); mmput(mm); - return ret; + return ret == -EBUSY ? -ETIME : ret; } int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq) diff --git a/drivers/base/arch_numa.c b/drivers/base/arch_numa.c index c99f2ab105e5..442ea239bba7 100644 --- a/drivers/base/arch_numa.c +++ b/drivers/base/arch_numa.c @@ -231,10 +231,6 @@ static int __init numa_init(int (*init_func)(void)) { int ret; - nodes_clear(numa_nodes_parsed); - nodes_clear(node_possible_map); - nodes_clear(node_online_map); - ret = numa_memblks_init(init_func, /* memblock_force_top_down */ false); if (ret < 0) goto out_free_distance; diff --git a/drivers/base/memory.c b/drivers/base/memory.c index bcfe2d9f4adb..5eead3346f1e 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -46,6 +46,15 @@ int mhp_online_type_from_str(const char *str) } return -EINVAL; } +EXPORT_SYMBOL_GPL(mhp_online_type_from_str); + +const char *mhp_online_type_to_str(int online_type) +{ + if (online_type < 0 || online_type >= (int)ARRAY_SIZE(online_type_to_str)) + return NULL; + return online_type_to_str[online_type]; +} +EXPORT_SYMBOL_GPL(mhp_online_type_to_str); #define to_memory_block(dev) container_of(dev, struct memory_block, dev) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 63253d1de5d7..dcfd896b733d 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -506,11 +506,7 @@ static int mmap_zero_prepare(struct vm_area_desc *desc) if (vma_desc_test(desc, VMA_SHARED_BIT)) return shmem_zero_setup_desc(desc); - /* - * This is a highly unique situation where we mark a MAP_PRIVATE mapping - * of /dev/zero anonymous, despite it not being. - */ - vma_desc_set_anonymous(desc); + /* MAP_PRIVATE semantics are taken care for us by core mm. */ return 0; } @@ -698,7 +694,7 @@ static const struct memdev { #ifdef CONFIG_DEVPORT [4] = { "port", &port_fops, 0, 0 }, #endif - [5] = { "zero", &zero_fops, FMODE_NOWAIT, 0666 }, + [DEVZERO_MINOR] = { "zero", &zero_fops, FMODE_NOWAIT, 0666 }, [7] = { "full", &full_fops, 0, 0666 }, [8] = { "random", &random_fops, FMODE_NOWAIT, 0666 }, [9] = { "urandom", &urandom_fops, FMODE_NOWAIT, 0666 }, diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h index 5909171a4428..bfc31923f3ff 100644 --- a/drivers/dax/bus.h +++ b/drivers/dax/bus.h @@ -16,6 +16,8 @@ struct dax_region; #define IORESOURCE_DAX_STATIC BIT(0) #define IORESOURCE_DAX_KMEM BIT(1) +#define DAX_KMEM_UNPLUGGED (-1) /* Do not create memory blocks */ + struct dax_region *alloc_dax_region(struct device *parent, int region_id, struct range *range, int target_node, unsigned int align, unsigned long flags); diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c index a18e2b968e4d..a48d699cf344 100644 --- a/drivers/dax/kmem.c +++ b/drivers/dax/kmem.c @@ -33,9 +33,7 @@ static int dax_kmem_range(struct dev_dax *dev_dax, int i, struct range *r) struct dev_dax_range *dax_range = &dev_dax->ranges[i]; struct range *range = &dax_range->range; - /* memory-block align the hotplug range */ - r->start = ALIGN(range->start, memory_block_size_bytes()); - r->end = ALIGN_DOWN(range->end + 1, memory_block_size_bytes()) - 1; + *r = memory_block_aligned_range(range); if (r->start >= r->end) { r->start = range->start; r->end = range->end; @@ -47,6 +45,8 @@ static int dax_kmem_range(struct dev_dax *dev_dax, int i, struct range *r) struct dax_kmem_data { const char *res_name; int mgid; + int state; + struct mutex lock; /* protects hotplug state transitions */ struct resource *res[]; }; @@ -65,16 +65,331 @@ static void kmem_put_memory_types(void) mt_put_memory_types(&kmem_memory_types); } +/* True for the online states a kmem dax device can hold. */ +static bool dax_kmem_state_is_online(int state) +{ + return state == MMOP_ONLINE || + state == MMOP_ONLINE_KERNEL || + state == MMOP_ONLINE_MOVABLE; +} + +/** + * dax_kmem_do_hotplug - hotplug memory for dax kmem device + * @dev_dax: the dev_dax instance + * @data: the dax_kmem_data structure with resource tracking + * @online_type: the online policy to use for the memory blocks + * + * Hotplugs all ranges in the dev_dax region as system memory with the + * provided online policy (offline, online, online_movable, online_kernel). + * + * Returns the number of successfully mapped ranges, or negative error. + */ +static int dax_kmem_do_hotplug(struct dev_dax *dev_dax, + struct dax_kmem_data *data, + int online_type) +{ + struct device *dev = &dev_dax->dev; + int i, rc, added = 0; + mhp_t mhp_flags; + + if (dax_kmem_state_is_online(data->state)) + return -EINVAL; + + if (online_type < MMOP_OFFLINE || online_type > MMOP_ONLINE_MOVABLE) + return -EINVAL; + + for (i = 0; i < dev_dax->nr_range; i++) { + struct range range; + + rc = dax_kmem_range(dev_dax, i, &range); + if (rc) + continue; + + /* + * init_resources() is best-effort: if a reservation conflict + * occurs it keeps the range but leaves res[i]=NULL. For hotplug + * on probe systems, this means kmem will partially online. + * + * We have to keep this behavior not to break those systems. + * For those systems - atomicity only applies to valid ranges. + */ + if (!data->res[i]) + continue; + + mhp_flags = MHP_NID_IS_MGID; + if (dev_dax->memmap_on_memory) + mhp_flags |= MHP_MEMMAP_ON_MEMORY; + + /* + * Ensure that future kexec'd kernels will not treat + * this as RAM automatically. + */ + rc = __add_memory_driver_managed(data->mgid, range.start, + range_len(&range), kmem_name, mhp_flags, + online_type); + + if (rc) { + dev_warn(dev, "mapping%d: %#llx-%#llx memory add failed\n", + i, range.start, range.end); + /* + * Release the reservation for the range that failed to + * add so a later hotremove does not try to remove memory + * that was never added. + */ + if (data->res[i]) { + remove_resource(data->res[i]); + kfree(data->res[i]); + data->res[i] = NULL; + } + if (added) + continue; + return rc; + } + added++; + } + + return added; +} + +/** + * dax_kmem_init_resources - create memory regions for dax kmem + * @dev_dax: the dev_dax instance + * @data: the dax_kmem_data structure with resource tracking + * + * Initializes all the resources for the DAX + * + * Returns the number of successfully mapped ranges, or negative error. + */ +static int dax_kmem_init_resources(struct dev_dax *dev_dax, + struct dax_kmem_data *data) +{ + struct device *dev = &dev_dax->dev; + int i, rc, mapped = 0; + + for (i = 0; i < dev_dax->nr_range; i++) { + struct resource *res; + struct range range; + + rc = dax_kmem_range(dev_dax, i, &range); + if (rc) + continue; + + /* Skip ranges already added */ + if (data->res[i]) + continue; + + /* Region is permanently reserved if hotremove fails. */ + res = request_mem_region(range.start, range_len(&range), + data->res_name); + if (!res) { + dev_warn(dev, "mapping%d: %#llx-%#llx could not reserve region\n", + i, range.start, range.end); + /* + * Once some memory has been onlined we can't + * assume that it can be un-onlined safely. + */ + if (mapped) + continue; + return -EBUSY; + } + data->res[i] = res; + /* + * Set flags appropriate for System RAM. Leave ..._BUSY clear + * so that add_memory() can add a child resource. Do not + * inherit flags from the parent since it may set new flags + * unknown to us that will break add_memory() later. + */ + res->flags = IORESOURCE_SYSTEM_RAM; + mapped++; + } + return mapped; +} + +#ifdef CONFIG_MEMORY_HOTREMOVE +/** + * dax_kmem_do_hotremove - hot-remove memory for dax kmem device + * @dev_dax: the dev_dax instance + * @data: the dax_kmem_data structure with resource tracking + * + * Offlines and removes every currently-added range in the dev_dax region + * atomically: either all ranges are offlined and removed, or none are and + * the device is returned to its prior state. + * + * Returns 0 on success, or a negative errno on failure. + */ +static int dax_kmem_do_hotremove(struct dev_dax *dev_dax, + struct dax_kmem_data *data) +{ + struct device *dev = &dev_dax->dev; + struct range *ranges; + int i, nr_ranges = 0, rc; + + ranges = kmalloc_objs(*ranges, dev_dax->nr_range); + if (!ranges) + return -ENOMEM; + + /* Collect the ranges that were actually added during probe. */ + for (i = 0; i < dev_dax->nr_range; i++) { + struct range range; + + if (!data->res[i]) + continue; + if (dax_kmem_range(dev_dax, i, &range)) + continue; + ranges[nr_ranges++] = range; + } + + /* Nothing added means nothing to remove. */ + if (!nr_ranges) { + kfree(ranges); + return 0; + } + + rc = offline_and_remove_memory_ranges(ranges, nr_ranges); + kfree(ranges); + if (rc) { + /* Recoverable: the ranges rolled back, nothing is leaked yet. */ + dev_err(dev, "hotremove failed, device left online: %d\n", rc); + return rc; + } + + /* All ranges removed; release the reserved resources. */ + for (i = 0; i < dev_dax->nr_range; i++) { + if (!data->res[i]) + continue; + remove_resource(data->res[i]); + kfree(data->res[i]); + data->res[i] = NULL; + } + + return 0; +} +#else +static int dax_kmem_do_hotremove(struct dev_dax *dev_dax, + struct dax_kmem_data *data) +{ + return -EBUSY; +} +#endif /* CONFIG_MEMORY_HOTREMOVE */ + +/** + * dax_kmem_cleanup_resources - remove the dax memory resources + * @dev_dax: the dev_dax instance + * @data: the dax_kmem_data structure with resource tracking + * + * Removes all resources in the dev_dax region. + */ +static void dax_kmem_cleanup_resources(struct dev_dax *dev_dax, + struct dax_kmem_data *data) +{ + int i; + + /* + * If the device unbind occurs before memory is hotremoved, we can never + * remove the memory (requires reboot). Attempting an offline operation + * here may cause deadlock and a failure to finish the unbind. + * + * Note: This leaks the resources. + */ + if (WARN(((data->state != DAX_KMEM_UNPLUGGED) && + (data->state != MMOP_OFFLINE)), + "Hotplug memory regions stuck online until reboot")) + return; + + for (i = 0; i < dev_dax->nr_range; i++) { + if (!data->res[i]) + continue; + remove_resource(data->res[i]); + kfree(data->res[i]); + data->res[i] = NULL; + } +} + +static int dax_kmem_parse_state(const char *buf) +{ + int online_type; + + /* "unplugged" is kmem-specific - the rest map to MMOP_ */ + if (sysfs_streq(buf, "unplugged")) + return DAX_KMEM_UNPLUGGED; + + online_type = mhp_online_type_from_str(buf); + /* Disallow "offline": it's not useful and creates race conditions */ + if (online_type == MMOP_OFFLINE) + return -EINVAL; + return online_type; +} + +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dax_kmem_data *data = dev_get_drvdata(dev); + const char *state_str; + + if (data->state == DAX_KMEM_UNPLUGGED) + state_str = "unplugged"; + else + state_str = mhp_online_type_to_str(data->state); + + return sysfs_emit(buf, "%s\n", state_str ?: "unknown"); +} + +static ssize_t state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct dev_dax *dev_dax = to_dev_dax(dev); + struct dax_kmem_data *data = dev_get_drvdata(dev); + int online_type; + int rc; + + online_type = dax_kmem_parse_state(buf); + if (online_type < DAX_KMEM_UNPLUGGED) + return online_type; + + guard(mutex)(&data->lock); + + /* Already in requested state */ + if (data->state == online_type) + return len; + + if (online_type == DAX_KMEM_UNPLUGGED) { + rc = dax_kmem_do_hotremove(dev_dax, data); + if (rc) + return rc; + data->state = DAX_KMEM_UNPLUGGED; + return len; + } + + /* Onlining is only allowed from the unplugged state. */ + if (data->state != DAX_KMEM_UNPLUGGED) + return -EBUSY; + + /* Re-acquire resources if previously unplugged, otherwise no-op */ + rc = dax_kmem_init_resources(dev_dax, data); + if (rc < 0) + return rc; + + rc = dax_kmem_do_hotplug(dev_dax, data, online_type); + if (rc < 0) { + /* Total failure, drop the reservations we took. */ + dax_kmem_cleanup_resources(dev_dax, data); + return rc; + } + + data->state = online_type; + return len; +} + static int dev_dax_kmem_probe(struct dev_dax *dev_dax) { struct device *dev = &dev_dax->dev; unsigned long total_len = 0, orig_len = 0; struct dax_kmem_data *data; struct memory_dev_type *mtype; - int i, rc, mapped = 0; - mhp_t mhp_flags; + int i, rc; int numa_node; int adist = MEMTIER_DEFAULT_DAX_ADISTANCE; + int online_type = mhp_get_default_online_type(); /* * Ensure good NUMA information for the persistent memory. @@ -133,68 +448,26 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax) if (rc < 0) goto err_reg_mgid; data->mgid = rc; + data->state = DAX_KMEM_UNPLUGGED; + mutex_init(&data->lock); - for (i = 0; i < dev_dax->nr_range; i++) { - struct resource *res; - struct range range; - - rc = dax_kmem_range(dev_dax, i, &range); - if (rc) - continue; - - /* Region is permanently reserved if hotremove fails. */ - res = request_mem_region(range.start, range_len(&range), data->res_name); - if (!res) { - dev_warn(dev, "mapping%d: %#llx-%#llx could not reserve region\n", - i, range.start, range.end); - /* - * Once some memory has been onlined we can't - * assume that it can be un-onlined safely. - */ - if (mapped) - continue; - rc = -EBUSY; - goto err_request_mem; - } - data->res[i] = res; - - /* - * Set flags appropriate for System RAM. Leave ..._BUSY clear - * so that add_memory() can add a child resource. Do not - * inherit flags from the parent since it may set new flags - * unknown to us that will break add_memory() below. - */ - res->flags = IORESOURCE_SYSTEM_RAM; - - mhp_flags = MHP_NID_IS_MGID; - if (dev_dax->memmap_on_memory) - mhp_flags |= MHP_MEMMAP_ON_MEMORY; - - /* - * Ensure that future kexec'd kernels will not treat - * this as RAM automatically. - */ - rc = add_memory_driver_managed(data->mgid, range.start, - range_len(&range), kmem_name, mhp_flags); + dev_set_drvdata(dev, data); - if (rc) { - dev_warn(dev, "mapping%d: %#llx-%#llx memory add failed\n", - i, range.start, range.end); - remove_resource(res); - kfree(res); - data->res[i] = NULL; - if (mapped) - continue; - goto err_request_mem; - } - mapped++; - } + rc = dax_kmem_init_resources(dev_dax, data); + if (rc < 0) + goto err_resources; - dev_set_drvdata(dev, data); + rc = dax_kmem_do_hotplug(dev_dax, data, online_type); + if (rc < 0) + goto err_hotplug; + data->state = online_type; return 0; -err_request_mem: +err_hotplug: + dax_kmem_cleanup_resources(dev_dax, data); +err_resources: + dev_set_drvdata(dev, NULL); memory_group_unregister(data->mgid); err_reg_mgid: kfree(data->res_name); @@ -206,61 +479,71 @@ err_dax_kmem_data: } #ifdef CONFIG_MEMORY_HOTREMOVE -static void dev_dax_kmem_remove(struct dev_dax *dev_dax) +/* + * Remove the device's added ranges with remove_memory(). + * Unlike the sysfs unplug path it never offlines and fails if the blocks are + * online (-EBUSY), so it is safe from unbind. Failures leak until reboot. + * + * Returns 0 only if every added range was removed. + */ +static int dax_kmem_remove_ranges(struct dev_dax *dev_dax, + struct dax_kmem_data *data) { - int i, success = 0; - int node = dev_dax->target_node; struct device *dev = &dev_dax->dev; - struct dax_kmem_data *data = dev_get_drvdata(dev); + int i, rc = 0; - /* - * We have one shot for removing memory, if some memory blocks were not - * offline prior to calling this function remove_memory() will fail, and - * there is no way to hotremove this memory until reboot because device - * unbind will succeed even if we return failure. - */ for (i = 0; i < dev_dax->nr_range; i++) { struct range range; - int rc; - rc = dax_kmem_range(dev_dax, i, &range); - if (rc) + if (!data->res[i] || dax_kmem_range(dev_dax, i, &range)) continue; - - /* range was never added during probe */ - if (!data->res[i]) { - success++; + if (remove_memory(range.start, range_len(&range))) { + dev_warn(dev, "mapping%d: %#llx-%#llx stuck online until reboot\n", + i, range.start, range.end); + rc = -EBUSY; continue; } + remove_resource(data->res[i]); + kfree(data->res[i]); + data->res[i] = NULL; + } + return rc; +} - rc = remove_memory(range.start, range_len(&range)); - if (rc == 0) { - remove_resource(data->res[i]); - kfree(data->res[i]); - data->res[i] = NULL; - success++; - continue; - } +static void dev_dax_kmem_remove(struct dev_dax *dev_dax) +{ + int node = dev_dax->target_node; + struct device *dev = &dev_dax->dev; + struct dax_kmem_data *data = dev_get_drvdata(dev); + + /* + * Remove every range that is still added. dax_kmem_remove_ranges() + * uses remove_memory(), which never offlines: an online block fails + * with -EBUSY rather than deadlocking an uninterruptible unbind. + * + * data->state only tracks daxX.Y/state writes, so it can be stale if + * blocks were toggled via memoryX/state. Do not trust it here and + * attempt simply remove_memory() - which reports the true state of + * each range anyway. Anything left online is leaked until reboot. + */ + if (dax_kmem_remove_ranges(dev_dax, data)) { + dev_err(dev, "Hotplug regions stuck online until reboot\n"); any_hotremove_failed = true; - dev_err(dev, - "mapping%d: %#llx-%#llx cannot be hotremoved until the next reboot\n", - i, range.start, range.end); + return; } - if (success >= dev_dax->nr_range) { - memory_group_unregister(data->mgid); - kfree(data->res_name); - kfree(data); - dev_set_drvdata(dev, NULL); - /* - * Clear the memtype association on successful unplug. - * If not, we have memory blocks left which can be - * offlined/onlined later. We need to keep memory_dev_type - * for that. This implies this reference will be around - * till next reboot. - */ - clear_node_memory_type(node, NULL); - } + memory_group_unregister(data->mgid); + kfree(data->res_name); + kfree(data); + dev_set_drvdata(dev, NULL); + /* + * Clear the memtype association on successful unplug. + * If not, we have memory blocks left which can be + * offlined/onlined later. We need to keep memory_dev_type + * for that. This implies this reference will be around + * till next reboot. + */ + clear_node_memory_type(node, NULL); } #else static void dev_dax_kmem_remove(struct dev_dax *dev_dax) @@ -276,10 +559,21 @@ static void dev_dax_kmem_remove(struct dev_dax *dev_dax) } #endif /* CONFIG_MEMORY_HOTREMOVE */ +static DEVICE_ATTR_RW(state); + +static struct attribute *dev_dax_kmem_attrs[] = { + &dev_attr_state.attr, + NULL, +}; +ATTRIBUTE_GROUPS(dev_dax_kmem); + static struct dax_device_driver device_dax_kmem_driver = { .probe = dev_dax_kmem_probe, .remove = dev_dax_kmem_remove, .type = DAXDRV_KMEM_TYPE, + .drv = { + .dev_groups = dev_dax_kmem_groups, + }, }; static int __init dax_kmem_init(void) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index e3ed684ddcf2..32a05d889b9a 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -1252,7 +1252,7 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, } vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_writecombine(vma_get_page_prot(vma)); vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); } diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c index 1c00a71ab3c9..7d9612075d31 100644 --- a/drivers/gpu/drm/drm_gem_dma_helper.c +++ b/drivers/gpu/drm/drm_gem_dma_helper.c @@ -540,7 +540,7 @@ int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct * vm_flags_mod(vma, VM_DONTDUMP | VM_DONTEXPAND, VM_PFNMAP); if (dma_obj->map_noncoherent) { - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); ret = dma_mmap_pages(drm_dev_dma_dev(dma_obj->base.dev), vma, vma->vm_end - vma->vm_start, diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index c989459eb215..06d019d51d3e 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -764,7 +764,7 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct return ret; vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); if (shmem->map_wc) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 18ddef94da47..cdb1521eb1cf 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -773,8 +773,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range, .end = end, .dev_private_owner = dev_private_owner, }; - unsigned long timeout = - jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); enum drm_gpusvm_scan_result state = DRM_GPUSVM_SCAN_UNPOPULATED, new_state; unsigned long *pfns; unsigned long npages = npages_in_range(start, end); @@ -788,22 +787,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range, hmm_range.hmm_pfns = pfns; retry: - hmm_range.notifier_seq = mmu_interval_read_begin(notifier); - mmap_read_lock(range->gpusvm->mm); - - while (true) { - err = hmm_range_fault(&hmm_range); - if (err == -EBUSY) { - if (time_after(jiffies, timeout)) - break; - - hmm_range.notifier_seq = - mmu_interval_read_begin(notifier); - continue; - } - break; - } - mmap_read_unlock(range->gpusvm->mm); + err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout); if (err) goto err_free; @@ -1423,6 +1407,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, void *zdd; unsigned long timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long remaining; unsigned long i, j; unsigned long npages = npages_in_range(pages_start, pages_end); unsigned long num_dma_mapped; @@ -1437,9 +1422,11 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, struct dma_iova_state *state = &svm_pages->state; retry: - if (time_after(jiffies, timeout)) + if (time_after_eq(jiffies, timeout)) return -EBUSY; + remaining = timeout - jiffies; + hmm_range.notifier_seq = mmu_interval_read_begin(notifier); if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages)) goto set_seqno; @@ -1454,21 +1441,7 @@ retry: } hmm_range.hmm_pfns = pfns; - while (true) { - mmap_read_lock(mm); - err = hmm_range_fault(&hmm_range); - mmap_read_unlock(mm); - - if (err == -EBUSY) { - if (time_after(jiffies, timeout)) - break; - - hmm_range.notifier_seq = - mmu_interval_read_begin(notifier); - continue; - } - break; - } + err = hmm_range_fault_unlocked_timeout(&hmm_range, remaining); mmput(mm); if (err) goto err_free; @@ -1741,8 +1714,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm, .end = drm_gpusvm_range_end(range), .dev_private_owner = NULL, }; - unsigned long timeout = - jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); unsigned long *pfns; unsigned long npages = npages_in_range(drm_gpusvm_range_start(range), drm_gpusvm_range_end(range)); @@ -1759,24 +1731,12 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm, } hmm_range.hmm_pfns = pfns; - while (!time_after(jiffies, timeout)) { - hmm_range.notifier_seq = mmu_interval_read_begin(notifier); - if (time_after(jiffies, timeout)) { - err = -ETIME; - break; - } - - mmap_read_lock(mm); - err = hmm_range_fault(&hmm_range); - mmap_read_unlock(mm); - if (err != -EBUSY) - break; - } + err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout); kvfree(pfns); mmput(mm); - return err; + return err == -EBUSY ? -ETIME : err; } EXPORT_SYMBOL_GPL(drm_gpusvm_range_evict); diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c index 4a794544b7dc..f00c27edbfb9 100644 --- a/drivers/gpu/drm/drm_pagemap.c +++ b/drivers/gpu/drm/drm_pagemap.c @@ -12,7 +12,7 @@ #include <drm/drm_pagemap_util.h> #include <drm/drm_print.h> -#if IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION) +#if IS_ENABLED(CONFIG_ARCH_HAS_PMD_SOFTLEAVES) #define DRM_PAGEMAP_PMD_ORDER HPAGE_PMD_ORDER #else #define DRM_PAGEMAP_PMD_ORDER (-1) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index b0436a1e103f..f9c8b7b2bfc7 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -6,6 +6,7 @@ #include <drm/drm_prime.h> #include <drm/drm_print.h> #include <linux/dma-mapping.h> +#include <linux/pagemap.h> #include <linux/shmem_fs.h> #include <linux/spinlock.h> #include <linux/vmalloc.h> @@ -132,7 +133,7 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj, vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); - vm_page_prot = vm_get_page_prot(vma->vm_flags); + vm_page_prot = vma_get_page_prot(vma); if (etnaviv_obj->flags & ETNA_BO_WC) { vma->vm_page_prot = pgprot_writecombine(vm_page_prot); @@ -188,7 +189,7 @@ static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf) } /* We don't use vmf->pgoff since that has the fake offset: */ - pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT; + pgoff = linear_page_delta(vma, vmf->address); pfn = page_to_pfn(pages[pgoff]); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 9a6270f3dca6..0208c9259572 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -377,13 +377,13 @@ static int exynos_drm_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct /* non-cachable as default. */ if (exynos_gem->flags & EXYNOS_BO_CACHABLE) - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); else if (exynos_gem->flags & EXYNOS_BO_WC) vma->vm_page_prot = - pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + pgprot_writecombine(vma_get_page_prot(vma)); else vma->vm_page_prot = - pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + pgprot_noncached(vma_get_page_prot(vma)); ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma); if (ret) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 88f1e86c8903..2708e8c68f4c 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -288,7 +288,7 @@ static vm_fault_t psb_gem_fault(struct vm_fault *vmf) /* Page relative to the VMA start - we must calculate this ourselves because vmf->pgoff is the fake GEM offset */ - page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT; + page_offset = linear_page_delta(vma, vmf->address); /* CPU view of the page, don't go via the GART for CPU writes */ if (pobj->stolen) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 0644f85c6c8e..9ca90c1bb5b4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -112,7 +112,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, vma = find_vma(mm, addr); if (vma && __vma_matches(vma, obj->base.filp, addr, args->size)) vma->vm_page_prot = - pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + pgprot_writecombine(vma_get_page_prot(vma)); else addr = -ENOMEM; mmap_write_unlock(mm); @@ -1024,7 +1024,7 @@ i915_gem_object_mmap(struct drm_i915_gem_object *obj, fput(anon); if (obj->ops->mmap_ops) { - vma->vm_page_prot = pgprot_decrypted(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_decrypted(vma_get_page_prot(vma)); vma->vm_ops = obj->ops->mmap_ops; vma->vm_private_data = obj->base.vma_node.driver_private; return 0; @@ -1035,7 +1035,7 @@ i915_gem_object_mmap(struct drm_i915_gem_object *obj, switch (mmo->mmap_type) { case I915_MMAP_TYPE_WC: vma->vm_page_prot = - pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + pgprot_writecombine(vma_get_page_prot(vma)); vma->vm_ops = &vm_ops_cpu; break; @@ -1043,19 +1043,19 @@ i915_gem_object_mmap(struct drm_i915_gem_object *obj, GEM_WARN_ON(1); fallthrough; case I915_MMAP_TYPE_WB: - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); vma->vm_ops = &vm_ops_cpu; break; case I915_MMAP_TYPE_UC: vma->vm_page_prot = - pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + pgprot_noncached(vma_get_page_prot(vma)); vma->vm_ops = &vm_ops_cpu; break; case I915_MMAP_TYPE_GTT: vma->vm_page_prot = - pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + pgprot_writecombine(vma_get_page_prot(vma)); vma->vm_ops = &vm_ops_gtt; break; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 06543ae60706..ef9440166295 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -325,7 +325,7 @@ void __shmem_writeback(size_t size, struct address_space *mapping) if (folio_mapped(folio)) folio_redirty_for_writepage(&wbc, folio); else - error = shmem_writeout(folio, NULL, NULL); + error = shmem_write_folio(folio); } } diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index efd3d3c9a449..6a78e242de7c 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -9,6 +9,7 @@ #include <linux/spinlock.h> #include <linux/shmem_fs.h> #include <linux/dma-buf.h> +#include <linux/pagemap.h> #include <drm/drm_dumb_buffers.h> #include <drm/drm_prime.h> @@ -360,7 +361,7 @@ static vm_fault_t msm_gem_fault(struct vm_fault *vmf) } /* We don't use vmf->pgoff since that has the fake offset: */ - pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT; + pgoff = linear_page_delta(vma, vmf->address); pfn = page_to_pfn(pages[pgoff]); @@ -1124,7 +1125,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct struct msm_gem_object *msm_obj = to_msm_bo(obj); vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = msm_gem_pgprot(msm_obj, vma_get_page_prot(vma)); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 20dba02d6175..9a6ee2e880c0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -55,7 +55,7 @@ static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) goto error_unlock; nouveau_bo_del_io_reserve_lru(bo); - prot = vm_get_page_prot(vma->vm_flags); + prot = vma_get_page_prot(vma); ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT); nouveau_bo_add_io_reserve_lru(bo); if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c index dcc92131488e..58735446d783 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -678,20 +678,22 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm, range.end = notifier->notifier.interval_tree.last + 1; while (true) { - if (time_after(jiffies, timeout)) { + long remaining = timeout - jiffies; + + /* + * The HMM timeout only bounds retries while HMM is walking and + * faulting the range. This fault is handled by a kernel worker, + * so fatal signals from the faulting process cannot stop an + * endless stream of invalidations here. + */ + if (time_after_eq(jiffies, timeout)) { ret = -EBUSY; goto out; } - range.notifier_seq = mmu_interval_read_begin(range.notifier); - mmap_read_lock(mm); - ret = hmm_range_fault(&range); - mmap_read_unlock(mm); - if (ret) { - if (ret == -EBUSY) - continue; + ret = hmm_range_fault_unlocked_timeout(&range, remaining); + if (ret) goto out; - } mutex_lock(&svmm->mutex); if (mmu_interval_read_retry(range.notifier, diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index ca3fb186bf19..4881777642d2 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -84,7 +84,7 @@ fallback: static int omap_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { - vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_writecombine(vma_get_page_prot(vma)); return fb_deferred_io_mmap(info, vma); } diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 8e013e4f2c6b..fb0e6f556b31 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -5,6 +5,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/pagemap.h> #include <linux/seq_file.h> #include <linux/shmem_fs.h> #include <linux/spinlock.h> @@ -359,7 +360,7 @@ static vm_fault_t omap_gem_fault_1d(struct drm_gem_object *obj, pgoff_t pgoff; /* We don't use vmf->pgoff since that has the fake offset: */ - pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT; + pgoff = linear_page_delta(vma, vmf->address); if (omap_obj->pages) { omap_gem_cpu_sync_page(obj, pgoff); @@ -407,7 +408,7 @@ static vm_fault_t omap_gem_fault_2d(struct drm_gem_object *obj, const int m = DIV_ROUND_UP(omap_obj->width << fmt, PAGE_SIZE); /* We don't use vmf->pgoff since that has the fake offset: */ - pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT; + pgoff = linear_page_delta(vma, vmf->address); /* * Actual address we start mapping at is rounded down to previous slot @@ -537,9 +538,9 @@ static int omap_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP | VM_IO | VM_MIXEDMAP); if (omap_obj->flags & OMAP_BO_WC) { - vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_writecombine(vma_get_page_prot(vma)); } else if (omap_obj->flags & OMAP_BO_UNCACHED) { - vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_noncached(vma_get_page_prot(vma)); } else { /* * We do have some private objects, at least for scanout buffers @@ -557,7 +558,7 @@ static int omap_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); vma_set_file(vma, obj->filp); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); } vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c index a1e2eb1ca7bb..770556353968 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.c +++ b/drivers/gpu/drm/panthor/panthor_gem.c @@ -776,7 +776,7 @@ static int panthor_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *v } vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); if (should_map_wc(bo)) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index b188539dca0b..9a1dc9f12072 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -255,7 +255,7 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj, */ vm_flags_mod(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP, VM_PFNMAP); - vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_writecombine(vma_get_page_prot(vma)); vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); if (rk_obj->pages) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 436394e04812..f76af733ea79 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -13,6 +13,7 @@ #include <linux/dma-buf.h> #include <linux/iommu.h> #include <linux/module.h> +#include <linux/pagemap.h> #include <linux/vmalloc.h> #include <drm/drm_drv.h> @@ -564,7 +565,7 @@ static vm_fault_t tegra_bo_fault(struct vm_fault *vmf) if (!bo->pages) return VM_FAULT_SIGBUS; - offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT; + offset = linear_page_delta(vma, vmf->address); page = bo->pages[offset]; return vmf_insert_page(vma, vmf->address, page); @@ -601,7 +602,7 @@ int __tegra_gem_mmap(struct drm_gem_object *gem, struct vm_area_struct *vma) vma->vm_pgoff = vm_pgoff; } else { - pgprot_t prot = vm_get_page_prot(vma->vm_flags); + pgprot_t prot = vma_get_page_prot(vma); vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP); diff --git a/drivers/gpu/drm/ttm/ttm_backup.c b/drivers/gpu/drm/ttm/ttm_backup.c index 3c067aadc52d..658eeab73255 100644 --- a/drivers/gpu/drm/ttm/ttm_backup.c +++ b/drivers/gpu/drm/ttm/ttm_backup.c @@ -160,7 +160,7 @@ ttm_backup_backup_folio(struct file *backup, struct folio *folio, if (writeback && !folio_mapped(to_folio) && folio_clear_dirty_for_io(to_folio)) { folio_set_reclaim(to_folio); - ret = shmem_writeout(to_folio, NULL, NULL); + ret = shmem_write_folio(to_folio); if (!folio_test_writeback(to_folio)) folio_clear_reclaim(to_folio); if (ret == AOP_WRITEPAGE_ACTIVATE) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index a80510489c45..88babf435ac2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -32,6 +32,7 @@ #define pr_fmt(fmt) "[TTM] " fmt #include <linux/export.h> +#include <linux/pagemap.h> #include <drm/ttm/ttm_bo.h> #include <drm/ttm/ttm_placement.h> @@ -208,9 +209,9 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, if (unlikely(err != 0)) return VM_FAULT_SIGBUS; - page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + - vma->vm_pgoff - drm_vma_node_start(&bo->base.vma_node); - page_last = vma_pages(vma) + vma->vm_pgoff - + page_offset = linear_page_index(vma, address) - + drm_vma_node_start(&bo->base.vma_node); + page_last = vma_end_pgoff(vma) - drm_vma_node_start(&bo->base.vma_node); if (unlikely(page_offset >= PFN_UP(bo->base.size))) diff --git a/drivers/gpu/drm/virtio/virtgpu_vram.c b/drivers/gpu/drm/virtio/virtgpu_vram.c index 4ae3cbc35dd3..544a6abddbc8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vram.c +++ b/drivers/gpu/drm/virtio/virtgpu_vram.c @@ -55,7 +55,7 @@ static int virtio_gpu_vram_mmap(struct drm_gem_object *obj, vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); vm_flags_set(vma, VM_MIXEDMAP | VM_DONTEXPAND); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); vma->vm_ops = &virtio_gpu_vram_vm_ops; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c index 45561bc1c9ef..a9fd4015a0ca 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c @@ -481,7 +481,7 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf) if (vbo->dirty && vbo->dirty->method == VMW_BO_DIRTY_MKWRITE) prot = vm_get_page_prot(vma->vm_flags & ~VM_SHARED); else - prot = vm_get_page_prot(vma->vm_flags); + prot = vma_get_page_prot(vma); ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault); if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index dcb48caa485d..9d119c95a569 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -281,7 +281,7 @@ static vm_fault_t barrier_fault(struct vm_fault *vmf) pgprot_t prot; int idx; - prot = vm_get_page_prot(vma->vm_flags); + prot = vma_get_page_prot(vma); if (drm_dev_enter(dev, &idx)) { unsigned long pfn; diff --git a/drivers/gpu/drm/xe/xe_mmio_gem.c b/drivers/gpu/drm/xe/xe_mmio_gem.c index 8c803ef233cc..3741ae60f532 100644 --- a/drivers/gpu/drm/xe/xe_mmio_gem.c +++ b/drivers/gpu/drm/xe/xe_mmio_gem.c @@ -149,7 +149,7 @@ static int xe_mmio_gem_mmap(struct drm_gem_object *base, struct vm_area_struct * /* Set vm_pgoff (used as a fake buffer offset by DRM) to 0 */ vma->vm_pgoff = 0; - vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + vma->vm_page_prot = pgprot_noncached(vma_get_page_prot(vma)); vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_DONTCOPY | VM_NORESERVE); diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index eec4c1da3f9e..dd158443f55f 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -80,7 +80,7 @@ static int xen_drm_front_gem_object_mmap(struct drm_gem_object *gem_obj, * which is mapped as Normal Inner Write-Back Outer Write-Back * Inner-Shareable. */ - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); /* * vm_operations_struct.fault handler will be called if CPU access diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c index 6d65e5b42152..dddaade31b5d 100644 --- a/drivers/hv/mshv_regions.c +++ b/drivers/hv/mshv_regions.c @@ -382,46 +382,6 @@ int mshv_region_get(struct mshv_mem_region *region) } /** - * mshv_region_hmm_fault_and_lock - Handle HMM faults and lock the memory region - * @region: Pointer to the memory region structure - * @range: Pointer to the HMM range structure - * - * This function performs the following steps: - * 1. Reads the notifier sequence for the HMM range. - * 2. Acquires a read lock on the memory map. - * 3. Handles HMM faults for the specified range. - * 4. Releases the read lock on the memory map. - * 5. If successful, locks the memory region mutex. - * 6. Verifies if the notifier sequence has changed during the operation. - * If it has, releases the mutex and returns -EBUSY to match with - * hmm_range_fault() return code for repeating. - * - * Return: 0 on success, a negative error code otherwise. - */ -static int mshv_region_hmm_fault_and_lock(struct mshv_mem_region *region, - struct hmm_range *range) -{ - int ret; - - range->notifier_seq = mmu_interval_read_begin(range->notifier); - mmap_read_lock(region->mreg_mni.mm); - ret = hmm_range_fault(range); - mmap_read_unlock(region->mreg_mni.mm); - if (ret) - return ret; - - mutex_lock(®ion->mreg_mutex); - - if (mmu_interval_read_retry(range->notifier, range->notifier_seq)) { - mutex_unlock(®ion->mreg_mutex); - cond_resched(); - return -EBUSY; - } - - return 0; -} - -/** * mshv_region_range_fault - Handle memory range faults for a given region. * @region: Pointer to the memory region structure. * @page_offset: Offset of the page within the region. @@ -452,13 +412,19 @@ static int mshv_region_range_fault(struct mshv_mem_region *region, range.start = region->start_uaddr + page_offset * HV_HYP_PAGE_SIZE; range.end = range.start + page_count * HV_HYP_PAGE_SIZE; - do { - ret = mshv_region_hmm_fault_and_lock(region, &range); - } while (ret == -EBUSY); - +again: + ret = hmm_range_fault_unlocked_timeout(&range, 0); if (ret) goto out; + mutex_lock(®ion->mreg_mutex); + + if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) { + mutex_unlock(®ion->mreg_mutex); + cond_resched(); + goto again; + } + for (i = 0; i < page_count; i++) region->mreg_pages[page_offset + i] = hmm_pfn_to_page(pfns[i]); diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index 404fa1cc3254..9cc21cd762d9 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -329,7 +329,7 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, struct mm_struct *owning_mm = umem_odp->umem.owning_mm; int pfn_index, dma_index, ret = 0, start_idx; unsigned int page_shift, hmm_order, pfn_start_idx; - unsigned long num_pfns, current_seq; + unsigned long num_pfns; struct hmm_range range = {}; unsigned long timeout; @@ -363,26 +363,18 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *umem_odp, u64 user_virt, } range.hmm_pfns = &(umem_odp->map.pfn_list[pfn_start_idx]); - timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); retry: - current_seq = range.notifier_seq = - mmu_interval_read_begin(&umem_odp->notifier); - - mmap_read_lock(owning_mm); - ret = hmm_range_fault(&range); - mmap_read_unlock(owning_mm); - if (unlikely(ret)) { - if (ret == -EBUSY && !time_after(jiffies, timeout)) - goto retry; + ret = hmm_range_fault_unlocked_timeout(&range, timeout); + if (unlikely(ret)) goto out_put_mm; - } start_idx = (range.start - ib_umem_start(umem_odp)) >> page_shift; dma_index = start_idx; mutex_lock(&umem_odp->umem_mutex); - if (mmu_interval_read_retry(&umem_odp->notifier, current_seq)) { + if (mmu_interval_read_retry(&umem_odp->notifier, range.notifier_seq)) { mutex_unlock(&umem_odp->umem_mutex); goto retry; } diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 772c78726893..79c2f00ed4d7 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -170,9 +170,8 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); - page = __alloc_pages_node(nid, - GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, - pg_order); + page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, + pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); diff --git a/drivers/net/ethernet/fungible/funeth/funeth_rx.c b/drivers/net/ethernet/fungible/funeth/funeth_rx.c index 7e2584895de3..d7000017ac2b 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_rx.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_rx.c @@ -103,7 +103,7 @@ static int funeth_alloc_page(struct funeth_rxq *q, struct funeth_rxbuf *rb, if (cache_get(q, rb)) return 0; - p = __alloc_pages_node(node, gfp | __GFP_NOWARN, 0); + p = alloc_pages_node(node, gfp | __GFP_NOWARN, 0); if (unlikely(!p)) return -ENOMEM; diff --git a/drivers/vfio/pci/nvgrace-gpu/main.c b/drivers/vfio/pci/nvgrace-gpu/main.c index d07dcacb76bd..963fd8ded20d 100644 --- a/drivers/vfio/pci/nvgrace-gpu/main.c +++ b/drivers/vfio/pci/nvgrace-gpu/main.c @@ -11,6 +11,7 @@ #include <linux/jiffies.h> #include <linux/sched.h> #include <linux/pci-p2pdma.h> +#include <linux/pagemap.h> #include <linux/pm_runtime.h> #include <linux/memory-failure.h> @@ -385,7 +386,7 @@ static unsigned long addr_to_pgoff(struct vm_area_struct *vma, u64 pgoff = vma->vm_pgoff & ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1); - return ((addr - vma->vm_start) >> PAGE_SHIFT) + pgoff; + return linear_page_delta(vma, addr) + pgoff; } static vm_fault_t nvgrace_gpu_vfio_pci_huge_fault(struct vm_fault *vmf, diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 3f11a9624b9c..a113c55845e1 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/notifier.h> +#include <linux/pagemap.h> #include <linux/pci.h> #include <linux/pm_runtime.h> #include <linux/slab.h> @@ -1780,7 +1781,7 @@ static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf, struct vm_area_struct *vma = vmf->vma; struct vfio_pci_core_device *vdev = vma->vm_private_data; unsigned long addr = vmf->address & ~((PAGE_SIZE << order) - 1); - unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; + unsigned long pgoff = linear_page_delta(vma, addr); unsigned long pfn = vma_to_pfn(vma) + pgoff; vm_fault_t ret = VM_FAULT_FALLBACK; diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c index 6ab60fcd0050..6d0a8c8e141a 100644 --- a/drivers/video/fbdev/core/fb_io_fops.c +++ b/drivers/video/fbdev/core/fb_io_fops.c @@ -161,7 +161,7 @@ int fb_io_mmap(struct fb_info *info, struct vm_area_struct *vma) len = info->fix.mmio_len; } - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = vma_get_page_prot(vma); vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start, vma->vm_end, start); |
