From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 5872645A58;
	Tue, 15 Oct 2024 18:51:51 +0200 (CEST)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id A19C8402EE;
	Tue, 15 Oct 2024 18:51:49 +0200 (CEST)
Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com
 [209.85.210.173])
 by mails.dpdk.org (Postfix) with ESMTP id 419EE400D7
 for <dev@dpdk.org>; Tue, 15 Oct 2024 18:51:48 +0200 (CEST)
Received: by mail-pf1-f173.google.com with SMTP id
 d2e1a72fcca58-71e625b00bcso1918258b3a.3
 for <dev@dpdk.org>; Tue, 15 Oct 2024 09:51:48 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=iol.unh.edu; s=unh-iol; t=1729011107; x=1729615907; darn=dpdk.org;
 h=cc:to:subject:message-id:date:from:in-reply-to:references
 :mime-version:from:to:cc:subject:date:message-id:reply-to;
 bh=lEx63chR6lw83O6IqxKWVQWv8mhjBYwp1vR5Vv4O6ls=;
 b=bH979D0t47bEtqosy6xIe7BQHe1/nf/AVRYGQG+uIeYwLYOZ265mrM4pRCVtTK6WWw
 Erqb+3ZzX46LipKHyttuxYHshh8OGAPer7TZD9BqWgmqD4GcUFMdChgVuI5lBO0EKtuz
 BIEWCKA/q2RXKHee8lZDl2aQ4RBdndsdsYHyI=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1729011107; x=1729615907;
 h=cc:to:subject:message-id:date:from:in-reply-to:references
 :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id
 :reply-to;
 bh=lEx63chR6lw83O6IqxKWVQWv8mhjBYwp1vR5Vv4O6ls=;
 b=MSf+0kJHcQ8WeZv5s30pHlKFNFw2rwX3m+Y9OD6DqljcmC6jLnlFQsbhk6h0HN1sOY
 Rr7yNDL28AtHyymmZHcR+fRy0JRRjF5HcJILqjsypQN607UBHPTZ/yLwAjloN5raxF7S
 a2LYeXw4e/AFKDywv2TstjACLfA/NZebzMG8uh3NpRug0btSeEO4/VGd7Xcb67m0+z5f
 LDmISkVPp3KJYpQvK7bLKpFH7tPTR/PJa5gIweVLXX8w36wBfq309qSHVZo6Xt/V/5wX
 oOdSa2Ey9COhlBz8dEy2y9cl5m+qyJxfXQ3tDFkAkcBgy5w0skF4epL4U94Y5Lgwj/Ab
 kBDg==
X-Forwarded-Encrypted: i=1;
 AJvYcCWQ9HF7Q3hv/LdLAdndQYnhyhNaKVF+HZP6BGjvsip5Wz440qLwyU6ZahnA6D61gCJRcMU=@dpdk.org
X-Gm-Message-State: AOJu0Yxq4DfZk8uIYN8BWpF9KxyoYde/kf8eVc6/xY9ReDrnbdbJQhoq
 TPuLhFC8EkO3itguvafzg481rT7E7HbaVUTgZ+pjh8T71OahuOO3xDW26Qk8HoN2PyKklTs2oJS
 YB8wOG04Mn7KxiqubZc98t7tf20P6imUY4brWoQ==
X-Google-Smtp-Source: AGHT+IFDjgmwTaL9d8luW8kTHT3rrzJnKPz7BelKA/HCfcPwuA7JuCInVYarmZwbTRj3hsKAFOmEzTJF/m0lMTgKvTg=
X-Received: by 2002:a05:6a00:928e:b0:71e:55e2:2c43 with SMTP id
 d2e1a72fcca58-71e55e23f97mr15244012b3a.14.1729011107411; Tue, 15 Oct 2024
 09:51:47 -0700 (PDT)
MIME-Version: 1.0
References: <20240812073209.1924286-1-zhang.yong25@zte.com.cn>
 <20241014081117.1704528-10-zhang.yong25@zte.com.cn>
In-Reply-To: <20241014081117.1704528-10-zhang.yong25@zte.com.cn>
From: Patrick Robb <probb@iol.unh.edu>
Date: Tue, 15 Oct 2024 12:50:22 -0400
Message-ID: <CAJvnSUC-Shm=T7_5TZYHe-yQH_ZZCygXzRAkaFDJf-4vZjHCBw@mail.gmail.com>
Subject: Re: [v3 5/5] raw/gdtc: add support for dequeue operation
To: Yong Zhang <zhang.yong25@zte.com.cn>
Cc: thomas@monjalon.net, techboard@dpdk.org, dev@dpdk.org, 
 wang.yong19@zte.com.cn, li.min10@zte.com.cn, ran.ming@zte.com.cn
