mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
synced 2026-09-09 00:08:12 +08:00
NOTE: This commit does not compile due to missing RHEL-specific fix-ups, which are split out into separate Git commits following this one. If git bisect selected this commit, run "git bisect skip" and try again. Repeat this until it selects a commit which compiles. This commit was generated using: rhdrm-merge-drm v7.0 RHEL-170739 JIRA: https://issues.redhat.com/browse/RHEL-170739 Conflicts: drivers/accel/ivpu/ivpu_fw.c drivers/dma-buf/dma-buf-mapping.c drivers/dma-buf/dma-buf.c drivers/dma-buf/udmabuf.c drivers/gpu/drm/Kconfig drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c drivers/gpu/drm/drm_fb_helper.c drivers/gpu/drm/drm_syncobj.c drivers/gpu/drm/i915/gem/i915_gemfs.c drivers/gpu/drm/imx/dw_hdmi-imx.c drivers/gpu/drm/xe/xe_device.c drivers/gpu/drm/xe/xe_nvm.c drivers/gpu/drm/xe/xe_pci.c drivers/gpu/drm/xe/xe_svm.c drivers/gpu/drm/xe/xe_vram.c include/drm/drm_gem.h Conflict resolution: diff --cc drivers/dma-buf/dma-buf.c index f701097a919b,11711874a325..c3f5f4ebb02b --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@@ -667,11 -760,6 +692,7 @@@ struct dma_buf *dma_buf_export(const st dmabuf->resv = resv; } - ret = dma_buf_stats_setup(dmabuf, file); - if (ret) - goto err_dmabuf; - + file->f_mode |= FMODE_LSEEK; file->private_data = dmabuf; file->f_path.dentry->d_fsdata = dmabuf; dmabuf->file = file; @@@ -738,9 -822,13 +758,13 @@@ struct dma_buf *dma_buf_get(int fd return ERR_PTR(-EINVAL); } - return file->private_data; + dmabuf = file->private_data; + + DMA_BUF_TRACE(trace_dma_buf_get, dmabuf, fd); + + return dmabuf; } -EXPORT_SYMBOL_NS_GPL(dma_buf_get, "DMA_BUF"); +EXPORT_SYMBOL_NS_GPL(dma_buf_get, DMA_BUF); /** * dma_buf_put - decreases refcount of the buffer @@@ -758,24 -846,64 +782,64 @@@ void dma_buf_put(struct dma_buf *dmabuf return; fput(dmabuf->file); + + DMA_BUF_TRACE(trace_dma_buf_put, dmabuf); } -EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF"); +EXPORT_SYMBOL_NS_GPL(dma_buf_put, DMA_BUF); - static void mangle_sg_table(struct sg_table *sg_table) + static int dma_buf_wrap_sg_table(struct sg_table **sg_table) { - #ifdef CONFIG_DMABUF_DEBUG - int i; - struct scatterlist *sg; - - /* To catch abuse of the underlying struct page by importers mix - * up the bits, but take care to preserve the low SG_ bits to - * not corrupt the sgt. The mixing is undone on unmap - * before passing the sgt back to the exporter. + struct scatterlist *to_sg, *from_sg; + struct sg_table *from = *sg_table; + struct dma_buf_sg_table_wrapper *to; + int i, ret; + + if (!IS_ENABLED(CONFIG_DMABUF_DEBUG)) + return 0; + + /* + * To catch abuse of the underlying struct page by importers copy the + * sg_table without copying the page_link and give only the copy back to + * the importer. */ - for_each_sgtable_sg(sg_table, sg, i) - sg->page_link ^= ~0xffUL; - #endif + to = kzalloc_obj(*to); + if (!to) + return -ENOMEM; + + ret = sg_alloc_table(&to->wrapper, from->nents, GFP_KERNEL); + if (ret) + goto free_to; + + to_sg = to->wrapper.sgl; + for_each_sgtable_dma_sg(from, from_sg, i) { + to_sg->offset = 0; + to_sg->length = 0; + sg_assign_page(to_sg, NULL); + sg_dma_address(to_sg) = sg_dma_address(from_sg); + sg_dma_len(to_sg) = sg_dma_len(from_sg); + to_sg = sg_next(to_sg); + } + + to->original = from; + *sg_table = &to->wrapper; + return 0; + + free_to: + kfree(to); + return ret; + } + + static void dma_buf_unwrap_sg_table(struct sg_table **sg_table) + { + struct dma_buf_sg_table_wrapper *copy; + if (!IS_ENABLED(CONFIG_DMABUF_DEBUG)) + return; + + copy = container_of(*sg_table, typeof(*copy), wrapper); + *sg_table = copy->original; + sg_free_table(©->wrapper); + kfree(copy); } static inline bool @@@ -956,9 -1087,12 +1023,12 @@@ void dma_buf_detach(struct dma_buf *dma if (dmabuf->ops->detach) dmabuf->ops->detach(dmabuf, attach); + DMA_BUF_TRACE(trace_dma_buf_detach, dmabuf, attach, + dma_buf_attachment_is_dynamic(attach), attach->dev); + kfree(attach); } -EXPORT_SYMBOL_NS_GPL(dma_buf_detach, "DMA_BUF"); +EXPORT_SYMBOL_NS_GPL(dma_buf_detach, DMA_BUF); /** * dma_buf_pin - Lock down the DMA-buf @@@ -1421,9 -1556,11 +1492,11 @@@ int dma_buf_mmap(struct dma_buf *dmabuf vma_set_file(vma, dmabuf->file); vma->vm_pgoff = pgoff; + DMA_BUF_TRACE(trace_dma_buf_mmap, dmabuf); + return dmabuf->ops->mmap(dmabuf, vma); } -EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, "DMA_BUF"); +EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF); /** * dma_buf_vmap - Create virtual mapping for the buffer object into kernel diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c index dfb6cfd83760,11d70fe4f75a..a25ad16a3198 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c @@@ -88,11 -89,12 +89,12 @@@ int amdgpu_map_static_csa(struct amdgpu } r = amdgpu_vm_bo_map(adev, *bo_va, csa_addr, 0, size, - AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | - AMDGPU_PTE_EXECUTABLE); + AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE | + AMDGPU_VM_PAGE_EXECUTABLE); if (r) { - DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r); + drm_err(adev_to_drm(adev), + "failed to do bo_map on static CSA, err=%d\n", r); amdgpu_vm_bo_del(adev, *bo_va); goto error; } diff --cc drivers/gpu/drm/drm_fb_helper.c index c75f940cebe6,05803169bed5..e8000a2e7847 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@@ -31,9 -31,6 +31,8 @@@ #include <linux/console.h> #include <linux/export.h> +#include <linux/pci.h> - #include <linux/sysrq.h> +#include <linux/vga_switcheroo.h> #include <drm/drm_atomic.h> #include <drm/drm_drv.h> @@@ -574,14 -438,6 +438,7 @@@ void drm_fb_helper_fini(struct drm_fb_h drm_fb_helper_release_info(fb_helper); - mutex_lock(&kernel_fb_helper_lock); - if (!list_empty(&fb_helper->kernel_fb_list)) { - list_del(&fb_helper->kernel_fb_list); - if (list_empty(&kernel_fb_helper_list)) - unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - } - mutex_unlock(&kernel_fb_helper_lock); + if (!fb_helper->client.funcs) drm_client_release(&fb_helper->client); } @@@ -1816,13 -1672,6 +1673,7 @@@ __drm_fb_helper_initial_config_and_unlo drm_info(dev, "fb%d: %s frame buffer device\n", info->node, info->fix.id); - mutex_lock(&kernel_fb_helper_lock); - if (list_empty(&kernel_fb_helper_list)) - register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - - list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); - mutex_unlock(&kernel_fb_helper_lock); + return 0; err_drm_fb_helper_release_info: diff --cc drivers/gpu/drm/drm_syncobj.c index 5c4eaaae4e43,8d9fd1917c6e..23b047941025 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@@ -713,34 -702,24 +702,27 @@@ static int drm_syncobj_fd_to_handle(str int fd, u32 *handle) { struct drm_syncobj *syncobj; - CLASS(fd, f)(fd); + struct fd f = fdget(fd); int ret; - if (fd_empty(f)) + if (!f.file) return -EINVAL; - if (fd_file(f)->f_op != &drm_syncobj_file_fops) + if (f.file->f_op != &drm_syncobj_file_fops) { + fdput(f); return -EINVAL; + } - /* take a reference to put in the idr */ + /* take a reference to put in the xarray */ - syncobj = fd_file(f)->private_data; + syncobj = f.file->private_data; drm_syncobj_get(syncobj); - idr_preload(GFP_KERNEL); - spin_lock(&file_private->syncobj_table_lock); - ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0, GFP_NOWAIT); - spin_unlock(&file_private->syncobj_table_lock); - idr_preload_end(); - - if (ret > 0) { - *handle = ret; - ret = 0; - } else + ret = xa_alloc(&file_private->syncobj_xa, handle, syncobj, xa_limit_32b, + GFP_KERNEL); + if (ret) drm_syncobj_put(syncobj); + fdput(f); return ret; } diff --cc drivers/gpu/drm/i915/display/intel_crtc.c index 7dc56bad1fa1,53378d2dcbec..3c89b9452863 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@@ -737,10 -750,9 +752,10 @@@ void intel_pipe_update_end(struct intel if (!state->base.legacy_cursor_update) intel_vrr_send_push(NULL, new_crtc_state); - local_irq_enable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_irq_enable(); - if (intel_vgpu_active(dev_priv)) + if (intel_parent_vgpu_active(display)) goto out; if (crtc->debug.start_vbl_count && diff --cc drivers/gpu/drm/i915/gvt/kvmgt.c index cc65eb26998e,ec62db5cc367..949586a9baa0 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@@ -50,12 -49,13 +49,13 @@@ #include <drm/drm_edid.h> #include <drm/drm_print.h> + #include "gvt.h" #include "i915_drv.h" #include "intel_gvt.h" - #include "gvt.h" + #include "sched_policy.h" -MODULE_IMPORT_NS("DMA_BUF"); -MODULE_IMPORT_NS("I915_GVT"); +MODULE_IMPORT_NS(DMA_BUF); +MODULE_IMPORT_NS(I915_GVT); /* helper macros copied from vfio-pci */ #define VFIO_PCI_OFFSET_SHIFT 40 diff --cc drivers/gpu/drm/imx/dw_hdmi-imx.c index b13b6800e398,398f3cce5532..7661af2492ff --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@@ -240,23 -241,29 +241,30 @@@ static int dw_hdmi_imx_probe(struct pla if (IS_ERR(hdmi->hdmi)) return PTR_ERR(hdmi->hdmi); - hdmi->bridge = of_drm_find_bridge(np); + hdmi->bridge = of_drm_find_and_get_bridge(np); if (!hdmi->bridge) { dev_err(hdmi->dev, "Unable to find bridge\n"); - dw_hdmi_remove(hdmi->hdmi); return -ENODEV; } - return component_add(&pdev->dev, &dw_hdmi_imx_ops); + ret = component_add(&pdev->dev, &dw_hdmi_imx_ops); + if (ret) { + drm_bridge_put(hdmi->bridge); + dw_hdmi_remove(hdmi->hdmi); + } + + return ret; } -static void dw_hdmi_imx_remove(struct platform_device *pdev) +static int dw_hdmi_imx_remove(struct platform_device *pdev) { struct imx_hdmi *hdmi = platform_get_drvdata(pdev); component_del(&pdev->dev, &dw_hdmi_imx_ops); + drm_bridge_put(hdmi->bridge); dw_hdmi_remove(hdmi->hdmi); + + return 0; } static struct platform_driver dw_hdmi_imx_platform_driver = { diff --cc drivers/gpu/drm/imx/ipuv3-plane.c index 792c82756779,0ea70b8fd743..85a2cee682d9 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@@ -307,15 -308,10 +307,15 @@@ static void ipu_plane_state_reset(struc plane->state = NULL; } - ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL); + ipu_state = kzalloc_obj(*ipu_state); - if (ipu_state) + if (ipu_state) { __drm_atomic_helper_plane_reset(plane, &ipu_state->base); + ipu_state->base.zpos = zpos; + ipu_state->base.normalized_zpos = zpos; + ipu_state->base.color_encoding = DRM_COLOR_YCBCR_BT601; + ipu_state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; + } } static struct drm_plane_state * diff --cc drivers/gpu/drm/tegra/drm.c index 5de42d3e3856,1dcef4e7d104..144df88af54d --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@@ -1329,10 -1330,13 +1329,8 @@@ static void host1x_drm_remove(struct ho kfree(tegra); drm_dev_put(drm); - - return 0; } -static void host1x_drm_shutdown(struct host1x_device *dev) -{ - drm_atomic_helper_shutdown(dev_get_drvdata(&dev->dev)); -} - #ifdef CONFIG_PM_SLEEP static int host1x_drm_suspend(struct device *dev) { diff --cc drivers/gpu/drm/xe/xe_device.c index 0d999b9ffd67,3eb06b27db7e..1714c90674d4 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@@ -367,8 -369,23 +368,22 @@@ static const struct file_operations xe_ #ifdef CONFIG_PROC_FS .show_fdinfo = drm_show_fdinfo, #endif - .fop_flags = FOP_UNSIGNED_OFFSET, }; + /** + * xe_is_xe_file() - Is the file an xe device file? + * @file: The file. + * + * Checks whether the file is opened against + * an xe device. + * + * Return: %true if an xe file, %false if not. + */ + bool xe_is_xe_file(const struct file *file) + { + return file->f_op == &xe_driver_fops; + } + static struct drm_driver driver = { /* Don't use MTRRs here; the Xserver or userspace app should * deal with them for Intel hardware. @@@ -907,6 -952,12 +950,11 @@@ int xe_device_probe(struct xe_device *x if (err) return err; - xe_nvm_init(xe); - + err = xe_soc_remapper_init(xe); + if (err) + return err; + ++ err = xe_heci_gsc_init(xe); if (err) return err; diff --cc drivers/gpu/drm/xe/xe_device_types.h index a614f5e81ce3,f689766adcb1..41ea23c0c3e9 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@@ -36,7 -37,9 +37,8 @@@ #endif struct dram_info; + struct drm_pagemap_shrinker; struct intel_display; -struct intel_dg_nvm_dev; struct xe_ggtt; struct xe_i2c; struct xe_pat_ops; diff --cc drivers/gpu/drm/xe/xe_exec.c index fc7862fac9e0,e05dabfcd43c..4c836de71330 --- a/drivers/gpu/drm/xe/xe_exec.c +++ b/drivers/gpu/drm/xe/xe_exec.c @@@ -155,8 -155,14 +154,8 @@@ int xe_exec_ioctl(struct drm_device *de goto err_exec_queue; } - if (atomic_read(&q->job_cnt) >= XE_MAX_JOB_COUNT_PER_EXEC_QUEUE) { - trace_xe_exec_queue_reach_max_job_count(q, XE_MAX_JOB_COUNT_PER_EXEC_QUEUE); - err = -EAGAIN; - goto err_exec_queue; - } - if (args->num_syncs) { - syncs = kcalloc(args->num_syncs, sizeof(*syncs), GFP_KERNEL); + syncs = kzalloc_objs(*syncs, args->num_syncs); if (!syncs) { err = -ENOMEM; goto err_exec_queue; diff --cc drivers/gpu/drm/xe/xe_guc_log.c index 86e85503bea7,538d4df0f7aa..da31e0fa9752 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@@ -7,9 -7,10 +7,11 @@@ #include <linux/fault-inject.h> + #include <linux/utsname.h> #include <drm/drm_managed.h> +#include <linux/vmalloc.h> + #include "abi/guc_lfd_abi.h" #include "regs/xe_guc_regs.h" #include "xe_bo.h" #include "xe_devcoredump.h" diff --cc drivers/gpu/drm/xe/xe_pci.c index 6941c6af66d2,5c0b3224f20d..8f355af9b121 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@@ -356,8 -364,13 +362,12 @@@ static const struct xe_device_desc bmg_ .has_fan_control = true, .has_flat_ccs = 1, .has_mbx_power_limits = true, + .has_mbx_thermal_info = true, - .has_gsc_nvm = 1, .has_heci_cscfi = 1, + .has_i2c = true, .has_late_bind = true, + .has_pre_prod_wa = 1, + .has_soc_remapper_telem = true, .has_sriov = true, .max_gt_per_tile = 2, .needs_scratch = true, @@@ -660,11 -690,19 +687,18 @@@ static int xe_info_init_early(struct xe /* runtime fusing may force flat_ccs to disabled later */ xe->info.has_flat_ccs = desc->has_flat_ccs; xe->info.has_mbx_power_limits = desc->has_mbx_power_limits; + xe->info.has_mbx_thermal_info = desc->has_mbx_thermal_info; - xe->info.has_gsc_nvm = desc->has_gsc_nvm; xe->info.has_heci_gscfi = desc->has_heci_gscfi; xe->info.has_heci_cscfi = desc->has_heci_cscfi; + xe->info.has_i2c = desc->has_i2c; xe->info.has_late_bind = desc->has_late_bind; xe->info.has_llc = desc->has_llc; + xe->info.has_mert = desc->has_mert; + xe->info.has_page_reclaim_hw_assist = desc->has_page_reclaim_hw_assist; + xe->info.has_pre_prod_wa = desc->has_pre_prod_wa; xe->info.has_pxp = desc->has_pxp; + xe->info.has_soc_remapper_sysctrl = desc->has_soc_remapper_sysctrl; + xe->info.has_soc_remapper_telem = desc->has_soc_remapper_telem; xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) && desc->has_sriov; xe->info.skip_guc_pc = desc->skip_guc_pc; diff --cc drivers/gpu/drm/xe/xe_vram.c --- a/drivers/gpu/drm/xe/xe_vram.c +++ b/drivers/gpu/drm/xe/xe_vram.c Upstream v7.0 moved the rebar code from xe_vram.c to xe_pci_rebar.c (382876afa75a). The new xe_pci_rebar.c uses PCI rebar APIs (pci_rebar_get_max_size, pci_rebar_size_supported, 4-arg pci_resize_resource) not available in RHEL. Kept the RHEL-compatible open-coded rebar implementation (release_bars, BAR_SIZE_SHIFT, 3-arg pci_resize_resource) in xe_vram.c, matching the v6.19 backport state. The incoming xe_pci_rebar.c will be removed in a follow-up fixup commit. diff --cc include/drm/drm_gem.h index aff540b11636,86f5846154f7..533d7ae256ff --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@@ -469,7 -472,9 +472,8 @@@ struct drm_gem_object .poll = drm_poll,\ .read = drm_read,\ .llseek = noop_llseek,\ + .get_unmapped_area = drm_gem_get_unmapped_area,\ - .mmap = drm_gem_mmap, \ - .fop_flags = FOP_UNSIGNED_OFFSET + .mmap = drm_gem_mmap /** * DEFINE_DRM_GEM_FOPS() - macro to generate file operations for GEM drivers Commit list: commit b2bce0e551e89af37cfcb1b1158d80f369eeea3f commit 8f565bdd14eec5611cc041dba4650e42ccdf71d9 commit 9be4f0f687048ba77428ceca11994676736507b7 commit dab751b4240f0f0eadea81f93ff0b439379bc6ae commit 78ff838a8ab78b3cd438e382ff5204b93db3237e commit c34a14bce7090862ebe5a64abe8d85df75e62737 commit de72d9df4f453c08da3d4a15ce75fbd5f891bd2e commit 1f2cf5295cdba71818288c9e495b4ef5097565ed commit fa18290bf0723b02bfa8d30d2e14722f0d096c2c commit d7e7a0048f6aceaadd19bda66de496c60b741cb1 commit dca0eb029f5770e18308db966cdeec4bb4b5a659 commit 1cefc3ac7d8451cebcfce209c53933fb6309e4e5 commit 5050d4a0af1e3b4970adf321f4a9296fe2ac532f commit 201c902870ec7b4141e4f403612a289701fafb80 commit 7c3342213a8b73f3100e3462074f5ded4fd9d675 commit 4f8b1e08c28945427a46b98144c20c22d0578885 commit 230d4c748113d83931a5b57c844fb71faf9eebe3 commit 5df82b17928b8f14d7167a5e199b4cb58bfe39e1 commit 8ad92b0733030841d5a728178f5c8a6f2c3e8f78 commit 90fd33c2626008b8c5e6c30c44b480c21ea41c2d commit 538187f17acd4bf94dfc98cdd8630559324fad43 commit 36a3efb32ed2eb3986be4bb02e2f298d0ff055e8 commit fb1dc1eab618f24ead88e2ea7ac057679eac4faf commit ac3423721117a6ad2e643ba74770e118124eff27 commit b5c0256a587eb50920ade41dd1b086039ec6bcfd commit d174cfb51dce71778822a8ab2dde772dad947409 commit 28d5533f2787c67fbfdb29018c8ef56ba964147f commit ca1eda5cd476ca5c948e697af528694071f0f92a commit 051964d94adc7b2f16921c1fc1969f7910d7129c commit 4fcefdf990cb14a3586e622ded7a18c287cf51e4 commit dc3fdd4ade8763aac3546835909b70c298b8e8f4 commit 2e129889622c391d4d1204a0da16e278d585124b commit 9b5f839e14a52c67492830b718d4ac8dddf04688 commit 685f36534968467a37ee7319673633b82dcebe09 commit 57cf9d5e45a88a4d3543dfd32c78f9bedca1b110 commit f3b04e27f7e5cf2af91d73112d9f81296ddad156 commit b800af732c6b844c8fe6465edf39c437f4a760e3 commit e32518d012ed9abd97b33832fc82fafdab40c12d commit 6b566d066c823a9ad1ec5a7043955349a71ce42b commit 2a6e417907593e908d164c743f812ad6413f3d7b commit 1a7fad2aea74065dcd81821c681103813fd0772b commit 0a4c2ddc711a9a0d3d9566379b217f2ae42d6152 commit 5b23aa423a637358a4b98cd18a4da020ca8398bc commit 8c171a9b8c4cb10b1942d3094f94e27c65232cf7 commit 7e2d78535432e44f908c6c44f73828cfd9c12aee commit b9241d0ed9cefc7f9b9bb65533494d7776964d79 commit a651be53c42ae1cd44d51a7e7913edbbee976c99 commit 3815e8f2ffe44396d10b100fbd38f511dfefbbc7 commit e8916738977e29a6f1e8edc593ee336f2bcf1b7d commit 4799ff418f9a68361331fdc7fc01f66dc314adb9 commit 95c04f442941cb9829e791d0bef460317a17819c commit 1314027632ae2d98ec7ba250495d1a6084caafc6 commit 69c9b1861e827a45021a0a10c1d0276a896dd0c2 commit 55fc11ce96e92dbae2aab1d692735f7a9b96fefd commit e4c8fde0bf2004fcd9c9dc8e3bc9bf6545a21a3e commit 074edfbdfba25493324807f749fbc86bf0af3a2d commit 59e7528dbfd52efbed05e0f11b2143217a12bc74 commit 83d2ea17d53f538724f0222f1cb5f60061efb06a commit 917714f2787db1f42cc41705e02cb381734ad663 commit 3947e482b5ebb95be49803fdd584a38f005f5042 commit e9bc4162bf39154c1eb8d5edb11a00fc30771c39 commit 008db7d4e1a465bf65c5cf7a4cc7ab041b2dc00e commit ba2562a391c66bff5bcc35583ce8c0beda862f03 commit 62a35753f547c7744c062750703c2ae9883b33c5 commit be675564cca58fd509b3666bbb1b7f61c6cc03f9 commit 7fc616a309e854f75bcc46e82b948065886ebddf commit b11f88699b13d7b6e314b9d19107aebdc79570f0 commit 1fe7ea3287ba35b92db7f8fecf773a6bc9273f51 commit 062a6b83d56066f86c1bed170265ecfa98b83175 commit bedad003e8e76ef37d069816ae418e7917c5f4d8 commit 175b9aaba3e2b32935204b46ff1ea6356b775801 commit 667fc27e81bc4bd0aae008b6c3f16df9e707707e commit f875dead3ec75ba37edf986603a69c89e4a771e6 commit 60a4661d12ca58c794337d09d26f3f57e235cd2d commit faa4b73bf75003ad89ed4d1afd3e9e59a48a63fd commit 8a579f4b2476fd1df07e2bca9fedc82a39a56a65 commit 008f3fcf31b7a7a6b13b774b76871679805c2661 commit fcee6854e6fb9ddff0597296728a4f7fd67bccc9 commit 3a344ddce25eb8b7cf63de8b5c54de10e5bb764f commit f50c11ba35da84450b3206b50618ecb6482968dc commit 423fb66fac7dbb5ee2b26c40e0d21c0ffb0d7533 commit 28aeaed130e8e587fd1b73b6d66ca41ccc5a1a31 commit e2b1c3a127665fbca7099c886e4f755785ea1118 commit 2d74a09360a920d87a4e9538797068a0f9e5e2e1 commit ed46f724b725e7692cee18f26901c6dbde33dff1 commit 1178b860605891dc728404dadff4dd6adeadb444 commit b8660fa66207ff36efcc0f1747845e423c7ad987 commit de4ca6f8e9277fed49192454b7940681977ab1e5 commit b3d3c83e00c7846bfa6c4aa12f64321849dd3819 commit 1807d61541d003eee90f7661d6b40245f6966e3a commit eef67acfffd8debdd8c7a3f08ee759cd6bf58fbe commit 3018e582da321c5f6d2f03847f9adb44e44cb0ee commit fff15f68eb06af4a77e349d419717bc9a2f4b37b commit aa4dc3eeff6d5c47ed08905e5cf7b9b77a646fea commit a8c02fddc9cf7d778a7a838660a679d6d68b0608 commit 62519b77aecad22b525eda482660ffa127e7ad80 commit 2e4ad5b0667244f496783c58de0995b9562d3344 commit a5f0cc8e0cd4007370af6985cb152001310cf20c commit 64fdf496a6929a0a194387d2bb5efaf5da2b542f commit ea944d57eac746f9bd9056134751708c48084207 commit 370f45b1cea859484691128ec205abc7e9402fb7 commit 8aa2945f049d7cfc7b3c9195a7341e8eb0d9c961 commit 07ba4ecfd111cb56464faf6ada9937b4e18fac23 commit dc5b3ef88ba7cc9f2748b75b6b127b2b400315cc commit f32df9e94d9565b4ce3067cf107afd687fca0851 commit 96b93ac214f9dd66294d975d86c5dee256faef91 commit 0f4435a1f46efc3177eb082cd3f73e29da5ab86a commit f4c8298cf5f5c2458f700546456601f3ca9b282b commit 69ef30d6c903c4b9cd75c50367acb1cd1f95d440 commit ac16a7ec0445c60962badbe34f8f33d352ceac6f commit 0a9231590f16f596541154f43375f3e2c419a3ef commit 79cb005c7134340d78e2fa8e526a6104fe492695 commit 0e72241a53e9188e88bb7b258266bccd615a4d60 commit 1fc30960150672b4c8f842ea00c75be766759bd8 commit 2e02254ef5f0c07980b39fb4c334b0e612b8581e commit 00937fe1921ab346b6f6a4beaa5c38e14733caa3 commit 07cf4b864f523f01d2bb522a05813df30b076ba8 commit 5b12958b1ffa7db44c276b2d394f3ddb9e0ebaca commit 4a938d3886d6dd29a54a2e6ebc03b6c2b7509ebf commit 0ae006dc48f3748fdee675052bc0e5e87b856ac2 commit dd62fe512d5980e86cdd5b77385012f5659775f0 commit 7f08cc5b3cc3bf6416f8b55bff906f67ed75637d commit dacda0cf75d5f4aa8da5404c21dc8ab4b7667799 commit 9fb1f1256e419fcd0e5000ea8aaa71a65575a90b commit 6028f59620927aee2e15a424004012ae05c50684 commit 8b8a6456ac253093a02dfe87590c446da7aa2c46 commit 8e2610d9a5edefb99b1a708796a8f733358e5898 commit 99234edab8e1fd3fd2309193a3b3169970a7e770 commit 726ceb5716da7657a65e01270c494ecd4cb0b242 commit e6d2fe31a76d4960b0005e8fcb5eb66d00ed2e14 commit 43fb9e113bf11d78e7c817e2696705f458753c79 commit 0aee7d2e32e554ca0969063694568975817494a4 commit f227ba9cc2a854b703dd127a575f6287a2f0d99b commit 28bf111ffee103e143038949e781a5c209070348 commit e48b99d863166c5131f6d6c0ed81107392bc421f commit 6b515868bc93a679de1d6037319580541bda2238 commit ebf08b1c52faab9f0638b0fa02d0031e311fb435 commit 8afc0198a4bd6988bd3f575be00dfdb628f0be5f commit 0646d0dd6665afa1e2c4fa7ba296a7ff880ab232 commit 1513904c46b61e483e4d61519c31078581bb6cb8 commit 40a9f77a28faa8a0803371903c15372026e2c050 commit 342ccffd9f77fc29fe1c05fd145e4d842bd2feaa commit 39a00914281eb33545777947cea5f7979d605115 commit 29fdc6e98d3c3657c8b4874ab3bfc75f9df59bf4 commit d2c6fde56d451ca48a5e03428535ce3dbc8fc910 commit 151df689fb75e46a6cafa9a2c407d44969f4bebe commit 3c0a60195b37af83bbbaf223cd3a78945bace49e commit 6e2d3b3e858942de4dbffffe3a617e80b1262f74 commit 19e8bc9456055e594d0f1c9677ea8a3a9983ec3e commit ddf2cb3c9e655dd9b7bb5172249f6c01fc251549 commit b6153b02220c4419b5e27ede0861e40f19fc7e7f commit 685d529fe1e9f8ebc116027d35de7bf95e830308 commit 7e1113e1de492ac1fed7bce105b08187ba9934b9 commit 2af6766f38d85af9aae9cfa009839cdb6ad80f14 commit 851f58d02f0d6c9c5fa8aee32fe349aaa9796758 commit 5232e84927197d5cb045ddea9c90fc143b64bf65 commit a3c2d0b40b108bd45d44f6c1dfa33c39d577adcd commit 55429c51d5db3db24c2ad561944c6a0ca922d476 commit 4356d21994f4ff5c87305b874939b359f16f6677 commit 61d9a43d70dc3e1709ecd14a34f6d5f01e21dfc9 commit 99820b4b7e50d9651f01d2d55b6b9ba92dcc5b99 commit 36c5dff41fd958c9e32d931eb90b5ae638a7e600 commit e85e9ccf3f8404007f62dff9a02273fcdeb44206 commit 357797f272c70f9b796636d2e795056f9e2e2b4f commit 01c724aa7bf84e9d081a56e0cbf1d282678ce144 commit 8b3cce3ad9c78ce3dae1c178f99352d50e12a3c0 commit 17f22465c5a5573724c942ca7147b4024631ef87 commit 1e759ed22a62680c79aab266d73baaa2bee4de9f commit ef4ed8621a15ea4979dd6c5bde436ae228c4bdfe commit 4dfb97060f22c6c5bea995302f0f58936d8f3271 commit 9a8c267b878a7b163735c9371c2ccf103b685e34 commit aa51f0309a0fc81d54e1dd0c1c8cc26bfb8babed commit 118afbc58df50c13121994a06ce332864405f448 commit e1c727e6288d50fc7b485c0a88112b0d8ec582e4 commit 450f04569ffd21e3caef878f22676694bbeadee0 commit 9d94c1cf6ef938abd4b849b66f8eab11e3c537ef commit 251be5fb4982ebb0f5a81b62d975bd770f3ad5c2 commit 8b5502145351bde87f522df082b9e41356898ba3 commit b1ea3babb67dcb8b0881c2ab49dfba88b1445856 commit eafc150549ec312afd8dda86eb3e53de735049ba commit 819c9ffd425971e0e913e5ee690f3485a28c1e0b commit 81e66a55a8d7c57c664520074c770484054f43b2 commit 6cf5d14a0bf730d6e45c407b7e3bedb1a5d8812f commit 066a1ddd8559fa494bf5137a1ef00c8761fcacf8 commit c87f586e55364d8ca8dae38d5d00f8dd267ca8bc commit b80961a86b40372b7cfb3065439377f7e7550e59 commit 7032361d8cb13ab48b2b79167967c3a29c075ce2 commit 1026c1a73a9686ff35ac100039f94f0725622447 commit f80e89446a460184a5f76c70522be70351a85a11 commit 046a10f4d74fd3e022d9b793c5e910dd9df0b1c0 commit a22461eddaf6a0f82ca2d02de2e180dcc16b3937 commit 6ea3aacc8e89298702812a1556eb1e378a80e02b commit 156fd724e18dd099267b4ceab485a995b8ba54bb commit ee30fde96bbae259fb8a744ee747b2ec733e9fc4 commit 2e2dab20dd664ea1ca6ed2342f6dc509496c9290 commit b5fbb94341a2b1d78b24713db454dcda2fc7194b commit 75e7d26281da46bc8570c61f44fe6093f120963a commit 4c2768704710a5d4585941288e6a8159dd6dd33d commit 43109e398d2d4ac8a932ac46fde34e55cec53d4c commit 203c7904f2d85ac768749112ddedb522965316f9 commit c296e3f2cec7325dc93a19cdcf3194a63b02c389 commit df5dd52a6de486e32576ac5851b4e9429182274b commit df9670191613cdea0e223f5070368a26312b12c3 commit 8fad54133b96a243af1fa593822a3f0af3b058ac commit 532f6f602e0653d037684822f8ef72e734717f35 commit 97afa2da35f3bab11d5c9885508ee1d6162b8d98 commit 4d7f266e688480fdd4103c90331b012cd1e8b859 commit 1552691f960a9ee182a80b754d076e055b7545c5 commit 41f231179a45068fdde2c6c9aa70cbca2eb11b49 commit 0f94e51b5320eacccc2626ab70b8d7e705332334 commit 657803cbcafde8caf11d207b042384577a3d5f17 commit 32e593d74c39249ae14c8f0de88eec677c621aa7 commit 276e411604b3a90ec9d243075f976e458139a006 commit cedf6765ecfd60197d90437ec648feb8b3e31cb1 commit ac5b392a8c355001c4c3f230a0e4b1f904e359ca commit ee8721bee80150ed1e4ee5ebb6aaf070802ac81b commit feb065155bab2fabc3545bf57ae31e86d02df9a1 commit 802620f5a9cf7231933cfce61817577b3b6543d9 commit c06da4b3573a2d3c906c185450d0b1059d02820e commit 688035f83ef0a3b492b9ff9748518d6d45b4f107 commit 2976aeb0de77da599ad37691963efbdcb07435ce commit 76ce2313709f13a6adbcaa1a43a8539c8f509f6a commit 54da99e5c3a7e114df8dbbd42a0fee2b3ed8aa15 commit 6cc3776b1f41cfc10bbe3dc6c70d0bf036a868d8 commit 78d91ba6bd7968d4750dad57c62bf5225ddcb388 commit 0b806d62fd5f59bcf07b971af15bab5bef191279 commit d4ee41f9e19ea89a9cdf32b14be3fe8823f64cc8 commit e58b4dea9054c85688c8f639ebdfc8115261dae2 commit c891b99d25ddbb6b8167f9bdb904d4abc5a53b6b commit 06bc18e0def7d926265480faa555bf0b67a35a90 commit dbcd754b845987f7157260c15e80ae19da81c9df commit 583d1fa19148c261868fa5c2382fe552c06a2164 commit c6c60a2290b335eb5b45c6c7eeb254f18027b3ec commit 88e721ab978a86426aa08da520de77430fa7bb84 commit ef7de33544a7a6783d7afe09496da362d1e90ba1 commit 29bce9c8b41d5c378263a927acb9a9074d0e7a0e commit 89f0b56f77c96c022cbc3b22d42664d0e93e3154 commit 16e076b036583702bb47554d3931b5e674dd9a8e commit c7e269aa565f4f3fce652ff690db3676c50f5098 commit ed455775c5a68b75e5f6ad6c8e0e3e9c98fd3f64 commit 8322adedc0f2ed98a1e12a8dbdfa4fbbb3f17fba commit c1daf37fec0d796ca01d0918ce65cc09fe4936f7 commit 7eeb0e5408bda883ac01bf71c1105892c82060e4 commit 9124732b14010f58849d6686d393246c864639ca commit fc40e8f6fc2de469b40494df9c12fda2c11dea3f commit 09fb6bccef8221544221ebeb97cffec3fb42920d commit c7ea291be0866ca562bb7d32d1646c08b2c3064d commit 6d87d7c69b5a1136d7c354911f1fe7792b6a40fd commit d8f94cb02af3cc64013373c94a4b7780782ea59c commit 624f494ee6e9c6b1bd16289c0de34e399950baa8 commit 944a8313a7ebbd4cfbb0a579d4f6283e125edc08 commit da33e457f6803dc48b2b74f8ade75c14624d85ca commit f861e54fb33b587687e335ef24431fceccfe536d commit 1cc854647450199e20cdbe0fbc3be1f5253d7693 commit 5a4236267d0b0e60639bb9fd33f4083a7abf32ed commit 8d251442f81a9c5114f2eee303e4e7305fb0f426 commit a7e427ff20418bbbac367ce78a3e786360988432 commit 93bba79e177159821c5b57f9b6632de1fd1d5e8b commit 2691ec6792d10340618a900d79417b058811507b commit 11bbc345d4843e1fe98382abe9e110addc585fc8 commit 9d2d49027c3a9628989c9ec70ebef9d241f49c1e commit 99bda20d6d4cac30ed6d357658d8bc328c3b27d9 commit a8a9a590221c1959716277d4b13fe658816afc0e commit 7cdf69d903759b81abde5973d703c93a742ddab7 commit c569b369cc2114526bec2ba0a41a49cfc27609b4 commit b64a14334ef3ebbcf70d11bc67d0934bdc0e390d commit 4ebaaa3b622238ea44fbaa21998ad76bd8417a8c commit 51db5336e16de25074ef63d29b8a762a25d193d3 commit 646013f513f38a3e75a60fde31ae0e6154ce19a7 commit 9877a865d62c9c3e0f4cc369dc9ca9f7f24f5ee9 commit 539d821df2938368c8b175cadd6f463de61d4be3 commit d514ed18f5771bd4efb981dbf8191f91be0d67e1 commit eaf5a2425e058ea08e7ffe5d46b1eb743c30ca92 commit 923a3c20f0e105fdfd17c3e61d383543df18d149 commit 27a136eaa3968fa0d4c9504891c646d3374e3372 commit 13aca3c0f492e193c9d823684813633087e75752 commit 2718942f48d41c4dc1c19a7a20720633191afd2f commit d09c7e266c8cd5590db59693ea3c3a66a55e63ab commit 36b266bd3aad0698591c2c93a112e2dd6b6678f6 commit 0bebe9b9fcb485c12d447b9352a53e761caded9d commit dcfe45bd860f0bdec82bfe3ae8632d231a6c4f28 commit 7cd88efd16f46023d2359430bb49781e879229c7 commit 4d65215145de002defa985136093566a20fdb435 commit bc5094e27e10259df655c45629c5e234957bbfb6 commit f6b1c1f5fd7237f77fc3880603ea54dcf0371a20 commit cf856ca9b999bc81d27bf8c4e1d7b5c7740bcea8 commit 5287e7ef748e4bad63c6f5f05348b022ec867407 commit 550c6f5b90d21b84d62e658f2e986ea24bf3adb4 commit c3cd568d31b6d41fc201b1d0506e4f6cab7e488a commit 591689ccbe091a43d4597cb1c4f2e4f51a589d80 commit 4c7838b56cbfc0f96e4eac275459b91957248f01 commit 708b8589f2605a170b572478a2fb3755bb9f272f commit 0b8c6bcd206ecd275ac6267b4feee2bcaa8f1a5f commit 22ef3af5d42b56d760722f0c62cde362cf4747f9 commit c92bb14151a59715c674d421d647e37dc6cedd6e commit b02c22359bac8bf40fa141b5e5b62776559de698 commit 0c24b83d82179cb634f1c56a34b1f5690a6509d4 commit 41273a8ce332aedbb08db6d20a63b66bb7852f34 commit 692c70f4d80247c622ce864672cbd0e3d8799189 commit e06d194201189ab611ac83c591c16d5f288a605d commit b9befc9a21bdeafb0f81b757c60df66e6e9feb17 commit e8f4ea34b6cfa7ac47a518e36193dcc7573f6afc commit 209529414ef0bcb46bf59f8368224e25167fc50d commit f752e79d38857011f1293fcb6c810409c3b669ee commit 60a300780d8abb4c98f2837059db63f6211a54f0 commit 1855fc6b09bc8f42c29cc4b6bf576dd08d2a6564 commit c174a6317be0aac7e1953eefd680af6b9be91bc2 commit c4031deddec903fc9472ca563a2d04f9c9ac8265 commit 1c254be41132c6bd41524659e06f9b1898234c98 commit fcfa8dbb087ec05cebdf177217fd5a01383a762b commit 11dcf72eb5c15c07332b3dc4ae921021f2fae426 commit 61a9a4138b57dda023ee4f473724c48d7fd3640b commit 73c6c22694430089a6f39f1677fbf598785376d3 commit 54c2d9739bb748d0f7d6aaa101562cfa5963551d commit de8955508b72f8a88afc3f2cbb62334d5f79ccc3 commit d8c2c6c33d494a7868584b0e741628af662bf621 commit bd68a1404b6fa2e7e9957b38ba22616faba43e75 commit d09c6b98f8080c3ae55d75023ed80fdbaf3519d4 commit 4af2e15c9bf240206aa14089791c28abc59eaa44 commit 755b5591739cc5c66158da596cf30853b613af5b commit 91c93c090dfc58a3dcc97bb5e43b27892e043e9f commit e87bfaf55e7311b9587c0163060c6939c36f077e commit 036c0e38bb3dcfe0af848aa94224e6967a4b616c commit 5056b75fedc01de0563267c53e1aa7e41357f37a commit db29ddf6505f3e831e000c95ae013b18a37f70bc commit b8c27208b28768e8a6162f69a05508ded61f03ac commit 3a338bb1144d622ca2daea67756ebc9301579785 commit 2634ef1b8c00207dde5101e926241957aa5652b8 commit e53833ac820645b0465b27b6beb69e0f1889d57a commit ecd3fdfbeefdf3ecd075349bf7535d950efd56b3 commit c78e31bcf586f1c910a2636650840f5ce1cb1c63 commit 74ce00932e7eec6a985c2b650e95fce0f334d772 commit 5e07a945856df30618be02a14e88180f09235ca0 commit ca4310e86b527c61f15a9e7b8b1dc062daba8463 commit 6d76189a84484060a93e961c6eed5593144c253d commit a6edaf570058bdee78d947294aa987cfa958b898 commit 201648dc812bdadbecf650ea11efa1b3fcee35e2 commit 08f133e932cccd9a039bde367fe436594220bde3 commit 4191fa9046b85f31e6803aa4e31758414010cf7c commit a3bba93360d7348a420180298827c8f4f9296b3e commit 036dd0380b709ce8f40d8e87c289b3662eabbfff commit bd3c91d6ca5e17263fc56d1d6c06d0b0270a8a29 commit 20f311b652e7f90792759f8c91e3ce3e77fdf3b4 commit 69249b477b95f91e56bb19ec53707253899458c4 commit 811ffdbf2042b6373a4f60159ca1c5ac92dfda16 commit 03fc40766d01b05175d3b657b78686d9805bf3c5 commit a574f53ed52e7c5c0e67e67efd76f296d42f0cdd commit c7062be3380cb20c8b1c4a935a13f1848ead0719 commit e1b385726f7f7fc75b6cd3c2216430de8a625a2d commit d28e92093ceffb424b9b0e36bbd391c83b1cfe78 commit 46e0c86caa172b6dc711ed595a3b4655666698d7 commit ec62b7ded978957ec74add4c1feccc986e2baeef commit c71980a3fc1dd7bf2f3c10b113d917e9f3cd10ae commit 297b0cebbcc3aad3fde692c988d5aa19f7b652b2 commit f9d8e880b1ac35ad8db82dbb56253634d525a584 commit 268614ae415e3e8b73e078d3a428b261eceaecd4 commit 4ed5116aacf6126ef9c7bc8cd7367ed6797e5c8f commit 1c85f12658fb42136197ab0b580c4f4d4b707875 commit 25140983ef074456d1939bd9684b8109b00d273e commit af441be8b75deb93ded51c54b9a2ba1e048b1c91 commit 473f12f820956988eb735d4cfd88ce0640f5d3af commit 5ba69099b66cc6dd63a3035c825c875871e88089 commit 7e00a84d11b0fc8a01a73383cd634353638cee5d commit d73e5302906a087b5aae3f09ec7936ef17213c52 commit dc21e39fd20c773cfa523b14030ce76190d96807 commit 7b0813f32a0c23a52bc174b9699ce7e0c3aa2ef6 commit 73aa1550dfeda9fff742dbba724c69d46e0908bf commit e220edf2d6fd6dbf08fa93790809500a80217948 commit d6d64bf9754c167a777e513d52005653b1cb1e3a commit fb61604a69fca0366efffb3abee8c0910024bdfa commit 3272cd887f2bc27825a6c053ca174dbb6eabc636 commit 42cbb68ce896ea472ebcdb310ad01b6712fd4d13 commit 3880d8e3c6ef2797900d5a437b705afe9baa815f commit 4ab27b01df629545de5a5f9889867b0f19438cd8 commit 6afc422e1a49d18b63f7042fb1cb6f519a972c8a commit def3488eb0fdb386044aced1a8fb2592b1e68896 commit c02288724b98cbc018231200891d66578f83f848 commit e4a3133c5b93ac27e3eaa50eab15465b31c9532d commit 7dedb906cdfec100061daf41f8e54266e975987d commit 03282bd20124125394f4540e9c6432615158b671 commit 531fe6e0fee85a1bdb5b8223a706fff654ed0a61 commit ae20768e30a84c80cf46aff49265e7c23ee3fe02 commit 0e7f7b3a20a8531463592086579f1db31b4a3483 commit 25888a46630875ea47024ee8d24614bf30f603a0 commit f433db9c4b36c0963616def8dcc4696d1aafb95e commit 4cd255b9694647b784f085ae144b727b6ffdfbfc commit 65cce2a172ff0f8b4a2d74a6c9a84243b94ca797 commit 26fc46d7942d0842ee9767a6d960ae5a9141f534 commit 1707d5760c71b813fb5a4b6ccedcf21bc0ecb481 commit fac682a1d1af12c6b9f97f7db91e1fbea2c40540 commit 4eb38fc0f1da9707b8866b4a91a4dd7c2becfda9 commit e1b73b64271d706079370b58b81292dafd373163 commit 018fd6d7d92d704709e8dfe497fe3aac1566e90f commit d59e9d2d556ad7ce228200a2e804b57bb77b6c47 commit 6b6de6266f4c0fb07e96c14f3da0126f7d11dc37 commit e80205f3a7fff55249b430c21afc99faac93010a commit b4f1e6a2718caef34bf990c705ff2bb64b730b77 commit 2a667e26fa87b45fe4d89ed0c6ffd82c94c0a8a5 commit 07506945e138c191e913aba86030111a93a5b119 commit 78996e1e98f822d16363e2a7703ca243eda59ba8 commit ad5f1ee0a9b03200b86db65fd946b686088b4b03 commit 6fb01a20daaaeb5521ec617f23f6b716f5b500af commit 25f687de6735beb5627e3f4d1445e3c4ce4b67e1 commit 442903eb83255da2aceec8e3184a3a8a9575b982 commit 08ba5ba01fa895c59f8462dcc4c6c4dee1760cb6 commit 3e22786128e5c822abecdd4fc9444b6b8ca38c32 commit e5fc897b076e0bd0bab9c32154fdb1bba6566127 commit f8692d2f9ae0a48bf378cc33717772c5f940ce0d commit 1fee035bee8d99436cde73b5727c8a19ac9534b6 commit 9c34a4c19efa8686737c03f1718618da58cae546 commit e08a675f940b2ec546236754718cd5f2a0054317 commit 4da4990337b34be49b95d99524c99910f4f0577f commit 1fca2832e02e72cff4574de99a37450e6c7fce4a commit 01bbc4a4b94789c7c3b997ea5aacd4ec5fa97a11 commit 2c0c485deaf96e403eb11d27d90de3e6099b2810 commit 75053887d6d8f527578ffcb1113bc336fae49b42 commit 61a3ade2f68b73d903428083c42b8a6c11c54161 commit 5701b7a93df7840ddf74399344f849d6292d8419 commit 18a695030bf91604c168ad352b764f506accf219 commit b34488070a80facd658b48171b0cad342018d20f commit dc17c8af96488fc802e753c551c39acf9ea73bc3 commit fe1c48e9bda60b1b4d4f1d84980c66dde7c1954a commit 8c293a93e81c2ab0345991e25887f86b94318787 commit 46905fb85ec7c6c4013a0a94dabbf454a9780b5e commit b824bf63894f42adbc8b29fd78e4ca1cee8c3779 commit 9f63bcbaced1e23ad5b9108f4fc5b187bebbd74d commit 0791b47395948a50545d0ce9c90a9291614954dc commit 20e3ce630c43eabd82ca863807ce06e9cc8a08e5 commit 3ddd11780fa0c376895516eea62d788a0fc6749e commit 8456b756e5f861472e2adf6582b72f30a954952f commit 5478777fd73a0f2d037e8f3f600a6c331a8e46a3 commit b0e0503cb46875fd37206584453efbe0fe756bf6 commit c5842537bd4317a1bc64670b4c7fc930cde47faa commit 723c504b5690ee1a75142ae4e3ed5cbaa9d90a9b commit 1803bdfb7e15706b7e2db4e55eb993bc1cc99758 commit a8b81d3ddbbf5c86d21234135483a1fe91b33c1a commit 2084f2746e8b5db8709e8aef22deb3107e85e771 commit 0229122fa169b465a3d13120f2c03259389792c5 commit 6186199f3218842462f4f269818a32467f4e543d commit a50d32c41fb25d772cc1c47b6abed8fb811d58c2 commit d3ff65243a52afa85166abaa8d00a44c17691dbd commit 448ee45353ef9fb1a34f5f26eb3f48923c6f0898 commit 8c5c0ea2f9c01dad2f83f4c9a4a049004058ae38 commit 3ec1a42f5f4ba877374a22a8da45d219772ac968 commit e3491fa3f3c94d47e7b82604ca7b9925987f1683 commit cc6b66d661fda4fb94c0099dd92b83f8de5c1bf4 commit 7380228401c4e67066b451665ed74286da0f4d1c commit b4742a9e7fd42c011cf805e3441dd188f22e325c commit 36b98a7229cd39d1e36edfbf3b2797b778e927a1 commit c7d1bc0b020454364933294c40897cdea4dcd432 commit f75227fb3fdfce1ffe2a737e90976cec4cb95218 commit f0ba2c1f12d37d11b169578aa7e066d2b6c8ce02 commit a08ea4bc7711f8c4eacbf5c63c334e71a226c2f8 commit 33becd7ccbef3b02fcfc8b6763aff826c71b78b8 commit 5f77e0b11dcc2ce92c0457f653732ee9756622a1 commit efb4febd527da4248b02eae495f601e2e0ba66b1 commit 7ea1c722fe1daa7dac0c6ee90352381c54107520 commit a95f01edd80b61b130befac595369c9e2ced4eb2 commit 85b0b7d7a3db4f35ccf87f5da9ce26267516d642 commit b2debbbb60f19ecec9567a518ef02ea40cdf89a4 commit 03d11f8564ca0e09e0e629ec75084e2265ae9207 commit 97b2e10e9467a4086e72cf9146d4699fc9baf1c0 commit 423888879412e94725ca2bdccd89414887d98e31 commit 8acdad9344cc7b4e7bc01f0dfea80093eb3768db commit 820b3d376e8a102c6aeab737ec6edebbbb710e04 commit 6b2e9b41b785dc97ae8c9a2c93869e3a710bd6e0 commit 3f6c060846be539fa1eab350f2e783fa724dba2f commit fdcc620b02e2e4af77d5c81f546dddea4eb7971f commit 6a45e909c65a8b3c5592b88ad37e2f7341683801 commit 67b032daa288b70df2e6cb2c3a9cefcae0c6fa5f commit 7a5fb05b5b18e531989aa55b10dfa4be0633207e commit 71776e0965f9f730af19c5f548827f2a7c91f5a8 commit 3849efdc7888d537f09c3dcfaea4b3cd377a102e commit e3b8d8cc8c60db6c2be1251664da68b3e021a672 commit 8b971ce0cbc71a10f1d19d2bb6f3dc5c6f07d9d9 commit 30a4dc6476da3d056bf86d87d79f381beb8556d2 commit c93f9b7db8b414a971ab076e3bb3774e53c6266d commit f364fb3cb40364e0c91ddc83bac90cfd09a5602b commit 127770bcfccc21e7de214be9c54527a789ab790f commit b42f3bf9536c9b710fd1d4deb7d1b0dc819dc72d commit 9827f482895fbdbef3d6beb05dcba475e98833ee commit 6c4c2e2c403530ea0a171b1376bfda8feb3ea4dc commit 1359282bd4ff16752c977d2f1a01a315c8df9f6b commit a5192fbb2ee4225122efdfcaea53d50e9f477055 commit a0f8297068cf5be9e07e765d499a482f5e55d454 commit edf47fb3d12adbd1747b798a454bc36ceb5912f7 commit 582c65e85498976ea8ec40c23b423311ea53cd94 commit bc0515ece3d50ea61f76795bcdb42b09640c11e1 commit e95b41846dab4f7b4d5a761b157d3cee7de737be commit 35bb80e6832920b5d22554a54601d392208fe019 commit bcd752c706c357229185a330ab450b86236d9031 commit 925ad0c26dd80d345018a3f7559799b7ad8f44e3 commit 9beb8dca9e749e9983e70b22e9823e6fcd519f91 commit ea78ec98265339997959eba3c9d764317614675a commit e06177ec7a36391c66216b55b7c112d5ba8c4cc1 commit c146c82f862e9c7e602a908891c3adf992ef2beb commit cd2c9c3015e642e28e1b528c52c06a79f350d600 commit ae09426f47ee64bd3f34fbe815ff61eb94cc3a6b commit 2396d65d94fc75d39f096b9777f9edc9c8e677c1 commit 7be45f5489769520aa9276137d0f1f543fb81286 commit d17592e61fa8e3b2d58df7c4a24abc8ac58b8d3f commit 62eedf1ccba534b318ca85d3890bf0951b9e0f87 commit 668e88877a9ba73182ad686e871e8678a7dbca61 commit 81e77c028848b7131d7653dd443a4049334a920b commit a00e305fba02a915cf2745bf6ef3f55537e65d57 commit f4e9fc967afdb53b1203f894fb4b68451a7fe202 commit 6d2b55f7d7011ebc11c933bc680ba1b050ce1e88 commit f88cb2660bd09fd76b54e6bd2e62f3d7501147b6 commit 4cabf00fcd09fd1dfbb3f345abe3ed2330157f22 commit 22ba3bb3ff2a8e5a509bfa13f3e362d0d36083fd commit e97dfc74700e68f6591e2faf895d7c987428d42f commit 2397a4c6624a8e192de8e4443fab578b41d9deca commit d6c862572b69fd92f1793738e2e8d7d326ba0740 commit 0c085485a90351bb38dc97c2df99ac2038d0d87c commit 1f5df537fa7910a6bdc96a7cb73c65fd30e2aab5 commit e540c47fc08e4480118e1f1b68adaf688d172528 commit eabccffbe0a06f8cdba5c37e295c7690f86c57a4 commit ad9f266be8b2db26c7cc754d401278959bb7895c commit c29ceb0fecda82067d424199a37474319331f265 commit ff9e240212f6693c293f9e58ade05bc887297a1e commit 74a658229bb027964713522706254b727373aa3b commit 1898840d6c4405092243bb7dfcc399ccb1177498 commit 495b190480dc78ad2dd10f8b96dfb5747fa48c4d commit 8e0187aec67a9f71e5b3726c1979e1d68db552ca commit cf356fe11dd42fb91f3a3f9b990cf237a3ce9841 commit c90ed18114f984d069a201406a92cfa4710b5578 commit 77385a2dc18a3fb6353df9a9c002755e41ff9b6b commit d0b6c5f226a0477c047c48d6914bf7dc6096acf7 commit b7cb3669b6645e36d21d005d45790ff4c5e0f4a1 commit 7ce7234189a84b1e0a8088b725d400c56ccdab3a commit 84d8beaf11571d45f1a46b7c39fc374026f3f072 commit e1c94109c76e8a77a21531bd53f6c63356c81158 commit 5b57c3c3f22336e8fd5edb7f0fef3c7823f8eac1 commit 6ef93f62533e4176f0aa94d125d742b778cee07e commit 2e133eda97c447d11997f2e2953e7d39b0096698 commit 4fbc61018b48e5373ff3a80b730620e530f0e85c commit e90a43c0c24e879bf3c7d541cf813f136636b1d2 commit a936896135633d3e9d6aad12b88d8be929ea306c commit f9ed1d463ecdd265059ebcc8642651e59588c6fd commit d6e81483282143d80c495a84b1e3fda31e77dedb commit 90254524ee84ef812e6329a14dd76e9f53db5023 commit e26e4225ae57faf7cd512df645b2c866fc2dce75 commit f9f3240018e8f5b68bb791102d4736b5883d8aab commit c28a1142766f9d80880c556fde4b94c3ad00ac96 commit 00e08fb2e7ce88e2ae366cbc79997d71d014b0ac commit 4c5f7d73883355990a4eb1964a02fc5664cfcf22 commit b79040d1136aeec48459f433a7b14e192475ee88 commit 6f894c92490be1bb27492a82544b4b1e4ad20915 commit cc52af1a961ff85ee1940d8d843dfc8f374f81b5 commit 3235a5b72317be613b69e22c3b2c9f2bec546253 commit ef7d4a6a497a947e863d94e729fb349afdf98b01 commit 7e40fe89dd9cb40c2a05f22dbfbbd425cd59a018 commit 51b9bb61e5bbfb488b080d1e85ae681ee95a0731 commit c58d8a6620cf2654bdd0732e85bc351660af4c0c commit bb418f99e6174d10f662dae4638837933bc4752d commit e2a6a4e6d408c0466136cecc2439278a6aaf604b commit 9987a6f34e4ed074c4868d8cc5d075594c019736 commit f24e96d69f5b9eb0f3b9c49e53c385c50729edfd commit 6a99e91a6ca8fec5882450128fb128265f86b32a commit 3efadf028783a49ab2941294187c8b6dd86bf7da commit 8e011f6d08abcd740a9c5157b2f79512a579bced commit d36137085a4aa2d2f039359a0d67d9e07667f2de commit d2e8d1bc840b849fc23d8812995645cc79990e7b commit 8d8cf42b03f149dcb545b547906306f3b474565e commit 7319c2ceb2d74d54f24b7f5409b97aed406f0189 commit 041baffb84a64ea792224852778a7ff7ddd3cefc commit 128d6e6255ea7c0f4d55d45025d1ce0343f6cd46 commit 04f0aa5d69b88e4b9078d2e5aa3a970c71917850 commit 65defc4a780885687b9ff669e6276f7ba7ffd8e9 commit e547890b9ae32202f280105b8725d64fd3934d73 commit 976dd750a14d4d0e680aa8f83265451976cddad7 commit 1b3d18de5535f2553d237d64a20f7a1a3947df68 commit 470cb09a2936d3c1ff8aeff46e3c14dcc4314e9b commit ee26c3b2765a34d1055660cbfd4f00766dd25412 commit d9ec63474648a258094704ce223c9249fa7bb279 commit bc5775c59258e1da6fe393845ee5cdd25ca618f3 commit 898a00f4b43311adfd4da1711ed2b72adc8c98a5 commit d630abd6042dc186a3c113f68709818ad8a07a79 commit 2a31ea17d5c69e51ea454485edd40e4aeff467c1 commit 71e7d7e81d6a08c2abb1bb1ff01107280db62abb commit 464a0bc0235f8333f77131433bb389a24efaf287 commit d716a5088c88391daea7a3bd2b26589060309a79 commit 1b5d39e6672fdee158c3306f5cb2df8975c77e5a commit c85285b32cc697d7612ee28a9ea9ded5e53d2b57 commit bb9343f122add786c57a6e8865209a9c6671bc9b commit 8b81c76885e8f61681cf4c7d6d0ce816809e3b2f commit 3131a43ecb346ae3b5287ee195779fc38c6fcd11 commit 9a3e975d6619c6fb8997ca59361768b4ec853565 commit 6601e0714bf08e6dfce04611796167255f63f222 commit d6b80e904bb00a188d9a59be6bf7e19b89e3954f commit 63c7f93b6033800e9bc4eca02949dc9d12553138 commit bd5840819aa12d1fc2831be1ceafb42237141be7 commit d69d3636f5f7a84bae7cd43473b3701ad9b7d544 commit 825aed0328588b2837636c1c5a0c48795d724617 commit 44ece22518594ec9ffd9ab8c4c500b522278289e commit b4abe06d6d82df6521f449357ca6b7c6ce9c0903 commit 9b1a0e0a15c97987fdf56a615f3d13995bafd042 commit 77ebc7c10d1607533cf7cf6c7a7b77105498d8b0 commit b912138df2993b6271500e5ecbd933acff14ac43 commit 2b192bebaf610abd4aa4f5fdf7282f3c2a347898 commit 9945e6a52f3c66b40ae30c2f4b79312a56fc9ba7 commit 684965d96a918f78c3fbd3ef55444aa9cdd7c5f6 commit 7c52f13b76c531ee2c503baafe52d357cab0c54a commit 13d99b01c0c9d93afb9413cc97a05854ae40f6ab commit 7ef2d25e477368bbd5c32e2265210e55644fdd48 commit 83f4151787c5dd2f38a426cb01423149baa3bbf5 commit 38b069333b58c86b7588d59cc55a065611190926 commit d8684ae1cdcf848d21e00bc0e0de821d694a207b commit 7f790dd21a931c61167f7bdc327aecf2cebad327 commit 4e899d9b4ea7798debb0c24e201a27fe2694d222 commit 8c88104ac6b8bdf5099a22165ff79348f84a0d77 commit 07d46ada28813393af461d9b739995d00368b93b commit 29551bf191005a6a61f2406e85b5017ccfbf221a commit 3b8fdaed8f57c93e7e6827328eeb05d4e770bba1 commit 63cb6443c7a798467e0a8b154dd8f1f950a5d1d5 commit c497e5979084224330cf1e789cc9fdce9097c5f2 commit bc12f3e1a84f16444aa33f0ee9edf829cf9ba796 commit d93a4354686b9a43d9f825a6859abba334b7ec86 commit b0c20d827e7773555d999638eac23e53dd358f4f commit b362de167daf2f1e42a6d5ea2d4e51e8d9d031fd commit 052039e3fe51bc1cbe700d5af9be009fb985cfd2 commit b8304863a3990d0f18c38e5b94191830a63ee1af commit 88b09229f34a8a2a0c6aa8a62eb6c96011181e3c commit 47f5cee4197719f5d06a899a2e827968a4e85d0b commit b07bac9bd708ec468cd1b8a5fe70ae2ac9b0a11c commit e057b2d2b8d815df3858a87dffafa2af37e5945b commit 33a5abd9a68394aa67f9618b20eee65ee8702ff4 commit ca415c4d4c17ad676a2c8981e1fcc432221dce79 commit 6e608bff259fd1eae5d381c5eb16b88413e16209 commit 8533051ce92015e9cc6f75e0d52119b9d91610b6 commit 4ac9048d05017449dde6320694d6e4700a8b9f5f commit ce3d65549c7a4ea4497546f49d18128281258ec5 commit 2b277b506138f501693f6278e675da259299e8aa commit 2359fe93138d80ca378072d4c743b8c17612f3e3 commit 99b98993ae010b86d0ec0d779c1c8be890057568 commit 20de1b0080b9889094d703927871da8f21fb624e commit ac488854890165b55a973dab7247aa2deea9cc02 commit 4855f26007d97b3dd7331d673d5410f1eaf30e24 commit be85d4124dbe6ed597c7a6a16e53d8b98684fab6 commit 5f0cc92fa0dab7cbb999dedc653f5857a62b2022 commit cbc1e99a9e0a6c8b22ddcbb40ca37457066f9493 commit ed2b818a24760d7adc92d2e9b0e135f2c33edd8c commit 29e208a08a8ebb0f214e815eee0a7beff778864f commit af586cc6df0bd56d4a3d05d5e6db0b193233fc51 commit 524696a19e34598c9173fdd5b32fb7e5d16a91d3 commit 08e583ad68577ff5135d2b6fad1d3b4b400074a5 commit 4fcae635887195d6ecc427d503d7671ca46bc11b commit d400dad620ab146303ba0d5ffd1b3c6639cc4fa1 commit 2b950ac91314ee25daafd3be37ca12db2540f80f commit 4ec227c1586fedebfe0f50761fc507fc443b089e commit 12323f9588ffbea2ef448679b50bf1eabca98b21 commit bb562c955e174f028ed06e92fdb23411ad456f0a commit a848986a384562bd64cf4e37bc128a8d78685add commit a1f83bd71376dbf4ca2126b4f6294173356cc5d3 commit 2db0936438a044b9403dc69140226dfbf89b0b96 commit bf2951e967fc241804613208268a14f493e9c3d7 commit e83f63da2ac776fbc30861e4ce8b798df6ee8a7a commit 63387cbbb714d9f0d179d9d4560de1408d0906de commit 3679a3ba427853df86de712e016624b4295e0554 commit 49a63bc8eda0304ba307f5ba68305f936174f72d commit 576e032e909c8a6bb3d907b4ef5f6abe0f644199 commit bf5e396957acafd46003318965500914d5f4edfa commit 2497eda57025abe1349207a9726da02aae699bca commit db2373ad05d41069f3eb39c6963a131b7fdc9f2b commit cea573a8e1ed83840a2173d153dd68e172849d44 commit 2f912935168a3122371f1de85eed8d9cce192d0c commit 9aeb31b2456452257ad1ff7ec566f21bab1f3e8a commit 8ae9d73b3a31f3f0da92973f2672ba7a6347db88 commit cb7a978c7c425e2666d6397f1297b3e8fe4f0a5d commit d38ec099aa6fb792e0a2064226074e57b17792a3 commit d8e4e7086ab1ad7dbe6dee3b9081abe65e86001b commit a1a445f3de8d3fd3f2e1c9e502058ae38531513f commit 20880a3fd5dd7bca1a079534cf6596bda92e107d commit b6b06640a84d59bcebbae9dad2af4f5db7993e07 commit 9498d18739b3e93b308809910692dd8eef862679 commit 81af7f1718a62c4eb9a1fc22263bf8a4f888fd05 commit 1bc44dee2647b720065b71d57e594f70ea52fb3e commit 20ba98326f4c69e6bf8d1f42942ece485a675b27 commit 0c9ad4728687f4e4c8cec290540a9dc0956d3243 commit db9ca58e164a9cb626ab13d22a0ada1a63887f1c commit 91689b5a7ce43e3742be6a249c7fc73be26b7d5f commit e4643ea3d2034f05e4a45fed2d0a5dab4d2ba600 commit 2d1fd547902da8ab4c48f542accf769a15bfce04 commit 6f744d7976e4910e478d1e46666aef96a71386ad commit db1882b3ff0c51d3ffdcdeee7ad1f9f01ea78453 commit fa0aa517dec92cec9a51d71aaa21c6d1a61c467f commit 8efa1a11e160dbe500b52ce21bf0c3f585e64206 commit a056771b30dc3c405cb81e22de96640d047d7097 commit 89745c19c66824e818b970972550c67fc271ec07 commit 6e7143e5e6e21f9d5572e0390f7089e6d53edf3c commit c5f91810725c06270c9388f3ebea3ec30dd6b64c commit 1eb2a5ed196ace28d19c3d17923261053ed51ff9 commit 49f47cbf5f0bf4124988d57e70d4362d01aa2b70 commit c9908d9c988810ad6253a8a1f70cf1baa23facb2 commit c63a52018675e75a19a04c2417ffaaf0ab1856f5 commit b9a0716a93abb03be79bdb52d9ac4bb98053f06e commit 4d70e12796a9d80b5a2bbaa22811e1b7be1c719b commit 005b7f7f93b44ffd93f337c216ddb44d8a7c276b commit 1ded9071c1b1ac2712420009710256bf95e90a80 commit e50a6ecebe0841d3dfa4d9415d4fae80bb5d91e8 commit 0a54edc19158b3402b6c39cc682789be05e3d47d commit ab39e2a8f7aed72929bfc1d58eb5e8766f1d85db commit ec02e49f21bc161ba19eca4a696613717b2ce2d2 commit 88d98e74adf3e20f678bb89581a5c3149fdbdeaa commit 5ae6cb153abc0448d28e6969f72fa5f7578048c1 commit 920c6af98e98e6afedf6318a75bac95af8415c6c commit 97f419848b1db69fc7ea99f385a7d2fa2b2ca454 commit efe24898485c5c831e629d9c6fb9350c35cb576f commit 5c3c3e7b654df01a69d49551a08b7863c09546f6 commit 2f9405aaa4297f95b42c39779e24f74587a0b6bc commit ce5971773651ad5c7e26aea29d72ea8887428774 commit 09af64eba63ece2d928295e61ab1d56ae264447c commit 4cffecaf127ae10ada4da0636f87e0170e347402 commit 487524c891d3cc21eb6d243c2885273c5b142b44 commit 97e16068d77a036908f69aba35486b21dee17a40 commit 7a100e6ddcc47c1f6ba7a19402de86ce24790621 commit 5bf763e908bf795da4ad538d21c1ec41f8021f76 commit 8592764933edc9c176e1904527e2190273b41bde commit fec2c3c01f1ca0cd2706941e78b9972e7f9474c0 commit 5e2e6b595d9d4ccd211ab19c0e47fcefdb29efe1 commit 0c8afa67aaa2d6cf523361f493d9b8224448ebea commit c57079937bf8dff763ec90a01573b3a1918d959e commit b440baf355912cc5d3664dcc5dac198d24ac1e56 commit 281a226314238e8adb08d11b765347687ffb38b9 commit 425fe550fb513b567bd6d01f397d274092a9c274 commit 332070795bd96193756cb4446eddc3ec9ff6a0e8 commit 9dde74fd9e65ddd952413d98a8a756e12d087627 commit fb084e4183e1d79ead103265cafc4b6bc0ecba03 commit c7b83a916d62c4d4447d7edf0bc5e06dc2afbdf8 commit cffa413f1c94d8da45b31dd958bfeaa72329991b commit 6a3591522930897c3fdb326c5d48b906b5c30b71 commit 5add3c3c280a35f7e258e9cef7607db5a2e56fdc commit 565ed40b5fc1242f7538a016fce5a85f802d4fb5 commit 8e7460eac786c72f48c4e04ce9be692b939428ce commit cc1b753487bb23e5a1c96c9864d515690e15b605 commit 92a73fec6acdcef3f2da7b2d1d4574308ebbe975 commit 0b1499051ab39d8958e43ff292f5e3a7324427bb commit 1f28404ad4712cae0f04532e1fb7b26f9c423292 commit 1867564b9080d096445f1c40b3fc360364735bb9 commit 78cfaaa11151a85fd3952c4f4f485308ffd3964b commit 3999f6d7f588819cd03aa6baa95cac9be7834e45 commit b1ec2916c929a58b533b7f652d0162299d8a6398 commit 2fb850a6aeb20b6a28c23dbddf1eaa704abb9ce9 commit e25b6f1334463c1dea3972222352f0cca035cb51 commit 260aef187f7ffaf03a1f4c51b5b748f1ca026696 commit 3755e200bc7ffcf56424008f7f97909904968f18 commit 2018e29176d659a2a1847b266a72288471b1125d commit 5c2d799491f20baca033245dfe86eec1f5b93256 commit a63bbb8ddde0f0060683f4a089669a8b2eefe0f1 commit 338465490cf7bd4a700ecd33e4855fee4622fa5f commit af90706f0eeca2ec78f73bdc164c5046bd8a9866 commit 3d50c69c5819b20149946fda084bb3d6bfda2c44 commit 13fe9fa7f41a2f3a0ce25d27297a379560e45b2d commit c954d3b517a9feb58bc1f7debde9ebfd101bda1a commit 9236cf0ade32f5b7fa5424c20663fa7ea40f8bcb commit 35ec71285c9311395b14bedc60fa94f6b7e24d2d commit 651065dca3f2a2e2cd2ddd3cdebeb7fe6c0da882 commit 844758bd99a86e6a07247784727fb337c4b979ca commit c2b40b1a4fbb0e9c078224bec3ea2e17f8076429 commit 15156936b26f14c403d75a9353c84c5b17312b61 commit 4f1b30fe9ef550651ea353714d1119431e76824a commit 89f23d42006630dd94c01a8c916f8c648141ad8e commit b47b9ecef309459278eb52f02b50eefdeaac4f6d commit cda83b099f117f2a28a77bf467af934cb39e49cf commit 607d07d8cc0b835a8701259f08a03dc149b79b4f commit 3f41307d589c2f25d556d47b165df808124cd0c4 commit 50c26c301c5176cc8b431044390e10ec862b9b77 commit a61bf068f1fe359203f1af191cb523b77dc32752 commit 0734802d6130076fe52d3c75bc618e64048c2765 commit 6a3e94ff052963dea8585fb7d5a2bb7dcf4140c6 commit b99690ffbca0994bb66e12deb20e37a34abf0ae6 commit 9dacae143e6ff18e77fbad6f1413fb8f2f975407 commit a13f152a6c09338a7f81efdd414425a9d8d50b16 commit 6bb14ea387fee901b62a29af568f39eeac23e451 commit 1b3cc68df363820537d6c837069db4c303ee58a9 commit 3629264e4d7dd255180e99ed6be05af57e4bea6b commit 9a864b5487c6f819488f64bb5ad3f5efcb720330 commit adf7968e52e8d9f1b76ecc46ac5720c0e61c9d51 commit 64ee50c6f025c0a62e173bd96c33e48da6012383 commit dcff3266cfc49000b95b461a41031db3cfc55c62 commit 5bad00377ec844d93947fd4c081abd2000a63dfc commit 82eaf3459dbf92ea78243150508740c007e0eea7 commit a6e6f8b50bbb2b7c12f09a4f9c5f5d9c67b45f8b commit 7394321a06638bf5132fec8d817cdfedc26057c2 commit e05b08d7d0162cf77fff119367fb1a2d5ab3e669 commit ee47c0ab23a041e0a34848488dee1a23c0940f21 commit 51293e589bafb4281a597986b3416471f67a79c2 commit 8d87fa19169eece7133db355b50767dcf0386c44 commit b0c5cf4f5917bf562082c30879d26ccd572df5a3 commit 50290b7a0df54f908cdf3eb87f52ee01664f3ef4 commit f04feb5b54419443e9937f5cc871f0612608f650 commit b7fa6016a2bb671306ec2cbd9b3134f903e5d83a commit dad13af3985c1d096d3141026d5a534f8aacb4e6 commit b7b106f937170eda2c65ecba5e6bd44bc4b40d46 commit 76242b98d4e46f2124caf08b786b657dbc71e5c9 commit 627508b391ea53eaacf1185e19998b287f69e5c0 commit 46c9e84cd66dbb9c2304e717f6c9fe4aa0ea5354 commit be4518128a58f61862bec66621e5d3da254a97ce commit f474911fe16b3baad218d5b8cd499cd8dc3eb3fb commit 72aee5f70ba47b939345a0d3414b51b0639c5b88 commit d1a4fc044cfd83741fae06c7e91019d139053f15 commit 16b5ad31952476fb925c401897fc171cd37f536b commit a599b98607decdc899630fc99a3a2847f6b72965 commit 565477dbca6eca0cfa3f6fefede3f6eb1e6e09b3 commit a26084328ac40c12096ef01482a7520346379453 commit 77f14f2f2d73f6955b856e7c91ca9fb7046da191 commit 33ac8d150af6be100161ec11106a8dd3f1f5b9e0 commit e44f47a9bf5104c9b9efcc8fc95a858c66f2d1e6 commit 14b60874c90a61ffb9c32787bc5f3fcde93b9cd4 commit eb9db59d96ce1ce8a207064f4a098c55ddd23fc3 commit 238dbc9d9f4a7396e87d357567e09dcd270d9e16 commit 4be5f2bc811a5811a8ec42dfbb603dbc12e8948a commit dff547e137be2f36c6c4d77172a03a54a38230d3 commit 2df55d9e66a2ad845286d15d865fa54117882b22 commit 54dc5842a81cacc6833c1f897ca332d2f931df01 commit 1f430b8d68e6d2cdf8825421d5c1e1caa746b483 commit f1d08a5864822684773105c60528e2abb577ca6c commit 0471ed20df6b92133a183d526d8f28592dbf0831 commit ec265e1f1cfcce6b03167868cadebf2d831e52b5 commit 0620837490e0401cb4e9965a1e0c462dbff1c97b commit 15e096960a7fe6b0163d0f35d908cc08d4ca83e8 commit e67870321a6af82c66fc41422d5c7af49e8a0234 commit a9f88c68f861f86f05b1272b0870f2973784616d commit 32eab46a6160ffdddf476d2924edde7fc34a28f8 commit c3a613a03902dc09a9b50d2f6ae67005908f4a7e commit b5179dbd1c14743ae80f0aaa28eaaf35c361608f commit ac1317df039d9e4a05e5acac4159e5c2021600aa commit fb3fba6933d169a4a12a7aa33cb68abfeed62ef4 commit 8a717c16ddf261118e9128d7f146d68a2567f087 commit c08c123d4cd6ec3ee482d607e29388d0db2d3f1d commit 969325a2597ebc4cb001a92992f06f698ab2b467 commit 6c8e404891e1059564d1a15a71d3d76070304dde commit 7bc0f871f992f1469229ffcd2b40a45ec5f695b0 commit c5fb82d113c6266e65fee2a7e0dc8f48c3bd12cc commit 9ec3c8ee16a07dff8be82aba595dd77c134c03c2 commit 08889b706d4f0b8d2352b7ca29c2d8df4d0787cd commit 345ad34565c371f71aeb37d048c845a0fea7eb3a commit 765ec7411b9d7a4b1f19c5ca3191c9039ac63c09 commit 5f1a87efd60d0d7ca612ea33127bccefbbe07a07 commit 80d3db9b62d2740b7cd1a10228ec04f6d61f1bae commit fb48cb435500dce125e1ba1640def3df251b7301 commit 7bf97992afa4e815f4ed84638340e2a93de65504 commit 71813ecc8436a6b10d528b305a827238e98530c9 commit f3255cf4490ef63b477c1142fc608cf6388e66d4 commit d6a3a678569431ed816ac490bf489541bc87b424 commit d805e879e15a126a00da2fd02cef0ad353365c6a commit 1908784fbc05201e6b969473989dc76d160546c3 commit a2e3dda51d550f4226a3e490469fde469ee57189 commit 255153afbcfdcf30d20048fb76a6d9418537b5d9 commit 6739e03a9affdc3d94134d8734299971ec8d8bf5 commit 1dee5a4db242e4e351570b74ab2b5793280eeac9 commit be19d803df438880528b20f541638507cbefc7e4 commit 19467b46c219878adfd81b9de3f9cb38a198fbe5 commit be843f34803520341324a8c4487caee6d8e14444 commit c09112ca3cc9f0d73a53adf4fe5103f6a06e061b commit 2873c8eaa1e9020b2cfa7abe39ea69af9f93058a commit 7bf11bc2f716f6824b3b3d418319967213aab2a5 commit 80d14983595ba3bc10d4e1349db295a5645276ce commit d780bbebaac137869ad5d95bd42e525fec812830 commit 4ca36702d808e67a68cb51163f3101875594d0ba commit 5e32a46f56035e329005f9d8fc7a317127e99909 commit 5bb6250c34781f3c6856b41454ea83325f2adc1e commit c4aba65c26fdf15e00b4591b615f5f30ef33633d commit 27a4250ca27a0995bbe66fc37c7f9bebc7a61744 commit 192bc98c6fcf8c602ceaf712dc0cd616ebd73f9d commit 5786499a42e6baaf27f28b64d3e55fb6b289141d commit 5558192707072d810b2c9792dfa7e4455d163705 commit 293a8fd7721a90987d9bf149feab60e756dac269 commit 9da0e06abda87b1f97014113d5231fdeb4700749 commit 5d7cb36254b5facd2a349331c1a47102d4e66e40 commit 7282066e55347b26cb31784059ab62c2de8a3e01 commit 3fdeae134ba956aacbd87d5532c025913c98fc49 commit 8f92a5fcbfe33f86b08f5f74dcc58a41425ea8c0 commit ae754f049ce1c01f09d175f80265970f0d5b4489 commit b9a7d5918bd436d64699b80af061f21c168df699 commit ceea3f7806a109baba4a23c9066eb9e86659408b commit 54af17788629fbf343c5a9ebc55454d6a5486ff8 commit 0dc4a8d6d096f97a00b10919e8ffe2466666f03c commit 6802c7ee360d98a018962adb8412d42dcca28272 commit 900699ba830fd3558ba00f55fbf014022dc7ecdb commit 40630210211a34f0714fe976530ccf1291e5ef78 commit aae766f5d31070284561073086ed0a8d2ae15856 commit 51489bae202f629abb5c896b00099f0de22c875d commit bb6a4985680b89653809bc4aa54c940796f14066 commit 59260fe5821ad108d0fda8a4a4fe0448e9821f27 commit 78df43b95885eb764666eac2ea8e21e2953175e1 commit 1bc99cdc1db9c74204ca3706bb60f0eba58bcb52 commit 0eccf37660aebf9be4b35dac6c30ae729c42a720 commit fcb6fc87f1a189c4b0141513556ed01419f4d90e commit 045033fb02e744d577316429aa082e581356b63b commit 65f329ff234705b07a6e4429499fdf578cccca49 commit c7830b51c77f85b95bd538b2d79a8de02cc05db1 commit 73b506e6aa11dd1e8f2bdd3d82280341c510b0a2 commit b3aa6769288303567d5a2f069778f37de32942f1 commit 5555a3074921285f8ba0346208db29f335e45b95 commit 91ce41427d468cd103a08970b448a42430f9e52f commit e70711be0d0ebdd0a9213446b657fe0815e38017 commit 349d4efadc1f831ebc0b872ba1e3a2b7dd58b72b commit 67ccf6c60bc324d78c24893e8c1eb6a62973838d commit 968290fa8a42d9d2d2fd0fcdeb82d7533e83071d commit 44b69cf1d35cad4a846208e769b34a648fd637bb commit 0030595c3e8b48b32a12b8354ce9dbe00efd632f commit 2e01c96d8e6cfc654bb4a12efc1b2a9133f10ba0 commit b1e2a6a57aa95f8192e8edb9edaecfd326745d32 commit d8ccbb5e228b093eba19027a281274e7faf2da4c commit 03a4c89db2ff0caf208e72425280b96762a7ac38 commit 364f168f6148277ba3344d1c54f9fdffea34816f commit d3336c935ecebb0185cce50848d9fdea665085f2 commit 44fc86f2a338e6c202565611b9725c9428ae7481 commit a41d94a7bb962fde26c9bccd4d6858b8c6bf507f commit a2a7e75020cbff0af16abae74a90bdff2834a191 commit 16592e75913d6ff7f68e192a7143f23d1dc67ac3 commit bf93f1fe50af23d670f83f801708bbbb173fc08a commit 1a856863b6f2830cb4561865cf5a8e28ae58a9f5 commit 98320bf3e39e433fb9c2b248bcfe6a5f6a3428f7 commit 0528287370390a77af9404de38091fe8f502280b commit b7c4040d0d131de5014fb02bbdbe8fa2b9c5b0b0 commit aa0f09f93dfb3b9383761a5e4792c2c950623447 commit 376fa6c9ac10f492e78af84fbef84bf93213470b commit b6ac64eed803d421ae53f280a68771b101000281 commit b78ec282bbf6b75f87358e4f634010855b770c8c commit fd25254f0bdd8c604052e88a8a77e8e9af8f4c87 commit 382dd7d23d1af3be58f07c9fabd571b760a3aff1 commit fcc4fc758e132a4512ba8176222fca61b0b7f1cf commit 09a75a234b21e6564e2c0bac517cf5bd2c6e1905 commit bc35ae1a09ca02c25df54327fb1e7a09d2556e1a commit 47ae1f938d1259d1e10e885dc64fe93f92f0ac7c commit ab90fd056cf4c7e10c25804eb5c601ee0e73705b commit 0cc0c5e7e4bde1b391d6e486a5f151d5de1a1069 commit ca7a44f92d31d539cafb73e839f5177d35b9334b commit e2fd14f579b841f54a9b7162fef15234d8c0627a commit 7aaaca3be44523c689648448dc127a711f0c3cb6 commit 0621f21cf3830c494bf8db8a7dbf9e24fff118d9 commit 8644084a74a4573278d6f454c6638ccd5965f4e2 commit 5c5189cf4b0cc0a22bac74a40743ee711cff07f8 commit 31dc58adda9874420ab8fa5a2f9c43377745753a commit 5847cf1aed00704e8202ffebea86b4f6bd618403 commit e6c7ebeaba4080562e71a59a788ac90b41e09240 commit 9edf6c09c5134f47e52268e6812ff64b416ca56e commit fe4d39879ad99781a18eb31692cbe02292cbc8f1 commit 217737bb5a17297aa7ac74ca6638628efc74c661 commit d4b8d132ce41a51241544cfa1cec8c401ff04002 commit 5fd4fef3f8e6b5be4e1df49f32efc8b200ed07d5 commit e291729873095262697758c389c8d7affa81bdcc commit 80be8286d098dc92cc48ab2d0f459dbb5cfde055 commit 2d70a10dd16a5baa3e977c12311d9d8aa2d13819 commit e7820045fde15d25b5b2706f03499e0cb9ae778e commit 60481d95ad989f556da15fa40bc6edb648324b02 commit 7bd5d763b8e125bec578ab66ce5d90a4c83e1bff commit acf07acfae919305eb96085dc0b11ab0382ae3e5 commit a0806e7fe7aa67e36b89593a02b2669efa721860 commit c14af4cc24e640e50d4c64b1930093a24402d4ce commit e418a8fdb9644712364eb582984eca0905664080 commit fab4099549a050703b87da012e5ebd75463bd654 commit 5a8c343d2e87a4d623934e73a0c3a200e2a47a42 commit 258cc2b687bf67f7872707061158aefddbc449e1 commit 3af6302d8c2ee37b9a791222947052ee2dfdea5b commit d0c989a0aad3ff047b72c89c91969a535f72dd2e commit c51bb53d5c68041dd02f66d9b638cda33647623e commit 864a8b2c1ff9e5767d6bb19854a671c30b3b268f commit 1005ab86cf75aec3462c1c58d6efa87871f2843f commit ba80939feca0d85ffa272a18c7c4763adf040114 commit 56c0a9c33cfd9c8035737746b7263266c230b80a commit af26fa751c2eef66916acbf0d3c3e9159da56186 commit a26198f12231718fda7edb574858388cd820df55 commit c2775aaa0ef666d5cec46850fdd18402071d0e16 commit 4aeaf3cbfa9f967e71849c66c6914ab6c2054581 commit 637fd8dedf10f8961782c29482edffaff1ccc7e2 commit 6ee1ee12ff334d50d346dc764b5bf0dd4d61ad7e commit 19eeae7600522ca873caf5d9e4d3d4593ea1c349 commit 9b24f63d825e771dafa137e6370c6bf44395e748 commit 87046288e8d540a0e893fec7c452ba0e91abf362 commit 0dd72af5528a404fca78ef0cad26582d34560c9b commit 216779827f8d52a39d94d43c47737a829991ad8c commit fb62a2067ca4555a6572d911e05919a311c010aa commit 155a748f14bc0b72783994dea7c5a12276730342 commit 6f3b631e395b971c7320830920185a7a2b44090f commit 685b7113e0a8087f683d61dad1dc1be78e6c57aa commit 379a3160633a469da240f40948464f20582c11e9 commit 19ba61ac06d2a4f1e58f92879b54a998ab23b4b1 commit 5946dbe1c802efef3b12a4eecab1471f725f4ca9 commit b4ba5c9509e80b8193e91ab103ffbdd304cd4ba7 commit b0dbd5db7cf1f81e4aaedd25cb5e72ce369387b2 commit 9862d2ac667a0e731aa75c17c1b146da809bc3ae commit a8936060a01715552cac818019ca5e88201a3b7b commit 2c6592221eb7812d7e2afd229c290bc79c2bfd04 commit af3303970da5ce5bfe6dffdd07f38f42aad603e0 commit fd3fece04db80c8877361bf4c9f59521ce457be0 commit 5ad5b0b7845c973bdec30ea8d486add9cdfdc543 commit 11dbb6d7b2dce45102be0de87fb2514c368e4a53 commit 7fcf8832000702577236fbe9c8ab48135a41a186 commit 0d2abc02910b10d25684d111f4d8b1265a35e03c commit c979d8db7b0f293111f2e83795ea353c8ed75de9 commit 878a4b73c11111ff5f820730f59a7f8c6fd59374 commit 73d08a87d6d421aeb973bb2079386e010a792803 commit 57c8690a84bec025a8bc22e5f867fd660c4a3e76 commit 179176134b535246f0b368b30e8ecad50066f896 commit 2b39d48a0ab368bca4c7a0458fa9cdd05ebcacb6 commit c29935e4092c61f57c204e7d61eebb91b0a2fad5 commit 0288a345f19b2162546352161509bb24614729e1 commit c8cf9ddc549fb93cb5a35f3fe23487b1e6707e74 commit 9596097be4bac5297acbbdb5f7c4ff2f4e42502e commit 5ab75f98fb6314709a2eae5f8c8450276c94425f commit 436d0d22aa7035a9f9b24fb14cd0e84d6571ea87 commit cdf6e4c0cdab129ffc4e41a8ac53a0738f805072 commit bb5dfe2f5630ce344c654c705d28b4e20cb9d334 commit 0d89268d20c961b6226a4aa948fdbe9f93021d95 commit 0099f2e92cacff128722c1c66173c3b4962e9b78 commit a6ea0a430aca5932b9c75d8e38deeb45665dd2ae commit f9f281e839b7518109a4b7efa8dbee425bd8bfad commit bd8150a1b3370a9f7761c5814202a3fe5a79f44f commit 7edb503fe4b6d67f47d8bb0dfafb8e699bb0f8a4 commit e9009c8b7401d5def4cef9c85200ae25dcb38a5b commit 95b36732fec4a954a107bb07aa4bff8793762938 commit deacae541a7210c675f1013ed5a276886b2f48d6 commit c01b52830fdc8e907e9f8462d5d7d798b7ed19dc commit 137a9127759fb6a6c526dece90fa78222c1164d6 commit 14b6a73ce1a33e20d6e526415c0af34a9e01f64a commit b1adfce26ed316cfc2f892615a7fbf4cf0f302ae commit 5e213a985d103ecd348ed4e9ae71292d86be9a71 commit caaed1dda7df9b4e21d439bb5e7750d4af4f1e78 commit 051114652b6b78c18720dbc6fef36ddb5e1da55b commit 06190e1c86e4a0a30adf47ca20614c29b692dafc commit 692ec65421799fdc4c97d09a1b349a29bc8d8a64 commit 1d72c4d3a1929c628fe87f50ade2e043b855528c commit babd0b8db9dbf6da541025e76eb58fbba2a2151c commit 8b140ae6d57f35735a33c8ace0ca79272ef1d5c6 commit e9d95194bd413b837a57096069bf85d71d48d7af commit 483f06ff8e56423d301a1b46a8b70285c1a8f3a3 commit a87a681860e857c9a0d05d084d4357bd2fbe9560 commit 152fc133419417bf33cbcd05060fba83dbdb36ad commit a5a9fd93d2c3c2bd31d27a25a601ae313d4aa74f commit 043fc9e961ef088aafc0f545c1efd8620d616c9f commit 7c0c19c076ffe84b8bcd5f927eb47452837f2c99 commit 3f0e3af4688deb797232c6ef7b45147601d9000d commit cc54eabdfbf0c5b6638edc50002cfafac1f1e18b commit 3902846af36beca676735540470a115b3d637263 commit 10dd1eaa80a56d3cf6d7c36b5269c8fed617f001 commit d42d701e132905d69be3a7808f2ec86bdb4c48d8 commit 936cae9254e55a39aeaa0c156a764d22f319338b commit 44e4c88951fa9c73bfbde8269e443ea5343dd2af commit 88dcab0650fd31072ed07a0d26fce5bbbbd8e7a1 commit d1010ca49b4f59b91cd64903e67b9547bdd2fa42 commit f8e8d7da251a73d584f87899cb92a27a56f2848d commit e3e4f03f256f5a1534174c5453ae98d9f508fb6f commit 618c144145ad3e409c2c0fa13a0efef1a9473d37 commit 34d65997489fe3485dd698025ea32b8aa74f0af4 commit 0c0dd10062bd31b3814c169e06e376c28ca42c95 commit fc1366016abe4103c0f0fac882811aea961ef213 commit 29f560a5238d6b9170ef9b63b5718e760eec4b24 commit 65653210edf35c2472f5c4963b028f67c73e80ae commit 52cd9bc47fdd1cc1a83fcdbca2df6baf2c4226d5 commit a68654bfb75cbb9ae878f81877e393b2fd8181ff commit c7fc0f372374cf463be2ba4b5b21c20c3c051bb6 commit 2f2a72de673513247cd6fae14e53f6c40c5841ef commit c812460e69d8448bbf504bdb95d8dbd19f30d5d7 commit ec9243d1b4f59ae5365add0f52fac7af2e4c18ce commit 698fa62f56aa3600efcfb11dd04f84e938dfc5fa commit 5e3f50fda28f8c2912110a4a597021eb05762356 commit 17de472698fd5e5d1e7dbd3360434dc7b763e671 commit 6a23e7b4332c10f8b56c33a9c5431b52ecff9aab commit 9bf4ca1e699c272defe9636f9812ff33a448d650 commit adca0ad92717d4752ad520faa667103eafb66195 commit 4e88de313ff4d1c67b644b1f39f9fb4089711b71 commit 38a0f4cf8c6147fd10baa206ab349f8ff724e391 commit 644673a69f2b6b7359c78b4a42c5ab17473545f9 commit 17d3c3365ba9e52596855d6acb71c3159be1b9c3 commit 0f13dead4e0385859f5c9c3625a19df116b389d3 commit 43d78aca8ed01a643f198b831231a6231f52d9d5 commit 96d45e34f8f9a459ae1a8d7a74638a96375d8597 commit 351fa2ff098eccb2a98640d02f31319c3ceca0bc commit aa39abc08e77d66ebb0c8c9ec4cc8d38ded34dc9 commit 52cb4a595fbce93b1ef940f9d1097be9245d9179 commit 7a0e86e3c9298c28f7bbbbb628bf1b7dd2de2916 commit 83b914f972bb706536edd2b84230b9c1ce39f275 commit 2e08feebe0353320651013c5bdab58c2a19a716b commit a87fef0880c4f52769b5a3c2fc1b2d73aaa04eb3 commit 6419fc157e55665dc8680deb1737dc4c53c33f94 commit 6abb6a0e1104279763d1561b8110c1db442c5fac commit 5f8d6f29c51ab8572fc1d3891952ca445e75a610 commit 0f8d0d764cc936cb834f39f0279c7776e0c1209d commit 4cdcfa64b6032ec68cdaa6c424b3b293cf7ff45c commit 44393331c79f5df14c1ff25f4a355f439a2dc8a2 commit b3a7767989e6519127ac5e0cde682c50ad587f3b commit 72f654f4247fbf0b0ddb9092052531deb6fb895b commit 701c47493328a8173996e7590733be3493af572f commit 29f4e7301910d7d1ece249cf34dfbe4dd7c2c6c4 commit bafb6863dd8cea94e7dc2f90979b30292e8ea31c commit 98466abe4ed949d6ae40bf3e2b1739e9ddd74af9 commit 38feb171b3f92d77e8061fafb5ddfffc2c13b672 commit 39c21b81112321cbe1267b02c77ecd2161ce19aa commit ca5d4db8db843be7ed35fc9334737490c2b58d32 commit 4f379370a49ccb747d8d87f2d8ee9bba965e1897 commit 6d74c9ff6ae5d246d601f855aab234b1cbaf4e15 commit 067e46a36bfc6897ebb0bd8a7f50ed98ca068ef2 commit 667912bbabc2044e00eecf7d0b5e00ad81ac2dfa commit 0d81c3982d32e4572fc91d5b8aca9e1a808a1820 commit 34199fde4a8604d9d3ad2d939c5eed530460cc79 commit 28665cad86f2830b966547afa996c3c20a432dfb commit c42852d83d0154cdb41626246a90aa64d1e4fb52 commit 3b7743701969e29d1956c40822e09acb3850d422 commit 359b9f088f53a3e0ff90e094cf1f4b32dc1d86f3 commit 8c502fd5b6e3831d8f138e8b1000c17b3add1929 commit 8ba2a9a987d047288b7b9b6617b3c3879b1e9731 commit 8d623384894cc04ae8637ba2137d168909c83f8a commit 4068f195d1385d8b36440d7d9e92eb718fb423fd commit 97cf0aace8eae6daa9e8f19047d36b741f022e3a commit a45eef15a2170b411ac441254fcd8d58b57bc92f commit 8376acce43aa958c2fff107a1d3d3a689a4eb85d commit c3c61d11419c6c8de0f0156c95d4dfb829121b3f commit ca184ac28af0e1b033fdd432ce79a1225751f360 commit 28aff13304196f4c6900602e8407a4b96147bef0 commit 72838568bddc935a3626c67c85940efa3a1e76c9 commit b9b393c68a10940b26d7a9c5d5d294bba887d440 commit 2f0d5ecae0f5604c87075237a919b68d38cc9500 commit cf3f100cec0192630e37e9cc9232186c61c0703b commit 96e97a562d067a6d867862db79864cc66aae99c2 commit 9858810e62ca6a85bd2e7795a92e00a4ffa1c545 commit d967509651601cddce7ff2a9f09479f3636f684d commit b7cccc8286bb9919a0952c812872da1dcfe9d390 commit efdc66fe12b07e7b7d28650bd8d4f7e3bb92c5d4 commit 0f744593adecfa12ce7c4bfc4a6c2850458c4e88 commit 1e5cd4adfc547bc0d0d69896e7696b96697ad0aa commit 872818e2357b026462b21e90aad115aa369966ba commit 16ac1b6a6b52ff0bbd87b6361b8b01d358dfdadc commit 99f77f6229c0766b980ae05affcf9f742d97de6a commit ac1e65d8ade46c09fb184579b81acadf36dcb91e commit a230696d4e009abb22b7a2f9d434f1555bfa08ca commit 53edf8604a7c594d1d5091deb7c11d2c3b2e6b79 commit 0839d8d24e6f1fc2587c4a976f44da9fa69ae3d0 commit 1883b2578df3e3577b429fd46776e788b2107ec0 commit e7b09b766ae2c2d0cb8e9a2d81b7b9dfca04a9b1 commit 1758cf3cfd3152530d875b9e5cb84eedafdb2e0b commit cdd9b2d7e4091cc549deadf3e160e41e795b8e26 commit a036db3953140d5c2816b056aa3e73b8e98d9bc0 commit 5a113e15d15605c07d57d923c9f4a0d52d403ecc commit cb958039323634631126cdbc94216b4037fee243 commit 75372d75a4e23783583998ed99d5009d555850da commit e9306b69e77574c676ebf3eeaa428da685cc6a25 commit 869e3869b9303ba104f14b70814cc5b4bb7ad7a9 commit 71573db5ad74b2087a4688cd1dda73ff082620f6 commit 15acb306c9efb98eaf760c76e3b02a6b7e2b974f commit fff90bb3d4e56586e06d405b683af67d6271023b commit e70f43c21dbfa305a304028577a8565379089768 commit 95f27831ee3c6afc2e3b7386c32545eba1f096d7 commit dd1ef5e2456558876244795bb22a4d90cb24f160 commit 58624c195b9a90950ebff166b72ee712f8d5a4c7 commit ddb5cf9b90c5201a833d5d65f96b359bf3acdd90 commit efffd56e4bd894e0935eea00e437f233b6cebc0d commit bb63e7257e6341aa1e48da07b13d2d00fd899fb3 commit 8f799b4e8cc0cf926019e40405dc3eab330ac643 commit e7994954c2bea9e754c5da546846fb1cd79f5151 commit a92c68eb1e19de9ea8de6c7d3bcfff6c3fcb3c10 commit ff4eca1f46f3c2c485055e2c31432ab1ec5dbb96 commit 401fabd6e2767e92cb5b23ec38948cec1d52c754 commit 7970e04d1705075e01f1e168e5b32c9c7680118b commit 22437f30d2f0265095eb1e14bf44d30e6663e676 commit 004311aa7d7ae1f591dff996232b15f2b480e93b commit c818b2651573b2ab3e5dc71dcbfe89b5e0fe9c13 commit a7ae0836917ca617434c416f9c61dc6024d04949 commit 9086170bfb925c90e298134791a9851ed626b873 commit 8d88aa149a297a179d8381ccf6170e48d666dc63 commit 987167b1199c428765b0f76b9b6587dd4ccde3e6 commit d758c8d6e2624d7be12a6c070a3387d6703e4a7c commit 65b65ffcf669c37e120bcfd3d9cef62ac961bc60 commit 6d24027d555e46e9f302523c95b3816198779f4d commit b1dcec9bd8a1de5fe04ecb3831f8db0a5c059970 commit c332fba805d659eca1f8e3a41d259c03421e81f1 commit 3a0cb885e111db34b22058a3b82e99e49f02ac94 commit 8d2511686ef55cfbdcc14d2f051224c3a16741d6 commit 49a498338417281f78594294c83707b140afde85 commit 9512d9fc2a7a4fee14854fbb3af89a8bf599f361 commit 65ce1f5834e9598e5120048010b4fe220e70473c commit ed7417e5b889769ef7f66edfd0f836fa812655bc commit 95eed73b871111123a8b1d31cb1fce7e902e49ea commit ef789ce4980b2bf9d61c53207f2b0aa1d32d9da8 commit dca84cc795df7f0cf790fbc2afcde53e6abd403a commit 61f028c13c42495964afb61974ec60c22230d81b commit c8b59651ebe678da004b71e8c20f79ed6881ea8d commit 8096e71bc875485dd34aa8bf5af15ab3c443cb54 commit 4a768c544f64eaa2fc7cfa91e46f43aa4aad0c40 commit ba3588410cedb1696cfe56ebefcc4401c6d0bb36 commit c40b50c3cfbe274f054c6a2d2fa62cd7c4650460 commit 7427f30e5c4938ebe813aa46e578cb5afc375de4 commit 85b4360d2b72b4a38497f5267da5cb817dd91b34 commit 44a95ffe685d3b9428ab81f632e9b34bb2e4641c commit 753d6b404e12ac950a6b9207ba788f7f2e0a6303 commit f55c1f62b6ce801d40b524bef97108d274a252b7 commit 756009d0fdfa15b5536de138aab0e5f15ab69f6d commit 9212733a30e349536e2c17baa5ac9b279b948877 commit 07b34db2a0982480a30fe001d5f480d9e58e24db commit 28e59c7e24ea1189bd925bf0efede4324ca3aaa6 commit e68aecf473449d625bc5e3e2f0c754711d5f680d commit 745395b51c26766b070f5761d97f9fbad15618c3 commit 2bd5dd6e720952778233636e0d0dd1ede3563634 commit 4d2dd780970d33d4dd66c718077ee703938b0a71 commit 8193ce906a8656892334b17e60e19ae7aeea220f commit ce46682f89111fd0ded74a90c1ea04b36780221b commit 2b68b9b80f9ee75d4e7e159aa082dcd8c1e4e05c commit 2b601460d1291310e4f04418eae2de93d0cc18d1 commit 3045a4eb12e9affb526cf24fb4a41d3487d55978 commit d30f75d2dba913754dbacb982b19b783a30253ea commit 66c9c0cfe765af7f30eac880da0fa047aea8617d commit ca59e33f5a1f642d13ae0e558fdbdd9aaa9fe203 commit cea6e6e8717e81de266aa496f44088b2b960aa32 commit a3753a331989d84024dcc0e3f301e4d0ebf4fda1 commit 6b2ff1d7c57ef49cd17ffe132173e05ab11a5213 commit bfef062695570842cf96358f2f46f4c6642c6689 commit def675cf3f107ba8da78ca0b8650997fdf667538 commit 318b1c36d82a0cd2b06a4bb43272fa6f1bc8adc1 commit 42ea9cf2f16b7131cb7302acb3dac510968f8bdc commit fb361a520a5861368c6c36717ff1900a35dde093 commit 6c160001661b6c4e20f5c31909c722741e14c2d8 commit d81e52fc61fb98dc98f9fdb166ab21f502cb701c commit 6cca686dfce79bf5bd5c1a680ed38a9f20669e39 commit e3a03d0ae16d6b56e893cce8e52b44140e1ed985 commit bcd600ab7f2e8ebf7eb5b6ab28dd479341c389e0 commit f4db9913e4d3dabe9ff3ea6178f2c1bc286012b8 commit 9163fe4d790fb4e16d6b0e23f55b43cddd3d4a65 commit 22d6d1b5868665fa10de94d310ae77bd809eb5e9 commit e921a5f7875da8e82cd8857269bdf60541f7a517 commit 3fd20580b96a6e9da65b94ac3b58ee288239b731 commit 8e051e38a8d45caf6a866d4ff842105b577953bb commit 0cba5b27f1924e9248b096fc746a1210be9c32c8 commit 6a681cd9034587fe3550868bacfbd639d1c6891f commit 83dc0ba2755296b5e5882e044c80973b7c3fce9e commit 83675851547e835c15252c601f41acf269c351d9 commit 37b812b7fdc2f1c7cb9e22c888776be7347097b0 commit 9d10cd526111a989eb353c3a4df9d4c79695ea8d commit 971c2b68bddb87f4929e66cd4563fca78b722210 commit 64aa8b3a60a825134f7d866adf05c024bbe0c24c commit 26b4309a3ab82a0697751cde52eb336c29c19035 commit 8304c44631c370646de35d343ddba078738d1719 commit 086714bbb96f63785da251e1f8d1ce3e716a6e42 commit 75e8635832a2e45d2a910c247eddd6b65d5ce6e1 commit c098b1aa2fa60fad42df8a1a6250099329e33311 commit 95adee9a04fa1eaa352e960e9d3387055fa03bb3 commit 69f83f167463bad26104af7fbc114ce1f80366b0 commit 7436a87db99d57196c49d10de35f41531993d5f1 commit afc399f7a5ea7bf405b2ef85c7470529b1a9e47c commit b626b1a1c9ccadd8861870a2a450f02e0c61ab88 commit e802c783be94bf71541a7e2ac8b1b5486aad10db commit 1d8847f457648ed4932019dcd3081bc27bcea936 commit 4fc30c2c5c61db88e3d6644bd3dd2032ec4bee06 commit ae219fdc952c315182b471f5aa71b379584b70ca commit 5a4e4e30f6dc4d2a68eec08257128906572f3346 commit a331631496a0af9a6f4e7e1860983afd8b1bb013 commit c6978643ea1c74c913f925c08ef9bafbdc031a04 commit ee184ab0ffb6cdd20527aa3b3729b824f52d3cd7 commit 3bf74137340a1ced1566f4f9e9c2f08cba7bdf7c commit 3519e9ea13b49e7b37a20fa3a11a9e1fc5441af5 commit 1c21f240fbc1e47b94e68abfa2da2c01ed29a74d commit bb33013bdd238129c8f8f29ed2e9bbdfa8caa643 commit 3c227be9065902f496a748068e0b2b6bd6f3f0a6 commit ab4c3dcf9a71582503b4fb25aeab884c696cab25 commit b703b31ea8cd22c1915cfdd6d8e39bf39ec64c8b commit fab06e956fce42f07ad35ca53073504bad2a080f commit 7d0507772406e129329983b8b807e5b499bd74fd commit 793e8f7d52814e096f63373eca643d2672366a5a commit 6ea52b6d8f33ae627f4dcf43b12b6e713a8b9331 commit 3906e7a3b26d683868704fe262db443207f392fe commit 607805abfb747b98f43aa57d6d9ba4caed4d106f commit 0607052a6aee1e3d218a99fae70ba9f14b3b47ed commit 6dad7fa8581e96321ec8a6a4f8160762466f539a commit d1c0978a7e7864fcaa7cdd562a8f938afcd2ad39 commit 388df23fda2db75abe988015a1dd681a43fcdf94 commit ce76a267341cb306016beedb24a205e892613716 commit 950cba9870f98a6db932f6b914f2d4786c87236c commit 87cac7a5f99e7c7ec9687e3f1e61138da41683b7 commit 227ef8cf93a5328642d844d0f61dbd941e90a2a9 commit 07972c070f4879a621b3194662b90ff66e25d666 commit a1018063f7553cdd380f153441905d98dfd0a9e5 commit d8a29980eb3dd4efff895317c74b4cce9636e14d commit 4bad57c21bb3569efde4dc81915b53f9a036678c commit 81af99cbd9e4f238011af811d544fff75641fc25 commit e005fd94e2e5867f2a4e66e5df85069cda6f0db4 commit a8bdd9310cc9b47d9ea851f6f5fb699aaa4930d6 commit a4b4385d0523e39a7c058cb5a6c8269e513126ca commit f675a276b84488e78287dd22c2e9461e4c008c66 commit d07490fb23958006bcecd6f2ba411571c099d104 commit 9d34e1a8cf7b643bca058a65f3441d90099b297f commit 35dd5e1c089b6fd9f503bb15ebc1138d5a3f887e commit 0bbca46cd50a527bded903ffe7f32e3761e825bd commit 31cb3cd7e7149983e279f3d6da3ae5757a965ea5 commit 7654c807f20701ebd1dc7e967270d017dcc36730 commit 32529d384cea3a9b939ff1b56aa30a13f8370129 commit e5e1a0000746ded4d9fa16fceda0748aec2b6e6a commit 33f86ac63031d0593e48eb0a738f2d1b1ee29879 commit 685d0dfc37d081e56374852165afc8ab3b3e8d5b commit cc4adab164b772a34b3340d644b7c4728498581e commit d4a814f400d4f3bd1e52f9b82e7d1f11b2721cf8 commit 5aaa5058dec5bfdcb24c42fe17ad91565a3037ca commit fc3336be9c6297282dd7968a597166b212cb0dc0 commit 5d42ee457ccd1fb5da4c7f817825b2806ec36956 commit 54f2fc76ddd3caa7ec8d6018b10147a82b8215ec commit e6048510c3197f3aa7eb4a6993b1edb22ff7ffa3 commit 17b2c526fd8026d8e0f4c0e7f94fc517e3901589 commit 1417281ca89c7f39eb91a8cd77e2fd9c25f3bb77 commit 942782883955b52f399b99ec6f0e6af2c7e8d440 commit 8cee62904caf95e5698fa0f2d420f5f22b4dea15 commit 0a62732e53d7e295e1733a2d9bf661e593d86675 commit 803a4cb8e3a4790c38be7e9bf64adfd2b6bdeeac commit c59ade93fbf530abe42afc4b79fef3cc771f91f1 commit bdc26342c49e1dc1afb48feeb20c9d74d15b784c commit a625dc4989a2affb8f06e7b418bf30e1474b99c1 commit d5db4f88e0db6fdbc3f3681458132c0d18a44a29 commit 4589712e0111352973131bad975023b25569287c commit c0d6f52f9b62479d61f8cd4faf9fb2f8bce6e301 commit 443c30f243a3f07c310650f827cb71c2a1d5500b commit 4321c5cac7f21e88d3bae9a67d5a6008d0b4a9c4 commit 5eb680a06007f2f6ea333d11a4e29039da90614b commit e51b709a6dd0b95bfd9df7626b7f4a9d325fc3ff commit f16a208cfb55dd39deab74957783a19b0130b261 commit 0314df64dd328261215215a201b578ffbd56d3db commit e924c7004b08e4e173782bad60b27841d889e371 commit 1de6763bdd0437473239103d7733b24f11e0d824 commit 05138e8ff287188be7b1bedf022c8b4fd1f09a25 commit eba6ffd126cd52358181ed5a179644a161f9c65f commit f12352471061df83a36edf54bbb16284793284e4 commit bc847787233277a337788568e90a6ee1557595eb commit e700f5d1560798aacf0e56fdcc70ee2c20bf56ec commit 06682206e2a1883354ed758c09efeb51f435adbd commit 5488a29596cdba93a60a79398dc9b69d5bdadf92 commit dc0e3aa54eaa4fc6efa1cf4467a487ea52b94f01 commit 1d5362145de96b5d00d590605cc94cdfa572b405 commit d51e390ae84857a999ad2046e074e97663e98e36 commit 3b3ddafde1c2b5262628b4463c7b6f4ccc6430b5 commit 4e7fd5aa3f3939dfcd8b0578de57f1cc00d6c31c commit 6dfebeee296cbb3296f06c28f3b2d053ec8374e7 commit 95d628c9e4738c070ba780488efbab894e583646 commit 68b271a3a94cfd6c7695a96b6398b52feb89e2c2 commit 2555f4e4a741d31e0496572a8ab4f55941b4e30e commit de93bc353361f5939f5257e6dcd9cb533dd7cce3 commit d25c67fd9d6fe0921024791bca3ab8a83ca32df7 commit fab47d2db5ca10c726459753224dd296506e0f97 commit d9fc0bdf9ce43225e4de2aec316ffb0acad65ea1 commit ea89b305b6364ea8190b5ee108b9d122e2886f34 commit 29b703d7addf767b99ba4af98ecddd5c1c91ef38 commit bbcad5a8896b2d3da75d2f0dd9c85f37757d8c37 commit e214d626253f5b180db10dedab161b7caa41f5e9 commit 966d70f1e160bdfdecaf7ff2b3f22ad088516e9f commit e53dcefe30df4f317161f36e8bc11926e7dd7a2e commit cf818707b543687f7cf99180ae0d218bab9a3205 commit 532e2c87d428d2dc18152f004c59be15281310bc commit afaf4250713e4678563914c6cfaf3e381562cf5f commit e3a6eff92bbd960b471966d9afccb4d584546d17 commit 9d03d404f4bf6f02cf690ef8c9608d8f0e4ce630 commit 0028b86b52f7609e36af635ef6cb908925306233 commit 56fff1941abd3ca3b6f394979614ca7972552f7f commit ad7b68b04342476bd26967fed58213c61bfe7785 commit b38d2c3302dfe7c22fde158c59cc55acd3744a26 commit 1412482b714358ffa30d38fd3dd0b05795163648 commit b2c6627e406d00bc53903ff6204aabb0c6a22b1a commit 5ec66bbc74883b73d169ceb25dcb7a5cb22e275b commit 121d87b28e1d9061d3aaa156c43a627d3cb5e620 commit ad3ebcc2d06875738cd463fb5424cda70cd94a34 commit eb3dad518e4da48ab6c6df16aa8895b8b0bd6ecf commit 7c60d964fbb100103730db9560f5594c1c4fc844 commit 474d54095090be8ea8701d4a16476f488aa06959 commit d39fb5ca7207a2a8824639b4fada20811d3f2bdf commit 801a6e61f5fbab2c0dd76c8360f45b625b49e410 commit 504f3cead6b04914c53831f9efce902b8d91c009 commit 852c68bf42965ee38b465d2d6f7b965eb0b5dc1d commit db7e7ea838c916ee4cdf26bee126fd36f58295dc commit 39385cbd4222fa37ac320c6368bf9d8a60fd47ef commit 96c2c72b817d70e8d110e78b0162e044a0c41f9f commit f7e06786512e730f750138b1221b6342bcf07859 commit dda702172dc26e080fe048b8f170eaccb8097c1a commit 1bf8b4642c5f511dd73653a25ed7cd0470118389 commit 6194f60c707e3878e120adeb36997075664d8429 commit 53868dd8774344051999c880115740da92f97feb commit 6ce8d536c80aa1f059e82184f0d1994436b1d526 commit 4a421335842bb622cb8685e66e0e177d4bae5363 commit bdad08670278829771626ea7b57c4db531e2544f commit 7cdb3d0367860d8e5a058b8658cf7ae85a4796d3 commit 6cf32edb5d6307bb55764d9c6df0af4e73c415f2 commit 06fee4fba93112c198232c351ef4348614a94590 commit 26b5cf26885078c0173301a0c12304e17463ba10 commit c37084e25f058b9e4c531ac6fc6f232533c566e8 commit 15b1d7b77e9836ff4184093163174a1ef28bbdd7 commit 5b8cfb0cebf93bd0f8b316084ce0589df8fd57ac commit ba448f9ed62cf5a89603a738e6de91fc6c42ab35 commit 592c5b80110d5e9e50873b5364818cb6f401e26d commit 0f2828150f7ab31a57fe3bce6c2d378103dab10a commit 37e6349e9328feb600568144411c18e3c35e3077 commit 7a3fbdfd19ec5992c0fc2d0bd83888644f5f2f38 commit 91544c45fa6a165abde6f2363bb7ded5843ef840 commit e0d11bdb294cd1325eeccfec05e07d8c2534b43e commit e698127eb7249d6c70fa8f2bdba469c0e54f2e2b commit 6704d98a4f48b7424edc0f7ae2a06c0a8af02e2f commit 205bd15619322a1429c1bf53831a284a12b25e2a commit 15392f76405ecb953216b437bed76ffa49cefb7b commit 1197366cca89a4c44c541ddedb8ce8bf0757993d commit 05762d9c7da1f7e8ec6c456f592a17390ad43ddd commit 637fee3954d4bd509ea9d95ad1780fc174489860 commit ba205ac3d6e83f56c4f824f23f1b4522cb844ff3 commit 8079b87c02e531cc91601f72ea8336dd2262fdf1 commit 82a9ab369a6785499ad18453bb76b1128403122e commit f28b0a13865f85f216d4ac9ede75bbf8745a524f commit c99d381d2dcece1cb18ae28706b12da271517dde commit 156c0ab1de4e917b106deb63cd7583fa45d7ce29 commit 0d9a49a2ce4738bb802cfc0c9ca5abdecd36e96e commit a6a4dd519cbe1fdf1f33e2942356dcc9c7b4c682 commit 3aca6f835ba1635e49d9b76d2102b218643d276e commit 2bddc36c121918a523132ee369a6c76da702748c commit e80b1d1aa1073230b6c25a1a72e88f37e425ccda commit 1f16866bdb1daed7a80ca79ae2837a9832a74fbc commit a2918f958d3f677ea93c0ac257cb6ba69b7abb7c commit b340ff216fdabfe71ba0cdd47e9835a141d08e10 commit 0a6d6ed694d72b66b0ed7a483d5effa01acd3951 commit 608fb0a78c42ee61cb567f9b918ee109663854bb commit 8fbe215d3764aedebdde92ed88cf64ae681276f8 commit 502d2d8e01c8930afd42363d543ed11298cbe34a commit f84b65b045f186b8fbaa32e090688ef3282b56c3 commit 2eec08ff09a416bf04b5716850da73a5084d0500 commit f2e0abdc88ce68cdba0a66ccc05a3e96b688a2c7 commit a60f627cf4ab474aebf15f62c55eadabab9780da commit 3e28a67a85f9b569066f6dfcddadb39294c0c9d4 commit 45c0a8a70253ab97e676b9791891e389a531664b commit fe6d29b082d49df336ebb92226a3c004ae9e3222 commit 7d08e0916a59e006c262dcd2f7168d0336c80265 commit a87da7a9fa7b5c39b01d7fa30415c9211e775f2e commit 05f8f36d0b836006a1f7a7d233789c8c80ea89df commit 31b153315b8702d0249aa44d83d9fbf42c5c7a79 commit 949adb4789fe3c24eea01d9c2efe94ab92694a0d commit eee8227dd18868bb16dbf72e2ab11d1a9008b874 commit 9a42510d6bc75324f1636f8e654d31ff08257a9a commit 8488fb054ea8a603921fe0a05bfc2bd43e64c5bc commit b8285d2ee73758386252cc3a67839bc463dfa1cc commit 2ac80621e0efcc145f15a05a60f185d26290c4bd commit 9ef84a307582a92ef055ef0bd3db10fd8ac75960 commit bb4099c7d90043673c8089ae1dce0d6c7d393f13 commit 0054d5a57a98c1a6783ffd9c8b7ceda8f8bb46d1 commit e121ccca8a4a5dd6fb5d395de6ef31ebfce7fb38 commit 9d6bd60695806782bec8562ab73aefafce067f05 commit 08a01ec306dbd0e096be8ee0cebb0e6a3b5fa413 commit c2d2ccc85faf8cc6934d50c18e43097eb453ade2 commit b82f0759346617b2cb84d8cc2d4a179795d4efd0 commit 0b39cb143d214fac7e30696ac1c53fad563fbb1a commit 1a77ecec8b35258c45b6963698e5dc378c67ef32 commit 1e5a335e2436a263cdc5c27ea7bbb0aa8137346a commit 22bd5f691665b3d427d21db077698d580a5e5266 commit 7c1ed3dc6769119e55473650cebacdb0ad8d0edb commit 4a0f94dfef34745a380a93b3a764d82e0ff840f4 commit 500449eb7008a1e60fd748b4c9d4c2b000cb88c7 commit 97a9689300eb2b393ba5efc17c8e5db835917080 commit e37fb0f818386d2c91474e1aee29fbf692fa08a3 commit 7b88453a476c9770c094c1f596e0b9fee208e65b commit da8c276035494e86f2cfda7afd92c3202c4c0997 commit c6fa06fc4c78ed6658bc77d41ceaca0c0121da48 commit 08b1eb621cc32819b7958a15cff10016b03b7aff commit 6ba60345f45eaf7cb4f89105d26083a4b9fd1cba commit 0274a54897f356f9c78767c4a2a5863f7dde90c6 commit 1714dcc4c2c53e41190896eba263ed6328bcf415 commit 8980be03b3f9a4b58197ef95d3b37efa41a25331 commit d6e04d2e675fefcb24cc8ba3b72a4adf98dabdb2 commit 073dcc0283703035cd4e6bf6aa11fbc63b8a9ca5 commit c4d53e567d3b6f6211d013e6c5c3672b26a49845 commit 9dc983a85eb9b546bbe2ef3f2345e338aa655789 commit d19512f5abb198daf29da877f6a02c667a95c03d commit 6e035abf98b05fd7f11d111f20f0377e0a0d68c3 commit 628299518894a41c95ffbe465f80b8ce36830007 commit 8b52d9ba085f0e1fee30aa4d1e4948494047b5fe commit 5d5ef6954979509fdf2fcdc74837be67b8192afb commit 904b2e5063af17087aa30edc6b11933d2d8cf01f commit 51cedb93da116e36490d66d9d034a3e071a604ce commit 666c654a5ae4090a3402ac14f399283934ea8104 commit 211ecfaaef186ee5230a77d054cdec7fbfc6724a commit 922f9dec5d19df4cfbb7070275e5c131d10c80f3 commit 5023ca80f9589295cb60735016e39fc5cc714243 commit c40c94693c87e092fea94fe8cbd751d216511793 commit c9be63d565789b56ca7b0197e2cb78a3671f95a8 commit 0c44d61945c4a80775292d96460aa2f22e62f86c commit ee41e5b63c8210525c936ee637a2c8d185ce873c commit 46a2cb7d24f21132e970cab52359210c3f5ea3c6 commit 314d30ad50622fc0d70da71509f9dff21545be14 commit 56423871e9eef1dd069bddef895207fa5ce275fe commit 8a70a26c9f34baea6c3199a9862ddaff4554a96d commit 39fc2bc4da0082c226cbee331f0a5d44db3997da commit ff205dc95a897b4b8c093b665702e83bffd04dc9 commit 3b948dd0366a0b64c02e4ed1aefdf7825942e803 commit f025a2b8d93358467b8e8f4b3a617e88c5f02fab commit 5cc7bbd9f1b74d9fe2f7ac08d6ba0477e8d2d65f commit 6952255ed97914abbf86fc3f92c9918945b885b8 commit f7afda7fcd169a9168695247d07ad94cf7b9798f commit 5028a24aa89a2c91b44964191ee8184e5f5c8cb2 commit 1099b651ae4d1de129adc073a657c03c94ef3d22 commit 3c5ab2407aaa116d5c3c7b0fa8dab395ecf24aec commit 2f5db9b4002470ea19380326c5a390647c56e780 commit 510e7261a7bcd6232e90f0b6b9f93303bdd29f8a commit 9b1b3dcd28c271fc8c4a87e81860f3a34b6d29b7 commit 0c61526621ec1916527d6f6226d8a466340cca22 commit 72c395024dac5e215136cbff793455f065603b06 commit fef0e649f8b42bdffe4a916dd46e1b1e9ad2f207 commit 85f24b0ace9aa79142f632fc3ccc730a8d2a4a28 commit 3381d7b2b3dd012d366b9ba9339f98d54bea69fd commit 939faf71cf7ca9ab3d1bd2912ac0e203d4d7156a commit 41f1a08645abb5ef7d2a3ed8835c747334878774 commit c6e62d002b7f0613f02d8707c80f2a7bd66808a0 commit fe26ae6ac8b88fcdac5036b557c129a17fe520d2 commit 57b85fd53fccfdf14ce7b36d919c31aa752255f8 commit ea06598e23f18005ff320e16f141e40a0c392d81 commit 34b11d0a7530ac374f889f4559f5dd85be86670e commit 64c94cd9be2e188ed07efeafa6a109bce638c967 commit 1a38ded4bc8ac09fd029ec656b1e2c98cc0d238c commit d2ca311a832098423261d19f8b9d8e2fc745073f commit d0728aee5090853d0b9982757f5fb1b13e2e2b27 commit 9156bf442ee56c0f883aa4c81af9c8471eef6846 commit 4a9c9882153a31818f25ef860e62d227f106e93f commit 4d687d06c3409e4e041c65645eab10520bd78afe commit 318917e1d8ecc89f820f4fabf79935f4fed718cd commit 4bff89bad90cff5b8422813f659317637d0a1994 commit 136114e0abf03005e182d75761ab694648e6d388 commit 0faccfa9ca8e9688f106c961972b885f7eb86941 commit 6386a0bcdb7e4c20943d3983520ebc22f041a226 commit 6246c12f52c389342358c3039475ef822921dcae commit 7d9ec9dc20ecdb1661f4538cd9112cd3d6a5f15a commit 0f2620c48640e6635270d54d2cd9d724e5a1338a commit e8c7156240a00fc3f13107dcd66aa5b51640cccb commit 1778a64f9bea4173f8eb3767d6f385c51fd09bf8 commit 226a40c06a183abaeb7529a4f54d6c203bd14407 commit ba038065655c45728be346d0b174a6da08d8a5c5 commit 5a19302cab5cec7ae7f1a60c619951e6c17d8742 commit f5a8292aab5be0f52b656ac393df4c26edac8e90 commit 41af6215cdbcecd12920f211239479027904abf3 commit 29b1b0b06defd4dcbb8af246270a9ad8686b89ed commit d76c66c6ad83994181967d7427385aab4c009ae0 commit e98bb71e246cd18c9718aba70718e845b6d134e8 commit 5cc934e089fd70f69e089b0620a83386c99fbcf8 commit ce1598f018ef7fd65f6e6a5b36a34dbf71aef6c8 commit a0562828d14410bc9b63c80ffb770e1ca7a7b27d commit f4011253c2287dab6517839c7f7ff8d178400bdb commit 4d632161e921b44c0b65561e26c6d74ae0dd5e0b commit c6948604eba672b63ff82d70f39238f4288e9e21 commit 782baa76ee46a9772b76b5df6d96e4645e362f07 commit 39a96f126d43e504be54230ff13834277b543802 commit 33ed922d24d0c73bdb51b2ddf8f2de8b42ffb015 commit cde3894904cf7820e8518f9df716ba50e91513fd commit 3ee1c72606bd2842f0f377fd4b118362af0323ae commit 044f8d3b1fac6ac89c560f61415000e6bdab3a03 commit 9aca641143cec1b25e76f54fc49187b17393c12f commit b18fc0ab837381c1a6ef28386602cd888f2d9edf commit f38bb9b0928638c09fefb26d9d22745bfbfc7586 commit 908d318f23d6b5d625bea093c5fc056238cdb7ff commit 49fe2c57bdc0acff9d2551ae337270b6fd8119d9 commit 57d00816c6a9c152f01b65bb7b3662f4d03ccd09 commit 5e9aec4ea350db868e38f901fa19bb1d70c7a6ed commit 8446c747370ab31a3ae0177227f0de3e65c8815c commit abde491143e4e12eecc41337910aace4e8d59603 commit fd1fa48b935f22c7d99713bf33846e14a6bb6ab9 commit cebcffe666cc82e68842e27852a019ca54072cb7 commit 218da1209de0d67eae3913e5b261ac57412889f9 commit 0b87d51690dd5131cbe9fbd23746b037aab89815 commit 8f582bcd132cf1290e1fbd56b9f783dabe637dd4 commit e9e0b48cd15b46dcb2bbc165f6b0fee698b855d6 commit ca4ee40bf13dbd3a4be3b40a00c33a1153d487e5 commit 9478c166c46934160135e197b049b5a05753f2ad commit 46120745bb4e7e1f09959624716b4c5d6e2c2e9e commit 777a02812f739af9e349cd0f695400a1d84053f4 commit bf7172cd25ed182f30af2cbb9f80c730dc717d8e commit 2a673fb4d787ce6672862cb693112378bff86abb commit fbbe32618e97eff81577a01eb7d9adcd64a216d7 commit 4a9b4e1fa52a6aaa1adbb7f759048df14afed54c commit bc6387a2e0c1562faa56ce2a98cef50cab809e08 commit 5e905ec67214444362b81345ef8fde63e58425b6 commit 1acec6ef0511b92e7974cc5a8768bfd3a659feaf commit 4e83a8d58e1c721a89b3ffe15f549007080272e2 commit b61d56516647aed3cee373237ce2913b9faf9285 commit 93d08a1cfc2fb6a5f3e9953eee807c66f38d5547 commit 2d01d88a532b8847757d3015c66beca315f496bf commit 42ebf3b31709255443df0e280a630feb7c3db0ab commit 3e2138510b2ad556a12a7b284a025a23992e4aa1 commit 2de34fbcab2063cd3d52e5872a801b9a5fc755d0 commit f402898bd101af3166bde236b7f6a43d926e17a0 commit 17ff034f805e032ed1358624a71381f9d6e29e9e commit 4a063f64f905310ae7ec81f2e1cc9fdefb7ac3d7 commit 7be41fb00e2c2a823f271a8318b453ca11812f1e commit eeccf287a2a517954b57cf9d733b3cf5d47afa34 commit 8175ea4159e9c4275503cb287802fae6d6a8a055 commit c6e2639cdcf07810dcd56c64ab1aeccaa5877035 commit 63b7f5826508a2b81e3010200d13ce92f0b2311d commit 4c595e75110ece20af3a68c1ebef8ed4c1b69afe commit d637dd7288814bc4dfbc851780f7a3eada1e13d3 commit d1d51519bc3bf4ae316203427d733a002d947cd0 commit b6a65009e7ce3f0cc72da18f186adb60717b51a0 commit d3b03850bddc775eacb13cb3969141cf725308ab commit 1b38a87b8f8020e8ef4563e7752a64182b5a39b9 commit 73463e26f7e2adc5e00873a8afb03ddf49fd838f commit a1e0a6b55216820286b31443724b26ed58e96e0b commit f0157ce46cf0e5e2257e19d590c9b16036ce26d4 commit 09da66f139b43c217e22435d6e50b0d9960f5183 commit 23c098b5fc89c17cec6b25ebe071f47a54b7d613 commit 096bb75e13cc508d3915b7604e356bcb12b17766 commit aa25c111a782e711d9eaad0adc3d5e086d175a29 commit 613b1737abe1bd0a65b49851e777231302095e28 commit e021ee995056ee7e58114edd92bcd4578d8b4bb5 commit e2a024345bce78a8e1ed7d9e84c859b05979e41e commit cbced93894d145239c83881d7fd953b7392c23a8 commit 4bd8b5f8bcb57b430c35494d8a2471ce5fd7661d commit 3ce2ad267079fcdd2c087bbbfb4f91bec527a4d5 commit c5f8658f97ec392eeaf355d4e9775ae1f23ca1d3 commit 496daa2759260374bb9c9b2196a849aa3bc513a8 commit 803ec1faf7c1823e6e3b1f2aaa81be18528c9436 commit 7a4a583db62818a362c5721a7b4624248f967647 commit ae9e8654579709c2f10b8c86a8467e1710d4599f commit d4a292c5f8e65d2784b703c67179f4f7d0c7846c commit 69050f8d6d075dc01af7a5f2f550a8067510366f commit 7a70c15bd1449f1eb30991772edce37b41e496fb commit bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43 commit 323bbfcf1ef8836d0d2ad9e2c1f1c684f0e3b5b3 commit 32a92f8c89326985e05dce8b22d3f0aa07a3e1bd commit 189f164e573e18d9f8876dbd3ad8fcbe11f93037 commit c17ee635fd3a482b2ad2bf5e269755c2eae5f25e commit eb4a7139e97374f42b7242cc754e77f1623fbcd5 commit 43d37df67f7770d8d261fdcb64ecc8c314e91303 commit 1bfd7575092420ba5a0b944953c95b74a5646ff8 commit 0879c3f04f67e2a1677c25dcc24669ce21eb6a6c commit 74b6e83942dcc9f3cca9e561b205a5b19940a344 commit c601fd5414315fc515f746b499110e46272e7243 commit 49abfa812617a7f2d0132c70d23ac98b389c6ec1 commit 7b7d7693a55d606d700beb9549c9f7f0e5d9c24f commit ea78f8c68f4f6211c557df49174c54d167821962 commit 64ac7c09fc44985ec9bb6a9db740899fa40ca613 commit 28dfe4317541e57fe52f9a290394cd29c348228b commit 5e0bcc7b88bcd081aaae6f481b10d9ab294fcb69 commit 480ad5f6ead4a47b969aab6618573cd6822bb6a4 commit a5fe1a54513196e4bc8f9170006057dc31e7155e commit b57c4ec98c17789136a4db948aec6daadceb5024 commit 6b0d812971370c64b837a2db4275410f478272fe commit 36d9579fed6c9429aa172f77bd28c58696ce8e2b commit 5e061aac4c0c9d26dffb81aec6c8d70bed048f2d commit 82a499d2cae69341191447de5e0bf35282676892 commit 103d53eb6fb11cfc3d502eb7b6efa706e139b947 commit 6e3f4514e3b432871ac81717d24f56b441857f77 commit fb797a70108f3fda83fde6dea30bee4be7d5df8b commit 2e3649e237237258a08d75afef96648dd2b379f7 commit cdc8a1e11f4d5b480ec750e28010c357185b95a6 commit e377182f0266f46f02d01838e6bde67b9dac0d66 commit 99f9b5343cae80eb0dfe050baf6c86d722b3ba2e commit c28b3ec3ca034fd1abc832fef46ce36eb13f8fad commit a4fa2355e0add57253468ef13bd08f11285f3b6e commit 389c2024cab817366e6b8345f679f41064fa94d6 commit 30d937f63bd19bbcaafa4b892eb251f8bbbf04ef commit 61ded1083b264ff67ca8c2de822c66b6febaf9a8 commit a58d487fb1a52579d3c37544ea371da78ed70c45 commit ace7dcc8181373a0338efa1686c5e36eb121dff2 commit a99cac460ddeb3705cb54a8421339f351586b25d commit a99d34e5ecb9a8f2212ee5a01140313bb115f9be commit b3368ecca9538b88ddf982ea99064860fd5add97 commit 89865e6dc8487b627302bdced3f965cd0c406835 commit 3091723785def05ebfe6a50866f87a044ae314ba commit 0cfe9c4838f1147713f6b5c02094cd4dc0c598fa commit 68785c5e79e0fc1eacf63026fbba32be3867f410 commit 2c1030f2e84885cc58bffef6af67d5b9d2e7098f commit a145bbff6f53ab80757a15eba5ad2ba8e3bdc9dc commit 048c1c4e51715ffddd4189745c07f530f34fbe37 commit 65b5c326ce4103620c977b8dcb1699bdac4da143 commit 8f3c6f08ababad2e3bdd239728cf66a9949446b4 commit 91d7e9df42598af28ca440b95b16a4e51a408771 commit ee8ade4d9678a456bb5ea675c270738b250eda68 commit 76e8173ba92e15eeb0421b7cdbaef20513193b51 commit 150bceb3e0a4a30950279d91ea0e8cc69a736742 commit 838ae99f9a77a5724ee6d4e7b7b1eb079147f888 commit 021f1b77f70d62351bba67b050b8d784641d817f commit 3fcb1cbd7678ec057c62dbfe49369cf65badf8a4 commit 3d3234d5daaacd468d1bc2c22ed8a26124e9da57 commit 431989960f9442b0d3b41d899005f8fcbcfc1130 commit 96bfe9ff7e88f0541002640acbcb3ec63c9d0130 commit cb47c882c31334aadc13ace80781728ed22a05ee commit 9d4837a26149355ffe3a1f80de80531eafdd3353 commit 062ea905fff7756b2e87143ffccaece5cdb44267 commit 52289ce48ef1f8a81cd39df1574098356e3c9d4c commit a6571045cf06c4aa749b4801382ae96650e2f0e1 commit 72ecb1dae72775fa9fea0159d8445d620a0a2295 commit 46d8a07b4ae262e2fec6ce2aa454e06243661265 commit 7149be786da012afc6bae293d38f8c1fff1fb90d commit 2f22702dc0fee06a240404e0f7ead5b789b253d8 commit d0d727746944096a6681dc6adb5f123fc5aa018d commit 237aab549676288d9255bb8dcc284738e56eaa31 commit 029ae067431ab9d0fca479bdabe780fa436706ea commit 1be2fca84f520105413d0d89ed04bb0ff742ab16 commit c2c79c6d5b939ae8a42ddb884f576bddae685672 commit bb5f1cd10101c2567bff4d0e760b74aee7c42f44 commit 5923a6e0459fdd3edac4ad5abccb24d777d8f1b6 commit 335b237d902c7362cb7228802e68374406b24acf commit 59bdbabccaa470ed94aae7d94a1229c7b0ff4681 commit 33efc6346e8cf75219673fe1ca1916ab40643728 commit becbab4a5a02156000f3aaff8bb70e8fd3e0d4cf commit 2ce75a0b7e1bfddbcb9bc8aeb2e5e7fa99971acf commit 3646ff28780b4c52c5b5081443199e7a430110e5 commit 3c9eced53749be418128170f89979f5d50547fd1 commit 8c835a10c021c08c3781305b806b15656c2dd7c8 commit dd0365021be3e8693680bb1d2616edf7d5e17800 commit ac57eb3b7d2ad649025b5a0fa207315f755ac4f6 commit c7feff27ea0a34540b4820abd0cdf0b5100516d4 commit c6cb77c474a32265e21c4871c7992468bf5e7638 commit b0a4dba7b623aa7cbc9efcc56b4af2ec8b274f3e commit 7caac659a837af9fd4cad85be851982b88859484 commit a55c2a5c8d680156495b7b1e2a9f5a3e313ba524 commit 2d7f05cddf4c268cc36256a2476946041dbdd36d commit 74ef7844dd8c27d6b94ebc102bb4677edd3e7696 commit 67253b28a61f0dff31f8f00dca8c9586f089b852 commit b49814033cb5224c818cfb04dccb3260da10cc4f commit 6270b1a5dab94665d7adce3dc78bc9066ed28bdd commit 10718159890bc99cbcc7b5a38dade05df335e797 commit ebe82c6e75cfc547154d0fd843b0dd6cca3d548f commit 2323b019651ad81c20a0f7f817c63392b3110652 commit 39f44f54afa58661ecae9c27e15f5dbce2372892 commit 0b26edac4ac5535df1f63e6e8ab44c24fe1acad7 commit a54403a534972af5d9ba5aaa3bb6ead612500ec6 commit 5d4e88bcfef29569a1db224ef15e28c603666c6d commit e5e6d67b1ce9764e67aef2d0eef9911af53ad99a commit cdb82ecbeccb55fae75a3c956b605f7801a30db1 commit 3cdd405831d8cc50a5eae086403402697bb98a4a commit 9c52f49545478aa47769378cd0b53c5005d6a846 commit f39e1270277f4b06db0b2c6ec9405b6dd766fb13 commit 3fc4648b53b7e393b91e63600e28e6f25c8ef0c5 commit 6bee098b91417654703e17eb5c1822c6dfd0c01d commit cffcb42c57686e9a801dfcf37a3d0c62e51c1c3e commit e9f58ff991dd4be13fd7a651bbf64329c090af09 commit 9787f7da186ee8143b7b6d914cfa0b6e7fee2648 commit 86650ee2241ff84207eaa298ab318533f3c21a38 commit 0162ab3220bac870e43e229e6e3024d1a21c3f26 commit 9b72283ec9b8685acdb3467de8fbc3352fdb70bb commit 26c638d5602e329e0b26281a74c6ec69dee12f23 commit fb3738693cbdce104bf12615e980a6a37ff9087d commit e0f82655df6fbb15b318e9d56724cd54b1cfb04d commit 7838dd8367419e9fc43b79c038321cb3c04de2a2 commit 38b8dcde231641f00eee977d245dbfe5f6b06e11 commit 9be6fd9fbd2032b683e51374497768af9aaa228a commit e6e3ea52bf07a0b7b9dff189616f189b83ee397a commit 01f2557aa684e514005541e71a3d01f4cd45c170 commit 65d046b2d8e0d6d855379a981869005fd6b6a41b commit 437eccb1a89d7038776d3119e54bfda119c6e92a commit a15130d588143a20592d55e2bb2be5489116a88f commit a6e77320badd1444b0429ff8b6f338b750a1dc4f commit 08441f10f4dc09fdeb64529953ac308abc79dd38 commit 6ad2a661ff0d3d94884947d2a593311ba46d34c2 commit bfa71b7a9dc6b5b8af157686e03308291141d00c commit 87997b6c6516e049cbaf2fc6810b213d587a06b1 commit aed3d041ab061ec8a64f50a3edda0f4db7280025 commit 2d300ebfc411205fa31ba7741c5821d381912381 commit 14b81abe7bdc25f8097906fc2f91276ffedb2d26 commit 37c2caa167b0b8aca4f74c32404c5288b876a2a3 commit cdbc3b62cfc2785da32b82260f852370cc1f2a6a commit 2f0e491faee43181b6a86e90f34016b256042fe1 commit 3e6dd28a11083e83e11a284d99fcc9eb748c321c commit 77fcf58df15edcf3f5b5421f24814fb72796def9 commit e8ab57b56402697a9bef50b71aecc613f0d61846 commit 56781a4597706cd25185b1dedc38841ec6c31496 commit 7150850146ebfa4ca998f653f264b8df6f7f85be commit 9da4f9964abcaeb6e19797d5e3b10faad338a786 commit 429aec2bc0ae1e20ce96066d57e9f91f79b660df commit 28922a43fdab715ed771175e8326ad7e13808be3 commit 4e9597f22a3cb8600c72fc266eaac57981d834c8 commit 90d239cc53723c1a3f89ce08eac17bf3a9e9f2d4 commit 06f4297134db37fb326047b1ed8194a23cdf057d commit bfe9e314d7574d1c5c851972e7aee342733819d2 commit f078634c184a9b5ccaa056e8b8d6cd32f7bff1b6 commit 45ebe43ea00d6b9f5b3e0db9c35b8ca2a96b7e70 commit 355223cb84eb71f0f591b5e122a3617351e3c431 commit aab01a88087446e01371fd186fbb33049d62da1b commit 83318d0c1f5fd3a5eae41bc4e5dc110d5be4907c commit 4dfce79e098915d8e5fc2b9e1d980bc3251dd32c commit 2f42c1a6161646cbd29b443459fd635d29eda634 commit 6d192b4f2d644d15d9a9f1d33dab05af936f6540 commit 7b9a3a910e96f20b101b0df6b1f5c77b023a4097 commit e2628e670bb0923fcdc00828bfcd67b26a7df020 commit 4fed244954c2dc9aafa333d08f66b14345225e03 commit 76903b2057c8677c2c006e87fede15f496555dc0 commit e3fb579872a8d9cf264c52710d5839de3afa6fc1 commit bce7cd6db2386e7a2b49ad3c09df0beabddfa3c4 commit 56b7432b7e8e6ae1b289cb405d16db4150ef193b commit a3ffaa5b397f4df9d6ac16b10583e9df8e6fa471 commit a018d1819f158991b7308e4f74609c6c029b670c commit 62f553d60a801384336f5867967c26ddf3b17038 commit 68484a648ade555842e0c75a392f3572b3d51998 commit 6caeace0d1471b33bb43b58893940cc90baca5b9 commit ced5c30e47d1cd52d6ae40f809223a6286854086 commit 4487571ef17a30d274600b3bd6965f497a881299 commit e927b36ae18b66b49219eaa9f46edc7b4fdbb25e commit daf470b8882b6f7f53cbfe9ec2b93a1b21528cdc commit 78746a474e92fc7aaed12219bec7c78ae1bd6156 commit e08e0754e690e4909cab83ac43fd2c93c6200514 commit 9c9a57e4e337f94e23ddf69263fd0685c91155fb commit 5e77923a3eb39cce91bf08ed7670f816bf86d4af commit f8995c2df519f382525ca4bc90553ad2ec611067 commit a4983968fa5b3179ab090407d325a71cdc96874e commit 857fa8f2a5b184c206c703a3d9ce05cea683cfed commit 9b454a3412764b2a64b1a00d1f4c4da1e6b1cf2b commit 82f5e5b443ae32fe28a068f58abf53b89feea5f2 commit 293fa6ebd46fffc2722b6c960f40f1eb74b08dba commit 75f53c4b2dbca831bf91e9befe06c9ad58f29352 commit 5401b9adebc9e5f68df58226f51493ef0e6ceb4d commit 75519f5df2a9b23f7bf305e12dc9a6e3e65c24b7 commit 7596459f3c93d8d45a1bf12d4d7526b50c15baa2 commit 4c71fd099513bfa8acab529b626e1f0097b76061 commit a13edf9b92fc4700b3020d7ea547a3d64dd33b63 commit 93be8c74b614a86a745b6ef1da0402a6c50e97de commit b3be33f2c18f7e3663d103a92cdd00b4771b4aa7 Signed-off-by: Anusha Srivatsa <asrivats@redhat.com>
1817 lines
44 KiB
C
1817 lines
44 KiB
C
/*
|
|
* Copyright 2008 Jerome Glisse.
|
|
* All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Authors:
|
|
* Jerome Glisse <glisse@freedesktop.org>
|
|
*/
|
|
|
|
#include <linux/file.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/sync_file.h>
|
|
#include <linux/dma-buf.h>
|
|
|
|
#include <drm/amdgpu_drm.h>
|
|
#include <drm/drm_syncobj.h>
|
|
#include <drm/ttm/ttm_tt.h>
|
|
|
|
#include "amdgpu_cs.h"
|
|
#include "amdgpu.h"
|
|
#include "amdgpu_trace.h"
|
|
#include "amdgpu_gmc.h"
|
|
#include "amdgpu_gem.h"
|
|
#include "amdgpu_ras.h"
|
|
#include "amdgpu_hmm.h"
|
|
|
|
static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_device *adev,
|
|
struct drm_file *filp,
|
|
union drm_amdgpu_cs *cs)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = filp->driver_priv;
|
|
|
|
if (cs->in.num_chunks == 0)
|
|
return -EINVAL;
|
|
|
|
memset(p, 0, sizeof(*p));
|
|
p->adev = adev;
|
|
p->filp = filp;
|
|
|
|
p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id);
|
|
if (!p->ctx)
|
|
return -EINVAL;
|
|
|
|
if (atomic_read(&p->ctx->guilty)) {
|
|
amdgpu_ctx_put(p->ctx);
|
|
return -ECANCELED;
|
|
}
|
|
|
|
amdgpu_sync_create(&p->sync);
|
|
drm_exec_init(&p->exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
|
|
DRM_EXEC_IGNORE_DUPLICATES, 0);
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_job_idx(struct amdgpu_cs_parser *p,
|
|
struct drm_amdgpu_cs_chunk_ib *chunk_ib)
|
|
{
|
|
struct drm_sched_entity *entity;
|
|
unsigned int i;
|
|
int r;
|
|
|
|
r = amdgpu_ctx_get_entity(p->ctx, chunk_ib->ip_type,
|
|
chunk_ib->ip_instance,
|
|
chunk_ib->ring, &entity);
|
|
if (r)
|
|
return r;
|
|
|
|
/*
|
|
* Abort if there is no run queue associated with this entity.
|
|
* Possibly because of disabled HW IP.
|
|
*/
|
|
if (entity->rq == NULL)
|
|
return -EINVAL;
|
|
|
|
/* Check if we can add this IB to some existing job */
|
|
for (i = 0; i < p->gang_size; ++i)
|
|
if (p->entities[i] == entity)
|
|
return i;
|
|
|
|
/* If not increase the gang size if possible */
|
|
if (i == AMDGPU_CS_GANG_SIZE)
|
|
return -EINVAL;
|
|
|
|
p->entities[i] = entity;
|
|
p->gang_size = i + 1;
|
|
return i;
|
|
}
|
|
|
|
static int amdgpu_cs_p1_ib(struct amdgpu_cs_parser *p,
|
|
struct drm_amdgpu_cs_chunk_ib *chunk_ib,
|
|
unsigned int *num_ibs)
|
|
{
|
|
int r;
|
|
|
|
r = amdgpu_cs_job_idx(p, chunk_ib);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
if (num_ibs[r] >= amdgpu_ring_max_ibs(chunk_ib->ip_type))
|
|
return -EINVAL;
|
|
|
|
++(num_ibs[r]);
|
|
p->gang_leader_idx = r;
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p1_user_fence(struct amdgpu_cs_parser *p,
|
|
struct drm_amdgpu_cs_chunk_fence *data,
|
|
uint32_t *offset)
|
|
{
|
|
struct drm_gem_object *gobj;
|
|
unsigned long size;
|
|
|
|
gobj = drm_gem_object_lookup(p->filp, data->handle);
|
|
if (gobj == NULL)
|
|
return -EINVAL;
|
|
|
|
p->uf_bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
|
|
drm_gem_object_put(gobj);
|
|
|
|
size = amdgpu_bo_size(p->uf_bo);
|
|
if (size != PAGE_SIZE || data->offset > (size - 8))
|
|
return -EINVAL;
|
|
|
|
if (amdgpu_ttm_tt_get_usermm(p->uf_bo->tbo.ttm))
|
|
return -EINVAL;
|
|
|
|
*offset = data->offset;
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p1_bo_handles(struct amdgpu_cs_parser *p,
|
|
struct drm_amdgpu_bo_list_in *data)
|
|
{
|
|
struct drm_amdgpu_bo_list_entry *info;
|
|
int r;
|
|
|
|
r = amdgpu_bo_create_list_entry_array(data, &info);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_bo_list_create(p->adev, p->filp, info, data->bo_number,
|
|
&p->bo_list);
|
|
if (r)
|
|
goto error_free;
|
|
|
|
kvfree(info);
|
|
return 0;
|
|
|
|
error_free:
|
|
kvfree(info);
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Copy the data from userspace and go over it the first time */
|
|
static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
|
|
union drm_amdgpu_cs *cs)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
unsigned int num_ibs[AMDGPU_CS_GANG_SIZE] = { };
|
|
struct amdgpu_vm *vm = &fpriv->vm;
|
|
uint64_t *chunk_array;
|
|
uint32_t uf_offset = 0;
|
|
size_t size;
|
|
int ret;
|
|
int i;
|
|
|
|
chunk_array = memdup_array_user(u64_to_user_ptr(cs->in.chunks),
|
|
cs->in.num_chunks,
|
|
sizeof(uint64_t));
|
|
if (IS_ERR(chunk_array))
|
|
return PTR_ERR(chunk_array);
|
|
|
|
p->nchunks = cs->in.num_chunks;
|
|
p->chunks = kvmalloc_objs(struct amdgpu_cs_chunk, p->nchunks);
|
|
if (!p->chunks) {
|
|
ret = -ENOMEM;
|
|
goto free_chunk;
|
|
}
|
|
|
|
for (i = 0; i < p->nchunks; i++) {
|
|
struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL;
|
|
struct drm_amdgpu_cs_chunk user_chunk;
|
|
|
|
chunk_ptr = u64_to_user_ptr(chunk_array[i]);
|
|
if (copy_from_user(&user_chunk, chunk_ptr,
|
|
sizeof(struct drm_amdgpu_cs_chunk))) {
|
|
ret = -EFAULT;
|
|
i--;
|
|
goto free_partial_kdata;
|
|
}
|
|
p->chunks[i].chunk_id = user_chunk.chunk_id;
|
|
p->chunks[i].length_dw = user_chunk.length_dw;
|
|
|
|
size = p->chunks[i].length_dw;
|
|
|
|
p->chunks[i].kdata = vmemdup_array_user(u64_to_user_ptr(user_chunk.chunk_data),
|
|
size,
|
|
sizeof(uint32_t));
|
|
if (IS_ERR(p->chunks[i].kdata)) {
|
|
ret = PTR_ERR(p->chunks[i].kdata);
|
|
i--;
|
|
goto free_partial_kdata;
|
|
}
|
|
size *= sizeof(uint32_t);
|
|
|
|
/* Assume the worst on the following checks */
|
|
ret = -EINVAL;
|
|
switch (p->chunks[i].chunk_id) {
|
|
case AMDGPU_CHUNK_ID_IB:
|
|
if (size < sizeof(struct drm_amdgpu_cs_chunk_ib))
|
|
goto free_partial_kdata;
|
|
|
|
ret = amdgpu_cs_p1_ib(p, p->chunks[i].kdata, num_ibs);
|
|
if (ret)
|
|
goto free_partial_kdata;
|
|
break;
|
|
|
|
case AMDGPU_CHUNK_ID_FENCE:
|
|
if (size < sizeof(struct drm_amdgpu_cs_chunk_fence))
|
|
goto free_partial_kdata;
|
|
|
|
ret = amdgpu_cs_p1_user_fence(p, p->chunks[i].kdata,
|
|
&uf_offset);
|
|
if (ret)
|
|
goto free_partial_kdata;
|
|
break;
|
|
|
|
case AMDGPU_CHUNK_ID_BO_HANDLES:
|
|
if (size < sizeof(struct drm_amdgpu_bo_list_in))
|
|
goto free_partial_kdata;
|
|
|
|
/* Only a single BO list is allowed to simplify handling. */
|
|
if (p->bo_list)
|
|
goto free_partial_kdata;
|
|
|
|
ret = amdgpu_cs_p1_bo_handles(p, p->chunks[i].kdata);
|
|
if (ret)
|
|
goto free_partial_kdata;
|
|
break;
|
|
|
|
case AMDGPU_CHUNK_ID_DEPENDENCIES:
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
|
|
case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
|
|
case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
|
|
break;
|
|
|
|
default:
|
|
goto free_partial_kdata;
|
|
}
|
|
}
|
|
|
|
if (!p->gang_size || (amdgpu_sriov_vf(p->adev) && p->gang_size > 1)) {
|
|
ret = -EINVAL;
|
|
goto free_all_kdata;
|
|
}
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
ret = amdgpu_job_alloc(p->adev, vm, p->entities[i], vm,
|
|
num_ibs[i], &p->jobs[i],
|
|
p->filp->client_id);
|
|
if (ret)
|
|
goto free_all_kdata;
|
|
switch (p->adev->enforce_isolation[fpriv->xcp_id]) {
|
|
case AMDGPU_ENFORCE_ISOLATION_DISABLE:
|
|
default:
|
|
p->jobs[i]->enforce_isolation = false;
|
|
p->jobs[i]->run_cleaner_shader = false;
|
|
break;
|
|
case AMDGPU_ENFORCE_ISOLATION_ENABLE:
|
|
p->jobs[i]->enforce_isolation = true;
|
|
p->jobs[i]->run_cleaner_shader = true;
|
|
break;
|
|
case AMDGPU_ENFORCE_ISOLATION_ENABLE_LEGACY:
|
|
p->jobs[i]->enforce_isolation = true;
|
|
p->jobs[i]->run_cleaner_shader = false;
|
|
break;
|
|
case AMDGPU_ENFORCE_ISOLATION_NO_CLEANER_SHADER:
|
|
p->jobs[i]->enforce_isolation = true;
|
|
p->jobs[i]->run_cleaner_shader = false;
|
|
break;
|
|
}
|
|
}
|
|
p->gang_leader = p->jobs[p->gang_leader_idx];
|
|
|
|
if (p->ctx->generation != p->gang_leader->generation) {
|
|
ret = -ECANCELED;
|
|
goto free_all_kdata;
|
|
}
|
|
|
|
if (p->uf_bo)
|
|
p->gang_leader->uf_addr = uf_offset;
|
|
kvfree(chunk_array);
|
|
|
|
/* Use this opportunity to fill in task info for the vm */
|
|
amdgpu_vm_set_task_info(vm);
|
|
|
|
return 0;
|
|
|
|
free_all_kdata:
|
|
i = p->nchunks - 1;
|
|
free_partial_kdata:
|
|
for (; i >= 0; i--)
|
|
kvfree(p->chunks[i].kdata);
|
|
kvfree(p->chunks);
|
|
p->chunks = NULL;
|
|
p->nchunks = 0;
|
|
free_chunk:
|
|
kvfree(chunk_array);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk,
|
|
unsigned int *ce_preempt,
|
|
unsigned int *de_preempt)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_ib *chunk_ib = chunk->kdata;
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
struct amdgpu_vm *vm = &fpriv->vm;
|
|
struct amdgpu_ring *ring;
|
|
struct amdgpu_job *job;
|
|
struct amdgpu_ib *ib;
|
|
int r;
|
|
|
|
r = amdgpu_cs_job_idx(p, chunk_ib);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
job = p->jobs[r];
|
|
ring = amdgpu_job_ring(job);
|
|
ib = &job->ibs[job->num_ibs++];
|
|
|
|
/* submissions to kernel queues are disabled */
|
|
if (ring->no_user_submission)
|
|
return -EINVAL;
|
|
|
|
/* MM engine doesn't support user fences */
|
|
if (p->uf_bo && ring->funcs->no_user_fence)
|
|
return -EINVAL;
|
|
|
|
if (!p->adev->debug_enable_ce_cs &&
|
|
chunk_ib->flags & AMDGPU_IB_FLAG_CE) {
|
|
dev_err_ratelimited(p->adev->dev, "CE CS is blocked, use debug=0x400 to override\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (chunk_ib->ip_type == AMDGPU_HW_IP_GFX &&
|
|
chunk_ib->flags & AMDGPU_IB_FLAG_PREEMPT) {
|
|
if (chunk_ib->flags & AMDGPU_IB_FLAG_CE)
|
|
(*ce_preempt)++;
|
|
else
|
|
(*de_preempt)++;
|
|
|
|
/* Each GFX command submit allows only 1 IB max
|
|
* preemptible for CE & DE */
|
|
if (*ce_preempt > 1 || *de_preempt > 1)
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (chunk_ib->flags & AMDGPU_IB_FLAG_PREAMBLE)
|
|
job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT;
|
|
|
|
r = amdgpu_ib_get(p->adev, vm, ring->funcs->parse_cs ?
|
|
chunk_ib->ib_bytes : 0,
|
|
AMDGPU_IB_POOL_DELAYED, ib);
|
|
if (r) {
|
|
drm_err(adev_to_drm(p->adev), "Failed to get ib !\n");
|
|
return r;
|
|
}
|
|
|
|
ib->gpu_addr = chunk_ib->va_start;
|
|
ib->length_dw = chunk_ib->ib_bytes / 4;
|
|
ib->flags = chunk_ib->flags;
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_dependencies(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_dep *deps = chunk->kdata;
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
unsigned int num_deps;
|
|
int i, r;
|
|
|
|
num_deps = chunk->length_dw * 4 /
|
|
sizeof(struct drm_amdgpu_cs_chunk_dep);
|
|
|
|
for (i = 0; i < num_deps; ++i) {
|
|
struct amdgpu_ctx *ctx;
|
|
struct drm_sched_entity *entity;
|
|
struct dma_fence *fence;
|
|
|
|
ctx = amdgpu_ctx_get(fpriv, deps[i].ctx_id);
|
|
if (ctx == NULL)
|
|
return -EINVAL;
|
|
|
|
r = amdgpu_ctx_get_entity(ctx, deps[i].ip_type,
|
|
deps[i].ip_instance,
|
|
deps[i].ring, &entity);
|
|
if (r) {
|
|
amdgpu_ctx_put(ctx);
|
|
return r;
|
|
}
|
|
|
|
fence = amdgpu_ctx_get_fence(ctx, entity, deps[i].handle);
|
|
amdgpu_ctx_put(ctx);
|
|
|
|
if (IS_ERR(fence))
|
|
return PTR_ERR(fence);
|
|
else if (!fence)
|
|
continue;
|
|
|
|
if (chunk->chunk_id == AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES) {
|
|
struct drm_sched_fence *s_fence;
|
|
struct dma_fence *old = fence;
|
|
|
|
s_fence = to_drm_sched_fence(fence);
|
|
fence = dma_fence_get(&s_fence->scheduled);
|
|
dma_fence_put(old);
|
|
}
|
|
|
|
r = amdgpu_sync_fence(&p->sync, fence, GFP_KERNEL);
|
|
dma_fence_put(fence);
|
|
if (r)
|
|
return r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p,
|
|
uint32_t handle, u64 point,
|
|
u64 flags)
|
|
{
|
|
struct dma_fence *fence;
|
|
int r;
|
|
|
|
r = drm_syncobj_find_fence(p->filp, handle, point, flags, &fence);
|
|
if (r) {
|
|
drm_err(adev_to_drm(p->adev), "syncobj %u failed to find fence @ %llu (%d)!\n",
|
|
handle, point, r);
|
|
return r;
|
|
}
|
|
|
|
r = amdgpu_sync_fence(&p->sync, fence, GFP_KERNEL);
|
|
dma_fence_put(fence);
|
|
return r;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_syncobj_in(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_sem *deps = chunk->kdata;
|
|
unsigned int num_deps;
|
|
int i, r;
|
|
|
|
num_deps = chunk->length_dw * 4 /
|
|
sizeof(struct drm_amdgpu_cs_chunk_sem);
|
|
for (i = 0; i < num_deps; ++i) {
|
|
r = amdgpu_syncobj_lookup_and_add(p, deps[i].handle, 0, 0);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_syncobj_timeline_wait(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps = chunk->kdata;
|
|
unsigned int num_deps;
|
|
int i, r;
|
|
|
|
num_deps = chunk->length_dw * 4 /
|
|
sizeof(struct drm_amdgpu_cs_chunk_syncobj);
|
|
for (i = 0; i < num_deps; ++i) {
|
|
r = amdgpu_syncobj_lookup_and_add(p, syncobj_deps[i].handle,
|
|
syncobj_deps[i].point,
|
|
syncobj_deps[i].flags);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_syncobj_out(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_sem *deps = chunk->kdata;
|
|
unsigned int num_deps;
|
|
int i;
|
|
|
|
num_deps = chunk->length_dw * 4 /
|
|
sizeof(struct drm_amdgpu_cs_chunk_sem);
|
|
|
|
if (p->post_deps)
|
|
return -EINVAL;
|
|
|
|
p->post_deps = kmalloc_objs(*p->post_deps, num_deps);
|
|
p->num_post_deps = 0;
|
|
|
|
if (!p->post_deps)
|
|
return -ENOMEM;
|
|
|
|
|
|
for (i = 0; i < num_deps; ++i) {
|
|
p->post_deps[i].syncobj =
|
|
drm_syncobj_find(p->filp, deps[i].handle);
|
|
if (!p->post_deps[i].syncobj)
|
|
return -EINVAL;
|
|
p->post_deps[i].chain = NULL;
|
|
p->post_deps[i].point = 0;
|
|
p->num_post_deps++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_syncobj_timeline_signal(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps = chunk->kdata;
|
|
unsigned int num_deps;
|
|
int i;
|
|
|
|
num_deps = chunk->length_dw * 4 /
|
|
sizeof(struct drm_amdgpu_cs_chunk_syncobj);
|
|
|
|
if (p->post_deps)
|
|
return -EINVAL;
|
|
|
|
p->post_deps = kmalloc_objs(*p->post_deps, num_deps);
|
|
p->num_post_deps = 0;
|
|
|
|
if (!p->post_deps)
|
|
return -ENOMEM;
|
|
|
|
for (i = 0; i < num_deps; ++i) {
|
|
struct amdgpu_cs_post_dep *dep = &p->post_deps[i];
|
|
|
|
dep->chain = NULL;
|
|
if (syncobj_deps[i].point) {
|
|
dep->chain = dma_fence_chain_alloc();
|
|
if (!dep->chain)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
dep->syncobj = drm_syncobj_find(p->filp,
|
|
syncobj_deps[i].handle);
|
|
if (!dep->syncobj) {
|
|
dma_fence_chain_free(dep->chain);
|
|
return -EINVAL;
|
|
}
|
|
dep->point = syncobj_deps[i].point;
|
|
p->num_post_deps++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_p2_shadow(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_cs_chunk *chunk)
|
|
{
|
|
struct drm_amdgpu_cs_chunk_cp_gfx_shadow *shadow = chunk->kdata;
|
|
int i;
|
|
|
|
if (shadow->flags & ~AMDGPU_CS_CHUNK_CP_GFX_SHADOW_FLAGS_INIT_SHADOW)
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
p->jobs[i]->shadow_va = shadow->shadow_va;
|
|
p->jobs[i]->csa_va = shadow->csa_va;
|
|
p->jobs[i]->gds_va = shadow->gds_va;
|
|
p->jobs[i]->init_shadow =
|
|
shadow->flags & AMDGPU_CS_CHUNK_CP_GFX_SHADOW_FLAGS_INIT_SHADOW;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_pass2(struct amdgpu_cs_parser *p)
|
|
{
|
|
unsigned int ce_preempt = 0, de_preempt = 0;
|
|
int i, r;
|
|
|
|
for (i = 0; i < p->nchunks; ++i) {
|
|
struct amdgpu_cs_chunk *chunk;
|
|
|
|
chunk = &p->chunks[i];
|
|
|
|
switch (chunk->chunk_id) {
|
|
case AMDGPU_CHUNK_ID_IB:
|
|
r = amdgpu_cs_p2_ib(p, chunk, &ce_preempt, &de_preempt);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
case AMDGPU_CHUNK_ID_DEPENDENCIES:
|
|
case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
|
|
r = amdgpu_cs_p2_dependencies(p, chunk);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
|
|
r = amdgpu_cs_p2_syncobj_in(p, chunk);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
|
|
r = amdgpu_cs_p2_syncobj_out(p, chunk);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
|
|
r = amdgpu_cs_p2_syncobj_timeline_wait(p, chunk);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
|
|
r = amdgpu_cs_p2_syncobj_timeline_signal(p, chunk);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
|
|
r = amdgpu_cs_p2_shadow(p, chunk);
|
|
if (r)
|
|
return r;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Convert microseconds to bytes. */
|
|
static u64 us_to_bytes(struct amdgpu_device *adev, s64 us)
|
|
{
|
|
if (us <= 0 || !adev->mm_stats.log2_max_MBps)
|
|
return 0;
|
|
|
|
/* Since accum_us is incremented by a million per second, just
|
|
* multiply it by the number of MB/s to get the number of bytes.
|
|
*/
|
|
return us << adev->mm_stats.log2_max_MBps;
|
|
}
|
|
|
|
static s64 bytes_to_us(struct amdgpu_device *adev, u64 bytes)
|
|
{
|
|
if (!adev->mm_stats.log2_max_MBps)
|
|
return 0;
|
|
|
|
return bytes >> adev->mm_stats.log2_max_MBps;
|
|
}
|
|
|
|
/* Returns how many bytes TTM can move right now. If no bytes can be moved,
|
|
* it returns 0. If it returns non-zero, it's OK to move at least one buffer,
|
|
* which means it can go over the threshold once. If that happens, the driver
|
|
* will be in debt and no other buffer migrations can be done until that debt
|
|
* is repaid.
|
|
*
|
|
* This approach allows moving a buffer of any size (it's important to allow
|
|
* that).
|
|
*
|
|
* The currency is simply time in microseconds and it increases as the clock
|
|
* ticks. The accumulated microseconds (us) are converted to bytes and
|
|
* returned.
|
|
*/
|
|
static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev,
|
|
u64 *max_bytes,
|
|
u64 *max_vis_bytes)
|
|
{
|
|
s64 time_us, increment_us;
|
|
u64 free_vram, total_vram, used_vram;
|
|
/* Allow a maximum of 200 accumulated ms. This is basically per-IB
|
|
* throttling.
|
|
*
|
|
* It means that in order to get full max MBps, at least 5 IBs per
|
|
* second must be submitted and not more than 200ms apart from each
|
|
* other.
|
|
*/
|
|
const s64 us_upper_bound = 200000;
|
|
|
|
if ((!adev->mm_stats.log2_max_MBps) || !ttm_resource_manager_used(&adev->mman.vram_mgr.manager)) {
|
|
*max_bytes = 0;
|
|
*max_vis_bytes = 0;
|
|
return;
|
|
}
|
|
|
|
total_vram = adev->gmc.real_vram_size - atomic64_read(&adev->vram_pin_size);
|
|
used_vram = ttm_resource_manager_usage(&adev->mman.vram_mgr.manager);
|
|
free_vram = used_vram >= total_vram ? 0 : total_vram - used_vram;
|
|
|
|
spin_lock(&adev->mm_stats.lock);
|
|
|
|
/* Increase the amount of accumulated us. */
|
|
time_us = ktime_to_us(ktime_get());
|
|
increment_us = time_us - adev->mm_stats.last_update_us;
|
|
adev->mm_stats.last_update_us = time_us;
|
|
adev->mm_stats.accum_us = min(adev->mm_stats.accum_us + increment_us,
|
|
us_upper_bound);
|
|
|
|
/* This prevents the short period of low performance when the VRAM
|
|
* usage is low and the driver is in debt or doesn't have enough
|
|
* accumulated us to fill VRAM quickly.
|
|
*
|
|
* The situation can occur in these cases:
|
|
* - a lot of VRAM is freed by userspace
|
|
* - the presence of a big buffer causes a lot of evictions
|
|
* (solution: split buffers into smaller ones)
|
|
*
|
|
* If 128 MB or 1/8th of VRAM is free, start filling it now by setting
|
|
* accum_us to a positive number.
|
|
*/
|
|
if (free_vram >= 128 * 1024 * 1024 || free_vram >= total_vram / 8) {
|
|
s64 min_us;
|
|
|
|
/* Be more aggressive on dGPUs. Try to fill a portion of free
|
|
* VRAM now.
|
|
*/
|
|
if (!(adev->flags & AMD_IS_APU))
|
|
min_us = bytes_to_us(adev, free_vram / 4);
|
|
else
|
|
min_us = 0; /* Reset accum_us on APUs. */
|
|
|
|
adev->mm_stats.accum_us = max(min_us, adev->mm_stats.accum_us);
|
|
}
|
|
|
|
/* This is set to 0 if the driver is in debt to disallow (optional)
|
|
* buffer moves.
|
|
*/
|
|
*max_bytes = us_to_bytes(adev, adev->mm_stats.accum_us);
|
|
|
|
/* Do the same for visible VRAM if half of it is free */
|
|
if (!amdgpu_gmc_vram_full_visible(&adev->gmc)) {
|
|
u64 total_vis_vram = adev->gmc.visible_vram_size;
|
|
u64 used_vis_vram =
|
|
amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr);
|
|
|
|
if (used_vis_vram < total_vis_vram) {
|
|
u64 free_vis_vram = total_vis_vram - used_vis_vram;
|
|
|
|
adev->mm_stats.accum_us_vis = min(adev->mm_stats.accum_us_vis +
|
|
increment_us, us_upper_bound);
|
|
|
|
if (free_vis_vram >= total_vis_vram / 2)
|
|
adev->mm_stats.accum_us_vis =
|
|
max(bytes_to_us(adev, free_vis_vram / 2),
|
|
adev->mm_stats.accum_us_vis);
|
|
}
|
|
|
|
*max_vis_bytes = us_to_bytes(adev, adev->mm_stats.accum_us_vis);
|
|
} else {
|
|
*max_vis_bytes = 0;
|
|
}
|
|
|
|
spin_unlock(&adev->mm_stats.lock);
|
|
}
|
|
|
|
/* Report how many bytes have really been moved for the last command
|
|
* submission. This can result in a debt that can stop buffer migrations
|
|
* temporarily.
|
|
*/
|
|
void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,
|
|
u64 num_vis_bytes)
|
|
{
|
|
spin_lock(&adev->mm_stats.lock);
|
|
adev->mm_stats.accum_us -= bytes_to_us(adev, num_bytes);
|
|
adev->mm_stats.accum_us_vis -= bytes_to_us(adev, num_vis_bytes);
|
|
spin_unlock(&adev->mm_stats.lock);
|
|
}
|
|
|
|
static int amdgpu_cs_bo_validate(void *param, struct amdgpu_bo *bo)
|
|
{
|
|
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
|
struct amdgpu_cs_parser *p = param;
|
|
struct ttm_operation_ctx ctx = {
|
|
.interruptible = true,
|
|
.no_wait_gpu = false,
|
|
.resv = bo->tbo.base.resv
|
|
};
|
|
uint32_t domain;
|
|
int r;
|
|
|
|
if (bo->tbo.pin_count)
|
|
return 0;
|
|
|
|
/* Don't move this buffer if we have depleted our allowance
|
|
* to move it. Don't move anything if the threshold is zero.
|
|
*/
|
|
if (p->bytes_moved < p->bytes_moved_threshold &&
|
|
(!bo->tbo.base.dma_buf ||
|
|
list_empty(&bo->tbo.base.dma_buf->attachments))) {
|
|
if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
|
|
(bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)) {
|
|
/* And don't move a CPU_ACCESS_REQUIRED BO to limited
|
|
* visible VRAM if we've depleted our allowance to do
|
|
* that.
|
|
*/
|
|
if (p->bytes_moved_vis < p->bytes_moved_vis_threshold)
|
|
domain = bo->preferred_domains;
|
|
else
|
|
domain = bo->allowed_domains;
|
|
} else {
|
|
domain = bo->preferred_domains;
|
|
}
|
|
} else {
|
|
domain = bo->allowed_domains;
|
|
}
|
|
|
|
retry:
|
|
amdgpu_bo_placement_from_domain(bo, domain);
|
|
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
|
|
|
p->bytes_moved += ctx.bytes_moved;
|
|
if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
|
|
amdgpu_res_cpu_visible(adev, bo->tbo.resource))
|
|
p->bytes_moved_vis += ctx.bytes_moved;
|
|
|
|
if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
|
|
domain = bo->allowed_domains;
|
|
goto retry;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|
union drm_amdgpu_cs *cs)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
struct ttm_operation_ctx ctx = { true, false };
|
|
struct amdgpu_vm *vm = &fpriv->vm;
|
|
struct amdgpu_bo_list_entry *e;
|
|
struct drm_gem_object *obj;
|
|
unsigned long index;
|
|
unsigned int i;
|
|
int r;
|
|
|
|
/* p->bo_list could already be assigned if AMDGPU_CHUNK_ID_BO_HANDLES is present */
|
|
if (cs->in.bo_list_handle) {
|
|
if (p->bo_list)
|
|
return -EINVAL;
|
|
|
|
r = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle,
|
|
&p->bo_list);
|
|
if (r)
|
|
return r;
|
|
} else if (!p->bo_list) {
|
|
/* Create a empty bo_list when no handle is provided */
|
|
r = amdgpu_bo_list_create(p->adev, p->filp, NULL, 0,
|
|
&p->bo_list);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
mutex_lock(&p->bo_list->bo_list_mutex);
|
|
|
|
/* Get userptr backing pages. If pages are updated after registered
|
|
* in amdgpu_gem_userptr_ioctl(), amdgpu_cs_list_validate() will do
|
|
* amdgpu_ttm_backend_bind() to flush and invalidate new pages
|
|
*/
|
|
amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) {
|
|
bool userpage_invalidated = false;
|
|
struct amdgpu_bo *bo = e->bo;
|
|
|
|
e->range = amdgpu_hmm_range_alloc(NULL);
|
|
if (unlikely(!e->range)) {
|
|
r = -ENOMEM;
|
|
goto out_free_user_pages;
|
|
}
|
|
|
|
r = amdgpu_ttm_tt_get_user_pages(bo, e->range);
|
|
if (r)
|
|
goto out_free_user_pages;
|
|
|
|
for (i = 0; i < bo->tbo.ttm->num_pages; i++) {
|
|
if (bo->tbo.ttm->pages[i] !=
|
|
hmm_pfn_to_page(e->range->hmm_range.hmm_pfns[i])) {
|
|
userpage_invalidated = true;
|
|
break;
|
|
}
|
|
}
|
|
e->user_invalidated = userpage_invalidated;
|
|
}
|
|
|
|
drm_exec_until_all_locked(&p->exec) {
|
|
r = amdgpu_vm_lock_pd(&fpriv->vm, &p->exec, 1 + p->gang_size);
|
|
drm_exec_retry_on_contention(&p->exec);
|
|
if (unlikely(r))
|
|
goto out_free_user_pages;
|
|
|
|
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
|
|
/* One fence for TTM and one for each CS job */
|
|
r = drm_exec_prepare_obj(&p->exec, &e->bo->tbo.base,
|
|
1 + p->gang_size);
|
|
drm_exec_retry_on_contention(&p->exec);
|
|
if (unlikely(r))
|
|
goto out_free_user_pages;
|
|
|
|
e->bo_va = amdgpu_vm_bo_find(vm, e->bo);
|
|
}
|
|
|
|
if (p->uf_bo) {
|
|
r = drm_exec_prepare_obj(&p->exec, &p->uf_bo->tbo.base,
|
|
1 + p->gang_size);
|
|
drm_exec_retry_on_contention(&p->exec);
|
|
if (unlikely(r))
|
|
goto out_free_user_pages;
|
|
}
|
|
}
|
|
|
|
amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) {
|
|
struct mm_struct *usermm;
|
|
|
|
usermm = amdgpu_ttm_tt_get_usermm(e->bo->tbo.ttm);
|
|
if (usermm && usermm != current->mm) {
|
|
r = -EPERM;
|
|
goto out_free_user_pages;
|
|
}
|
|
|
|
if (amdgpu_ttm_tt_is_userptr(e->bo->tbo.ttm) &&
|
|
e->user_invalidated) {
|
|
amdgpu_bo_placement_from_domain(e->bo,
|
|
AMDGPU_GEM_DOMAIN_CPU);
|
|
r = ttm_bo_validate(&e->bo->tbo, &e->bo->placement,
|
|
&ctx);
|
|
if (r)
|
|
goto out_free_user_pages;
|
|
|
|
amdgpu_ttm_tt_set_user_pages(e->bo->tbo.ttm,
|
|
e->range);
|
|
}
|
|
}
|
|
|
|
amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold,
|
|
&p->bytes_moved_vis_threshold);
|
|
p->bytes_moved = 0;
|
|
p->bytes_moved_vis = 0;
|
|
|
|
r = amdgpu_vm_validate(p->adev, &fpriv->vm, NULL,
|
|
amdgpu_cs_bo_validate, p);
|
|
if (r) {
|
|
drm_err(adev_to_drm(p->adev), "amdgpu_vm_validate() failed.\n");
|
|
goto out_free_user_pages;
|
|
}
|
|
|
|
drm_exec_for_each_locked_object(&p->exec, index, obj) {
|
|
r = amdgpu_cs_bo_validate(p, gem_to_amdgpu_bo(obj));
|
|
if (unlikely(r))
|
|
goto out_free_user_pages;
|
|
}
|
|
|
|
if (p->uf_bo) {
|
|
r = amdgpu_ttm_alloc_gart(&p->uf_bo->tbo);
|
|
if (unlikely(r))
|
|
goto out_free_user_pages;
|
|
|
|
p->gang_leader->uf_addr += amdgpu_bo_gpu_offset(p->uf_bo);
|
|
}
|
|
|
|
amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved,
|
|
p->bytes_moved_vis);
|
|
|
|
for (i = 0; i < p->gang_size; ++i)
|
|
amdgpu_job_set_resources(p->jobs[i], p->bo_list->gds_obj,
|
|
p->bo_list->gws_obj,
|
|
p->bo_list->oa_obj);
|
|
return 0;
|
|
|
|
out_free_user_pages:
|
|
amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) {
|
|
amdgpu_hmm_range_free(e->range);
|
|
e->range = NULL;
|
|
}
|
|
mutex_unlock(&p->bo_list->bo_list_mutex);
|
|
return r;
|
|
}
|
|
|
|
static void trace_amdgpu_cs_ibs(struct amdgpu_cs_parser *p)
|
|
{
|
|
int i, j;
|
|
|
|
if (!trace_amdgpu_cs_enabled())
|
|
return;
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
struct amdgpu_job *job = p->jobs[i];
|
|
|
|
for (j = 0; j < job->num_ibs; ++j)
|
|
trace_amdgpu_cs(p, job, &job->ibs[j]);
|
|
}
|
|
}
|
|
|
|
static int amdgpu_cs_patch_ibs(struct amdgpu_cs_parser *p,
|
|
struct amdgpu_job *job)
|
|
{
|
|
struct amdgpu_ring *ring = amdgpu_job_ring(job);
|
|
struct amdgpu_device *adev = ring->adev;
|
|
unsigned int i;
|
|
int r;
|
|
|
|
/* Only for UVD/VCE VM emulation */
|
|
if (!ring->funcs->parse_cs && !ring->funcs->patch_cs_in_place)
|
|
return 0;
|
|
|
|
for (i = 0; i < job->num_ibs; ++i) {
|
|
struct amdgpu_ib *ib = &job->ibs[i];
|
|
struct amdgpu_bo_va_mapping *m;
|
|
struct amdgpu_bo *aobj;
|
|
uint64_t va_start;
|
|
uint8_t *kptr;
|
|
|
|
va_start = ib->gpu_addr & AMDGPU_GMC_HOLE_MASK;
|
|
r = amdgpu_cs_find_mapping(p, va_start, &aobj, &m);
|
|
if (r) {
|
|
drm_err(adev_to_drm(p->adev), "IB va_start is invalid\n");
|
|
return r;
|
|
}
|
|
|
|
if ((va_start + ib->length_dw * 4) >
|
|
(m->last + 1) * AMDGPU_GPU_PAGE_SIZE) {
|
|
drm_err(adev_to_drm(p->adev), "IB va_start+ib_bytes is invalid\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* the IB should be reserved at this point */
|
|
r = amdgpu_bo_kmap(aobj, (void **)&kptr);
|
|
if (r)
|
|
return r;
|
|
|
|
kptr += va_start - (m->start * AMDGPU_GPU_PAGE_SIZE);
|
|
|
|
if (ring->funcs->parse_cs) {
|
|
memcpy(ib->ptr, kptr, ib->length_dw * 4);
|
|
amdgpu_bo_kunmap(aobj);
|
|
|
|
r = amdgpu_ring_parse_cs(ring, p, job, ib);
|
|
if (r)
|
|
return r;
|
|
|
|
if (ib->sa_bo)
|
|
ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
|
|
} else {
|
|
ib->ptr = (uint32_t *)kptr;
|
|
r = amdgpu_ring_patch_cs_in_place(ring, p, job, ib);
|
|
amdgpu_bo_kunmap(aobj);
|
|
if (r)
|
|
return r;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_patch_jobs(struct amdgpu_cs_parser *p)
|
|
{
|
|
unsigned int i;
|
|
int r;
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
r = amdgpu_cs_patch_ibs(p, p->jobs[i]);
|
|
if (r)
|
|
return r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
struct amdgpu_job *job = p->gang_leader;
|
|
struct amdgpu_device *adev = p->adev;
|
|
struct amdgpu_vm *vm = &fpriv->vm;
|
|
struct amdgpu_bo_list_entry *e;
|
|
struct amdgpu_bo_va *bo_va;
|
|
unsigned int i;
|
|
int r;
|
|
|
|
/*
|
|
* We can't use gang submit on with reserved VMIDs when the VM changes
|
|
* can't be invalidated by more than one engine at the same time.
|
|
*/
|
|
if (p->gang_size > 1 && !adev->vm_manager.concurrent_flush) {
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
struct drm_sched_entity *entity = p->entities[i];
|
|
struct drm_gpu_scheduler *sched = entity->rq->sched;
|
|
struct amdgpu_ring *ring = to_amdgpu_ring(sched);
|
|
|
|
if (amdgpu_vmid_uses_reserved(vm, ring->vm_hub))
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
if (!amdgpu_vm_ready(vm))
|
|
return -EINVAL;
|
|
|
|
r = amdgpu_vm_clear_freed(adev, vm, NULL);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_sync_fence(&p->sync, fpriv->prt_va->last_pt_update,
|
|
GFP_KERNEL);
|
|
if (r)
|
|
return r;
|
|
|
|
if (fpriv->csa_va) {
|
|
bo_va = fpriv->csa_va;
|
|
BUG_ON(!bo_va);
|
|
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update,
|
|
GFP_KERNEL);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
/* FIXME: In theory this loop shouldn't be needed any more when
|
|
* amdgpu_vm_handle_moved handles all moved BOs that are reserved
|
|
* with p->ticket. But removing it caused test regressions, so I'm
|
|
* leaving it here for now.
|
|
*/
|
|
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
|
|
bo_va = e->bo_va;
|
|
if (bo_va == NULL)
|
|
continue;
|
|
|
|
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update,
|
|
GFP_KERNEL);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
r = amdgpu_vm_handle_moved(adev, vm, &p->exec.ticket);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_vm_update_pdes(adev, vm, false);
|
|
if (r)
|
|
return r;
|
|
|
|
r = amdgpu_sync_fence(&p->sync, vm->last_update, GFP_KERNEL);
|
|
if (r)
|
|
return r;
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
job = p->jobs[i];
|
|
|
|
if (!job->vm)
|
|
continue;
|
|
|
|
job->vm_pd_addr = amdgpu_gmc_pd_addr(vm->root.bo);
|
|
}
|
|
|
|
if (adev->debug_vm) {
|
|
/* Invalidate all BOs to test for userspace bugs */
|
|
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
|
|
struct amdgpu_bo *bo = e->bo;
|
|
|
|
/* ignore duplicates */
|
|
if (!bo)
|
|
continue;
|
|
|
|
amdgpu_vm_bo_invalidate(bo, false);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
struct drm_gpu_scheduler *sched;
|
|
struct drm_gem_object *obj;
|
|
struct dma_fence *fence;
|
|
unsigned long index;
|
|
unsigned int i;
|
|
int r;
|
|
|
|
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
|
|
if (r) {
|
|
if (r != -ERESTARTSYS)
|
|
drm_err(adev_to_drm(p->adev), "amdgpu_ctx_wait_prev_fence failed.\n");
|
|
return r;
|
|
}
|
|
|
|
drm_exec_for_each_locked_object(&p->exec, index, obj) {
|
|
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
|
|
|
struct dma_resv *resv = bo->tbo.base.resv;
|
|
enum amdgpu_sync_mode sync_mode;
|
|
|
|
sync_mode = amdgpu_bo_explicit_sync(bo) ?
|
|
AMDGPU_SYNC_EXPLICIT : AMDGPU_SYNC_NE_OWNER;
|
|
r = amdgpu_sync_resv(p->adev, &p->sync, resv, sync_mode,
|
|
&fpriv->vm);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
r = amdgpu_sync_push_to_job(&p->sync, p->jobs[i]);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
sched = p->gang_leader->base.entity->rq->sched;
|
|
while ((fence = amdgpu_sync_get_fence(&p->sync))) {
|
|
struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
|
|
|
|
/*
|
|
* When we have an dependency it might be necessary to insert a
|
|
* pipeline sync to make sure that all caches etc are flushed and the
|
|
* next job actually sees the results from the previous one
|
|
* before we start executing on the same scheduler ring.
|
|
*/
|
|
if (!s_fence || s_fence->sched != sched) {
|
|
dma_fence_put(fence);
|
|
continue;
|
|
}
|
|
|
|
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence,
|
|
GFP_KERNEL);
|
|
dma_fence_put(fence);
|
|
if (r)
|
|
return r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < p->num_post_deps; ++i) {
|
|
if (p->post_deps[i].chain && p->post_deps[i].point) {
|
|
drm_syncobj_add_point(p->post_deps[i].syncobj,
|
|
p->post_deps[i].chain,
|
|
p->fence, p->post_deps[i].point);
|
|
p->post_deps[i].chain = NULL;
|
|
} else {
|
|
drm_syncobj_replace_fence(p->post_deps[i].syncobj,
|
|
p->fence);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
|
union drm_amdgpu_cs *cs)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
|
struct amdgpu_job *leader = p->gang_leader;
|
|
struct amdgpu_bo_list_entry *e;
|
|
struct drm_gem_object *gobj;
|
|
unsigned long index;
|
|
unsigned int i;
|
|
uint64_t seq;
|
|
int r;
|
|
|
|
for (i = 0; i < p->gang_size; ++i)
|
|
drm_sched_job_arm(&p->jobs[i]->base);
|
|
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
struct dma_fence *fence;
|
|
|
|
if (p->jobs[i] == leader)
|
|
continue;
|
|
|
|
fence = &p->jobs[i]->base.s_fence->scheduled;
|
|
dma_fence_get(fence);
|
|
r = drm_sched_job_add_dependency(&leader->base, fence);
|
|
if (r) {
|
|
dma_fence_put(fence);
|
|
return r;
|
|
}
|
|
}
|
|
|
|
if (p->gang_size > 1) {
|
|
for (i = 0; i < p->gang_size; ++i)
|
|
amdgpu_job_set_gang_leader(p->jobs[i], leader);
|
|
}
|
|
|
|
/* No memory allocation is allowed while holding the notifier lock.
|
|
* The lock is held until amdgpu_cs_submit is finished and fence is
|
|
* added to BOs.
|
|
*/
|
|
mutex_lock(&p->adev->notifier_lock);
|
|
|
|
/* If userptr are invalidated after amdgpu_cs_parser_bos(), return
|
|
* -EAGAIN, drmIoctl in libdrm will restart the amdgpu_cs_ioctl.
|
|
*/
|
|
r = 0;
|
|
amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) {
|
|
r |= !amdgpu_hmm_range_valid(e->range);
|
|
amdgpu_hmm_range_free(e->range);
|
|
e->range = NULL;
|
|
}
|
|
if (r) {
|
|
r = -EAGAIN;
|
|
mutex_unlock(&p->adev->notifier_lock);
|
|
return r;
|
|
}
|
|
|
|
p->fence = dma_fence_get(&leader->base.s_fence->finished);
|
|
drm_exec_for_each_locked_object(&p->exec, index, gobj) {
|
|
|
|
ttm_bo_move_to_lru_tail_unlocked(&gem_to_amdgpu_bo(gobj)->tbo);
|
|
|
|
/* Everybody except for the gang leader uses READ */
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
if (p->jobs[i] == leader)
|
|
continue;
|
|
|
|
dma_resv_add_fence(gobj->resv,
|
|
&p->jobs[i]->base.s_fence->finished,
|
|
DMA_RESV_USAGE_READ);
|
|
}
|
|
|
|
/* The gang leader as remembered as writer */
|
|
dma_resv_add_fence(gobj->resv, p->fence, DMA_RESV_USAGE_WRITE);
|
|
}
|
|
|
|
seq = amdgpu_ctx_add_fence(p->ctx, p->entities[p->gang_leader_idx],
|
|
p->fence);
|
|
amdgpu_cs_post_dependencies(p);
|
|
|
|
if ((leader->preamble_status & AMDGPU_PREAMBLE_IB_PRESENT) &&
|
|
!p->ctx->preamble_presented) {
|
|
leader->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT_FIRST;
|
|
p->ctx->preamble_presented = true;
|
|
}
|
|
|
|
cs->out.handle = seq;
|
|
leader->uf_sequence = seq;
|
|
|
|
amdgpu_vm_bo_trace_cs(&fpriv->vm, &p->exec.ticket);
|
|
for (i = 0; i < p->gang_size; ++i) {
|
|
amdgpu_job_free_resources(p->jobs[i]);
|
|
trace_amdgpu_cs_ioctl(p->jobs[i]);
|
|
drm_sched_entity_push_job(&p->jobs[i]->base);
|
|
p->jobs[i] = NULL;
|
|
}
|
|
|
|
amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm);
|
|
|
|
mutex_unlock(&p->adev->notifier_lock);
|
|
mutex_unlock(&p->bo_list->bo_list_mutex);
|
|
return 0;
|
|
}
|
|
|
|
/* Cleanup the parser structure */
|
|
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
|
|
{
|
|
unsigned int i;
|
|
|
|
amdgpu_sync_free(&parser->sync);
|
|
drm_exec_fini(&parser->exec);
|
|
|
|
for (i = 0; i < parser->num_post_deps; i++) {
|
|
drm_syncobj_put(parser->post_deps[i].syncobj);
|
|
kfree(parser->post_deps[i].chain);
|
|
}
|
|
kfree(parser->post_deps);
|
|
|
|
dma_fence_put(parser->fence);
|
|
|
|
if (parser->ctx)
|
|
amdgpu_ctx_put(parser->ctx);
|
|
if (parser->bo_list)
|
|
amdgpu_bo_list_put(parser->bo_list);
|
|
|
|
for (i = 0; i < parser->nchunks; i++)
|
|
kvfree(parser->chunks[i].kdata);
|
|
kvfree(parser->chunks);
|
|
for (i = 0; i < parser->gang_size; ++i) {
|
|
if (parser->jobs[i])
|
|
amdgpu_job_free(parser->jobs[i]);
|
|
}
|
|
amdgpu_bo_unref(&parser->uf_bo);
|
|
}
|
|
|
|
int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|
{
|
|
struct amdgpu_device *adev = drm_to_adev(dev);
|
|
struct amdgpu_cs_parser parser;
|
|
int r;
|
|
|
|
if (amdgpu_ras_intr_triggered())
|
|
return -EHWPOISON;
|
|
|
|
if (!adev->accel_working)
|
|
return -EBUSY;
|
|
|
|
r = amdgpu_cs_parser_init(&parser, adev, filp, data);
|
|
if (r) {
|
|
drm_err_ratelimited(dev, "Failed to initialize parser %d!\n", r);
|
|
return r;
|
|
}
|
|
|
|
r = amdgpu_cs_pass1(&parser, data);
|
|
if (r)
|
|
goto error_fini;
|
|
|
|
r = amdgpu_cs_pass2(&parser);
|
|
if (r)
|
|
goto error_fini;
|
|
|
|
r = amdgpu_cs_parser_bos(&parser, data);
|
|
if (r) {
|
|
if (r == -ENOMEM)
|
|
drm_err(dev, "Not enough memory for command submission!\n");
|
|
else if (r != -ERESTARTSYS && r != -EAGAIN)
|
|
drm_dbg(dev, "Failed to process the buffer list %d!\n", r);
|
|
goto error_fini;
|
|
}
|
|
|
|
r = amdgpu_cs_patch_jobs(&parser);
|
|
if (r)
|
|
goto error_backoff;
|
|
|
|
r = amdgpu_cs_vm_handling(&parser);
|
|
if (r)
|
|
goto error_backoff;
|
|
|
|
r = amdgpu_cs_sync_rings(&parser);
|
|
if (r)
|
|
goto error_backoff;
|
|
|
|
trace_amdgpu_cs_ibs(&parser);
|
|
|
|
r = amdgpu_cs_submit(&parser, data);
|
|
if (r)
|
|
goto error_backoff;
|
|
|
|
amdgpu_cs_parser_fini(&parser);
|
|
return 0;
|
|
|
|
error_backoff:
|
|
mutex_unlock(&parser.bo_list->bo_list_mutex);
|
|
|
|
error_fini:
|
|
amdgpu_cs_parser_fini(&parser);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* amdgpu_cs_wait_ioctl - wait for a command submission to finish
|
|
*
|
|
* @dev: drm device
|
|
* @data: data from userspace
|
|
* @filp: file private
|
|
*
|
|
* Wait for the command submission identified by handle to finish.
|
|
*/
|
|
int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *filp)
|
|
{
|
|
union drm_amdgpu_wait_cs *wait = data;
|
|
unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout);
|
|
struct drm_sched_entity *entity;
|
|
struct amdgpu_ctx *ctx;
|
|
struct dma_fence *fence;
|
|
long r;
|
|
|
|
ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id);
|
|
if (ctx == NULL)
|
|
return -EINVAL;
|
|
|
|
r = amdgpu_ctx_get_entity(ctx, wait->in.ip_type, wait->in.ip_instance,
|
|
wait->in.ring, &entity);
|
|
if (r) {
|
|
amdgpu_ctx_put(ctx);
|
|
return r;
|
|
}
|
|
|
|
fence = amdgpu_ctx_get_fence(ctx, entity, wait->in.handle);
|
|
if (IS_ERR(fence))
|
|
r = PTR_ERR(fence);
|
|
else if (fence) {
|
|
r = dma_fence_wait_timeout(fence, true, timeout);
|
|
if (r > 0 && fence->error)
|
|
r = fence->error;
|
|
dma_fence_put(fence);
|
|
} else
|
|
r = 1;
|
|
|
|
amdgpu_ctx_put(ctx);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
memset(wait, 0, sizeof(*wait));
|
|
wait->out.status = (r == 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* amdgpu_cs_get_fence - helper to get fence from drm_amdgpu_fence
|
|
*
|
|
* @adev: amdgpu device
|
|
* @filp: file private
|
|
* @user: drm_amdgpu_fence copied from user space
|
|
*/
|
|
static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev,
|
|
struct drm_file *filp,
|
|
struct drm_amdgpu_fence *user)
|
|
{
|
|
struct drm_sched_entity *entity;
|
|
struct amdgpu_ctx *ctx;
|
|
struct dma_fence *fence;
|
|
int r;
|
|
|
|
ctx = amdgpu_ctx_get(filp->driver_priv, user->ctx_id);
|
|
if (ctx == NULL)
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
r = amdgpu_ctx_get_entity(ctx, user->ip_type, user->ip_instance,
|
|
user->ring, &entity);
|
|
if (r) {
|
|
amdgpu_ctx_put(ctx);
|
|
return ERR_PTR(r);
|
|
}
|
|
|
|
fence = amdgpu_ctx_get_fence(ctx, entity, user->seq_no);
|
|
amdgpu_ctx_put(ctx);
|
|
|
|
return fence;
|
|
}
|
|
|
|
int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *filp)
|
|
{
|
|
struct amdgpu_device *adev = drm_to_adev(dev);
|
|
union drm_amdgpu_fence_to_handle *info = data;
|
|
struct dma_fence *fence;
|
|
struct drm_syncobj *syncobj;
|
|
struct sync_file *sync_file;
|
|
int fd, r;
|
|
|
|
fence = amdgpu_cs_get_fence(adev, filp, &info->in.fence);
|
|
if (IS_ERR(fence))
|
|
return PTR_ERR(fence);
|
|
|
|
if (!fence)
|
|
fence = dma_fence_get_stub();
|
|
|
|
switch (info->in.what) {
|
|
case AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ:
|
|
r = drm_syncobj_create(&syncobj, 0, fence);
|
|
dma_fence_put(fence);
|
|
if (r)
|
|
return r;
|
|
r = drm_syncobj_get_handle(filp, syncobj, &info->out.handle);
|
|
drm_syncobj_put(syncobj);
|
|
return r;
|
|
|
|
case AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD:
|
|
r = drm_syncobj_create(&syncobj, 0, fence);
|
|
dma_fence_put(fence);
|
|
if (r)
|
|
return r;
|
|
r = drm_syncobj_get_fd(syncobj, (int *)&info->out.handle);
|
|
drm_syncobj_put(syncobj);
|
|
return r;
|
|
|
|
case AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD:
|
|
fd = get_unused_fd_flags(O_CLOEXEC);
|
|
if (fd < 0) {
|
|
dma_fence_put(fence);
|
|
return fd;
|
|
}
|
|
|
|
sync_file = sync_file_create(fence);
|
|
dma_fence_put(fence);
|
|
if (!sync_file) {
|
|
put_unused_fd(fd);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
fd_install(fd, sync_file->file);
|
|
info->out.handle = fd;
|
|
return 0;
|
|
|
|
default:
|
|
dma_fence_put(fence);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* amdgpu_cs_wait_all_fences - wait on all fences to signal
|
|
*
|
|
* @adev: amdgpu device
|
|
* @filp: file private
|
|
* @wait: wait parameters
|
|
* @fences: array of drm_amdgpu_fence
|
|
*/
|
|
static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev,
|
|
struct drm_file *filp,
|
|
union drm_amdgpu_wait_fences *wait,
|
|
struct drm_amdgpu_fence *fences)
|
|
{
|
|
uint32_t fence_count = wait->in.fence_count;
|
|
unsigned int i;
|
|
long r = 1;
|
|
|
|
for (i = 0; i < fence_count; i++) {
|
|
struct dma_fence *fence;
|
|
unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns);
|
|
|
|
fence = amdgpu_cs_get_fence(adev, filp, &fences[i]);
|
|
if (IS_ERR(fence))
|
|
return PTR_ERR(fence);
|
|
else if (!fence)
|
|
continue;
|
|
|
|
r = dma_fence_wait_timeout(fence, true, timeout);
|
|
if (r > 0 && fence->error)
|
|
r = fence->error;
|
|
|
|
dma_fence_put(fence);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
if (r == 0)
|
|
break;
|
|
}
|
|
|
|
memset(wait, 0, sizeof(*wait));
|
|
wait->out.status = (r > 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* amdgpu_cs_wait_any_fence - wait on any fence to signal
|
|
*
|
|
* @adev: amdgpu device
|
|
* @filp: file private
|
|
* @wait: wait parameters
|
|
* @fences: array of drm_amdgpu_fence
|
|
*/
|
|
static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev,
|
|
struct drm_file *filp,
|
|
union drm_amdgpu_wait_fences *wait,
|
|
struct drm_amdgpu_fence *fences)
|
|
{
|
|
unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns);
|
|
uint32_t fence_count = wait->in.fence_count;
|
|
uint32_t first = ~0;
|
|
struct dma_fence **array;
|
|
unsigned int i;
|
|
long r;
|
|
|
|
/* Prepare the fence array */
|
|
array = kzalloc_objs(struct dma_fence *, fence_count);
|
|
|
|
if (array == NULL)
|
|
return -ENOMEM;
|
|
|
|
for (i = 0; i < fence_count; i++) {
|
|
struct dma_fence *fence;
|
|
|
|
fence = amdgpu_cs_get_fence(adev, filp, &fences[i]);
|
|
if (IS_ERR(fence)) {
|
|
r = PTR_ERR(fence);
|
|
goto err_free_fence_array;
|
|
} else if (fence) {
|
|
array[i] = fence;
|
|
} else { /* NULL, the fence has been already signaled */
|
|
r = 1;
|
|
first = i;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
r = dma_fence_wait_any_timeout(array, fence_count, true, timeout,
|
|
&first);
|
|
if (r < 0)
|
|
goto err_free_fence_array;
|
|
|
|
out:
|
|
memset(wait, 0, sizeof(*wait));
|
|
wait->out.status = (r > 0);
|
|
wait->out.first_signaled = first;
|
|
|
|
if (first < fence_count && array[first])
|
|
r = array[first]->error;
|
|
else
|
|
r = 0;
|
|
|
|
err_free_fence_array:
|
|
for (i = 0; i < fence_count; i++)
|
|
dma_fence_put(array[i]);
|
|
kfree(array);
|
|
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* amdgpu_cs_wait_fences_ioctl - wait for multiple command submissions to finish
|
|
*
|
|
* @dev: drm device
|
|
* @data: data from userspace
|
|
* @filp: file private
|
|
*/
|
|
int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *filp)
|
|
{
|
|
struct amdgpu_device *adev = drm_to_adev(dev);
|
|
union drm_amdgpu_wait_fences *wait = data;
|
|
struct drm_amdgpu_fence *fences;
|
|
int r;
|
|
|
|
/* Get the fences from userspace */
|
|
fences = memdup_array_user(u64_to_user_ptr(wait->in.fences),
|
|
wait->in.fence_count,
|
|
sizeof(struct drm_amdgpu_fence));
|
|
if (IS_ERR(fences))
|
|
return PTR_ERR(fences);
|
|
|
|
if (wait->in.wait_all)
|
|
r = amdgpu_cs_wait_all_fences(adev, filp, wait, fences);
|
|
else
|
|
r = amdgpu_cs_wait_any_fence(adev, filp, wait, fences);
|
|
|
|
kfree(fences);
|
|
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* amdgpu_cs_find_mapping - find bo_va for VM address
|
|
*
|
|
* @parser: command submission parser context
|
|
* @addr: VM address
|
|
* @bo: resulting BO of the mapping found
|
|
* @map: Placeholder to return found BO mapping
|
|
*
|
|
* Search the buffer objects in the command submission context for a certain
|
|
* virtual memory address. Returns allocation structure when found, NULL
|
|
* otherwise.
|
|
*/
|
|
int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
|
|
uint64_t addr, struct amdgpu_bo **bo,
|
|
struct amdgpu_bo_va_mapping **map)
|
|
{
|
|
struct amdgpu_fpriv *fpriv = parser->filp->driver_priv;
|
|
struct ttm_operation_ctx ctx = { false, false };
|
|
struct amdgpu_vm *vm = &fpriv->vm;
|
|
struct amdgpu_bo_va_mapping *mapping;
|
|
int i, r;
|
|
|
|
addr /= AMDGPU_GPU_PAGE_SIZE;
|
|
|
|
mapping = amdgpu_vm_bo_lookup_mapping(vm, addr);
|
|
if (!mapping || !mapping->bo_va || !mapping->bo_va->base.bo)
|
|
return -EINVAL;
|
|
|
|
*bo = mapping->bo_va->base.bo;
|
|
*map = mapping;
|
|
|
|
/* Double check that the BO is reserved by this CS */
|
|
if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->exec.ticket)
|
|
return -EINVAL;
|
|
|
|
/* Make sure VRAM is allocated contigiously */
|
|
(*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
|
if ((*bo)->tbo.resource->mem_type == TTM_PL_VRAM &&
|
|
!((*bo)->tbo.resource->placement & TTM_PL_FLAG_CONTIGUOUS)) {
|
|
|
|
amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
|
|
for (i = 0; i < (*bo)->placement.num_placement; i++)
|
|
(*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
|
|
r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
return amdgpu_ttm_alloc_gart(&(*bo)->tbo);
|
|
}
|