Loading drivers/staging/android/ion/ion.h +7 −0 Original line number Diff line number Diff line Loading @@ -159,6 +159,12 @@ struct ion_device { int heap_cnt; }; /* refer to include/linux/pm.h */ struct ion_pm_ops { int (*freeze)(struct ion_heap *heap); int (*restore)(struct ion_heap *heap); }; /** * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory Loading @@ -184,6 +190,7 @@ struct ion_heap_ops { int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma); int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); struct ion_pm_ops pm; }; /** Loading drivers/staging/android/ion/ion_system_secure_heap.c +38 −0 Original line number Diff line number Diff line Loading @@ -343,6 +343,41 @@ static int ion_system_secure_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, gfp_mask, nr_to_scan); } static int ion_system_secure_heap_pm_freeze(struct ion_heap *heap) { struct ion_system_secure_heap *secure_heap; unsigned long count; long sz; struct shrink_control sc = { .gfp_mask = GFP_HIGHUSER, }; secure_heap = container_of(heap, struct ion_system_secure_heap, heap); sz = atomic_long_read(&heap->total_allocated); if (sz) { pr_err("%s: %lx bytes won't be saved across hibernation. Aborting.", __func__, sz); return -EINVAL; } /* Since userspace is frozen, no more requests will be queued */ cancel_delayed_work_sync(&secure_heap->prefetch_work); count = heap->shrinker.count_objects(&heap->shrinker, &sc); sc.nr_to_scan = count; heap->shrinker.scan_objects(&heap->shrinker, &sc); count = heap->shrinker.count_objects(&heap->shrinker, &sc); if (count) { pr_err("%s: Failed to free all objects - %ld remaining", __func__, count); return -EINVAL; } return 0; } static struct ion_heap_ops system_secure_heap_ops = { .allocate = ion_system_secure_heap_allocate, .free = ion_system_secure_heap_free, Loading @@ -350,6 +385,9 @@ static struct ion_heap_ops system_secure_heap_ops = { .unmap_kernel = ion_system_secure_heap_unmap_kernel, .map_user = ion_system_secure_heap_map_user, .shrink = ion_system_secure_heap_shrink, .pm = { .freeze = ion_system_secure_heap_pm_freeze, } }; struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *unused) Loading drivers/staging/android/ion/msm/msm_ion_of.c +57 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,62 @@ static int msm_ion_probe(struct platform_device *pdev) return err; } static int msm_ion_pm_freeze(struct device *dev) { struct ion_device *ion_dev = dev_get_drvdata(dev); struct ion_heap *heap; int ret; plist_for_each_entry(heap, &ion_dev->heaps, node) { if (heap->ops->pm.freeze) { ret = heap->ops->pm.freeze(heap); if (ret) { dev_err(dev, "%s freeze callback failed\n", heap->name); goto undo; } } } return 0; undo: list_for_each_entry_continue_reverse(heap, &ion_dev->heaps.node_list, node.node_list) if (heap->ops->pm.restore) heap->ops->pm.restore(heap); return ret; } static int msm_ion_pm_restore(struct device *dev) { struct ion_device *ion_dev = dev_get_drvdata(dev); struct ion_heap *heap; int ret = 0; plist_for_each_entry(heap, &ion_dev->heaps, node) { int rc; if (heap->ops->pm.restore) { rc = heap->ops->pm.restore(heap); if (rc) { dev_err(dev, "%s restore callback failed.\n", heap->name); if (!ret) ret = rc; } } } return ret; } static const struct dev_pm_ops msm_ion_pm_ops = { .freeze = msm_ion_pm_freeze, .restore = msm_ion_pm_restore, }; static const struct of_device_id msm_ion_match_table[] = { {.compatible = ION_COMPAT_STR}, {}, Loading @@ -354,6 +410,7 @@ static struct platform_driver msm_ion_driver = { .driver = { .name = "ion-msm", .of_match_table = msm_ion_match_table, .pm = &msm_ion_pm_ops, }, }; Loading Loading
drivers/staging/android/ion/ion.h +7 −0 Original line number Diff line number Diff line Loading @@ -159,6 +159,12 @@ struct ion_device { int heap_cnt; }; /* refer to include/linux/pm.h */ struct ion_pm_ops { int (*freeze)(struct ion_heap *heap); int (*restore)(struct ion_heap *heap); }; /** * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory Loading @@ -184,6 +190,7 @@ struct ion_heap_ops { int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma); int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); struct ion_pm_ops pm; }; /** Loading
drivers/staging/android/ion/ion_system_secure_heap.c +38 −0 Original line number Diff line number Diff line Loading @@ -343,6 +343,41 @@ static int ion_system_secure_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, gfp_mask, nr_to_scan); } static int ion_system_secure_heap_pm_freeze(struct ion_heap *heap) { struct ion_system_secure_heap *secure_heap; unsigned long count; long sz; struct shrink_control sc = { .gfp_mask = GFP_HIGHUSER, }; secure_heap = container_of(heap, struct ion_system_secure_heap, heap); sz = atomic_long_read(&heap->total_allocated); if (sz) { pr_err("%s: %lx bytes won't be saved across hibernation. Aborting.", __func__, sz); return -EINVAL; } /* Since userspace is frozen, no more requests will be queued */ cancel_delayed_work_sync(&secure_heap->prefetch_work); count = heap->shrinker.count_objects(&heap->shrinker, &sc); sc.nr_to_scan = count; heap->shrinker.scan_objects(&heap->shrinker, &sc); count = heap->shrinker.count_objects(&heap->shrinker, &sc); if (count) { pr_err("%s: Failed to free all objects - %ld remaining", __func__, count); return -EINVAL; } return 0; } static struct ion_heap_ops system_secure_heap_ops = { .allocate = ion_system_secure_heap_allocate, .free = ion_system_secure_heap_free, Loading @@ -350,6 +385,9 @@ static struct ion_heap_ops system_secure_heap_ops = { .unmap_kernel = ion_system_secure_heap_unmap_kernel, .map_user = ion_system_secure_heap_map_user, .shrink = ion_system_secure_heap_shrink, .pm = { .freeze = ion_system_secure_heap_pm_freeze, } }; struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *unused) Loading
drivers/staging/android/ion/msm/msm_ion_of.c +57 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,62 @@ static int msm_ion_probe(struct platform_device *pdev) return err; } static int msm_ion_pm_freeze(struct device *dev) { struct ion_device *ion_dev = dev_get_drvdata(dev); struct ion_heap *heap; int ret; plist_for_each_entry(heap, &ion_dev->heaps, node) { if (heap->ops->pm.freeze) { ret = heap->ops->pm.freeze(heap); if (ret) { dev_err(dev, "%s freeze callback failed\n", heap->name); goto undo; } } } return 0; undo: list_for_each_entry_continue_reverse(heap, &ion_dev->heaps.node_list, node.node_list) if (heap->ops->pm.restore) heap->ops->pm.restore(heap); return ret; } static int msm_ion_pm_restore(struct device *dev) { struct ion_device *ion_dev = dev_get_drvdata(dev); struct ion_heap *heap; int ret = 0; plist_for_each_entry(heap, &ion_dev->heaps, node) { int rc; if (heap->ops->pm.restore) { rc = heap->ops->pm.restore(heap); if (rc) { dev_err(dev, "%s restore callback failed.\n", heap->name); if (!ret) ret = rc; } } } return ret; } static const struct dev_pm_ops msm_ion_pm_ops = { .freeze = msm_ion_pm_freeze, .restore = msm_ion_pm_restore, }; static const struct of_device_id msm_ion_match_table[] = { {.compatible = ION_COMPAT_STR}, {}, Loading @@ -354,6 +410,7 @@ static struct platform_driver msm_ion_driver = { .driver = { .name = "ion-msm", .of_match_table = msm_ion_match_table, .pm = &msm_ion_pm_ops, }, }; Loading