Content-Type: multipart/alternative; boundary="000000000000ded3b2062486c4f9"
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

--000000000000ded3b2062486c4f9
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

It looks like this did not get processed correctly by patchwork, or there
is an issue with the patchfiles.

https://patchwork.dpdk.org/project/dpdk/list/?series=3D&submitter=3D&state=
=3D&q=3Dgdtc&archive=3D&delegate=3D

Can you resubmit? It was not picked up by 3/4 of the CI labs.

On Mon, Oct 14, 2024 at 4:16=E2=80=AFAM Yong Zhang <zhang.yong25@zte.com.cn=
> wrote:

> Add rawdev dequeue operation for gdtc devices.
>
> Signed-off-by: Yong Zhang <zhang.yong25@zte.com.cn>
> ---
>  drivers/raw/gdtc/gdtc_rawdev.c | 113 +++++++++++++++++++++++++++++++++
>  1 file changed, 113 insertions(+)
>
>
> diff --git a/drivers/raw/gdtc/gdtc_rawdev.c b/drivers/raw/gdtc/gdtc_rawde=
v.c
> index 03f7cc1a8e..8e9543f402 100644
> --- a/drivers/raw/gdtc/gdtc_rawdev.c
> +++ b/drivers/raw/gdtc/gdtc_rawdev.c
> @@ -88,6 +88,8 @@
>  #define LOW32_MASK                              0xffffffff
>  #define LOW16_MASK                              0xffff
>
> +#define ZXDH_GDMA_TC_CNT_MAX                    0x10000
> +
>  #define IDX_TO_ADDR(addr, idx, t) \
>      ((t)((uintptr_t)(addr) + (idx) * sizeof(struct zxdh_gdma_buff_desc))=
)
>
> @@ -526,6 +528,116 @@ zxdh_gdma_rawdev_enqueue_bufs(struct rte_rawdev *de=
v,
>
>      return count;
>  }
> +
> +static inline void
>
> +zxdh_gdma_used_idx_update(struct zxdh_gdma_queue *queue, uint16_t cnt, u=
int8_t data_bd_err)
> +{
> +    uint16_t idx =3D 0;
> +
> +    if (queue->sw_ring.used_idx + cnt < queue->queue_size)
> +        queue->sw_ring.used_idx +=3D cnt;
> +    else
>
> +        queue->sw_ring.used_idx =3D queue->sw_ring.used_idx + cnt - queu=
e->queue_size;
> +
> +    if (data_bd_err =3D=3D 1) {
> +        /* Update job status, the last job status is error */
> +        if (queue->sw_ring.used_idx =3D=3D 0)
> +            idx =3D queue->queue_size - 1;
> +        else
> +            idx =3D queue->sw_ring.used_idx - 1;
> +
> +        queue->sw_ring.job[idx]->status =3D 1;
> +    }
> +}
> +
> +static int
> +zxdh_gdma_rawdev_dequeue_bufs(struct rte_rawdev *dev,
> +                        __rte_unused struct rte_rawdev_buf **buffers,
> +                        uint32_t count,
> +                        rte_rawdev_obj_t context)
> +{
> +    struct zxdh_gdma_queue *queue =3D NULL;
> +    struct zxdh_gdma_enqdeq *e_context =3D NULL;
> +    uint16_t queue_id =3D 0;
> +    uint32_t val =3D 0;
> +    uint16_t tc_cnt =3D 0;
> +    uint16_t diff_cnt =3D 0;
> +    uint16_t i =3D 0;
> +    uint16_t bd_idx =3D 0;
> +    uint64_t next_bd_addr =3D 0;
> +    uint8_t data_bd_err =3D 0;
> +
> +    if ((dev =3D=3D NULL) || (context =3D=3D NULL))
> +        return -EINVAL;
> +
> +    e_context =3D (struct zxdh_gdma_enqdeq *)context;
> +    queue_id =3D e_context->vq_id;
> +    queue =3D zxdh_gdma_get_queue(dev, queue_id);
> +    if ((queue =3D=3D NULL) || (queue->enable =3D=3D 0))
> +        return -EINVAL;
> +
> +    if (queue->sw_ring.pend_cnt =3D=3D 0)
> +        goto deq_job;
> +
> +    /* Get data transmit count */
> +    val =3D zxdh_gdma_read_reg(dev, queue_id, ZXDH_GDMA_TC_CNT_OFFSET);
> +    tc_cnt =3D val & LOW16_MASK;
> +    if (tc_cnt >=3D queue->tc_cnt)
> +        diff_cnt =3D tc_cnt - queue->tc_cnt;
> +    else
> +        diff_cnt =3D tc_cnt + ZXDH_GDMA_TC_CNT_MAX - queue->tc_cnt;
> +
> +    queue->tc_cnt =3D tc_cnt;
> +
> +    /* Data transmit error, channel stopped */
> +    if ((val & ZXDH_GDMA_ERR_STATUS) !=3D 0) {
>
> +        next_bd_addr  =3D zxdh_gdma_read_reg(dev, queue_id, ZXDH_GDMA_LL=
I_L_OFFSET);
> +        next_bd_addr |=3D ((uint64_t)zxdh_gdma_read_reg(dev, queue_id,
> +                            ZXDH_GDMA_LLI_H_OFFSET) << 32);
> +        next_bd_addr  =3D next_bd_addr << 6;
>
> +        bd_idx =3D (next_bd_addr - queue->ring.ring_mem) / sizeof(struct=
 zxdh_gdma_buff_desc);
>
> +        if ((val & ZXDH_GDMA_SRC_DATA_ERR) || (val & ZXDH_GDMA_DST_ADDR_=
ERR)) {
> +            diff_cnt++;
> +            data_bd_err =3D 1;
> +        }
>
> +        ZXDH_PMD_LOG(INFO, "queue%d is err(0x%x) next_bd_idx:%u ll_addr:=
0x%"PRIx64" def user:0x%x",
> +                    queue_id, val, bd_idx, next_bd_addr, queue->user);
> +
> +        ZXDH_PMD_LOG(INFO, "Clean up error status");
> +        val =3D ZXDH_GDMA_ERR_STATUS | ZXDH_GDMA_ERR_INTR_ENABLE;
> +        zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_TC_CNT_OFFSET, val)=
;
> +
> +        ZXDH_PMD_LOG(INFO, "Restart channel");
> +        zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_XFERSIZE_OFFSET, 0)=
;
> +        zxdh_gdma_control_cal(&val, 0);
> +        zxdh_gdma_write_reg(dev, queue_id, ZXDH_GDMA_CONTROL_OFFSET, val=
);
> +    }
> +
> +    if (diff_cnt !=3D 0) {
> +        zxdh_gdma_used_idx_update(queue, diff_cnt, data_bd_err);
> +        queue->sw_ring.deq_cnt +=3D diff_cnt;
> +        queue->sw_ring.pend_cnt -=3D diff_cnt;
> +    }
> +
> +deq_job:
> +    if (queue->sw_ring.deq_cnt =3D=3D 0)
> +        return 0;
> +    else if (queue->sw_ring.deq_cnt < count)
> +        count =3D queue->sw_ring.deq_cnt;
> +
> +    queue->sw_ring.deq_cnt -=3D count;
> +
> +    for (i =3D 0; i < count; i++) {
> +        e_context->job[i] =3D queue->sw_ring.job[queue->sw_ring.deq_idx]=
;
> +        queue->sw_ring.job[queue->sw_ring.deq_idx] =3D NULL;
> +        if (++queue->sw_ring.deq_idx >=3D queue->queue_size)
> +            queue->sw_ring.deq_idx -=3D queue->queue_size;
> +    }
> +    queue->sw_ring.free_cnt +=3D count;
> +
> +    return count;
> +}
> +
>  static const struct rte_rawdev_ops zxdh_gdma_rawdev_ops =3D {
>      .dev_info_get =3D zxdh_gdma_rawdev_info_get,
>      .dev_configure =3D zxdh_gdma_rawdev_configure,
>
> @@ -540,6 +652,7 @@ static const struct rte_rawdev_ops zxdh_gdma_rawdev_o=
ps =3D {
>      .attr_get =3D zxdh_gdma_rawdev_get_attr,
>
>      .enqueue_bufs =3D zxdh_gdma_rawdev_enqueue_bufs,
> +    .dequeue_bufs =3D zxdh_gdma_rawdev_dequeue_bufs,
>  };
>
>  static int
> --
> 2.43.0
>

--000000000000ded3b2062486c4f9
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: base64

PGRpdiBkaXI9Imx0ciI+SXQgbG9va3MgbGlrZSB0aGlzIGRpZCBub3QgZ2V0IHByb2Nlc3NlZCBj
b3JyZWN0bHkgYnkgcGF0Y2h3b3JrLCBvciB0aGVyZSBpcyBhbiBpc3N1ZSB3aXRoIHRoZSBwYXRj
aGZpbGVzLsKgPGRpdj48YnI+PC9kaXY+PGRpdj48YSBocmVmPSJodHRwczovL3BhdGNod29yay5k
cGRrLm9yZy9wcm9qZWN0L2RwZGsvbGlzdC8/c2VyaWVzPSZhbXA7c3VibWl0dGVyPSZhbXA7c3Rh
dGU9JmFtcDtxPWdkdGMmYW1wO2FyY2hpdmU9JmFtcDtkZWxlZ2F0ZT0iPmh0dHBzOi8vcGF0Y2h3
b3JrLmRwZGsub3JnL3Byb2plY3QvZHBkay9saXN0Lz9zZXJpZXM9JmFtcDtzdWJtaXR0ZXI9JmFt
cDtzdGF0ZT0mYW1wO3E9Z2R0YyZhbXA7YXJjaGl2ZT0mYW1wO2RlbGVnYXRlPTwvYT48YnI+PC9k
aXY+PGRpdj48YnI+PC9kaXY+PGRpdj5DYW4geW91IHJlc3VibWl0PyBJdCB3YXMgbm90IHBpY2tl
ZCB1cCBieSAzLzQgb2YgdGhlIENJIGxhYnMuPC9kaXY+PC9kaXY+PGJyPjxkaXYgY2xhc3M9Imdt
YWlsX3F1b3RlIj48ZGl2IGRpcj0ibHRyIiBjbGFzcz0iZ21haWxfYXR0ciI+T24gTW9uLCBPY3Qg
MTQsIDIwMjQgYXQgNDoxNuKAr0FNIFlvbmcgWmhhbmcgJmx0OzxhIGhyZWY9Im1haWx0bzp6aGFu
Zy55b25nMjVAenRlLmNvbS5jbiI+emhhbmcueW9uZzI1QHp0ZS5jb20uY248L2E+Jmd0OyB3cm90
ZTo8YnI+PC9kaXY+PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBzdHlsZT0ibWFyZ2lu
OjBweCAwcHggMHB4IDAuOGV4O2JvcmRlci1sZWZ0OjFweCBzb2xpZCByZ2IoMjA0LDIwNCwyMDQp
O3BhZGRpbmctbGVmdDoxZXgiPkFkZMKgcmF3ZGV2wqBkZXF1ZXVlwqBvcGVyYXRpb27CoGZvcsKg
Z2R0Y8KgZGV2aWNlcy48YnI+DQo8YnI+U2lnbmVkLW9mZi1ieTrCoFlvbmfCoFpoYW5nwqAmbHQ7
PGEgaHJlZj0ibWFpbHRvOnpoYW5nLnlvbmcyNUB6dGUuY29tLmNuIiB0YXJnZXQ9Il9ibGFuayI+
emhhbmcueW9uZzI1QHp0ZS5jb20uY248L2E+Jmd0Ow0KPGJyPi0tLTxicj7CoGRyaXZlcnMvcmF3
L2dkdGMvZ2R0Y19yYXdkZXYuY8KgfMKgMTEzwqArKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKys8YnI+wqAxwqBmaWxlwqBjaGFuZ2VkLMKgMTEzwqBpbnNlcnRpb25zKCspPGJyPg0KPGJy
PmRpZmbCoC0tZ2l0wqBhL2RyaXZlcnMvcmF3L2dkdGMvZ2R0Y19yYXdkZXYuY8KgYi9kcml2ZXJz
L3Jhdy9nZHRjL2dkdGNfcmF3ZGV2LmM8YnI+aW5kZXjCoDAzZjdjYzFhOGUuLjhlOTU0M2Y0MDLC
oDEwMDY0NDxicj4tLS3CoGEvZHJpdmVycy9yYXcvZ2R0Yy9nZHRjX3Jhd2Rldi5jPGJyPisrK8Kg
Yi9kcml2ZXJzL3Jhdy9nZHRjL2dkdGNfcmF3ZGV2LmM8YnI+QEDCoC04OCw2wqArODgsOMKgQEA8
YnI+wqAjZGVmaW5lwqBMT1czMl9NQVNLwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC
oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgMHhmZmZmZmZmZjxicj7CoCNkZWZpbmXCoExPVzE2
X01BU0vCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg
wqDCoMKgwqAweGZmZmY8YnI+wqANCjxicj4rI2RlZmluZcKgWlhESF9HRE1BX1RDX0NOVF9NQVjC
oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgMHgxMDAwMDxicj4rPGJyPsKg
I2RlZmluZcKgSURYX1RPX0FERFIoYWRkcizCoGlkeCzCoHQpwqBcPGJyPsKgwqDCoMKgwqAoKHQp
KCh1aW50cHRyX3QpKGFkZHIpwqArwqAoaWR4KcKgKsKgc2l6ZW9mKHN0cnVjdMKgenhkaF9nZG1h
X2J1ZmZfZGVzYykpKTxicj7CoA0KPGJyPkBAwqAtNTI2LDbCoCs1MjgsMTE2wqBAQMKgenhkaF9n
ZG1hX3Jhd2Rldl9lbnF1ZXVlX2J1ZnMoc3RydWN0wqBydGVfcmF3ZGV2wqAqZGV2LDxicj7CoA0K
PGJyPsKgwqDCoMKgwqByZXR1cm7CoGNvdW50Ozxicj7CoH08YnI+Kzxicj4rc3RhdGljwqBpbmxp
bmXCoHZvaWQ8YnI+K3p4ZGhfZ2RtYV91c2VkX2lkeF91cGRhdGUoc3RydWN0wqB6eGRoX2dkbWFf
cXVldWXCoCpxdWV1ZSzCoHVpbnQxNl90wqBjbnQswqB1aW50OF90wqBkYXRhX2JkX2Vycik8YnI+
K3s8YnI+K8KgwqDCoMKgdWludDE2X3TCoGlkeMKgPcKgMDs8YnI+Kzxicj4rwqDCoMKgwqBpZsKg
KHF1ZXVlLSZndDtzd19yaW5nLnVzZWRfaWR4wqArwqBjbnTCoCZsdDvCoHF1ZXVlLSZndDtxdWV1
ZV9zaXplKTxicj4rwqDCoMKgwqDCoMKgwqDCoHF1ZXVlLSZndDtzd19yaW5nLnVzZWRfaWR4wqAr
PcKgY250Ozxicj4rwqDCoMKgwqBlbHNlPGJyPivCoMKgwqDCoMKgwqDCoMKgcXVldWUtJmd0O3N3
X3JpbmcudXNlZF9pZHjCoD3CoHF1ZXVlLSZndDtzd19yaW5nLnVzZWRfaWR4wqArwqBjbnTCoC3C
oHF1ZXVlLSZndDtxdWV1ZV9zaXplOzxicj4rPGJyPivCoMKgwqDCoGlmwqAoZGF0YV9iZF9lcnLC
oD09wqAxKcKgezxicj4rwqDCoMKgwqDCoMKgwqDCoC8qwqBVcGRhdGXCoGpvYsKgc3RhdHVzLMKg
dGhlwqBsYXN0wqBqb2LCoHN0YXR1c8KgaXPCoGVycm9ywqAqLzxicj4rwqDCoMKgwqDCoMKgwqDC
oGlmwqAocXVldWUtJmd0O3N3X3JpbmcudXNlZF9pZHjCoD09wqAwKTxicj4rwqDCoMKgwqDCoMKg
wqDCoMKgwqDCoMKgaWR4wqA9wqBxdWV1ZS0mZ3Q7cXVldWVfc2l6ZcKgLcKgMTs8YnI+K8KgwqDC
oMKgwqDCoMKgwqBlbHNlPGJyPivCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBpZHjCoD3CoHF1ZXVl
LSZndDtzd19yaW5nLnVzZWRfaWR4wqAtwqAxOzxicj4rPGJyPivCoMKgwqDCoMKgwqDCoMKgcXVl
dWUtJmd0O3N3X3Jpbmcuam9iW2lkeF0tJmd0O3N0YXR1c8KgPcKgMTs8YnI+K8KgwqDCoMKgfTxi
cj4rfTxicj4rPGJyPitzdGF0aWPCoGludDxicj4renhkaF9nZG1hX3Jhd2Rldl9kZXF1ZXVlX2J1
ZnMoc3RydWN0wqBydGVfcmF3ZGV2wqAqZGV2LDxicj4rwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg
wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgX19ydGVfdW51c2VkwqBzdHJ1Y3TCoHJ0ZV9yYXdkZXZf
YnVmwqAqKmJ1ZmZlcnMsPGJyPivCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC
oMKgwqDCoMKgwqB1aW50MzJfdMKgY291bnQsPGJyPivCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC
oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBydGVfcmF3ZGV2X29ial90wqBjb250ZXh0KTxicj4rezxi
cj4rwqDCoMKgwqBzdHJ1Y3TCoHp4ZGhfZ2RtYV9xdWV1ZcKgKnF1ZXVlwqA9wqBOVUxMOzxicj4r
wqDCoMKgwqBzdHJ1Y3TCoHp4ZGhfZ2RtYV9lbnFkZXHCoCplX2NvbnRleHTCoD3CoE5VTEw7PGJy
PivCoMKgwqDCoHVpbnQxNl90wqBxdWV1ZV9pZMKgPcKgMDs8YnI+K8KgwqDCoMKgdWludDMyX3TC
oHZhbMKgPcKgMDs8YnI+K8KgwqDCoMKgdWludDE2X3TCoHRjX2NudMKgPcKgMDs8YnI+K8KgwqDC
oMKgdWludDE2X3TCoGRpZmZfY250wqA9wqAwOzxicj4rwqDCoMKgwqB1aW50MTZfdMKgacKgPcKg
MDs8YnI+K8KgwqDCoMKgdWludDE2X3TCoGJkX2lkeMKgPcKgMDs8YnI+K8KgwqDCoMKgdWludDY0
X3TCoG5leHRfYmRfYWRkcsKgPcKgMDs8YnI+K8KgwqDCoMKgdWludDhfdMKgZGF0YV9iZF9lcnLC
oD3CoDA7PGJyPis8YnI+K8KgwqDCoMKgaWbCoCgoZGV2wqA9PcKgTlVMTCnCoHx8wqAoY29udGV4
dMKgPT3CoE5VTEwpKTxicj4rwqDCoMKgwqDCoMKgwqDCoHJldHVybsKgLUVJTlZBTDs8YnI+Kzxi
cj4rwqDCoMKgwqBlX2NvbnRleHTCoD3CoChzdHJ1Y3TCoHp4ZGhfZ2RtYV9lbnFkZXHCoCopY29u
dGV4dDs8YnI+K8KgwqDCoMKgcXVldWVfaWTCoD3CoGVfY29udGV4dC0mZ3Q7dnFfaWQ7PGJyPivC
oMKgwqDCoHF1ZXVlwqA9wqB6eGRoX2dkbWFfZ2V0X3F1ZXVlKGRldizCoHF1ZXVlX2lkKTs8YnI+
K8KgwqDCoMKgaWbCoCgocXVldWXCoD09wqBOVUxMKcKgfHzCoChxdWV1ZS0mZ3Q7ZW5hYmxlwqA9
PcKgMCkpPGJyPivCoMKgwqDCoMKgwqDCoMKgcmV0dXJuwqAtRUlOVkFMOzxicj4rPGJyPivCoMKg
wqDCoGlmwqAocXVldWUtJmd0O3N3X3JpbmcucGVuZF9jbnTCoD09wqAwKTxicj4rwqDCoMKgwqDC
oMKgwqDCoGdvdG/CoGRlcV9qb2I7PGJyPis8YnI+K8KgwqDCoMKgLyrCoEdldMKgZGF0YcKgdHJh
bnNtaXTCoGNvdW50wqAqLzxicj4rwqDCoMKgwqB2YWzCoD3CoHp4ZGhfZ2RtYV9yZWFkX3JlZyhk
ZXYswqBxdWV1ZV9pZCzCoFpYREhfR0RNQV9UQ19DTlRfT0ZGU0VUKTs8YnI+K8KgwqDCoMKgdGNf
Y250wqA9wqB2YWzCoCZhbXA7wqBMT1cxNl9NQVNLOzxicj4rwqDCoMKgwqBpZsKgKHRjX2NudMKg
Jmd0Oz3CoHF1ZXVlLSZndDt0Y19jbnQpPGJyPivCoMKgwqDCoMKgwqDCoMKgZGlmZl9jbnTCoD3C
oHRjX2NudMKgLcKgcXVldWUtJmd0O3RjX2NudDs8YnI+K8KgwqDCoMKgZWxzZTxicj4rwqDCoMKg
wqDCoMKgwqDCoGRpZmZfY250wqA9wqB0Y19jbnTCoCvCoFpYREhfR0RNQV9UQ19DTlRfTUFYwqAt
wqBxdWV1ZS0mZ3Q7dGNfY250Ozxicj4rPGJyPivCoMKgwqDCoHF1ZXVlLSZndDt0Y19jbnTCoD3C
oHRjX2NudDs8YnI+Kzxicj4rwqDCoMKgwqAvKsKgRGF0YcKgdHJhbnNtaXTCoGVycm9yLMKgY2hh
bm5lbMKgc3RvcHBlZMKgKi88YnI+K8KgwqDCoMKgaWbCoCgodmFswqAmYW1wO8KgWlhESF9HRE1B
X0VSUl9TVEFUVVMpwqAhPcKgMCnCoHs8YnI+K8KgwqDCoMKgwqDCoMKgwqBuZXh0X2JkX2FkZHLC
oMKgPcKgenhkaF9nZG1hX3JlYWRfcmVnKGRldizCoHF1ZXVlX2lkLMKgWlhESF9HRE1BX0xMSV9M
X09GRlNFVCk7PGJyPivCoMKgwqDCoMKgwqDCoMKgbmV4dF9iZF9hZGRywqB8PcKgKCh1aW50NjRf
dCl6eGRoX2dkbWFfcmVhZF9yZWcoZGV2LMKgcXVldWVfaWQsPGJyPivCoMKgwqDCoMKgwqDCoMKg
wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoFpYREhfR0RNQV9MTElfSF9P
RkZTRVQpwqAmbHQ7Jmx0O8KgMzIpOzxicj4rwqDCoMKgwqDCoMKgwqDCoG5leHRfYmRfYWRkcsKg
wqA9wqBuZXh0X2JkX2FkZHLCoCZsdDsmbHQ7wqA2Ozxicj4rwqDCoMKgwqDCoMKgwqDCoGJkX2lk
eMKgPcKgKG5leHRfYmRfYWRkcsKgLcKgcXVldWUtJmd0O3JpbmcucmluZ19tZW0pwqAvwqBzaXpl
b2Yoc3RydWN0wqB6eGRoX2dkbWFfYnVmZl9kZXNjKTs8YnI+K8KgwqDCoMKgwqDCoMKgwqBpZsKg
KCh2YWzCoCZhbXA7wqBaWERIX0dETUFfU1JDX0RBVEFfRVJSKcKgfHzCoCh2YWzCoCZhbXA7wqBa
WERIX0dETUFfRFNUX0FERFJfRVJSKSnCoHs8YnI+K8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoGRp
ZmZfY250Kys7PGJyPivCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBkYXRhX2JkX2VycsKgPcKgMTs8
YnI+K8KgwqDCoMKgwqDCoMKgwqB9PGJyPivCoMKgwqDCoMKgwqDCoMKgWlhESF9QTURfTE9HKElO
Rk8swqAmcXVvdDtxdWV1ZSVkwqBpc8KgZXJyKDB4JXgpwqBuZXh0X2JkX2lkeDoldcKgbGxfYWRk
cjoweCUmcXVvdDtQUkl4NjQmcXVvdDvCoGRlZsKgdXNlcjoweCV4JnF1b3Q7LDxicj4rwqDCoMKg
wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHF1ZXVlX2lkLMKgdmFsLMKgYmRfaWR4
LMKgbmV4dF9iZF9hZGRyLMKgcXVldWUtJmd0O3VzZXIpOzxicj4rPGJyPivCoMKgwqDCoMKgwqDC
oMKgWlhESF9QTURfTE9HKElORk8swqAmcXVvdDtDbGVhbsKgdXDCoGVycm9ywqBzdGF0dXMmcXVv
dDspOzxicj4rwqDCoMKgwqDCoMKgwqDCoHZhbMKgPcKgWlhESF9HRE1BX0VSUl9TVEFUVVPCoHzC
oFpYREhfR0RNQV9FUlJfSU5UUl9FTkFCTEU7PGJyPivCoMKgwqDCoMKgwqDCoMKgenhkaF9nZG1h
X3dyaXRlX3JlZyhkZXYswqBxdWV1ZV9pZCzCoFpYREhfR0RNQV9UQ19DTlRfT0ZGU0VULMKgdmFs
KTs8YnI+Kzxicj4rwqDCoMKgwqDCoMKgwqDCoFpYREhfUE1EX0xPRyhJTkZPLMKgJnF1b3Q7UmVz
dGFydMKgY2hhbm5lbCZxdW90Oyk7PGJyPivCoMKgwqDCoMKgwqDCoMKgenhkaF9nZG1hX3dyaXRl
X3JlZyhkZXYswqBxdWV1ZV9pZCzCoFpYREhfR0RNQV9YRkVSU0laRV9PRkZTRVQswqAwKTs8YnI+
K8KgwqDCoMKgwqDCoMKgwqB6eGRoX2dkbWFfY29udHJvbF9jYWwoJmFtcDt2YWwswqAwKTs8YnI+
K8KgwqDCoMKgwqDCoMKgwqB6eGRoX2dkbWFfd3JpdGVfcmVnKGRldizCoHF1ZXVlX2lkLMKgWlhE
SF9HRE1BX0NPTlRST0xfT0ZGU0VULMKgdmFsKTs8YnI+K8KgwqDCoMKgfTxicj4rPGJyPivCoMKg
wqDCoGlmwqAoZGlmZl9jbnTCoCE9wqAwKcKgezxicj4rwqDCoMKgwqDCoMKgwqDCoHp4ZGhfZ2Rt
YV91c2VkX2lkeF91cGRhdGUocXVldWUswqBkaWZmX2NudCzCoGRhdGFfYmRfZXJyKTs8YnI+K8Kg
wqDCoMKgwqDCoMKgwqBxdWV1ZS0mZ3Q7c3dfcmluZy5kZXFfY250wqArPcKgZGlmZl9jbnQ7PGJy
PivCoMKgwqDCoMKgwqDCoMKgcXVldWUtJmd0O3N3X3JpbmcucGVuZF9jbnTCoC09wqBkaWZmX2Nu
dDs8YnI+K8KgwqDCoMKgfTxicj4rPGJyPitkZXFfam9iOjxicj4rwqDCoMKgwqBpZsKgKHF1ZXVl
LSZndDtzd19yaW5nLmRlcV9jbnTCoD09wqAwKTxicj4rwqDCoMKgwqDCoMKgwqDCoHJldHVybsKg
MDs8YnI+K8KgwqDCoMKgZWxzZcKgaWbCoChxdWV1ZS0mZ3Q7c3dfcmluZy5kZXFfY250wqAmbHQ7
wqBjb3VudCk8YnI+K8KgwqDCoMKgwqDCoMKgwqBjb3VudMKgPcKgcXVldWUtJmd0O3N3X3Jpbmcu
ZGVxX2NudDs8YnI+Kzxicj4rwqDCoMKgwqBxdWV1ZS0mZ3Q7c3dfcmluZy5kZXFfY250wqAtPcKg
Y291bnQ7PGJyPis8YnI+K8KgwqDCoMKgZm9ywqAoacKgPcKgMDvCoGnCoCZsdDvCoGNvdW50O8Kg
aSsrKcKgezxicj4rwqDCoMKgwqDCoMKgwqDCoGVfY29udGV4dC0mZ3Q7am9iW2ldwqA9wqBxdWV1
ZS0mZ3Q7c3dfcmluZy5qb2JbcXVldWUtJmd0O3N3X3JpbmcuZGVxX2lkeF07PGJyPivCoMKgwqDC
oMKgwqDCoMKgcXVldWUtJmd0O3N3X3Jpbmcuam9iW3F1ZXVlLSZndDtzd19yaW5nLmRlcV9pZHhd
wqA9wqBOVUxMOzxicj4rwqDCoMKgwqDCoMKgwqDCoGlmwqAoKytxdWV1ZS0mZ3Q7c3dfcmluZy5k
ZXFfaWR4wqAmZ3Q7PcKgcXVldWUtJmd0O3F1ZXVlX3NpemUpPGJyPivCoMKgwqDCoMKgwqDCoMKg
wqDCoMKgwqBxdWV1ZS0mZ3Q7c3dfcmluZy5kZXFfaWR4wqAtPcKgcXVldWUtJmd0O3F1ZXVlX3Np
emU7PGJyPivCoMKgwqDCoH08YnI+K8KgwqDCoMKgcXVldWUtJmd0O3N3X3JpbmcuZnJlZV9jbnTC
oCs9wqBjb3VudDs8YnI+Kzxicj4rwqDCoMKgwqByZXR1cm7CoGNvdW50Ozxicj4rfTxicj4rPGJy
PsKgc3RhdGljwqBjb25zdMKgc3RydWN0wqBydGVfcmF3ZGV2X29wc8KgenhkaF9nZG1hX3Jhd2Rl
dl9vcHPCoD3CoHs8YnI+wqDCoMKgwqDCoC5kZXZfaW5mb19nZXTCoD3CoHp4ZGhfZ2RtYV9yYXdk
ZXZfaW5mb19nZXQsPGJyPsKgwqDCoMKgwqAuZGV2X2NvbmZpZ3VyZcKgPcKgenhkaF9nZG1hX3Jh
d2Rldl9jb25maWd1cmUsPGJyPkBAwqAtNTQwLDbCoCs2NTIsN8KgQEDCoHN0YXRpY8KgY29uc3TC
oHN0cnVjdMKgcnRlX3Jhd2Rldl9vcHPCoHp4ZGhfZ2RtYV9yYXdkZXZfb3BzwqA9wqB7PGJyPsKg
wqDCoMKgwqAuYXR0cl9nZXTCoD3CoHp4ZGhfZ2RtYV9yYXdkZXZfZ2V0X2F0dHIsPGJyPsKgDQo8
YnI+wqDCoMKgwqDCoC5lbnF1ZXVlX2J1ZnPCoD3CoHp4ZGhfZ2RtYV9yYXdkZXZfZW5xdWV1ZV9i
dWZzLDxicj4rwqDCoMKgwqAuZGVxdWV1ZV9idWZzwqA9wqB6eGRoX2dkbWFfcmF3ZGV2X2RlcXVl
dWVfYnVmcyw8YnI+wqB9Ozxicj7CoA0KPGJyPsKgc3RhdGljwqBpbnQ8YnI+LS3CoA0KPGJyPjIu
NDMuMDxicj48L2Jsb2NrcXVvdGU+PC9kaXY+DQo=
--000000000000ded3b2062486c4f9--