From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Zhou, David(ChunMing)" Subject: Re: [PATCH 1/2] drm/syncobj: add an output syncobj parameter to find_fence Date: Thu, 23 May 2019 12:11:20 +0000 Message-ID: <-puwqkvl1kf9u-b7x3md-nw9l5d8fjhc1-57ay9i80p3ne5zfq-v36laytxxssb-707g2imrn1o7-kvonq5nbuaig-6dlanc9wrlar1w0zlrxn0apu-qaxsb6-ac864zux0f2o3d8y3zq369i3-f7fg8.1558613478804@email.android.com> References: <20190523114620.19335-1-lionel.g.landwerlin@intel.com>, <20190523114620.19335-2-lionel.g.landwerlin@intel.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0762037779==" Return-path: In-Reply-To: <20190523114620.19335-2-lionel.g.landwerlin@intel.com> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Lionel Landwerlin , "intel-gfx@lists.freedesktop.org" Cc: "Zhou, David(ChunMing)" , "Koenig, Christian" , DRI-Devel List-Id: dri-devel@lists.freedesktop.org --===============0762037779== Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_puwqkvl1kf9ub7x3mdnw9l5d8fjhc157ay9i80p3ne5zfqv36laytxx_" --_000_puwqkvl1kf9ub7x3mdnw9l5d8fjhc157ay9i80p3ne5zfqv36laytxx_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable can you make the parameter optional? Otherwise looks good to me. -David -------- Original Message -------- Subject: [PATCH 1/2] drm/syncobj: add an output syncobj parameter to find_f= ence From: Lionel Landwerlin To: intel-gfx@lists.freedesktop.org CC: Lionel Landwerlin ,"Koenig, Christian" ,"Zhou, David(ChunMing)" ,Eric A= nholt ,DRI-Devel [CAUTION: External Email] We would like to get both the fence & the syncobj in i915 rather than doing 2 calls to drm_syncobj_find() & drm_syncobj_find_fence(). Signed-off-by: Lionel Landwerlin Cc: Christian Koenig Cc: David(ChunMing) Zhou Cc: Eric Anholt CC: DRI-Devel --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++- drivers/gpu/drm/drm_syncobj.c | 45 +++++++++++++++++--------- drivers/gpu/drm/v3d/v3d_gem.c | 5 ++- include/drm/drm_syncobj.h | 1 + 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/a= mdgpu/amdgpu_cs.c index 2f6239b6be6f..09fde3c73a2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1124,10 +1124,11 @@ static int amdgpu_syncobj_lookup_and_add_to_sync(st= ruct amdgpu_cs_parser *p, uint32_t handle, u64 point= , u64 flags) { + struct drm_syncobj *syncobj; struct dma_fence *fence; int r; - r =3D drm_syncobj_find_fence(p->filp, handle, point, flags, &fence)= ; + r =3D drm_syncobj_find_fence(p->filp, handle, point, flags, &syncob= j, &fence); if (r) { DRM_ERROR("syncobj %u failed to find fence @ %llu (%d)!\n", handle, point, r); @@ -1136,6 +1137,7 @@ static int amdgpu_syncobj_lookup_and_add_to_sync(stru= ct amdgpu_cs_parser *p, r =3D amdgpu_sync_fence(p->adev, &p->job->sync, fence, true); dma_fence_put(fence); + drm_syncobj_put(syncobj); return r; } diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 3d400905100b..f2fd0c1fb1d3 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -222,29 +222,32 @@ static void drm_syncobj_assign_null_handle(struct drm= _syncobj *syncobj) * @handle: sync object handle to lookup. * @point: timeline point * @flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or not + * @syncobj: out parameter for the syncobj * @fence: out parameter for the fence * * This is just a convenience function that combines drm_syncobj_find() an= d * drm_syncobj_fence_get(). * - * Returns 0 on success or a negative error value on failure. On success @= fence - * contains a reference to the fence, which must be released by calling - * dma_fence_put(). + * Returns 0 on success or a negative error value on failure. On + * success @syncobj and @fence contains a reference respectively to + * the syncobj and to the fence, which must be released by calling + * respectively drm_syncobj_put() and dma_fence_put(). */ int drm_syncobj_find_fence(struct drm_file *file_private, u32 handle, u64 point, u64 flags, + struct drm_syncobj **syncobj, struct dma_fence **fence) { - struct drm_syncobj *syncobj =3D drm_syncobj_find(file_private, hand= le); struct syncobj_wait_entry wait; u64 timeout =3D nsecs_to_jiffies64(DRM_SYNCOBJ_WAIT_FOR_SUBMIT_TIME= OUT); int ret; - if (!syncobj) + *syncobj =3D drm_syncobj_find(file_private, handle); + + if (!(*syncobj)) return -ENOENT; - *fence =3D drm_syncobj_fence_get(syncobj); - drm_syncobj_put(syncobj); + *fence =3D drm_syncobj_fence_get(*syncobj); if (*fence) { ret =3D dma_fence_chain_find_seqno(fence, point); @@ -255,13 +258,15 @@ int drm_syncobj_find_fence(struct drm_file *file_priv= ate, ret =3D -EINVAL; } - if (!(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)) + if (!(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)) { + drm_syncobj_put(*syncobj); return ret; + } memset(&wait, 0, sizeof(wait)); wait.task =3D current; wait.point =3D point; - drm_syncobj_fence_add_wait(syncobj, &wait); + drm_syncobj_fence_add_wait(*syncobj, &wait); do { set_current_state(TASK_INTERRUPTIBLE); @@ -286,7 +291,10 @@ int drm_syncobj_find_fence(struct drm_file *file_priva= te, *fence =3D wait.fence; if (wait.node.next) - drm_syncobj_remove_wait(syncobj, &wait); + drm_syncobj_remove_wait(*syncobj, &wait); + + if (ret) + drm_syncobj_put(*syncobj); return ret; } @@ -531,6 +539,7 @@ static int drm_syncobj_export_sync_file(struct drm_file= *file_private, int handle, int *p_fd) { int ret; + struct drm_syncobj *syncobj; struct dma_fence *fence; struct sync_file *sync_file; int fd =3D get_unused_fd_flags(O_CLOEXEC); @@ -538,13 +547,14 @@ static int drm_syncobj_export_sync_file(struct drm_fi= le *file_private, if (fd < 0) return fd; - ret =3D drm_syncobj_find_fence(file_private, handle, 0, 0, &fence); + ret =3D drm_syncobj_find_fence(file_private, handle, 0, 0, &syncobj= , &fence); if (ret) goto err_put_fd; sync_file =3D sync_file_create(fence); dma_fence_put(fence); + drm_syncobj_put(syncobj); if (!sync_file) { ret =3D -EINVAL; @@ -682,7 +692,8 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, = void *data, static int drm_syncobj_transfer_to_timeline(struct drm_file *file_private, struct drm_syncobj_transfer *ar= gs) { - struct drm_syncobj *timeline_syncobj =3D NULL; + struct drm_syncobj *timeline_syncobj; + struct drm_syncobj *src_syncobj; struct dma_fence *fence; struct dma_fence_chain *chain; int ret; @@ -693,7 +704,7 @@ static int drm_syncobj_transfer_to_timeline(struct drm_= file *file_private, } ret =3D drm_syncobj_find_fence(file_private, args->src_handle, args->src_point, args->flags, - &fence); + &src_syncobj, &fence); if (ret) goto err; chain =3D kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL); @@ -704,6 +715,7 @@ static int drm_syncobj_transfer_to_timeline(struct drm_= file *file_private, drm_syncobj_add_point(timeline_syncobj, chain, fence, args->dst_poi= nt); err1: dma_fence_put(fence); + drm_syncobj_put(src_syncobj); err: drm_syncobj_put(timeline_syncobj); @@ -714,7 +726,8 @@ static int drm_syncobj_transfer_to_binary(struct drm_file *file_private, struct drm_syncobj_transfer *args) { - struct drm_syncobj *binary_syncobj =3D NULL; + struct drm_syncobj *binary_syncobj; + struct drm_syncobj *src_syncobj; struct dma_fence *fence; int ret; @@ -722,11 +735,13 @@ drm_syncobj_transfer_to_binary(struct drm_file *file_= private, if (!binary_syncobj) return -ENOENT; ret =3D drm_syncobj_find_fence(file_private, args->src_handle, - args->src_point, args->flags, &fence); + args->src_point, args->flags, + &src_syncobj, &fence); if (ret) goto err; drm_syncobj_replace_fence(binary_syncobj, fence); dma_fence_put(fence); + drm_syncobj_put(src_syncobj); err: drm_syncobj_put(binary_syncobj); diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 27e0f87075d9..26bd3a2e39ca 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -431,6 +431,7 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file= _priv, struct v3d_job *job, void (*free)(struct kref *ref), u32 in_sync) { + struct drm_syncobj *in_syncobj =3D NULL; struct dma_fence *in_fence =3D NULL; int ret; @@ -443,10 +444,12 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *fi= le_priv, xa_init_flags(&job->deps, XA_FLAGS_ALLOC); - ret =3D drm_syncobj_find_fence(file_priv, in_sync, 0, 0, &in_fence)= ; + ret =3D drm_syncobj_find_fence(file_priv, in_sync, 0, 0, &syncobj, = &in_fence); if (ret =3D=3D -EINVAL) goto fail; + drm_syncobj_put(in_sync); + ret =3D drm_gem_fence_array_add(&job->deps, in_fence); if (ret) goto fail; diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index 6cf7243a1dc5..08eca690f783 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -121,6 +121,7 @@ void drm_syncobj_replace_fence(struct drm_syncobj *sync= obj, struct dma_fence *fence); int drm_syncobj_find_fence(struct drm_file *file_private, u32 handle, u64 point, u64 flags, + struct drm_syncobj **syncobj, struct dma_fence **fence); void drm_syncobj_free(struct kref *kref); int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, -- 2.21.0.392.gf8f6787159e --_000_puwqkvl1kf9ub7x3mdnw9l5d8fjhc157ay9i80p3ne5zfqv36laytxx_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
can you make the parameter optional? Otherwise looks good to me.

-David

-------- Original Message --------
Subject: [PATCH 1/2] drm/syncobj: add an output syncobj parameter to find_f= ence
From: Lionel Landwerlin
To: intel-gfx@lists.freedesktop.org
CC: Lionel Landwerlin ,"Koenig, Christian" ,"Zhou, David(Chu= nMing)" ,Eric Anholt ,DRI-Devel

[CAUTION: External Email]

We would like to get both the fence & the syncobj in i915 rather than doing 2 calls to drm_syncobj_find() & drm_syncobj_find_fence().

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: Christian Koenig <Christian.Koenig@amd.com>
Cc: David(ChunMing) Zhou <David1.Zhou@amd.com>
Cc: Eric Anholt <eric@anholt.net>
CC: DRI-Devel <dri-devel@lists.freedesktop.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c |  4 ++-
 drivers/gpu/drm/drm_syncobj.c      &nbs= p;   | 45 +++++++++++= ++++++---------
 drivers/gpu/drm/v3d/v3d_gem.c      &nbs= p;   |  5 ++-
 include/drm/drm_syncobj.h       &n= bsp;      |  1 +
 4 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/a= mdgpu/amdgpu_cs.c
index 2f6239b6be6f..09fde3c73a2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1124,10 +1124,11 @@ static int amdgpu_syncobj_lookup_and_add_to_syn= c(struct amdgpu_cs_parser *p,
            &nb= sp;            =             &nb= sp;           uint32_t ha= ndle, u64 point,
            &nb= sp;            =             &nb= sp;           u64 flags)<= br>  {
+       struct drm_syncobj *syncobj;
        struct dma_fence *fence;
        int r;

-       r =3D drm_syncobj_find_fence(p->fi= lp, handle, point, flags, &fence);
+       r =3D drm_syncobj_find_fence(p-&g= t;filp, handle, point, flags, &syncobj, &fence);
        if (r) {
            &nb= sp;   DRM_ERROR("syncobj %u failed to find fence @ %llu (%d)= !\n",
            &nb= sp;            = handle, point, r);
@@ -1136,6 +1137,7 @@ static int amdgpu_syncobj_lookup_and_add_to_sync(= struct amdgpu_cs_parser *p,

        r =3D amdgpu_sync_fence(p->ad= ev, &p->job->sync, fence, true);
        dma_fence_put(fence);
+       drm_syncobj_put(syncobj);

        return r;
 }
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c<= br> index 3d400905100b..f2fd0c1fb1d3 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -222,29 +222,32 @@ static void drm_syncobj_assign_null_handle(struct= drm_syncobj *syncobj)
  * @handle: sync object handle to lookup.
  * @point: timeline point
  * @flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or not
+ * @syncobj: out parameter for the syncobj
  * @fence: out parameter for the fence
  *
  * This is just a convenience function that combines drm_syncobj_find= () and
  * drm_syncobj_fence_get().
  *
- * Returns 0 on success or a negative error value on failure. On success @= fence
- * contains a reference to the fence, which must be released by calling - * dma_fence_put().
+ * Returns 0 on success or a negative error value on failure. On
+ * success @syncobj and @fence contains a reference respectively to + * the syncobj and to the fence, which must be released by calling
+ * respectively drm_syncobj_put() and dma_fence_put().
  */
 int drm_syncobj_find_fence(struct drm_file *file_private,
            &nb= sp;            =   u32 handle, u64 point, u64 flags,
+           &nbs= p;            &= nbsp; struct drm_syncobj **syncobj,
            &nb= sp;            =   struct dma_fence **fence)
 {
-       struct drm_syncobj *syncobj =3D drm_s= yncobj_find(file_private, handle);
        struct syncobj_wait_entry wait;<= br>         u64 timeout =3D nsecs_to_jiffies= 64(DRM_SYNCOBJ_WAIT_FOR_SUBMIT_TIMEOUT);
        int ret;

-       if (!syncobj)
+       *syncobj =3D drm_syncobj_find(fil= e_private, handle);
+
+       if (!(*syncobj))
            &nb= sp;   return -ENOENT;

-       *fence =3D drm_syncobj_fence_get(sync= obj);
-       drm_syncobj_put(syncobj);
+       *fence =3D drm_syncobj_fence_get(= *syncobj);

        if (*fence) {
            &nb= sp;   ret =3D dma_fence_chain_find_seqno(fence, point);
@@ -255,13 +258,15 @@ int drm_syncobj_find_fence(struct drm_file *file_= private,
            &nb= sp;   ret =3D -EINVAL;
        }

-       if (!(flags & DRM_SYNCOBJ_WAIT_FL= AGS_WAIT_FOR_SUBMIT))
+       if (!(flags & DRM_SYNCOBJ_WAI= T_FLAGS_WAIT_FOR_SUBMIT)) {
+           &nbs= p;   drm_syncobj_put(*syncobj);
            &nb= sp;   return ret;
+       }

        memset(&wait, 0, sizeof(wait= ));
        wait.task =3D current;
        wait.point =3D point;
-       drm_syncobj_fence_add_wait(syncobj, &= amp;wait);
+       drm_syncobj_fence_add_wait(*synco= bj, &wait);

        do {
            &nb= sp;   set_current_state(TASK_INTERRUPTIBLE);
@@ -286,7 +291,10 @@ int drm_syncobj_find_fence(struct drm_file *file_p= rivate,
        *fence =3D wait.fence;

        if (wait.node.next)
-            &n= bsp;  drm_syncobj_remove_wait(syncobj, &wait);
+           &nbs= p;   drm_syncobj_remove_wait(*syncobj, &wait);
+
+       if (ret)
+           &nbs= p;   drm_syncobj_put(*syncobj);

        return ret;
 }
@@ -531,6 +539,7 @@ static int drm_syncobj_export_sync_file(struct drm_= file *file_private,
            &nb= sp;            =             &nb= sp;  int handle, int *p_fd)
 {
        int ret;
+       struct drm_syncobj *syncobj;
        struct dma_fence *fence;
        struct sync_file *sync_file;
        int fd =3D get_unused_fd_flags(O= _CLOEXEC);
@@ -538,13 +547,14 @@ static int drm_syncobj_export_sync_file(struct dr= m_file *file_private,
        if (fd < 0)
            &nb= sp;   return fd;

-       ret =3D drm_syncobj_find_fence(file_p= rivate, handle, 0, 0, &fence);
+       ret =3D drm_syncobj_find_fence(fi= le_private, handle, 0, 0, &syncobj, &fence);
        if (ret)
            &nb= sp;   goto err_put_fd;

        sync_file =3D sync_file_create(f= ence);

        dma_fence_put(fence);
+       drm_syncobj_put(syncobj);

        if (!sync_file) {
            &nb= sp;   ret =3D -EINVAL;
@@ -682,7 +692,8 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *d= ev, void *data,
 static int drm_syncobj_transfer_to_timeline(struct drm_file *file_pri= vate,
            &nb= sp;            =             &nb= sp;      struct drm_syncobj_transfer *args)
 {
-       struct drm_syncobj *timeline_syncobj = =3D NULL;
+       struct drm_syncobj *timeline_sync= obj;
+       struct drm_syncobj *src_syncobj;<= br>         struct dma_fence *fence;
        struct dma_fence_chain *chain;         int ret;
@@ -693,7 +704,7 @@ static int drm_syncobj_transfer_to_timeline(struct = drm_file *file_private,
        }
        ret =3D drm_syncobj_find_fence(f= ile_private, args->src_handle,
            &nb= sp;            =             args->= ;src_point, args->flags,
-            &n= bsp;            = ;           &fence);<= br> +           &nbs= p;            &= nbsp;           &src_= syncobj, &fence);
        if (ret)
            &nb= sp;   goto err;
        chain =3D kzalloc(sizeof(struct = dma_fence_chain), GFP_KERNEL);
@@ -704,6 +715,7 @@ static int drm_syncobj_transfer_to_timeline(struct = drm_file *file_private,
        drm_syncobj_add_point(timeline_s= yncobj, chain, fence, args->dst_point);
 err1:
        dma_fence_put(fence);
+       drm_syncobj_put(src_syncobj);
 err:
        drm_syncobj_put(timeline_syncobj= );

@@ -714,7 +726,8 @@ static int
 drm_syncobj_transfer_to_binary(struct drm_file *file_private,
            &nb= sp;            =       struct drm_syncobj_transfer *args)
 {
-       struct drm_syncobj *binary_syncobj = =3D NULL;
+       struct drm_syncobj *binary_syncob= j;
+       struct drm_syncobj *src_syncobj;<= br>         struct dma_fence *fence;
        int ret;

@@ -722,11 +735,13 @@ drm_syncobj_transfer_to_binary(struct drm_file *f= ile_private,
        if (!binary_syncobj)
            &nb= sp;   return -ENOENT;
        ret =3D drm_syncobj_find_fence(f= ile_private, args->src_handle,
-            &n= bsp;            = ;           args->src_= point, args->flags, &fence);
+           &nbs= p;            &= nbsp;           args->= src_point, args->flags,
+           &nbs= p;            &= nbsp;           &src_= syncobj, &fence);
        if (ret)
            &nb= sp;   goto err;
        drm_syncobj_replace_fence(binary= _syncobj, fence);
        dma_fence_put(fence);
+       drm_syncobj_put(src_syncobj);
 err:
        drm_syncobj_put(binary_syncobj);=

diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c<= br> index 27e0f87075d9..26bd3a2e39ca 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -431,6 +431,7 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *= file_priv,
             st= ruct v3d_job *job, void (*free)(struct kref *ref),
             u3= 2 in_sync)
 {
+       struct drm_syncobj *in_syncobj = =3D NULL;
        struct dma_fence *in_fence =3D N= ULL;
        int ret;

@@ -443,10 +444,12 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file= *file_priv,

        xa_init_flags(&job->deps,= XA_FLAGS_ALLOC);

-       ret =3D drm_syncobj_find_fence(file_p= riv, in_sync, 0, 0, &in_fence);
+       ret =3D drm_syncobj_find_fence(fi= le_priv, in_sync, 0, 0, &syncobj, &in_fence);
        if (ret =3D=3D -EINVAL)
            &nb= sp;   goto fail;

+       drm_syncobj_put(in_sync);
+
        ret =3D drm_gem_fence_array_add(= &job->deps, in_fence);
        if (ret)
            &nb= sp;   goto fail;
diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h
index 6cf7243a1dc5..08eca690f783 100644
--- a/include/drm/drm_syncobj.h
+++ b/include/drm/drm_syncobj.h
@@ -121,6 +121,7 @@ void drm_syncobj_replace_fence(struct drm_syncobj *= syncobj,
            &nb= sp;            =       struct dma_fence *fence);
 int drm_syncobj_find_fence(struct drm_file *file_private,
            &nb= sp;            =   u32 handle, u64 point, u64 flags,
+           &nbs= p;            &= nbsp; struct drm_syncobj **syncobj,
            &nb= sp;            =   struct dma_fence **fence);
 void drm_syncobj_free(struct kref *kref);
 int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t fla= gs,
--
2.21.0.392.gf8f6787159e

--_000_puwqkvl1kf9ub7x3mdnw9l5d8fjhc157ay9i80p3ne5zfqv36laytxx_-- --===============0762037779== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSW50ZWwtZ2Z4 IG1haWxpbmcgbGlzdApJbnRlbC1nZnhAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlz dHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vaW50ZWwtZ2Z4 --===============0762037779==--