All of lore.kernel.org
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD
@ 2021-11-02  3:17 Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
                   ` (10 more replies)
  0 siblings, 11 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

This patch set contains refactor patches and code check patches.

Chengwen Feng (1):
  net/hns3: remove PF/VF duplicate code

Huisong Li (7):
  net/hns3: fix the shift of DMA address in Rx/Tx queue
  net/hns3: remove a redundant function declaration
  net/hns3: modifying code alignment
  net/hns3: use unsigned integer for bitwise operations
  net/hns3: extract a common file
  net/hns3: remove magic numbers
  net/hns3: fix the return value of the function

Min Hu (Connor) (1):
  net/hns3: add hns3 flow header file

 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_common.c    | 762 ++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_common.h    |  61 +++
 drivers/net/hns3/hns3_ethdev.c    | 748 +----------------------------
 drivers/net/hns3/hns3_ethdev.h    |  47 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 327 +------------
 drivers/net/hns3/hns3_fdir.h      |  31 --
 drivers/net/hns3/hns3_flow.c      |   1 +
 drivers/net/hns3/hns3_flow.h      |  44 ++
 drivers/net/hns3/hns3_intr.c      |   2 +-
 drivers/net/hns3/hns3_mbx.c       |   2 +-
 drivers/net/hns3/hns3_rxtx.c      |   8 +-
 drivers/net/hns3/hns3_rxtx.h      |   1 -
 drivers/net/hns3/hns3_tm.c        |   2 +-
 drivers/net/hns3/meson.build      |   1 +
 15 files changed, 901 insertions(+), 1138 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_common.c
 create mode 100644 drivers/net/hns3/hns3_common.h
 create mode 100644 drivers/net/hns3/hns3_flow.h

-- 
2.33.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

The patch obtains the upper 32 bits of the Rx/Tx queue DMA address in one
step instead of two steps.

Fixes: bba636698316 ("net/hns3: support Rx/Tx and related operations")

Signed-off-by: Huisong Li <lihuisong@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index ceb98025f8..00af73c850 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -322,7 +322,7 @@ hns3_init_rx_queue_hw(struct hns3_rx_queue *rxq)
 
 	hns3_write_dev(rxq, HNS3_RING_RX_BASEADDR_L_REG, (uint32_t)dma_addr);
 	hns3_write_dev(rxq, HNS3_RING_RX_BASEADDR_H_REG,
-		       (uint32_t)((dma_addr >> 31) >> 1));
+		       (uint32_t)(dma_addr >> 32));
 
 	hns3_write_dev(rxq, HNS3_RING_RX_BD_LEN_REG,
 		       hns3_buf_size2type(rx_buf_len));
@@ -337,7 +337,7 @@ hns3_init_tx_queue_hw(struct hns3_tx_queue *txq)
 
 	hns3_write_dev(txq, HNS3_RING_TX_BASEADDR_L_REG, (uint32_t)dma_addr);
 	hns3_write_dev(txq, HNS3_RING_TX_BASEADDR_H_REG,
-		       (uint32_t)((dma_addr >> 31) >> 1));
+		       (uint32_t)(dma_addr >> 32));
 
 	hns3_write_dev(txq, HNS3_RING_TX_BD_NUM_REG,
 		       HNS3_CFG_DESC_NUM(txq->nb_tx_desc));
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 2/9] net/hns3: remove a redundant function declaration
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 3/9] net/hns3: modifying code alignment Min Hu (Connor)
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

This patch removes a redundant function declaration for
hns3_rx_check_vec_support().

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index 33ee8c61a0..63bafc68b6 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -711,7 +711,6 @@ uint16_t hns3_recv_pkts_vec_sve(void *rx_queue, struct rte_mbuf **rx_pkts,
 int hns3_rx_burst_mode_get(struct rte_eth_dev *dev,
 			   __rte_unused uint16_t queue_id,
 			   struct rte_eth_burst_mode *mode);
-int hns3_rx_check_vec_support(struct rte_eth_dev *dev);
 uint16_t hns3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
 			uint16_t nb_pkts);
 uint16_t hns3_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 3/9] net/hns3: modifying code alignment
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

This patch modifies some code alignment issues to make the code style more
consistent.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 00af73c850..7e55b24cb8 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -1907,7 +1907,7 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	 */
 	if (hns->is_vf || hw->vlan_mode == HNS3_SW_SHIFT_AND_DISCARD_MODE)
 		rxq->pvid_sw_discard_en = hw->port_base_vlan_cfg.state ==
-				       HNS3_PORT_BASE_VLAN_ENABLE;
+						HNS3_PORT_BASE_VLAN_ENABLE;
 	else
 		rxq->pvid_sw_discard_en = false;
 	rxq->ptype_en = hns3_dev_get_support(hw, RXD_ADV_LAYOUT) ? true : false;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 4/9] net/hns3: use unsigned integer for bitwise operations
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (2 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 3/9] net/hns3: modifying code alignment Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 5/9] net/hns3: extract a common file Min Hu (Connor)
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

Bitwise operations should be used only with unsigned integer. This patch
modifies some code that does not meet this rule.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_ethdev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index ccae75baa0..50e73b00b7 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2104,7 +2104,7 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 	int max_tc = 0;
 	int i;
 
-	if ((rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
+	if (((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
 	    (tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
 	     tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY)) {
 		hns3_err(hw, "VMDQ is not supported, rx_mq_mode = %d, tx_mq_mode = %d.",
@@ -2114,7 +2114,7 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 
 	dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
 	dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
-	if (rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
+	if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
 		if (dcb_rx_conf->nb_tcs > pf->tc_max) {
 			hns3_err(hw, "nb_tcs(%u) > max_tc(%u) driver supported.",
 				 dcb_rx_conf->nb_tcs, pf->tc_max);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 5/9] net/hns3: extract a common file
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (3 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

This patch extracts a common file to store the common code for PF and VF
driver.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_common.c    | 427 +++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_common.h    |  48 ++++
 drivers/net/hns3/hns3_ethdev.c    | 430 +-----------------------------
 drivers/net/hns3/hns3_ethdev.h    |  30 +--
 drivers/net/hns3/hns3_ethdev_vf.c |   1 +
 drivers/net/hns3/hns3_intr.c      |   2 +-
 drivers/net/hns3/hns3_mbx.c       |   2 +-
 drivers/net/hns3/hns3_rxtx.c      |   2 +-
 drivers/net/hns3/meson.build      |   1 +
 10 files changed, 485 insertions(+), 460 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_common.c
 create mode 100644 drivers/net/hns3/hns3_common.h

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index 50769c6226..2ce59d8de6 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -5,7 +5,7 @@
 #include <ethdev_pci.h>
 #include <rte_io.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_regs.h"
 #include "hns3_intr.h"
 #include "hns3_logs.h"
diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
new file mode 100644
index 0000000000..5fe0ff5ce7
--- /dev/null
+++ b/drivers/net/hns3/hns3_common.c
@@ -0,0 +1,427 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#include <rte_kvargs.h>
+
+#include "hns3_logs.h"
+#include "hns3_common.h"
+
+static int
+hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
+{
+	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
+
+	RTE_SET_USED(key);
+
+	if (strcmp(value, "vec") == 0)
+		hint = HNS3_IO_FUNC_HINT_VEC;
+	else if (strcmp(value, "sve") == 0)
+		hint = HNS3_IO_FUNC_HINT_SVE;
+	else if (strcmp(value, "simple") == 0)
+		hint = HNS3_IO_FUNC_HINT_SIMPLE;
+	else if (strcmp(value, "common") == 0)
+		hint = HNS3_IO_FUNC_HINT_COMMON;
+
+	/* If the hint is valid then update output parameters */
+	if (hint != HNS3_IO_FUNC_HINT_NONE)
+		*(uint32_t *)extra_args = hint;
+
+	return 0;
+}
+
+static const char *
+hns3_get_io_hint_func_name(uint32_t hint)
+{
+	switch (hint) {
+	case HNS3_IO_FUNC_HINT_VEC:
+		return "vec";
+	case HNS3_IO_FUNC_HINT_SVE:
+		return "sve";
+	case HNS3_IO_FUNC_HINT_SIMPLE:
+		return "simple";
+	case HNS3_IO_FUNC_HINT_COMMON:
+		return "common";
+	default:
+		return "none";
+	}
+}
+
+static int
+hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
+{
+	uint64_t val;
+
+	RTE_SET_USED(key);
+
+	val = strtoull(value, NULL, 16);
+	*(uint64_t *)extra_args = val;
+
+	return 0;
+}
+
+static int
+hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
+{
+	uint32_t val;
+
+	RTE_SET_USED(key);
+
+	val = strtoul(value, NULL, 10);
+	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
+		*(uint16_t *)extra_args = val;
+
+	return 0;
+}
+
+void
+hns3_parse_devargs(struct rte_eth_dev *dev)
+{
+	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
+	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
+	struct hns3_hw *hw = &hns->hw;
+	uint64_t dev_caps_mask = 0;
+	struct rte_kvargs *kvlist;
+
+	if (dev->device->devargs == NULL)
+		return;
+
+	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
+	if (!kvlist)
+		return;
+
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
+			   &hns3_parse_io_hint_func, &rx_func_hint);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
+			   &hns3_parse_io_hint_func, &tx_func_hint);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
+			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
+			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
+
+	rte_kvargs_free(kvlist);
+
+	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
+		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
+			  hns3_get_io_hint_func_name(rx_func_hint));
+	hns->rx_func_hint = rx_func_hint;
+	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
+		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
+			  hns3_get_io_hint_func_name(tx_func_hint));
+	hns->tx_func_hint = tx_func_hint;
+
+	if (dev_caps_mask != 0)
+		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
+			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
+	hns->dev_caps_mask = dev_caps_mask;
+}
+
+void
+hns3_clock_gettime(struct timeval *tv)
+{
+#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
+#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
+#else
+#define CLOCK_TYPE CLOCK_MONOTONIC
+#endif
+#define NSEC_TO_USEC_DIV 1000
+
+	struct timespec spec;
+	(void)clock_gettime(CLOCK_TYPE, &spec);
+
+	tv->tv_sec = spec.tv_sec;
+	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
+}
+
+uint64_t
+hns3_clock_calctime_ms(struct timeval *tv)
+{
+	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
+		tv->tv_usec / USEC_PER_MSEC;
+}
+
+uint64_t
+hns3_clock_gettime_ms(void)
+{
+	struct timeval tv;
+
+	hns3_clock_gettime(&tv);
+	return hns3_clock_calctime_ms(&tv);
+}
+
+void hns3_ether_format_addr(char *buf, uint16_t size,
+			    const struct rte_ether_addr *ether_addr)
+{
+	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
+		ether_addr->addr_bytes[0],
+		ether_addr->addr_bytes[4],
+		ether_addr->addr_bytes[5]);
+}
+
+static int
+hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
+			   struct rte_ether_addr *mc_addr_set,
+			   uint32_t nb_mc_addr)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	uint16_t mac_addrs_capa;
+	uint32_t i;
+	uint32_t j;
+
+	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
+		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
+			 "invalid. valid range: 0~%d",
+			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
+		return -EINVAL;
+	}
+
+	/* Check if input mac addresses are valid */
+	for (i = 0; i < nb_mc_addr; i++) {
+		addr = &mc_addr_set[i];
+		if (!rte_is_multicast_ether_addr(addr)) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_err(hw,
+				 "failed to set mc mac addr, addr(%s) invalid.",
+				 mac_str);
+			return -EINVAL;
+		}
+
+		/* Check if there are duplicate addresses */
+		for (j = i + 1; j < nb_mc_addr; j++) {
+			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
+				hns3_ether_format_addr(mac_str,
+						      RTE_ETHER_ADDR_FMT_SIZE,
+						      addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. two same addrs(%s).",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * Check if there are duplicate addresses between mac_addrs
+		 * and mc_addr_set
+		 */
+		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
+					      HNS3_UC_MACADDR_NUM;
+		for (j = 0; j < mac_addrs_capa; j++) {
+			if (rte_is_same_ether_addr(addr,
+						   &hw->data->mac_addrs[j])) {
+				hns3_ether_format_addr(mac_str,
+						       RTE_ETHER_ADDR_FMT_SIZE,
+						       addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. addrs(%s) has already "
+					 "configured in mac_addr add API",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int
+hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			  struct rte_ether_addr *mc_addr_set,
+			  uint32_t nb_mc_addr)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_ether_addr *addr;
+	int cur_addr_num;
+	int set_addr_num;
+	int num;
+	int ret;
+	int i;
+
+	/* Check if input parameters are valid */
+	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
+	if (ret)
+		return ret;
+
+	rte_spinlock_lock(&hw->lock);
+	cur_addr_num = hw->mc_addrs_num;
+	for (i = 0; i < cur_addr_num; i++) {
+		num = cur_addr_num - i - 1;
+		addr = &hw->mc_addrs[num];
+		ret = hw->ops.del_mc_mac_addr(hw, addr);
+		if (ret) {
+			rte_spinlock_unlock(&hw->lock);
+			return ret;
+		}
+
+		hw->mc_addrs_num--;
+	}
+
+	set_addr_num = (int)nb_mc_addr;
+	for (i = 0; i < set_addr_num; i++) {
+		addr = &mc_addr_set[i];
+		ret = hw->ops.add_mc_mac_addr(hw, addr);
+		if (ret) {
+			rte_spinlock_unlock(&hw->lock);
+			return ret;
+		}
+
+		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
+		hw->mc_addrs_num++;
+	}
+	rte_spinlock_unlock(&hw->lock);
+
+	return 0;
+}
+
+int
+hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct hns3_hw *hw = &hns->hw;
+	struct rte_ether_addr *addr;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		if (!rte_is_multicast_ether_addr(addr))
+			continue;
+		if (del)
+			ret = hw->ops.del_mc_mac_addr(hw, addr);
+		else
+			ret = hw->ops.add_mc_mac_addr(hw, addr);
+		if (ret) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
+				 del ? "Remove" : "Restore", mac_str, ret);
+		}
+	}
+	return ret;
+}
+
+int
+hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_hw_ops *ops = &hw->ops;
+	struct rte_ether_addr *addr;
+	uint16_t mac_addrs_capa;
+	int ret = 0;
+	int i;
+
+	mac_addrs_capa =
+		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
+	for (i = 0; i < mac_addrs_capa; i++) {
+		addr = &hw->data->mac_addrs[i];
+		if (rte_is_zero_ether_addr(addr))
+			continue;
+		if (rte_is_multicast_ether_addr(addr))
+			ret = del ? ops->del_mc_mac_addr(hw, addr) :
+			      ops->add_mc_mac_addr(hw, addr);
+		else
+			ret = del ? ops->del_uc_mac_addr(hw, addr) :
+			      ops->add_uc_mac_addr(hw, addr);
+
+		if (ret) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					       addr);
+			hns3_err(hw, "failed to %s mac addr(%s) index:%d ret = %d.",
+				 del ? "remove" : "restore", mac_str, i, ret);
+		}
+	}
+
+	return ret;
+}
+
+static bool
+hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		/* Check if there are duplicate addresses in mc_addrs[] */
+		if (rte_is_same_ether_addr(addr, mc_addr)) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					       addr);
+			hns3_err(hw, "failed to add mc mac addr, same addrs"
+				 "(%s) is added by the set_mc_mac_addr_list "
+				 "API", mac_str);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int
+hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	rte_spinlock_lock(&hw->lock);
+
+	/*
+	 * In hns3 network engine adding UC and MC mac address with different
+	 * commands with firmware. We need to determine whether the input
+	 * address is a UC or a MC address to call different commands.
+	 * By the way, it is recommended calling the API function named
+	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
+	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
+	 * may affect the specifications of UC mac addresses.
+	 */
+	if (rte_is_multicast_ether_addr(mac_addr)) {
+		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
+			rte_spinlock_unlock(&hw->lock);
+			return -EINVAL;
+		}
+		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
+	} else {
+		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
+	}
+	rte_spinlock_unlock(&hw->lock);
+	if (ret) {
+		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
+			 ret);
+	}
+
+	return ret;
+}
+
+void
+hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	/* index will be checked by upper level rte interface */
+	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	rte_spinlock_lock(&hw->lock);
+
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
+	else
+		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
+	rte_spinlock_unlock(&hw->lock);
+	if (ret) {
+		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
+			 ret);
+	}
+}
+
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
new file mode 100644
index 0000000000..094a0bc5ff
--- /dev/null
+++ b/drivers/net/hns3/hns3_common.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#ifndef _HNS3_COMMON_H_
+#define _HNS3_COMMON_H_
+
+#include <sys/time.h>
+
+#include "hns3_ethdev.h"
+
+enum {
+	HNS3_IO_FUNC_HINT_NONE = 0,
+	HNS3_IO_FUNC_HINT_VEC,
+	HNS3_IO_FUNC_HINT_SVE,
+	HNS3_IO_FUNC_HINT_SIMPLE,
+	HNS3_IO_FUNC_HINT_COMMON
+};
+
+#define HNS3_DEVARG_RX_FUNC_HINT	"rx_func_hint"
+#define HNS3_DEVARG_TX_FUNC_HINT	"tx_func_hint"
+
+#define HNS3_DEVARG_DEV_CAPS_MASK	"dev_caps_mask"
+
+#define HNS3_DEVARG_MBX_TIME_LIMIT_MS	"mbx_time_limit_ms"
+
+#define MSEC_PER_SEC              1000L
+#define USEC_PER_MSEC             1000L
+
+void hns3_clock_gettime(struct timeval *tv);
+uint64_t hns3_clock_calctime_ms(struct timeval *tv);
+uint64_t hns3_clock_gettime_ms(void);
+
+void hns3_parse_devargs(struct rte_eth_dev *dev);
+
+int hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del);
+int hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del);
+int hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		      __rte_unused uint32_t idx, __rte_unused uint32_t pool);
+
+void hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx);
+int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			      struct rte_ether_addr *mc_addr_set,
+			      uint32_t nb_mc_addr);
+void hns3_ether_format_addr(char *buf, uint16_t size,
+			    const struct rte_ether_addr *ether_addr);
+
+#endif /* _HNS3_COMMON_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 50e73b00b7..2f1ecffd5a 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -6,9 +6,9 @@
 #include <rte_bus_pci.h>
 #include <ethdev_pci.h>
 #include <rte_pci.h>
-#include <rte_kvargs.h>
 
 #include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_rxtx.h"
 #include "hns3_intr.h"
@@ -105,14 +105,6 @@ static int hns3_do_stop(struct hns3_adapter *hns);
 static int hns3_check_port_speed(struct hns3_hw *hw, uint32_t link_speeds);
 static int hns3_cfg_mac_mode(struct hns3_hw *hw, bool enable);
 
-void hns3_ether_format_addr(char *buf, uint16_t size,
-			    const struct rte_ether_addr *ether_addr)
-{
-	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
-		ether_addr->addr_bytes[0],
-		ether_addr->addr_bytes[4],
-		ether_addr->addr_bytes[5]);
-}
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -1609,68 +1601,6 @@ hns3_add_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static bool
-hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct rte_ether_addr *addr;
-	int i;
-
-	for (i = 0; i < hw->mc_addrs_num; i++) {
-		addr = &hw->mc_addrs[i];
-		/* Check if there are duplicate addresses in mc_addrs[] */
-		if (rte_is_same_ether_addr(addr, mc_addr)) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					       addr);
-			hns3_err(hw, "failed to add mc mac addr, same addrs"
-				 "(%s) is added by the set_mc_mac_addr_list "
-				 "API", mac_str);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-int
-hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
-		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret;
-
-	rte_spinlock_lock(&hw->lock);
-
-	/*
-	 * In hns3 network engine adding UC and MC mac address with different
-	 * commands with firmware. We need to determine whether the input
-	 * address is a UC or a MC address to call different commands.
-	 * By the way, it is recommended calling the API function named
-	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
-	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
-	 * may affect the specifications of UC mac addresses.
-	 */
-	if (rte_is_multicast_ether_addr(mac_addr)) {
-		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
-			rte_spinlock_unlock(&hw->lock);
-			return -EINVAL;
-		}
-		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
-	} else {
-		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
-	}
-	rte_spinlock_unlock(&hw->lock);
-	if (ret) {
-		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-				      mac_addr);
-		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
-			 ret);
-	}
-
-	return ret;
-}
-
 static int
 hns3_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 {
@@ -1699,30 +1629,6 @@ hns3_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-void
-hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	/* index will be checked by upper level rte interface */
-	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret;
-
-	rte_spinlock_lock(&hw->lock);
-
-	if (rte_is_multicast_ether_addr(mac_addr))
-		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
-	else
-		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
-	rte_spinlock_unlock(&hw->lock);
-	if (ret) {
-		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-				      mac_addr);
-		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
-			 ret);
-	}
-}
-
 static int
 hns3_set_default_mac_addr(struct rte_eth_dev *dev,
 			  struct rte_ether_addr *mac_addr)
@@ -1787,41 +1693,6 @@ hns3_set_default_mac_addr(struct rte_eth_dev *dev,
 	return ret;
 }
 
-int
-hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_hw_ops *ops = &hw->ops;
-	struct rte_ether_addr *addr;
-	uint16_t mac_addrs_capa;
-	int ret = 0;
-	int i;
-
-	mac_addrs_capa =
-		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
-	for (i = 0; i < mac_addrs_capa; i++) {
-		addr = &hw->data->mac_addrs[i];
-		if (rte_is_zero_ether_addr(addr))
-			continue;
-		if (rte_is_multicast_ether_addr(addr))
-			ret = del ? ops->del_mc_mac_addr(hw, addr) :
-			      ops->add_mc_mac_addr(hw, addr);
-		else
-			ret = del ? ops->del_uc_mac_addr(hw, addr) :
-			      ops->add_uc_mac_addr(hw, addr);
-
-		if (ret) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					       addr);
-			hns3_err(hw, "failed to %s mac addr(%s) index:%d ret = %d.",
-				 del ? "remove" : "restore", mac_str, i, ret);
-		}
-	}
-
-	return ret;
-}
-
 static void
 hns3_update_desc_vfid(struct hns3_cmd_desc *desc, uint8_t vfid, bool clr)
 {
@@ -1947,150 +1818,6 @@ hns3_remove_mc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static int
-hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
-			   struct rte_ether_addr *mc_addr_set,
-			   uint32_t nb_mc_addr)
-{
-	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct rte_ether_addr *addr;
-	uint16_t mac_addrs_capa;
-	uint32_t i;
-	uint32_t j;
-
-	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
-		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
-			 "invalid. valid range: 0~%d",
-			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
-		return -EINVAL;
-	}
-
-	/* Check if input mac addresses are valid */
-	for (i = 0; i < nb_mc_addr; i++) {
-		addr = &mc_addr_set[i];
-		if (!rte_is_multicast_ether_addr(addr)) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					      addr);
-			hns3_err(hw,
-				 "failed to set mc mac addr, addr(%s) invalid.",
-				 mac_str);
-			return -EINVAL;
-		}
-
-		/* Check if there are duplicate addresses */
-		for (j = i + 1; j < nb_mc_addr; j++) {
-			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
-				hns3_ether_format_addr(mac_str,
-						      RTE_ETHER_ADDR_FMT_SIZE,
-						      addr);
-				hns3_err(hw, "failed to set mc mac addr, "
-					 "addrs invalid. two same addrs(%s).",
-					 mac_str);
-				return -EINVAL;
-			}
-		}
-
-		/*
-		 * Check if there are duplicate addresses between mac_addrs
-		 * and mc_addr_set
-		 */
-		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
-					      HNS3_UC_MACADDR_NUM;
-		for (j = 0; j < mac_addrs_capa; j++) {
-			if (rte_is_same_ether_addr(addr,
-						   &hw->data->mac_addrs[j])) {
-				hns3_ether_format_addr(mac_str,
-						       RTE_ETHER_ADDR_FMT_SIZE,
-						       addr);
-				hns3_err(hw, "failed to set mc mac addr, "
-					 "addrs invalid. addrs(%s) has already "
-					 "configured in mac_addr add API",
-					 mac_str);
-				return -EINVAL;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int
-hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			  struct rte_ether_addr *mc_addr_set,
-			  uint32_t nb_mc_addr)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_ether_addr *addr;
-	int cur_addr_num;
-	int set_addr_num;
-	int num;
-	int ret;
-	int i;
-
-	/* Check if input parameters are valid */
-	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
-	if (ret)
-		return ret;
-
-	rte_spinlock_lock(&hw->lock);
-	cur_addr_num = hw->mc_addrs_num;
-	for (i = 0; i < cur_addr_num; i++) {
-		num = cur_addr_num - i - 1;
-		addr = &hw->mc_addrs[num];
-		ret = hw->ops.del_mc_mac_addr(hw, addr);
-		if (ret) {
-			rte_spinlock_unlock(&hw->lock);
-			return ret;
-		}
-
-		hw->mc_addrs_num--;
-	}
-
-	set_addr_num = (int)nb_mc_addr;
-	for (i = 0; i < set_addr_num; i++) {
-		addr = &mc_addr_set[i];
-		ret = hw->ops.add_mc_mac_addr(hw, addr);
-		if (ret) {
-			rte_spinlock_unlock(&hw->lock);
-			return ret;
-		}
-
-		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
-		hw->mc_addrs_num++;
-	}
-	rte_spinlock_unlock(&hw->lock);
-
-	return 0;
-}
-
-int
-hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
-	struct rte_ether_addr *addr;
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < hw->mc_addrs_num; i++) {
-		addr = &hw->mc_addrs[i];
-		if (!rte_is_multicast_ether_addr(addr))
-			continue;
-		if (del)
-			ret = hw->ops.del_mc_mac_addr(hw, addr);
-		else
-			ret = hw->ops.add_mc_mac_addr(hw, addr);
-		if (ret) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					      addr);
-			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
-				 del ? "Remove" : "Restore", mac_str, ret);
-		}
-	}
-	return ret;
-}
-
 static int
 hns3_check_mq_mode(struct rte_eth_dev *dev)
 {
@@ -7110,161 +6837,6 @@ hns3_get_module_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
-void
-hns3_clock_gettime(struct timeval *tv)
-{
-#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
-#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
-#else
-#define CLOCK_TYPE CLOCK_MONOTONIC
-#endif
-#define NSEC_TO_USEC_DIV 1000
-
-	struct timespec spec;
-	(void)clock_gettime(CLOCK_TYPE, &spec);
-
-	tv->tv_sec = spec.tv_sec;
-	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
-}
-
-uint64_t
-hns3_clock_calctime_ms(struct timeval *tv)
-{
-	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
-		tv->tv_usec / USEC_PER_MSEC;
-}
-
-uint64_t
-hns3_clock_gettime_ms(void)
-{
-	struct timeval tv;
-
-	hns3_clock_gettime(&tv);
-	return hns3_clock_calctime_ms(&tv);
-}
-
-static int
-hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
-{
-	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
-
-	RTE_SET_USED(key);
-
-	if (strcmp(value, "vec") == 0)
-		hint = HNS3_IO_FUNC_HINT_VEC;
-	else if (strcmp(value, "sve") == 0)
-		hint = HNS3_IO_FUNC_HINT_SVE;
-	else if (strcmp(value, "simple") == 0)
-		hint = HNS3_IO_FUNC_HINT_SIMPLE;
-	else if (strcmp(value, "common") == 0)
-		hint = HNS3_IO_FUNC_HINT_COMMON;
-
-	/* If the hint is valid then update output parameters */
-	if (hint != HNS3_IO_FUNC_HINT_NONE)
-		*(uint32_t *)extra_args = hint;
-
-	return 0;
-}
-
-static const char *
-hns3_get_io_hint_func_name(uint32_t hint)
-{
-	switch (hint) {
-	case HNS3_IO_FUNC_HINT_VEC:
-		return "vec";
-	case HNS3_IO_FUNC_HINT_SVE:
-		return "sve";
-	case HNS3_IO_FUNC_HINT_SIMPLE:
-		return "simple";
-	case HNS3_IO_FUNC_HINT_COMMON:
-		return "common";
-	default:
-		return "none";
-	}
-}
-
-static int
-hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
-{
-	uint64_t val;
-
-	RTE_SET_USED(key);
-
-	val = strtoull(value, NULL, 16);
-	*(uint64_t *)extra_args = val;
-
-	return 0;
-}
-
-static int
-hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
-{
-	uint32_t val;
-
-	RTE_SET_USED(key);
-
-	val = strtoul(value, NULL, 10);
-
-	/*
-	 * 500ms is empirical value in process of mailbox communication. If
-	 * the delay value is set to one lower thanthe empirical value, mailbox
-	 * communication may fail.
-	 */
-	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
-		*(uint16_t *)extra_args = val;
-
-	return 0;
-}
-
-void
-hns3_parse_devargs(struct rte_eth_dev *dev)
-{
-	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
-	struct hns3_adapter *hns = dev->data->dev_private;
-	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
-	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
-	struct hns3_hw *hw = &hns->hw;
-	uint64_t dev_caps_mask = 0;
-	struct rte_kvargs *kvlist;
-
-	if (dev->device->devargs == NULL)
-		return;
-
-	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
-	if (!kvlist)
-		return;
-
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
-			   &hns3_parse_io_hint_func, &rx_func_hint);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
-			   &hns3_parse_io_hint_func, &tx_func_hint);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
-			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
-			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
-
-	rte_kvargs_free(kvlist);
-
-	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
-		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
-			  hns3_get_io_hint_func_name(rx_func_hint));
-	hns->rx_func_hint = rx_func_hint;
-	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
-		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
-			  hns3_get_io_hint_func_name(tx_func_hint));
-	hns->tx_func_hint = tx_func_hint;
-
-	if (dev_caps_mask != 0)
-		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
-			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
-	hns->dev_caps_mask = dev_caps_mask;
-
-	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
-		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
-				mbx_time_limit_ms);
-	hns->mbx_time_limit_ms = mbx_time_limit_ms;
-}
-
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index f3cc88f43e..634018c847 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -6,7 +6,6 @@
 #define _HNS3_ETHDEV_H_
 
 #include <pthread.h>
-#include <sys/time.h>
 #include <ethdev_driver.h>
 #include <rte_byteorder.h>
 #include <rte_io.h>
@@ -869,14 +868,6 @@ struct hns3_adapter {
 	struct hns3_ptype_table ptype_tbl __rte_cache_aligned;
 };
 
-enum {
-	HNS3_IO_FUNC_HINT_NONE = 0,
-	HNS3_IO_FUNC_HINT_VEC,
-	HNS3_IO_FUNC_HINT_SVE,
-	HNS3_IO_FUNC_HINT_SIMPLE,
-	HNS3_IO_FUNC_HINT_COMMON
-};
-
 #define HNS3_DEVARG_RX_FUNC_HINT	"rx_func_hint"
 #define HNS3_DEVARG_TX_FUNC_HINT	"tx_func_hint"
 
@@ -1011,13 +1002,6 @@ static inline uint32_t hns3_read_reg(void *base, uint32_t reg)
 		}							\
 	} while (0)
 
-#define MSEC_PER_SEC              1000L
-#define USEC_PER_MSEC             1000L
-
-void hns3_clock_gettime(struct timeval *tv);
-uint64_t hns3_clock_calctime_ms(struct timeval *tv);
-uint64_t hns3_clock_gettime_ms(void);
-
 static inline uint64_t
 hns3_atomic_test_bit(unsigned int nr, volatile uint64_t *addr)
 {
@@ -1047,28 +1031,20 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 	return __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED) & mask;
 }
 
+uint32_t hns3_get_speed_capa(struct hns3_hw *hw);
+
 int hns3_buffer_alloc(struct hns3_hw *hw);
 int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
 			  const struct rte_flow_ops **ops);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
-void hns3_ether_format_addr(char *buf, uint16_t size,
-			const struct rte_ether_addr *ether_addr);
 int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
 		       struct rte_eth_dev_info *info);
 void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
-void hns3_parse_devargs(struct rte_eth_dev *dev);
 void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
-int hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del);
-int hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del);
-int hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
-		__rte_unused uint32_t idx, __rte_unused uint32_t pool);
-void hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx);
-int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			struct rte_ether_addr *mc_addr_set,
-							uint32_t nb_mc_addr);
+
 int hns3_restore_ptp(struct hns3_adapter *hns);
 int hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
 				    struct rte_eth_conf *conf);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 27701a919e..d06f863249 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -10,6 +10,7 @@
 #include <rte_vfio.h>
 
 #include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_rxtx.h"
 #include "hns3_regs.h"
diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c
index 3484c76d23..66dc509086 100644
--- a/drivers/net/hns3/hns3_intr.c
+++ b/drivers/net/hns3/hns3_intr.c
@@ -8,7 +8,7 @@
 #include <rte_io.h>
 #include <rte_malloc.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_intr.h"
 #include "hns3_regs.h"
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 245652e2ed..b3563d4694 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -5,7 +5,7 @@
 #include <ethdev_driver.h>
 #include <rte_io.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_regs.h"
 #include "hns3_logs.h"
 #include "hns3_intr.h"
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 7e55b24cb8..d26e262335 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -16,7 +16,7 @@
 #include <rte_vect.h>
 #endif
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_rxtx.h"
 #include "hns3_regs.h"
 #include "hns3_logs.h"
diff --git a/drivers/net/hns3/meson.build b/drivers/net/hns3/meson.build
index a99e0dbb74..8a4c7cc100 100644
--- a/drivers/net/hns3/meson.build
+++ b/drivers/net/hns3/meson.build
@@ -29,6 +29,7 @@ sources = files(
         'hns3_mp.c',
         'hns3_tm.c',
         'hns3_ptp.c',
+        'hns3_common.c',
 )
 
 deps += ['hash']
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 6/9] net/hns3: add hns3 flow header file
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (4 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 5/9] net/hns3: extract a common file Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 7/9] net/hns3: remove magic numbers Min Hu (Connor)
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

This patch adds a hns3_flow.h to make the code easier to maintain.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_ethdev.c    |  1 +
 drivers/net/hns3/hns3_ethdev.h    |  3 +--
 drivers/net/hns3/hns3_ethdev_vf.c |  1 +
 drivers/net/hns3/hns3_fdir.h      | 31 ----------------------
 drivers/net/hns3/hns3_flow.c      |  1 +
 drivers/net/hns3/hns3_flow.h      | 44 +++++++++++++++++++++++++++++++
 6 files changed, 48 insertions(+), 33 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_flow.h

diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 2f1ecffd5a..2f4beacb87 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -15,6 +15,7 @@
 #include "hns3_regs.h"
 #include "hns3_dcb.h"
 #include "hns3_mp.h"
+#include "hns3_flow.h"
 
 #define HNS3_SERVICE_INTERVAL		1000000 /* us */
 #define HNS3_SERVICE_QUICK_INTERVAL	10
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 634018c847..a28c7c262b 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -17,6 +17,7 @@
 #include "hns3_fdir.h"
 #include "hns3_stats.h"
 #include "hns3_tm.h"
+#include "hns3_flow.h"
 
 /* Vendor ID */
 #define PCI_VENDOR_ID_HUAWEI			0x19e5
@@ -1034,8 +1035,6 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 uint32_t hns3_get_speed_capa(struct hns3_hw *hw);
 
 int hns3_buffer_alloc(struct hns3_hw *hw);
-int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
-			  const struct rte_flow_ops **ops);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index d06f863249..7e60090fd3 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -17,6 +17,7 @@
 #include "hns3_intr.h"
 #include "hns3_dcb.h"
 #include "hns3_mp.h"
+#include "hns3_flow.h"
 
 #define HNS3VF_KEEP_ALIVE_INTERVAL	2000000 /* us */
 #define HNS3VF_SERVICE_INTERVAL		1000000 /* us */
diff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h
index 3f610f7b11..f9efff3b52 100644
--- a/drivers/net/hns3/hns3_fdir.h
+++ b/drivers/net/hns3/hns3_fdir.h
@@ -5,8 +5,6 @@
 #ifndef _HNS3_FDIR_H_
 #define _HNS3_FDIR_H_
 
-#include <rte_flow.h>
-
 struct hns3_fd_key_cfg {
 	uint8_t key_sel;
 	uint8_t inner_sipv6_word_en;
@@ -124,14 +122,6 @@ struct hns3_fd_ad_data {
 	uint16_t rule_id;
 };
 
-struct hns3_flow_counter {
-	LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
-	uint32_t shared:1;   /* Share counter ID with other flow rules. */
-	uint32_t ref_cnt:31; /* Reference counter. */
-	uint16_t id;   /* Counter ID. */
-	uint64_t hits; /* Number of packets matched by the rule. */
-};
-
 #define HNS3_RULE_FLAG_FDID		0x1
 #define HNS3_RULE_FLAG_VF_ID		0x2
 #define HNS3_RULE_FLAG_COUNTER		0x4
@@ -173,21 +163,7 @@ struct hns3_fdir_rule_ele {
 	struct hns3_fdir_rule fdir_conf;
 };
 
-/* rss filter list structure */
-struct hns3_rss_conf_ele {
-	TAILQ_ENTRY(hns3_rss_conf_ele) entries;
-	struct hns3_rss_conf filter_info;
-};
-
-/* hns3_flow memory list structure */
-struct hns3_flow_mem {
-	TAILQ_ENTRY(hns3_flow_mem) entries;
-	struct rte_flow *flow;
-};
-
 TAILQ_HEAD(hns3_fdir_rule_list, hns3_fdir_rule_ele);
-TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);
-TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
 
 /*
  *  A structure used to define fields of a FDIR related info.
@@ -199,11 +175,6 @@ struct hns3_fdir_info {
 	struct hns3_fd_cfg fd_cfg;
 };
 
-struct rte_flow {
-	enum rte_filter_type filter_type;
-	void *rule;
-	uint32_t counter_id;
-};
 struct hns3_adapter;
 
 int hns3_init_fd_config(struct hns3_adapter *hns);
@@ -213,8 +184,6 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns,
 			     struct hns3_fdir_rule *rule, bool del);
 int hns3_clear_all_fdir_filter(struct hns3_adapter *hns);
 int hns3_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value);
-void hns3_flow_init(struct rte_eth_dev *dev);
-void hns3_flow_uninit(struct rte_eth_dev *dev);
 int hns3_restore_all_fdir_filter(struct hns3_adapter *hns);
 
 #endif /* _HNS3_FDIR_H_ */
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index da6918fddd..9f2f9cb6cd 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -8,6 +8,7 @@
 
 #include "hns3_ethdev.h"
 #include "hns3_logs.h"
+#include "hns3_flow.h"
 
 /* Default default keys */
 static uint8_t hns3_hash_key[] = {
diff --git a/drivers/net/hns3/hns3_flow.h b/drivers/net/hns3/hns3_flow.h
new file mode 100644
index 0000000000..2eb451b720
--- /dev/null
+++ b/drivers/net/hns3/hns3_flow.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#ifndef _HNS3_FLOW_H_
+#define _HNS3_FLOW_H_
+
+#include <rte_flow.h>
+
+struct hns3_flow_counter {
+	LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
+	uint32_t shared:1;   /* Share counter ID with other flow rules. */
+	uint32_t ref_cnt:31; /* Reference counter. */
+	uint16_t id;   /* Counter ID. */
+	uint64_t hits; /* Number of packets matched by the rule. */
+};
+
+struct rte_flow {
+	enum rte_filter_type filter_type;
+	void *rule;
+	uint32_t counter_id;
+};
+
+/* rss filter list structure */
+struct hns3_rss_conf_ele {
+	TAILQ_ENTRY(hns3_rss_conf_ele) entries;
+	struct hns3_rss_conf filter_info;
+};
+
+/* hns3_flow memory list structure */
+struct hns3_flow_mem {
+	TAILQ_ENTRY(hns3_flow_mem) entries;
+	struct rte_flow *flow;
+};
+
+TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);
+TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
+
+int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
+			  const struct rte_flow_ops **ops);
+void hns3_flow_init(struct rte_eth_dev *dev);
+void hns3_flow_uninit(struct rte_eth_dev *dev);
+
+#endif /* _HNS3_FLOW_H_ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 7/9] net/hns3: remove magic numbers
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (5 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

Removing magic numbers with macros.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c | 4 ++--
 drivers/net/hns3/hns3_common.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 5fe0ff5ce7..290999f594 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -54,7 +54,7 @@ hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
 
 	RTE_SET_USED(key);
 
-	val = strtoull(value, NULL, 16);
+	val = strtoull(value, NULL, HNS3_CONVERT_TO_HEXADECIMAL);
 	*(uint64_t *)extra_args = val;
 
 	return 0;
@@ -67,7 +67,7 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 
 	RTE_SET_USED(key);
 
-	val = strtoul(value, NULL, 10);
+	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
 		*(uint16_t *)extra_args = val;
 
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 094a0bc5ff..68f9b1b96a 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -9,6 +9,9 @@
 
 #include "hns3_ethdev.h"
 
+#define HNS3_CONVERT_TO_DECIMAL 10
+#define HNS3_CONVERT_TO_HEXADECIMAL 16
+
 enum {
 	HNS3_IO_FUNC_HINT_NONE = 0,
 	HNS3_IO_FUNC_HINT_VEC,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 8/9] net/hns3: fix the return value of the function
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (6 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 7/9] net/hns3: remove magic numbers Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Huisong Li <lihuisong@huawei.com>

Fixing the return value of the function to clear static warning.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 290999f594..974219f9bf 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -154,10 +154,10 @@ hns3_clock_gettime_ms(void)
 void hns3_ether_format_addr(char *buf, uint16_t size,
 			    const struct rte_ether_addr *ether_addr)
 {
-	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
-		ether_addr->addr_bytes[0],
-		ether_addr->addr_bytes[4],
-		ether_addr->addr_bytes[5]);
+	(void)snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
+			ether_addr->addr_bytes[0],
+			ether_addr->addr_bytes[4],
+			ether_addr->addr_bytes[5]);
 }
 
 static int
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (7 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
@ 2021-11-02  3:17 ` Min Hu (Connor)
  2021-11-04 14:55   ` Ferruh Yigit
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
  10 siblings, 1 reply; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-02  3:17 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, thomas

From: Chengwen Feng <fengchengwen@huawei.com>

This patch remove PF/VF duplicate code of:
1. get firmware version.
2. get device info.
3. rx interrupt related functions.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c    | 337 +++++++++++++++++++++++++++++-
 drivers/net/hns3/hns3_common.h    |  10 +
 drivers/net/hns3/hns3_ethdev.c    | 313 +--------------------------
 drivers/net/hns3/hns3_ethdev.h    |  14 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 325 +---------------------------
 drivers/net/hns3/hns3_tm.c        |   2 +-
 6 files changed, 361 insertions(+), 640 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 974219f9bf..c9797d839d 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -3,9 +3,153 @@
  */
 
 #include <rte_kvargs.h>
+#include <rte_bus_pci.h>
+#include <ethdev_pci.h>
+#include <rte_pci.h>
 
-#include "hns3_logs.h"
 #include "hns3_common.h"
+#include "hns3_logs.h"
+#include "hns3_regs.h"
+#include "hns3_rxtx.h"
+
+int
+hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+		    size_t fw_size)
+{
+	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint32_t version = hw->fw_version;
+	int ret;
+
+	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
+				      HNS3_FW_VERSION_BYTE3_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
+				      HNS3_FW_VERSION_BYTE2_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
+				      HNS3_FW_VERSION_BYTE1_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
+				      HNS3_FW_VERSION_BYTE0_S));
+	if (ret < 0)
+		return -EINVAL;
+
+	ret += 1; /* add the size of '\0' */
+	if (fw_size < (size_t)ret)
+		return ret;
+	else
+		return 0;
+}
+
+int
+hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
+{
+	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint16_t queue_num = hw->tqps_num;
+
+	/*
+	 * In interrupt mode, 'max_rx_queues' is set based on the number of
+	 * MSI-X interrupt resources of the hardware.
+	 */
+	if (hw->data->dev_conf.intr_conf.rxq == 1)
+		queue_num = hw->intr_tqps_num;
+
+	info->max_rx_queues = queue_num;
+	info->max_tx_queues = hw->tqps_num;
+	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
+	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
+	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
+	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
+	info->rx_offload_capa = (DEV_RX_OFFLOAD_IPV4_CKSUM |
+				 DEV_RX_OFFLOAD_TCP_CKSUM |
+				 DEV_RX_OFFLOAD_UDP_CKSUM |
+				 DEV_RX_OFFLOAD_SCTP_CKSUM |
+				 DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
+				 DEV_RX_OFFLOAD_OUTER_UDP_CKSUM |
+				 DEV_RX_OFFLOAD_SCATTER |
+				 DEV_RX_OFFLOAD_VLAN_STRIP |
+				 DEV_RX_OFFLOAD_VLAN_FILTER |
+				 DEV_RX_OFFLOAD_RSS_HASH |
+				 DEV_RX_OFFLOAD_TCP_LRO);
+	info->tx_offload_capa = (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+				 DEV_TX_OFFLOAD_IPV4_CKSUM |
+				 DEV_TX_OFFLOAD_TCP_CKSUM |
+				 DEV_TX_OFFLOAD_UDP_CKSUM |
+				 DEV_TX_OFFLOAD_SCTP_CKSUM |
+				 DEV_TX_OFFLOAD_MULTI_SEGS |
+				 DEV_TX_OFFLOAD_TCP_TSO |
+				 DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+				 DEV_TX_OFFLOAD_GRE_TNL_TSO |
+				 DEV_TX_OFFLOAD_GENEVE_TNL_TSO |
+				 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
+				 DEV_TX_OFFLOAD_VLAN_INSERT);
+
+	if (!hw->port_base_vlan_cfg.state)
+		info->tx_offload_capa |= DEV_TX_OFFLOAD_QINQ_INSERT;
+
+	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
+		info->tx_offload_capa |= DEV_TX_OFFLOAD_OUTER_UDP_CKSUM;
+
+	if (hns3_dev_get_support(hw, INDEP_TXRX))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
+	if (hns3_dev_get_support(hw, PTP))
+		info->rx_offload_capa |= DEV_RX_OFFLOAD_TIMESTAMP;
+
+	info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = HNS3_MAX_RING_DESC,
+		.nb_min = HNS3_MIN_RING_DESC,
+		.nb_align = HNS3_ALIGN_RING_DESC,
+	};
+
+	info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = HNS3_MAX_RING_DESC,
+		.nb_min = HNS3_MIN_RING_DESC,
+		.nb_align = HNS3_ALIGN_RING_DESC,
+		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
+		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
+	};
+
+	info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
+		/*
+		 * If there are no available Rx buffer descriptors, incoming
+		 * packets are always dropped by hardware based on hns3 network
+		 * engine.
+		 */
+		.rx_drop_en = 1,
+		.offloads = 0,
+	};
+	info->default_txconf = (struct rte_eth_txconf) {
+		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
+		.offloads = 0,
+	};
+
+	info->reta_size = hw->rss_ind_tbl_size;
+	info->hash_key_size = HNS3_RSS_KEY_SIZE;
+	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
+
+	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
+	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
+	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
+	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
+	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
+	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
+
+	/*
+	 * Next is the PF/VF difference section.
+	 */
+	if (!hns->is_vf) {
+		info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
+		info->rx_offload_capa |= DEV_RX_OFFLOAD_KEEP_CRC;
+		info->speed_capa = hns3_get_speed_capa(hw);
+	} else {
+		info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
+	}
+
+	return 0;
+}
 
 static int
 hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
@@ -68,6 +212,12 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 	RTE_SET_USED(key);
 
 	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
+
+	/*
+	 * 500ms is empirical value in process of mailbox communication. If
+	 * the delay value is set to one lower thanthe empirical value, mailbox
+	 * communication may fail.
+	 */
 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
 		*(uint16_t *)extra_args = val;
 
@@ -116,6 +266,11 @@ hns3_parse_devargs(struct rte_eth_dev *dev)
 		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
 			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
 	hns->dev_caps_mask = dev_caps_mask;
+
+	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
+		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
+				mbx_time_limit_ms);
+	hns->mbx_time_limit_ms = mbx_time_limit_ms;
 }
 
 void
@@ -425,3 +580,183 @@ hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
 	}
 }
 
+int
+hns3_init_ring_with_vector(struct hns3_hw *hw)
+{
+	uint16_t vec;
+	int ret;
+	int i;
+
+	/*
+	 * In hns3 network engine, vector 0 is always the misc interrupt of this
+	 * function, vector 1~N can be used respectively for the queues of the
+	 * function. Tx and Rx queues with the same number share the interrupt
+	 * vector. In the initialization clearing the all hardware mapping
+	 * relationship configurations between queues and interrupt vectors is
+	 * needed, so some error caused by the residual configurations, such as
+	 * the unexpected Tx interrupt, can be avoid.
+	 */
+	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
+	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
+		vec = vec - 1; /* the last interrupt is reserved */
+	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
+	for (i = 0; i < hw->intr_tqps_num; i++) {
+		/*
+		 * Set gap limiter/rate limiter/quanity limiter algorithm
+		 * configuration for interrupt coalesce of queue's interrupt.
+		 */
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
+		/*
+		 * QL(quantity limiter) is not used currently, just set 0 to
+		 * close it.
+		 */
+		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
+
+		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
+						    HNS3_RING_TYPE_TX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "fail to unbind TX ring(%d) with "
+					  "vector: %u, ret=%d", i, vec, ret);
+			return ret;
+		}
+
+		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
+						    HNS3_RING_TYPE_RX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "fail to unbind RX ring(%d) with "
+					  "vector: %u, ret=%d", i, vec, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int
+hns3_map_rx_interrupt(struct rte_eth_dev *dev)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
+	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
+	uint32_t intr_vector;
+	uint16_t q_id;
+	int ret;
+
+	/*
+	 * hns3 needs a separate interrupt to be used as event interrupt which
+	 * could not be shared with task queue pair, so KERNEL drivers need
+	 * support multiple interrupt vectors.
+	 */
+	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
+	    !rte_intr_cap_multiple(intr_handle))
+		return 0;
+
+	rte_intr_disable(intr_handle);
+	intr_vector = hw->used_rx_queues;
+	/* creates event fd for each intr vector when MSIX is used */
+	if (rte_intr_efd_enable(intr_handle, intr_vector))
+		return -EINVAL;
+
+	/* Allocate vector list */
+	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
+				    hw->used_rx_queues)) {
+		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
+			 hw->used_rx_queues);
+		ret = -ENOMEM;
+		goto alloc_intr_vec_error;
+	}
+
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+
+	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+		ret = hw->ops.bind_ring_with_vector(hw, vec, true,
+						    HNS3_RING_TYPE_RX, q_id);
+		if (ret)
+			goto bind_vector_error;
+
+		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
+			goto bind_vector_error;
+		/*
+		 * If there are not enough efds (e.g. not enough interrupt),
+		 * remaining queues will be bond to the last interrupt.
+		 */
+		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
+			vec++;
+	}
+	rte_intr_enable(intr_handle);
+	return 0;
+
+bind_vector_error:
+	rte_intr_vec_list_free(intr_handle);
+alloc_intr_vec_error:
+	rte_intr_efd_disable(intr_handle);
+	return ret;
+}
+
+void
+hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
+	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
+	uint16_t q_id;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return;
+
+	/* unmap the ring with vector */
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			(void)hw->ops.bind_ring_with_vector(hw, vec, false,
+							HNS3_RING_TYPE_RX,
+							q_id);
+			if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
+				vec++;
+		}
+	}
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	rte_intr_vec_list_free(intr_handle);
+}
+
+int
+hns3_restore_rx_interrupt(struct hns3_hw *hw)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	uint16_t q_id;
+	int ret;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hw->ops.bind_ring_with_vector(hw,
+				rte_intr_vec_list_index_get(intr_handle,
+								   q_id),
+				true, HNS3_RING_TYPE_RX, q_id);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
\ No newline at end of file
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 68f9b1b96a..0dbb1c0413 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -30,6 +30,11 @@ enum {
 #define MSEC_PER_SEC              1000L
 #define USEC_PER_MSEC             1000L
 
+int hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+			size_t fw_size);
+int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
+		       struct rte_eth_dev_info *info);
+
 void hns3_clock_gettime(struct timeval *tv);
 uint64_t hns3_clock_calctime_ms(struct timeval *tv);
 uint64_t hns3_clock_gettime_ms(void);
@@ -48,4 +53,9 @@ int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
 void hns3_ether_format_addr(char *buf, uint16_t size,
 			    const struct rte_ether_addr *ether_addr);
 
+int hns3_init_ring_with_vector(struct hns3_hw *hw);
+int hns3_map_rx_interrupt(struct rte_eth_dev *dev);
+void hns3_unmap_rx_interrupt(struct rte_eth_dev *dev);
+int hns3_restore_rx_interrupt(struct hns3_hw *hw);
+
 #endif /* _HNS3_COMMON_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 2f4beacb87..847e660f44 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -1929,62 +1929,6 @@ hns3_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id, bool en,
 	return 0;
 }
 
-static int
-hns3_init_ring_with_vector(struct hns3_hw *hw)
-{
-	uint16_t vec;
-	int ret;
-	int i;
-
-	/*
-	 * In hns3 network engine, vector 0 is always the misc interrupt of this
-	 * function, vector 1~N can be used respectively for the queues of the
-	 * function. Tx and Rx queues with the same number share the interrupt
-	 * vector. In the initialization clearing the all hardware mapping
-	 * relationship configurations between queues and interrupt vectors is
-	 * needed, so some error caused by the residual configurations, such as
-	 * the unexpected Tx interrupt, can be avoid.
-	 */
-	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
-	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
-		vec = vec - 1; /* the last interrupt is reserved */
-	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
-	for (i = 0; i < hw->intr_tqps_num; i++) {
-		/*
-		 * Set gap limiter/rate limiter/quanity limiter algorithm
-		 * configuration for interrupt coalesce of queue's interrupt.
-		 */
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
-		/*
-		 * QL(quantity limiter) is not used currently, just set 0 to
-		 * close it.
-		 */
-		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
-
-		ret = hns3_bind_ring_with_vector(hw, vec, false,
-						 HNS3_RING_TYPE_TX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "PF fail to unbind TX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-
-		ret = hns3_bind_ring_with_vector(hw, vec, false,
-						 HNS3_RING_TYPE_RX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "PF fail to unbind RX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3_setup_dcb(struct rte_eth_dev *dev)
 {
@@ -2255,7 +2199,7 @@ hns3_get_firber_port_speed_capa(uint32_t supported_speed)
 	return speed_capa;
 }
 
-static uint32_t
+uint32_t
 hns3_get_speed_capa(struct hns3_hw *hw)
 {
 	struct hns3_mac *mac = &hw->mac;
@@ -2274,134 +2218,6 @@ hns3_get_speed_capa(struct hns3_hw *hw)
 	return speed_capa;
 }
 
-int
-hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint16_t queue_num = hw->tqps_num;
-
-	/*
-	 * In interrupt mode, 'max_rx_queues' is set based on the number of
-	 * MSI-X interrupt resources of the hardware.
-	 */
-	if (hw->data->dev_conf.intr_conf.rxq == 1)
-		queue_num = hw->intr_tqps_num;
-
-	info->max_rx_queues = queue_num;
-	info->max_tx_queues = hw->tqps_num;
-	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
-	info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
-	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
-	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
-	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_KEEP_CRC |
-				 RTE_ETH_RX_OFFLOAD_SCATTER |
-				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
-				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
-				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
-				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
-	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
-				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
-				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
-				 hns3_txvlan_cap_get(hw));
-
-	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
-		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
-
-	if (hns3_dev_get_support(hw, INDEP_TXRX))
-		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
-				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
-
-	if (hns3_dev_get_support(hw, PTP))
-		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
-
-	info->rx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-	};
-
-	info->tx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
-		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
-	};
-
-	info->speed_capa = hns3_get_speed_capa(hw);
-	info->default_rxconf = (struct rte_eth_rxconf) {
-		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
-		/*
-		 * If there are no available Rx buffer descriptors, incoming
-		 * packets are always dropped by hardware based on hns3 network
-		 * engine.
-		 */
-		.rx_drop_en = 1,
-		.offloads = 0,
-	};
-	info->default_txconf = (struct rte_eth_txconf) {
-		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
-		.offloads = 0,
-	};
-
-	info->reta_size = hw->rss_ind_tbl_size;
-	info->hash_key_size = HNS3_RSS_KEY_SIZE;
-	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
-
-	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-
-	return 0;
-}
-
-static int
-hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
-		    size_t fw_size)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint32_t version = hw->fw_version;
-	int ret;
-
-	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
-				      HNS3_FW_VERSION_BYTE3_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
-				      HNS3_FW_VERSION_BYTE2_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
-				      HNS3_FW_VERSION_BYTE1_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
-				      HNS3_FW_VERSION_BYTE0_S));
-	if (ret < 0)
-		return -EINVAL;
-
-	ret += 1; /* add the size of '\0' */
-	if (fw_size < (size_t)ret)
-		return ret;
-	else
-		return 0;
-}
-
 static int
 hns3_update_port_link_info(struct rte_eth_dev *eth_dev)
 {
@@ -5280,98 +5096,6 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue)
 	return ret;
 }
 
-static int
-hns3_map_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint32_t intr_vector;
-	uint16_t q_id;
-	int ret;
-
-	/*
-	 * hns3 needs a separate interrupt to be used as event interrupt which
-	 * could not be shared with task queue pair, so KERNEL drivers need
-	 * support multiple interrupt vectors.
-	 */
-	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
-	    !rte_intr_cap_multiple(intr_handle))
-		return 0;
-
-	rte_intr_disable(intr_handle);
-	intr_vector = hw->used_rx_queues;
-	/* creates event fd for each intr vector when MSIX is used */
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -EINVAL;
-
-	/* Allocate vector list */
-	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
-				    hw->used_rx_queues)) {
-		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
-			 hw->used_rx_queues);
-		ret = -ENOMEM;
-		goto alloc_intr_vec_error;
-	}
-
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-
-	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-		ret = hns3_bind_ring_with_vector(hw, vec, true,
-						 HNS3_RING_TYPE_RX, q_id);
-		if (ret)
-			goto bind_vector_error;
-
-		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
-			goto bind_vector_error;
-		/*
-		 * If there are not enough efds (e.g. not enough interrupt),
-		 * remaining queues will be bond to the last interrupt.
-		 */
-		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
-			vec++;
-	}
-	rte_intr_enable(intr_handle);
-	return 0;
-
-bind_vector_error:
-	rte_intr_vec_list_free(intr_handle);
-alloc_intr_vec_error:
-	rte_intr_efd_disable(intr_handle);
-	return ret;
-}
-
-static int
-hns3_restore_rx_interrupt(struct hns3_hw *hw)
-{
-	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint16_t q_id;
-	int ret;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return 0;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			ret = hns3_bind_ring_with_vector(hw,
-				rte_intr_vec_list_index_get(intr_handle,
-								   q_id),
-				true, HNS3_RING_TYPE_RX, q_id);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
 static void
 hns3_restore_filter(struct rte_eth_dev *dev)
 {
@@ -5502,40 +5226,6 @@ hns3_do_stop(struct hns3_adapter *hns)
 	return 0;
 }
 
-static void
-hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_adapter *hns = dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t q_id;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return;
-
-	/* unmap the ring with vector */
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			(void)hns3_bind_ring_with_vector(hw, vec, false,
-							 HNS3_RING_TYPE_RX,
-							 q_id);
-			if (vec < base + rte_intr_nb_efd_get(intr_handle)
-									- 1)
-				vec++;
-		}
-	}
-	/* Clean datapath event and queue/vec mapping */
-	rte_intr_efd_disable(intr_handle);
-	rte_intr_vec_list_free(intr_handle);
-}
-
 static int
 hns3_dev_stop(struct rte_eth_dev *dev)
 {
@@ -6926,6 +6616,7 @@ hns3_init_hw_ops(struct hns3_hw *hw)
 	hw->ops.del_mc_mac_addr = hns3_remove_mc_mac_addr;
 	hw->ops.add_uc_mac_addr = hns3_add_uc_mac_addr;
 	hw->ops.del_uc_mac_addr = hns3_remove_uc_mac_addr;
+	hw->ops.bind_ring_with_vector = hns3_bind_ring_with_vector;
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index a28c7c262b..55518a913d 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -437,6 +437,9 @@ struct hns3_hw_ops {
 				struct rte_ether_addr *mac_addr);
 	int (*del_uc_mac_addr)(struct hns3_hw *hw,
 				struct rte_ether_addr *mac_addr);
+	int (*bind_ring_with_vector)(struct hns3_hw *hw, uint16_t vector_id,
+				bool en, enum hns3_ring_type queue_type,
+				uint16_t queue_id);
 };
 
 #define HNS3_INTR_MAPPING_VEC_RSV_ONE		0
@@ -1038,8 +1041,6 @@ int hns3_buffer_alloc(struct hns3_hw *hw);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
-int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
-		       struct rte_eth_dev_info *info);
 void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
 void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
@@ -1071,13 +1072,4 @@ is_reset_pending(struct hns3_adapter *hns)
 	return ret;
 }
 
-static inline uint64_t
-hns3_txvlan_cap_get(struct hns3_hw *hw)
-{
-	if (hw->port_base_vlan_cfg.state)
-		return RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
-	else
-		return RTE_ETH_TX_OFFLOAD_VLAN_INSERT | RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
-}
-
 #endif /* _HNS3_ETHDEV_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 7e60090fd3..d8a99693e0 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -422,7 +422,7 @@ hns3vf_restore_promisc(struct hns3_adapter *hns)
 }
 
 static int
-hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
+hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id,
 			     bool mmap, enum hns3_ring_type queue_type,
 			     uint16_t queue_id)
 {
@@ -434,7 +434,7 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
 	memset(&bind_msg, 0, sizeof(bind_msg));
 	code = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :
 		HNS3_MBX_UNMAP_RING_TO_VECTOR;
-	bind_msg.vector_id = vector_id;
+	bind_msg.vector_id = (uint8_t)vector_id;
 
 	if (queue_type == HNS3_RING_TYPE_RX)
 		bind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;
@@ -454,62 +454,6 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
 	return ret;
 }
 
-static int
-hns3vf_init_ring_with_vector(struct hns3_hw *hw)
-{
-	uint16_t vec;
-	int ret;
-	int i;
-
-	/*
-	 * In hns3 network engine, vector 0 is always the misc interrupt of this
-	 * function, vector 1~N can be used respectively for the queues of the
-	 * function. Tx and Rx queues with the same number share the interrupt
-	 * vector. In the initialization clearing the all hardware mapping
-	 * relationship configurations between queues and interrupt vectors is
-	 * needed, so some error caused by the residual configurations, such as
-	 * the unexpected Tx interrupt, can be avoid.
-	 */
-	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
-	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
-		vec = vec - 1; /* the last interrupt is reserved */
-	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
-	for (i = 0; i < hw->intr_tqps_num; i++) {
-		/*
-		 * Set gap limiter/rate limiter/quanity limiter algorithm
-		 * configuration for interrupt coalesce of queue's interrupt.
-		 */
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
-		/*
-		 * QL(quantity limiter) is not used currently, just set 0 to
-		 * close it.
-		 */
-		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
-
-		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
-						   HNS3_RING_TYPE_TX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "VF fail to unbind TX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-
-		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
-						   HNS3_RING_TYPE_RX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "VF fail to unbind RX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3vf_dev_configure(struct rte_eth_dev *dev)
 {
@@ -649,102 +593,6 @@ hns3vf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	return 0;
 }
 
-static int
-hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint16_t q_num = hw->tqps_num;
-
-	/*
-	 * In interrupt mode, 'max_rx_queues' is set based on the number of
-	 * MSI-X interrupt resources of the hardware.
-	 */
-	if (hw->data->dev_conf.intr_conf.rxq == 1)
-		q_num = hw->intr_tqps_num;
-
-	info->max_rx_queues = q_num;
-	info->max_tx_queues = hw->tqps_num;
-	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
-	info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
-	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
-	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
-
-	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCATTER |
-				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
-				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
-				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
-				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
-	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
-				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
-				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
-				 hns3_txvlan_cap_get(hw));
-
-	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
-		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
-
-	if (hns3_dev_get_support(hw, INDEP_TXRX))
-		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
-				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
-
-	info->rx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-	};
-
-	info->tx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
-		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
-	};
-
-	info->default_rxconf = (struct rte_eth_rxconf) {
-		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
-		/*
-		 * If there are no available Rx buffer descriptors, incoming
-		 * packets are always dropped by hardware based on hns3 network
-		 * engine.
-		 */
-		.rx_drop_en = 1,
-		.offloads = 0,
-	};
-	info->default_txconf = (struct rte_eth_txconf) {
-		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
-		.offloads = 0,
-	};
-
-	info->reta_size = hw->rss_ind_tbl_size;
-	info->hash_key_size = HNS3_RSS_KEY_SIZE;
-	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
-
-	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-
-	return 0;
-}
-
 static void
 hns3vf_clear_event_cause(struct hns3_hw *hw, uint32_t regclr)
 {
@@ -1633,7 +1481,7 @@ hns3vf_init_hardware(struct hns3_adapter *hns)
 	 * some error caused by the residual configurations, such as the
 	 * unexpected interrupt, can be avoid.
 	 */
-	ret = hns3vf_init_ring_with_vector(hw);
+	ret = hns3_init_ring_with_vector(hw);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to init ring intr vector: %d", ret);
 		goto err_init_hardware;
@@ -1820,41 +1668,6 @@ hns3vf_do_stop(struct hns3_adapter *hns)
 	return 0;
 }
 
-static void
-hns3vf_unmap_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t q_id;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return;
-
-	/* unmap the ring with vector */
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			(void)hns3vf_bind_ring_with_vector(hw, vec, false,
-							   HNS3_RING_TYPE_RX,
-							   q_id);
-			if (vec < base + rte_intr_nb_efd_get(intr_handle)
-			    - 1)
-				vec++;
-		}
-	}
-	/* Clean datapath event and queue/vec mapping */
-	rte_intr_efd_disable(intr_handle);
-
-	/* Cleanup vector list */
-	rte_intr_vec_list_free(intr_handle);
-}
-
 static int
 hns3vf_dev_stop(struct rte_eth_dev *dev)
 {
@@ -1876,7 +1689,7 @@ hns3vf_dev_stop(struct rte_eth_dev *dev)
 	if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0) {
 		hns3_stop_tqps(hw);
 		hns3vf_do_stop(hns);
-		hns3vf_unmap_rx_interrupt(dev);
+		hns3_unmap_rx_interrupt(dev);
 		hw->adapter_state = HNS3_NIC_CONFIGURED;
 	}
 	hns3_rx_scattered_reset(dev);
@@ -1917,34 +1730,6 @@ hns3vf_dev_close(struct rte_eth_dev *eth_dev)
 	return ret;
 }
 
-static int
-hns3vf_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
-		      size_t fw_size)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint32_t version = hw->fw_version;
-	int ret;
-
-	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
-				      HNS3_FW_VERSION_BYTE3_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
-				      HNS3_FW_VERSION_BYTE2_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
-				      HNS3_FW_VERSION_BYTE1_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
-				      HNS3_FW_VERSION_BYTE0_S));
-	if (ret < 0)
-		return -EINVAL;
-
-	ret += 1; /* add the size of '\0' */
-	if (fw_size < (size_t)ret)
-		return ret;
-	else
-		return 0;
-}
-
 static int
 hns3vf_dev_link_update(struct rte_eth_dev *eth_dev,
 		       __rte_unused int wait_to_complete)
@@ -2006,99 +1791,6 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 	return ret;
 }
 
-static int
-hns3vf_map_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint32_t intr_vector;
-	uint16_t q_id;
-	int ret;
-
-	/*
-	 * hns3 needs a separate interrupt to be used as event interrupt which
-	 * could not be shared with task queue pair, so KERNEL drivers need
-	 * support multiple interrupt vectors.
-	 */
-	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
-	    !rte_intr_cap_multiple(intr_handle))
-		return 0;
-
-	rte_intr_disable(intr_handle);
-	intr_vector = hw->used_rx_queues;
-	/* It creates event fd for each intr vector when MSIX is used */
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -EINVAL;
-
-	/* Allocate vector list */
-	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
-				    hw->used_rx_queues)) {
-		hns3_err(hw, "Failed to allocate %u rx_queues"
-			 " intr_vec", hw->used_rx_queues);
-		ret = -ENOMEM;
-		goto vf_alloc_intr_vec_error;
-	}
-
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-
-	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-		ret = hns3vf_bind_ring_with_vector(hw, vec, true,
-						   HNS3_RING_TYPE_RX, q_id);
-		if (ret)
-			goto vf_bind_vector_error;
-
-		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
-			goto vf_bind_vector_error;
-
-		/*
-		 * If there are not enough efds (e.g. not enough interrupt),
-		 * remaining queues will be bond to the last interrupt.
-		 */
-		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
-			vec++;
-	}
-	rte_intr_enable(intr_handle);
-	return 0;
-
-vf_bind_vector_error:
-	rte_intr_vec_list_free(intr_handle);
-vf_alloc_intr_vec_error:
-	rte_intr_efd_disable(intr_handle);
-	return ret;
-}
-
-static int
-hns3vf_restore_rx_interrupt(struct hns3_hw *hw)
-{
-	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint16_t q_id;
-	int ret;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return 0;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			ret = hns3vf_bind_ring_with_vector(hw,
-				rte_intr_vec_list_index_get(intr_handle,
-								   q_id),
-				true, HNS3_RING_TYPE_RX, q_id);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
 static void
 hns3vf_restore_filter(struct rte_eth_dev *dev)
 {
@@ -2124,7 +1816,7 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
-	ret = hns3vf_map_rx_interrupt(dev);
+	ret = hns3_map_rx_interrupt(dev);
 	if (ret)
 		goto map_rx_inter_err;
 
@@ -2441,7 +2133,7 @@ hns3vf_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_vlan_table;
 
-	ret = hns3vf_restore_rx_interrupt(hw);
+	ret = hns3_restore_rx_interrupt(hw);
 	if (ret)
 		goto err_vlan_table;
 
@@ -2615,8 +2307,8 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.xstats_reset       = hns3_dev_xstats_reset,
 	.xstats_get_by_id   = hns3_dev_xstats_get_by_id,
 	.xstats_get_names_by_id = hns3_dev_xstats_get_names_by_id,
-	.dev_infos_get      = hns3vf_dev_infos_get,
-	.fw_version_get     = hns3vf_fw_version_get,
+	.dev_infos_get      = hns3_dev_infos_get,
+	.fw_version_get     = hns3_fw_version_get,
 	.rx_queue_setup     = hns3_rx_queue_setup,
 	.tx_queue_setup     = hns3_tx_queue_setup,
 	.rx_queue_release   = hns3_dev_rx_queue_release,
@@ -2665,6 +2357,7 @@ hns3vf_init_hw_ops(struct hns3_hw *hw)
 	hw->ops.del_mc_mac_addr = hns3vf_remove_mc_mac_addr;
 	hw->ops.add_uc_mac_addr = hns3vf_add_uc_mac_addr;
 	hw->ops.del_uc_mac_addr = hns3vf_remove_uc_mac_addr;
+	hw->ops.bind_ring_with_vector = hns3vf_bind_ring_with_vector;
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_tm.c b/drivers/net/hns3/hns3_tm.c
index 44b607af7a..e1089b6bd0 100644
--- a/drivers/net/hns3/hns3_tm.c
+++ b/drivers/net/hns3/hns3_tm.c
@@ -4,7 +4,7 @@
 
 #include <rte_malloc.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_dcb.h"
 #include "hns3_logs.h"
 #include "hns3_tm.h"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
@ 2021-11-04 14:55   ` Ferruh Yigit
  2021-11-05  2:49     ` Min Hu (Connor)
  0 siblings, 1 reply; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-04 14:55 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: thomas

On 11/2/2021 3:17 AM, Min Hu (Connor) wrote:
> From: Chengwen Feng <fengchengwen@huawei.com>
> 
> This patch remove PF/VF duplicate code of:
> 1. get firmware version.
> 2. get device info.
> 3. rx interrupt related functions.
> 
> Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>

<...>

> +int
> +hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
> +{
> +	struct hns3_adapter *hns = eth_dev->data->dev_private;
> +	struct hns3_hw *hw = &hns->hw;
> +	uint16_t queue_num = hw->tqps_num;
> +
> +	/*
> +	 * In interrupt mode, 'max_rx_queues' is set based on the number of
> +	 * MSI-X interrupt resources of the hardware.
> +	 */
> +	if (hw->data->dev_conf.intr_conf.rxq == 1)
> +		queue_num = hw->intr_tqps_num;
> +
> +	info->max_rx_queues = queue_num;
> +	info->max_tx_queues = hw->tqps_num;
> +	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
> +	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
> +	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
> +	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
> +	info->rx_offload_capa = (DEV_RX_OFFLOAD_IPV4_CKSUM |
> +				 DEV_RX_OFFLOAD_TCP_CKSUM |
> +				 DEV_RX_OFFLOAD_UDP_CKSUM |
> +				 DEV_RX_OFFLOAD_SCTP_CKSUM |
> +				 DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
> +				 DEV_RX_OFFLOAD_OUTER_UDP_CKSUM |
> +				 DEV_RX_OFFLOAD_SCATTER |
> +				 DEV_RX_OFFLOAD_VLAN_STRIP |
> +				 DEV_RX_OFFLOAD_VLAN_FILTER |
> +				 DEV_RX_OFFLOAD_RSS_HASH |
> +				 DEV_RX_OFFLOAD_TCP_LRO);
> +	info->tx_offload_capa = (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
> +				 DEV_TX_OFFLOAD_IPV4_CKSUM |
> +				 DEV_TX_OFFLOAD_TCP_CKSUM |
> +				 DEV_TX_OFFLOAD_UDP_CKSUM |
> +				 DEV_TX_OFFLOAD_SCTP_CKSUM |
> +				 DEV_TX_OFFLOAD_MULTI_SEGS |
> +				 DEV_TX_OFFLOAD_TCP_TSO |
> +				 DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
> +				 DEV_TX_OFFLOAD_GRE_TNL_TSO |
> +				 DEV_TX_OFFLOAD_GENEVE_TNL_TSO |
> +				 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
> +				 DEV_TX_OFFLOAD_VLAN_INSERT);

The function changed while moving, please be aware renamed macros in upsteram.
Can you please rebase your patch on top of latest next-net?


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (8 preceding siblings ...)
  2021-11-02  3:17 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
@ 2021-11-05  2:46 ` Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
                     ` (8 more replies)
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
  10 siblings, 9 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

This patch set contains refactor patches and code check patches.

Chengwen Feng (1):
  net/hns3: remove PF/VF duplicate code

Huisong Li (7):
  net/hns3: fix the shift of DMA address in Rx/Tx queue
  net/hns3: remove a redundant function declaration
  net/hns3: modifying code alignment
  net/hns3: use unsigned integer for bitwise operations
  net/hns3: extract a common file
  net/hns3: remove magic numbers
  net/hns3: fix the return value of the function

Min Hu (Connor) (1):
  net/hns3: add hns3 flow header file
---
v2:
* rebase patch on top of latest next-net

 drivers/net/hns3.tar.gz           | Bin 0 -> 203522 bytes
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_common.c    | 763 ++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_common.h    |  61 +++
 drivers/net/hns3/hns3_ethdev.c    | 749 +----------------------------
 drivers/net/hns3/hns3_ethdev.h    |  47 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 328 +------------
 drivers/net/hns3/hns3_fdir.h      |  31 --
 drivers/net/hns3/hns3_flow.c      |   1 +
 drivers/net/hns3/hns3_flow.h      |  44 ++
 drivers/net/hns3/hns3_intr.c      |   2 +-
 drivers/net/hns3/hns3_mbx.c       |   2 +-
 drivers/net/hns3/hns3_rxtx.c      |   8 +-
 drivers/net/hns3/hns3_rxtx.h      |   1 -
 drivers/net/hns3/hns3_tm.c        |   2 +-
 drivers/net/hns3/meson.build      |   1 +
 16 files changed, 902 insertions(+), 1140 deletions(-)
 create mode 100644 drivers/net/hns3.tar.gz
 create mode 100644 drivers/net/hns3/hns3_common.c
 create mode 100644 drivers/net/hns3/hns3_common.h
 create mode 100644 drivers/net/hns3/hns3_flow.h

-- 
2.33.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05 17:03     ` Ferruh Yigit
  2021-11-05 17:05     ` Ferruh Yigit
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
                     ` (7 subsequent siblings)
  8 siblings, 2 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

The patch obtains the upper 32 bits of the Rx/Tx queue DMA address in one
step instead of two steps.

Fixes: bba636698316 ("net/hns3: support Rx/Tx and related operations")

Signed-off-by: Huisong Li <lihuisong@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index ceb98025f8..00af73c850 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -322,7 +322,7 @@ hns3_init_rx_queue_hw(struct hns3_rx_queue *rxq)
 
 	hns3_write_dev(rxq, HNS3_RING_RX_BASEADDR_L_REG, (uint32_t)dma_addr);
 	hns3_write_dev(rxq, HNS3_RING_RX_BASEADDR_H_REG,
-		       (uint32_t)((dma_addr >> 31) >> 1));
+		       (uint32_t)(dma_addr >> 32));
 
 	hns3_write_dev(rxq, HNS3_RING_RX_BD_LEN_REG,
 		       hns3_buf_size2type(rx_buf_len));
@@ -337,7 +337,7 @@ hns3_init_tx_queue_hw(struct hns3_tx_queue *txq)
 
 	hns3_write_dev(txq, HNS3_RING_TX_BASEADDR_L_REG, (uint32_t)dma_addr);
 	hns3_write_dev(txq, HNS3_RING_TX_BASEADDR_H_REG,
-		       (uint32_t)((dma_addr >> 31) >> 1));
+		       (uint32_t)(dma_addr >> 32));
 
 	hns3_write_dev(txq, HNS3_RING_TX_BD_NUM_REG,
 		       HNS3_CFG_DESC_NUM(txq->nb_tx_desc));
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 2/9] net/hns3: remove a redundant function declaration
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 3/9] net/hns3: modifying code alignment Min Hu (Connor)
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

This patch removes a redundant function declaration for
hns3_rx_check_vec_support().

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index 33ee8c61a0..63bafc68b6 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -711,7 +711,6 @@ uint16_t hns3_recv_pkts_vec_sve(void *rx_queue, struct rte_mbuf **rx_pkts,
 int hns3_rx_burst_mode_get(struct rte_eth_dev *dev,
 			   __rte_unused uint16_t queue_id,
 			   struct rte_eth_burst_mode *mode);
-int hns3_rx_check_vec_support(struct rte_eth_dev *dev);
 uint16_t hns3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
 			uint16_t nb_pkts);
 uint16_t hns3_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 3/9] net/hns3: modifying code alignment
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

This patch modifies some code alignment issues to make the code style more
consistent.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 00af73c850..7e55b24cb8 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -1907,7 +1907,7 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	 */
 	if (hns->is_vf || hw->vlan_mode == HNS3_SW_SHIFT_AND_DISCARD_MODE)
 		rxq->pvid_sw_discard_en = hw->port_base_vlan_cfg.state ==
-				       HNS3_PORT_BASE_VLAN_ENABLE;
+						HNS3_PORT_BASE_VLAN_ENABLE;
 	else
 		rxq->pvid_sw_discard_en = false;
 	rxq->ptype_en = hns3_dev_get_support(hw, RXD_ADV_LAYOUT) ? true : false;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 4/9] net/hns3: use unsigned integer for bitwise operations
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (2 preceding siblings ...)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 3/9] net/hns3: modifying code alignment Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: extract a common file Min Hu (Connor)
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

Bitwise operations should be used only with unsigned integer. This patch
modifies some code that does not meet this rule.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_ethdev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index c5543c48ef..ddf85a1705 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2104,7 +2104,7 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 	int max_tc = 0;
 	int i;
 
-	if ((rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
+	if (((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
 	    (tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
 	     tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY)) {
 		hns3_err(hw, "VMDQ is not supported, rx_mq_mode = %d, tx_mq_mode = %d.",
@@ -2114,7 +2114,7 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 
 	dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
 	dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
-	if (rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
+	if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
 		if (dcb_rx_conf->nb_tcs > pf->tc_max) {
 			hns3_err(hw, "nb_tcs(%u) > max_tc(%u) driver supported.",
 				 dcb_rx_conf->nb_tcs, pf->tc_max);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 5/9] net/hns3: extract a common file
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (3 preceding siblings ...)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05 17:11     ` Ferruh Yigit
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
                     ` (3 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

This patch extracts a common file to store the common code for PF and VF
driver.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_common.c    | 427 +++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_common.h    |  48 ++++
 drivers/net/hns3/hns3_ethdev.c    | 430 +-----------------------------
 drivers/net/hns3/hns3_ethdev.h    |  30 +--
 drivers/net/hns3/hns3_ethdev_vf.c |   1 +
 drivers/net/hns3/hns3_intr.c      |   2 +-
 drivers/net/hns3/hns3_mbx.c       |   2 +-
 drivers/net/hns3/hns3_rxtx.c      |   2 +-
 drivers/net/hns3/meson.build      |   1 +
 10 files changed, 485 insertions(+), 460 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_common.c
 create mode 100644 drivers/net/hns3/hns3_common.h

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index 50769c6226..2ce59d8de6 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -5,7 +5,7 @@
 #include <ethdev_pci.h>
 #include <rte_io.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_regs.h"
 #include "hns3_intr.h"
 #include "hns3_logs.h"
diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
new file mode 100644
index 0000000000..5fe0ff5ce7
--- /dev/null
+++ b/drivers/net/hns3/hns3_common.c
@@ -0,0 +1,427 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#include <rte_kvargs.h>
+
+#include "hns3_logs.h"
+#include "hns3_common.h"
+
+static int
+hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
+{
+	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
+
+	RTE_SET_USED(key);
+
+	if (strcmp(value, "vec") == 0)
+		hint = HNS3_IO_FUNC_HINT_VEC;
+	else if (strcmp(value, "sve") == 0)
+		hint = HNS3_IO_FUNC_HINT_SVE;
+	else if (strcmp(value, "simple") == 0)
+		hint = HNS3_IO_FUNC_HINT_SIMPLE;
+	else if (strcmp(value, "common") == 0)
+		hint = HNS3_IO_FUNC_HINT_COMMON;
+
+	/* If the hint is valid then update output parameters */
+	if (hint != HNS3_IO_FUNC_HINT_NONE)
+		*(uint32_t *)extra_args = hint;
+
+	return 0;
+}
+
+static const char *
+hns3_get_io_hint_func_name(uint32_t hint)
+{
+	switch (hint) {
+	case HNS3_IO_FUNC_HINT_VEC:
+		return "vec";
+	case HNS3_IO_FUNC_HINT_SVE:
+		return "sve";
+	case HNS3_IO_FUNC_HINT_SIMPLE:
+		return "simple";
+	case HNS3_IO_FUNC_HINT_COMMON:
+		return "common";
+	default:
+		return "none";
+	}
+}
+
+static int
+hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
+{
+	uint64_t val;
+
+	RTE_SET_USED(key);
+
+	val = strtoull(value, NULL, 16);
+	*(uint64_t *)extra_args = val;
+
+	return 0;
+}
+
+static int
+hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
+{
+	uint32_t val;
+
+	RTE_SET_USED(key);
+
+	val = strtoul(value, NULL, 10);
+	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
+		*(uint16_t *)extra_args = val;
+
+	return 0;
+}
+
+void
+hns3_parse_devargs(struct rte_eth_dev *dev)
+{
+	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
+	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
+	struct hns3_hw *hw = &hns->hw;
+	uint64_t dev_caps_mask = 0;
+	struct rte_kvargs *kvlist;
+
+	if (dev->device->devargs == NULL)
+		return;
+
+	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
+	if (!kvlist)
+		return;
+
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
+			   &hns3_parse_io_hint_func, &rx_func_hint);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
+			   &hns3_parse_io_hint_func, &tx_func_hint);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
+			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
+			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
+
+	rte_kvargs_free(kvlist);
+
+	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
+		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
+			  hns3_get_io_hint_func_name(rx_func_hint));
+	hns->rx_func_hint = rx_func_hint;
+	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
+		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
+			  hns3_get_io_hint_func_name(tx_func_hint));
+	hns->tx_func_hint = tx_func_hint;
+
+	if (dev_caps_mask != 0)
+		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
+			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
+	hns->dev_caps_mask = dev_caps_mask;
+}
+
+void
+hns3_clock_gettime(struct timeval *tv)
+{
+#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
+#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
+#else
+#define CLOCK_TYPE CLOCK_MONOTONIC
+#endif
+#define NSEC_TO_USEC_DIV 1000
+
+	struct timespec spec;
+	(void)clock_gettime(CLOCK_TYPE, &spec);
+
+	tv->tv_sec = spec.tv_sec;
+	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
+}
+
+uint64_t
+hns3_clock_calctime_ms(struct timeval *tv)
+{
+	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
+		tv->tv_usec / USEC_PER_MSEC;
+}
+
+uint64_t
+hns3_clock_gettime_ms(void)
+{
+	struct timeval tv;
+
+	hns3_clock_gettime(&tv);
+	return hns3_clock_calctime_ms(&tv);
+}
+
+void hns3_ether_format_addr(char *buf, uint16_t size,
+			    const struct rte_ether_addr *ether_addr)
+{
+	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
+		ether_addr->addr_bytes[0],
+		ether_addr->addr_bytes[4],
+		ether_addr->addr_bytes[5]);
+}
+
+static int
+hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
+			   struct rte_ether_addr *mc_addr_set,
+			   uint32_t nb_mc_addr)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	uint16_t mac_addrs_capa;
+	uint32_t i;
+	uint32_t j;
+
+	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
+		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
+			 "invalid. valid range: 0~%d",
+			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
+		return -EINVAL;
+	}
+
+	/* Check if input mac addresses are valid */
+	for (i = 0; i < nb_mc_addr; i++) {
+		addr = &mc_addr_set[i];
+		if (!rte_is_multicast_ether_addr(addr)) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_err(hw,
+				 "failed to set mc mac addr, addr(%s) invalid.",
+				 mac_str);
+			return -EINVAL;
+		}
+
+		/* Check if there are duplicate addresses */
+		for (j = i + 1; j < nb_mc_addr; j++) {
+			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
+				hns3_ether_format_addr(mac_str,
+						      RTE_ETHER_ADDR_FMT_SIZE,
+						      addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. two same addrs(%s).",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * Check if there are duplicate addresses between mac_addrs
+		 * and mc_addr_set
+		 */
+		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
+					      HNS3_UC_MACADDR_NUM;
+		for (j = 0; j < mac_addrs_capa; j++) {
+			if (rte_is_same_ether_addr(addr,
+						   &hw->data->mac_addrs[j])) {
+				hns3_ether_format_addr(mac_str,
+						       RTE_ETHER_ADDR_FMT_SIZE,
+						       addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. addrs(%s) has already "
+					 "configured in mac_addr add API",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int
+hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			  struct rte_ether_addr *mc_addr_set,
+			  uint32_t nb_mc_addr)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_ether_addr *addr;
+	int cur_addr_num;
+	int set_addr_num;
+	int num;
+	int ret;
+	int i;
+
+	/* Check if input parameters are valid */
+	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
+	if (ret)
+		return ret;
+
+	rte_spinlock_lock(&hw->lock);
+	cur_addr_num = hw->mc_addrs_num;
+	for (i = 0; i < cur_addr_num; i++) {
+		num = cur_addr_num - i - 1;
+		addr = &hw->mc_addrs[num];
+		ret = hw->ops.del_mc_mac_addr(hw, addr);
+		if (ret) {
+			rte_spinlock_unlock(&hw->lock);
+			return ret;
+		}
+
+		hw->mc_addrs_num--;
+	}
+
+	set_addr_num = (int)nb_mc_addr;
+	for (i = 0; i < set_addr_num; i++) {
+		addr = &mc_addr_set[i];
+		ret = hw->ops.add_mc_mac_addr(hw, addr);
+		if (ret) {
+			rte_spinlock_unlock(&hw->lock);
+			return ret;
+		}
+
+		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
+		hw->mc_addrs_num++;
+	}
+	rte_spinlock_unlock(&hw->lock);
+
+	return 0;
+}
+
+int
+hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct hns3_hw *hw = &hns->hw;
+	struct rte_ether_addr *addr;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		if (!rte_is_multicast_ether_addr(addr))
+			continue;
+		if (del)
+			ret = hw->ops.del_mc_mac_addr(hw, addr);
+		else
+			ret = hw->ops.add_mc_mac_addr(hw, addr);
+		if (ret) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
+				 del ? "Remove" : "Restore", mac_str, ret);
+		}
+	}
+	return ret;
+}
+
+int
+hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_hw_ops *ops = &hw->ops;
+	struct rte_ether_addr *addr;
+	uint16_t mac_addrs_capa;
+	int ret = 0;
+	int i;
+
+	mac_addrs_capa =
+		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
+	for (i = 0; i < mac_addrs_capa; i++) {
+		addr = &hw->data->mac_addrs[i];
+		if (rte_is_zero_ether_addr(addr))
+			continue;
+		if (rte_is_multicast_ether_addr(addr))
+			ret = del ? ops->del_mc_mac_addr(hw, addr) :
+			      ops->add_mc_mac_addr(hw, addr);
+		else
+			ret = del ? ops->del_uc_mac_addr(hw, addr) :
+			      ops->add_uc_mac_addr(hw, addr);
+
+		if (ret) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					       addr);
+			hns3_err(hw, "failed to %s mac addr(%s) index:%d ret = %d.",
+				 del ? "remove" : "restore", mac_str, i, ret);
+		}
+	}
+
+	return ret;
+}
+
+static bool
+hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		/* Check if there are duplicate addresses in mc_addrs[] */
+		if (rte_is_same_ether_addr(addr, mc_addr)) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					       addr);
+			hns3_err(hw, "failed to add mc mac addr, same addrs"
+				 "(%s) is added by the set_mc_mac_addr_list "
+				 "API", mac_str);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int
+hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	rte_spinlock_lock(&hw->lock);
+
+	/*
+	 * In hns3 network engine adding UC and MC mac address with different
+	 * commands with firmware. We need to determine whether the input
+	 * address is a UC or a MC address to call different commands.
+	 * By the way, it is recommended calling the API function named
+	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
+	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
+	 * may affect the specifications of UC mac addresses.
+	 */
+	if (rte_is_multicast_ether_addr(mac_addr)) {
+		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
+			rte_spinlock_unlock(&hw->lock);
+			return -EINVAL;
+		}
+		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
+	} else {
+		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
+	}
+	rte_spinlock_unlock(&hw->lock);
+	if (ret) {
+		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
+			 ret);
+	}
+
+	return ret;
+}
+
+void
+hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	/* index will be checked by upper level rte interface */
+	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	rte_spinlock_lock(&hw->lock);
+
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
+	else
+		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
+	rte_spinlock_unlock(&hw->lock);
+	if (ret) {
+		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
+			 ret);
+	}
+}
+
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
new file mode 100644
index 0000000000..094a0bc5ff
--- /dev/null
+++ b/drivers/net/hns3/hns3_common.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#ifndef _HNS3_COMMON_H_
+#define _HNS3_COMMON_H_
+
+#include <sys/time.h>
+
+#include "hns3_ethdev.h"
+
+enum {
+	HNS3_IO_FUNC_HINT_NONE = 0,
+	HNS3_IO_FUNC_HINT_VEC,
+	HNS3_IO_FUNC_HINT_SVE,
+	HNS3_IO_FUNC_HINT_SIMPLE,
+	HNS3_IO_FUNC_HINT_COMMON
+};
+
+#define HNS3_DEVARG_RX_FUNC_HINT	"rx_func_hint"
+#define HNS3_DEVARG_TX_FUNC_HINT	"tx_func_hint"
+
+#define HNS3_DEVARG_DEV_CAPS_MASK	"dev_caps_mask"
+
+#define HNS3_DEVARG_MBX_TIME_LIMIT_MS	"mbx_time_limit_ms"
+
+#define MSEC_PER_SEC              1000L
+#define USEC_PER_MSEC             1000L
+
+void hns3_clock_gettime(struct timeval *tv);
+uint64_t hns3_clock_calctime_ms(struct timeval *tv);
+uint64_t hns3_clock_gettime_ms(void);
+
+void hns3_parse_devargs(struct rte_eth_dev *dev);
+
+int hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del);
+int hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del);
+int hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		      __rte_unused uint32_t idx, __rte_unused uint32_t pool);
+
+void hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx);
+int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			      struct rte_ether_addr *mc_addr_set,
+			      uint32_t nb_mc_addr);
+void hns3_ether_format_addr(char *buf, uint16_t size,
+			    const struct rte_ether_addr *ether_addr);
+
+#endif /* _HNS3_COMMON_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index ddf85a1705..2ddd29515a 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -6,9 +6,9 @@
 #include <rte_bus_pci.h>
 #include <ethdev_pci.h>
 #include <rte_pci.h>
-#include <rte_kvargs.h>
 
 #include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_rxtx.h"
 #include "hns3_intr.h"
@@ -105,14 +105,6 @@ static int hns3_do_stop(struct hns3_adapter *hns);
 static int hns3_check_port_speed(struct hns3_hw *hw, uint32_t link_speeds);
 static int hns3_cfg_mac_mode(struct hns3_hw *hw, bool enable);
 
-void hns3_ether_format_addr(char *buf, uint16_t size,
-			    const struct rte_ether_addr *ether_addr)
-{
-	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
-		ether_addr->addr_bytes[0],
-		ether_addr->addr_bytes[4],
-		ether_addr->addr_bytes[5]);
-}
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -1609,68 +1601,6 @@ hns3_add_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static bool
-hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct rte_ether_addr *addr;
-	int i;
-
-	for (i = 0; i < hw->mc_addrs_num; i++) {
-		addr = &hw->mc_addrs[i];
-		/* Check if there are duplicate addresses in mc_addrs[] */
-		if (rte_is_same_ether_addr(addr, mc_addr)) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					       addr);
-			hns3_err(hw, "failed to add mc mac addr, same addrs"
-				 "(%s) is added by the set_mc_mac_addr_list "
-				 "API", mac_str);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-int
-hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
-		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret;
-
-	rte_spinlock_lock(&hw->lock);
-
-	/*
-	 * In hns3 network engine adding UC and MC mac address with different
-	 * commands with firmware. We need to determine whether the input
-	 * address is a UC or a MC address to call different commands.
-	 * By the way, it is recommended calling the API function named
-	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
-	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
-	 * may affect the specifications of UC mac addresses.
-	 */
-	if (rte_is_multicast_ether_addr(mac_addr)) {
-		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
-			rte_spinlock_unlock(&hw->lock);
-			return -EINVAL;
-		}
-		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
-	} else {
-		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
-	}
-	rte_spinlock_unlock(&hw->lock);
-	if (ret) {
-		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-				      mac_addr);
-		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
-			 ret);
-	}
-
-	return ret;
-}
-
 static int
 hns3_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 {
@@ -1699,30 +1629,6 @@ hns3_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-void
-hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	/* index will be checked by upper level rte interface */
-	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret;
-
-	rte_spinlock_lock(&hw->lock);
-
-	if (rte_is_multicast_ether_addr(mac_addr))
-		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
-	else
-		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
-	rte_spinlock_unlock(&hw->lock);
-	if (ret) {
-		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-				      mac_addr);
-		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
-			 ret);
-	}
-}
-
 static int
 hns3_set_default_mac_addr(struct rte_eth_dev *dev,
 			  struct rte_ether_addr *mac_addr)
@@ -1787,41 +1693,6 @@ hns3_set_default_mac_addr(struct rte_eth_dev *dev,
 	return ret;
 }
 
-int
-hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_hw_ops *ops = &hw->ops;
-	struct rte_ether_addr *addr;
-	uint16_t mac_addrs_capa;
-	int ret = 0;
-	int i;
-
-	mac_addrs_capa =
-		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
-	for (i = 0; i < mac_addrs_capa; i++) {
-		addr = &hw->data->mac_addrs[i];
-		if (rte_is_zero_ether_addr(addr))
-			continue;
-		if (rte_is_multicast_ether_addr(addr))
-			ret = del ? ops->del_mc_mac_addr(hw, addr) :
-			      ops->add_mc_mac_addr(hw, addr);
-		else
-			ret = del ? ops->del_uc_mac_addr(hw, addr) :
-			      ops->add_uc_mac_addr(hw, addr);
-
-		if (ret) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					       addr);
-			hns3_err(hw, "failed to %s mac addr(%s) index:%d ret = %d.",
-				 del ? "remove" : "restore", mac_str, i, ret);
-		}
-	}
-
-	return ret;
-}
-
 static void
 hns3_update_desc_vfid(struct hns3_cmd_desc *desc, uint8_t vfid, bool clr)
 {
@@ -1947,150 +1818,6 @@ hns3_remove_mc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static int
-hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
-			   struct rte_ether_addr *mc_addr_set,
-			   uint32_t nb_mc_addr)
-{
-	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct rte_ether_addr *addr;
-	uint16_t mac_addrs_capa;
-	uint32_t i;
-	uint32_t j;
-
-	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
-		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
-			 "invalid. valid range: 0~%d",
-			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
-		return -EINVAL;
-	}
-
-	/* Check if input mac addresses are valid */
-	for (i = 0; i < nb_mc_addr; i++) {
-		addr = &mc_addr_set[i];
-		if (!rte_is_multicast_ether_addr(addr)) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					      addr);
-			hns3_err(hw,
-				 "failed to set mc mac addr, addr(%s) invalid.",
-				 mac_str);
-			return -EINVAL;
-		}
-
-		/* Check if there are duplicate addresses */
-		for (j = i + 1; j < nb_mc_addr; j++) {
-			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
-				hns3_ether_format_addr(mac_str,
-						      RTE_ETHER_ADDR_FMT_SIZE,
-						      addr);
-				hns3_err(hw, "failed to set mc mac addr, "
-					 "addrs invalid. two same addrs(%s).",
-					 mac_str);
-				return -EINVAL;
-			}
-		}
-
-		/*
-		 * Check if there are duplicate addresses between mac_addrs
-		 * and mc_addr_set
-		 */
-		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
-					      HNS3_UC_MACADDR_NUM;
-		for (j = 0; j < mac_addrs_capa; j++) {
-			if (rte_is_same_ether_addr(addr,
-						   &hw->data->mac_addrs[j])) {
-				hns3_ether_format_addr(mac_str,
-						       RTE_ETHER_ADDR_FMT_SIZE,
-						       addr);
-				hns3_err(hw, "failed to set mc mac addr, "
-					 "addrs invalid. addrs(%s) has already "
-					 "configured in mac_addr add API",
-					 mac_str);
-				return -EINVAL;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int
-hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			  struct rte_ether_addr *mc_addr_set,
-			  uint32_t nb_mc_addr)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_ether_addr *addr;
-	int cur_addr_num;
-	int set_addr_num;
-	int num;
-	int ret;
-	int i;
-
-	/* Check if input parameters are valid */
-	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
-	if (ret)
-		return ret;
-
-	rte_spinlock_lock(&hw->lock);
-	cur_addr_num = hw->mc_addrs_num;
-	for (i = 0; i < cur_addr_num; i++) {
-		num = cur_addr_num - i - 1;
-		addr = &hw->mc_addrs[num];
-		ret = hw->ops.del_mc_mac_addr(hw, addr);
-		if (ret) {
-			rte_spinlock_unlock(&hw->lock);
-			return ret;
-		}
-
-		hw->mc_addrs_num--;
-	}
-
-	set_addr_num = (int)nb_mc_addr;
-	for (i = 0; i < set_addr_num; i++) {
-		addr = &mc_addr_set[i];
-		ret = hw->ops.add_mc_mac_addr(hw, addr);
-		if (ret) {
-			rte_spinlock_unlock(&hw->lock);
-			return ret;
-		}
-
-		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
-		hw->mc_addrs_num++;
-	}
-	rte_spinlock_unlock(&hw->lock);
-
-	return 0;
-}
-
-int
-hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
-	struct rte_ether_addr *addr;
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < hw->mc_addrs_num; i++) {
-		addr = &hw->mc_addrs[i];
-		if (!rte_is_multicast_ether_addr(addr))
-			continue;
-		if (del)
-			ret = hw->ops.del_mc_mac_addr(hw, addr);
-		else
-			ret = hw->ops.add_mc_mac_addr(hw, addr);
-		if (ret) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					      addr);
-			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
-				 del ? "Remove" : "Restore", mac_str, ret);
-		}
-	}
-	return ret;
-}
-
 static int
 hns3_check_mq_mode(struct rte_eth_dev *dev)
 {
@@ -7111,161 +6838,6 @@ hns3_get_module_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
-void
-hns3_clock_gettime(struct timeval *tv)
-{
-#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
-#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
-#else
-#define CLOCK_TYPE CLOCK_MONOTONIC
-#endif
-#define NSEC_TO_USEC_DIV 1000
-
-	struct timespec spec;
-	(void)clock_gettime(CLOCK_TYPE, &spec);
-
-	tv->tv_sec = spec.tv_sec;
-	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
-}
-
-uint64_t
-hns3_clock_calctime_ms(struct timeval *tv)
-{
-	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
-		tv->tv_usec / USEC_PER_MSEC;
-}
-
-uint64_t
-hns3_clock_gettime_ms(void)
-{
-	struct timeval tv;
-
-	hns3_clock_gettime(&tv);
-	return hns3_clock_calctime_ms(&tv);
-}
-
-static int
-hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
-{
-	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
-
-	RTE_SET_USED(key);
-
-	if (strcmp(value, "vec") == 0)
-		hint = HNS3_IO_FUNC_HINT_VEC;
-	else if (strcmp(value, "sve") == 0)
-		hint = HNS3_IO_FUNC_HINT_SVE;
-	else if (strcmp(value, "simple") == 0)
-		hint = HNS3_IO_FUNC_HINT_SIMPLE;
-	else if (strcmp(value, "common") == 0)
-		hint = HNS3_IO_FUNC_HINT_COMMON;
-
-	/* If the hint is valid then update output parameters */
-	if (hint != HNS3_IO_FUNC_HINT_NONE)
-		*(uint32_t *)extra_args = hint;
-
-	return 0;
-}
-
-static const char *
-hns3_get_io_hint_func_name(uint32_t hint)
-{
-	switch (hint) {
-	case HNS3_IO_FUNC_HINT_VEC:
-		return "vec";
-	case HNS3_IO_FUNC_HINT_SVE:
-		return "sve";
-	case HNS3_IO_FUNC_HINT_SIMPLE:
-		return "simple";
-	case HNS3_IO_FUNC_HINT_COMMON:
-		return "common";
-	default:
-		return "none";
-	}
-}
-
-static int
-hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
-{
-	uint64_t val;
-
-	RTE_SET_USED(key);
-
-	val = strtoull(value, NULL, 16);
-	*(uint64_t *)extra_args = val;
-
-	return 0;
-}
-
-static int
-hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
-{
-	uint32_t val;
-
-	RTE_SET_USED(key);
-
-	val = strtoul(value, NULL, 10);
-
-	/*
-	 * 500ms is empirical value in process of mailbox communication. If
-	 * the delay value is set to one lower thanthe empirical value, mailbox
-	 * communication may fail.
-	 */
-	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
-		*(uint16_t *)extra_args = val;
-
-	return 0;
-}
-
-void
-hns3_parse_devargs(struct rte_eth_dev *dev)
-{
-	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
-	struct hns3_adapter *hns = dev->data->dev_private;
-	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
-	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
-	struct hns3_hw *hw = &hns->hw;
-	uint64_t dev_caps_mask = 0;
-	struct rte_kvargs *kvlist;
-
-	if (dev->device->devargs == NULL)
-		return;
-
-	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
-	if (!kvlist)
-		return;
-
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
-			   &hns3_parse_io_hint_func, &rx_func_hint);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
-			   &hns3_parse_io_hint_func, &tx_func_hint);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
-			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
-			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
-
-	rte_kvargs_free(kvlist);
-
-	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
-		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
-			  hns3_get_io_hint_func_name(rx_func_hint));
-	hns->rx_func_hint = rx_func_hint;
-	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
-		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
-			  hns3_get_io_hint_func_name(tx_func_hint));
-	hns->tx_func_hint = tx_func_hint;
-
-	if (dev_caps_mask != 0)
-		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
-			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
-	hns->dev_caps_mask = dev_caps_mask;
-
-	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
-		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
-				mbx_time_limit_ms);
-	hns->mbx_time_limit_ms = mbx_time_limit_ms;
-}
-
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index f3cc88f43e..634018c847 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -6,7 +6,6 @@
 #define _HNS3_ETHDEV_H_
 
 #include <pthread.h>
-#include <sys/time.h>
 #include <ethdev_driver.h>
 #include <rte_byteorder.h>
 #include <rte_io.h>
@@ -869,14 +868,6 @@ struct hns3_adapter {
 	struct hns3_ptype_table ptype_tbl __rte_cache_aligned;
 };
 
-enum {
-	HNS3_IO_FUNC_HINT_NONE = 0,
-	HNS3_IO_FUNC_HINT_VEC,
-	HNS3_IO_FUNC_HINT_SVE,
-	HNS3_IO_FUNC_HINT_SIMPLE,
-	HNS3_IO_FUNC_HINT_COMMON
-};
-
 #define HNS3_DEVARG_RX_FUNC_HINT	"rx_func_hint"
 #define HNS3_DEVARG_TX_FUNC_HINT	"tx_func_hint"
 
@@ -1011,13 +1002,6 @@ static inline uint32_t hns3_read_reg(void *base, uint32_t reg)
 		}							\
 	} while (0)
 
-#define MSEC_PER_SEC              1000L
-#define USEC_PER_MSEC             1000L
-
-void hns3_clock_gettime(struct timeval *tv);
-uint64_t hns3_clock_calctime_ms(struct timeval *tv);
-uint64_t hns3_clock_gettime_ms(void);
-
 static inline uint64_t
 hns3_atomic_test_bit(unsigned int nr, volatile uint64_t *addr)
 {
@@ -1047,28 +1031,20 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 	return __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED) & mask;
 }
 
+uint32_t hns3_get_speed_capa(struct hns3_hw *hw);
+
 int hns3_buffer_alloc(struct hns3_hw *hw);
 int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
 			  const struct rte_flow_ops **ops);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
-void hns3_ether_format_addr(char *buf, uint16_t size,
-			const struct rte_ether_addr *ether_addr);
 int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
 		       struct rte_eth_dev_info *info);
 void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
-void hns3_parse_devargs(struct rte_eth_dev *dev);
 void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
-int hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del);
-int hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del);
-int hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
-		__rte_unused uint32_t idx, __rte_unused uint32_t pool);
-void hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx);
-int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			struct rte_ether_addr *mc_addr_set,
-							uint32_t nb_mc_addr);
+
 int hns3_restore_ptp(struct hns3_adapter *hns);
 int hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
 				    struct rte_eth_conf *conf);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 242ccf7f9f..1df8966cea 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -10,6 +10,7 @@
 #include <rte_vfio.h>
 
 #include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_rxtx.h"
 #include "hns3_regs.h"
diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c
index 3484c76d23..66dc509086 100644
--- a/drivers/net/hns3/hns3_intr.c
+++ b/drivers/net/hns3/hns3_intr.c
@@ -8,7 +8,7 @@
 #include <rte_io.h>
 #include <rte_malloc.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_intr.h"
 #include "hns3_regs.h"
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 245652e2ed..b3563d4694 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -5,7 +5,7 @@
 #include <ethdev_driver.h>
 #include <rte_io.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_regs.h"
 #include "hns3_logs.h"
 #include "hns3_intr.h"
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 7e55b24cb8..d26e262335 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -16,7 +16,7 @@
 #include <rte_vect.h>
 #endif
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_rxtx.h"
 #include "hns3_regs.h"
 #include "hns3_logs.h"
diff --git a/drivers/net/hns3/meson.build b/drivers/net/hns3/meson.build
index a99e0dbb74..8a4c7cc100 100644
--- a/drivers/net/hns3/meson.build
+++ b/drivers/net/hns3/meson.build
@@ -29,6 +29,7 @@ sources = files(
         'hns3_mp.c',
         'hns3_tm.c',
         'hns3_ptp.c',
+        'hns3_common.c',
 )
 
 deps += ['hash']
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 6/9] net/hns3: add hns3 flow header file
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (4 preceding siblings ...)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: extract a common file Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: remove magic numbers Min Hu (Connor)
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

This patch adds a hns3_flow.h to make the code easier to maintain.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_ethdev.c    |  1 +
 drivers/net/hns3/hns3_ethdev.h    |  3 +--
 drivers/net/hns3/hns3_ethdev_vf.c |  1 +
 drivers/net/hns3/hns3_fdir.h      | 31 ----------------------
 drivers/net/hns3/hns3_flow.c      |  1 +
 drivers/net/hns3/hns3_flow.h      | 44 +++++++++++++++++++++++++++++++
 6 files changed, 48 insertions(+), 33 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_flow.h

diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 2ddd29515a..181694bf8c 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -15,6 +15,7 @@
 #include "hns3_regs.h"
 #include "hns3_dcb.h"
 #include "hns3_mp.h"
+#include "hns3_flow.h"
 
 #define HNS3_SERVICE_INTERVAL		1000000 /* us */
 #define HNS3_SERVICE_QUICK_INTERVAL	10
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 634018c847..a28c7c262b 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -17,6 +17,7 @@
 #include "hns3_fdir.h"
 #include "hns3_stats.h"
 #include "hns3_tm.h"
+#include "hns3_flow.h"
 
 /* Vendor ID */
 #define PCI_VENDOR_ID_HUAWEI			0x19e5
@@ -1034,8 +1035,6 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 uint32_t hns3_get_speed_capa(struct hns3_hw *hw);
 
 int hns3_buffer_alloc(struct hns3_hw *hw);
-int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
-			  const struct rte_flow_ops **ops);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 1df8966cea..8632c8f19b 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -17,6 +17,7 @@
 #include "hns3_intr.h"
 #include "hns3_dcb.h"
 #include "hns3_mp.h"
+#include "hns3_flow.h"
 
 #define HNS3VF_KEEP_ALIVE_INTERVAL	2000000 /* us */
 #define HNS3VF_SERVICE_INTERVAL		1000000 /* us */
diff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h
index 3f610f7b11..f9efff3b52 100644
--- a/drivers/net/hns3/hns3_fdir.h
+++ b/drivers/net/hns3/hns3_fdir.h
@@ -5,8 +5,6 @@
 #ifndef _HNS3_FDIR_H_
 #define _HNS3_FDIR_H_
 
-#include <rte_flow.h>
-
 struct hns3_fd_key_cfg {
 	uint8_t key_sel;
 	uint8_t inner_sipv6_word_en;
@@ -124,14 +122,6 @@ struct hns3_fd_ad_data {
 	uint16_t rule_id;
 };
 
-struct hns3_flow_counter {
-	LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
-	uint32_t shared:1;   /* Share counter ID with other flow rules. */
-	uint32_t ref_cnt:31; /* Reference counter. */
-	uint16_t id;   /* Counter ID. */
-	uint64_t hits; /* Number of packets matched by the rule. */
-};
-
 #define HNS3_RULE_FLAG_FDID		0x1
 #define HNS3_RULE_FLAG_VF_ID		0x2
 #define HNS3_RULE_FLAG_COUNTER		0x4
@@ -173,21 +163,7 @@ struct hns3_fdir_rule_ele {
 	struct hns3_fdir_rule fdir_conf;
 };
 
-/* rss filter list structure */
-struct hns3_rss_conf_ele {
-	TAILQ_ENTRY(hns3_rss_conf_ele) entries;
-	struct hns3_rss_conf filter_info;
-};
-
-/* hns3_flow memory list structure */
-struct hns3_flow_mem {
-	TAILQ_ENTRY(hns3_flow_mem) entries;
-	struct rte_flow *flow;
-};
-
 TAILQ_HEAD(hns3_fdir_rule_list, hns3_fdir_rule_ele);
-TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);
-TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
 
 /*
  *  A structure used to define fields of a FDIR related info.
@@ -199,11 +175,6 @@ struct hns3_fdir_info {
 	struct hns3_fd_cfg fd_cfg;
 };
 
-struct rte_flow {
-	enum rte_filter_type filter_type;
-	void *rule;
-	uint32_t counter_id;
-};
 struct hns3_adapter;
 
 int hns3_init_fd_config(struct hns3_adapter *hns);
@@ -213,8 +184,6 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns,
 			     struct hns3_fdir_rule *rule, bool del);
 int hns3_clear_all_fdir_filter(struct hns3_adapter *hns);
 int hns3_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value);
-void hns3_flow_init(struct rte_eth_dev *dev);
-void hns3_flow_uninit(struct rte_eth_dev *dev);
 int hns3_restore_all_fdir_filter(struct hns3_adapter *hns);
 
 #endif /* _HNS3_FDIR_H_ */
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index da6918fddd..9f2f9cb6cd 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -8,6 +8,7 @@
 
 #include "hns3_ethdev.h"
 #include "hns3_logs.h"
+#include "hns3_flow.h"
 
 /* Default default keys */
 static uint8_t hns3_hash_key[] = {
diff --git a/drivers/net/hns3/hns3_flow.h b/drivers/net/hns3/hns3_flow.h
new file mode 100644
index 0000000000..2eb451b720
--- /dev/null
+++ b/drivers/net/hns3/hns3_flow.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#ifndef _HNS3_FLOW_H_
+#define _HNS3_FLOW_H_
+
+#include <rte_flow.h>
+
+struct hns3_flow_counter {
+	LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
+	uint32_t shared:1;   /* Share counter ID with other flow rules. */
+	uint32_t ref_cnt:31; /* Reference counter. */
+	uint16_t id;   /* Counter ID. */
+	uint64_t hits; /* Number of packets matched by the rule. */
+};
+
+struct rte_flow {
+	enum rte_filter_type filter_type;
+	void *rule;
+	uint32_t counter_id;
+};
+
+/* rss filter list structure */
+struct hns3_rss_conf_ele {
+	TAILQ_ENTRY(hns3_rss_conf_ele) entries;
+	struct hns3_rss_conf filter_info;
+};
+
+/* hns3_flow memory list structure */
+struct hns3_flow_mem {
+	TAILQ_ENTRY(hns3_flow_mem) entries;
+	struct rte_flow *flow;
+};
+
+TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);
+TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
+
+int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
+			  const struct rte_flow_ops **ops);
+void hns3_flow_init(struct rte_eth_dev *dev);
+void hns3_flow_uninit(struct rte_eth_dev *dev);
+
+#endif /* _HNS3_FLOW_H_ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 7/9] net/hns3: remove magic numbers
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (5 preceding siblings ...)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
  8 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

Removing magic numbers with macros.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c | 4 ++--
 drivers/net/hns3/hns3_common.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 5fe0ff5ce7..290999f594 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -54,7 +54,7 @@ hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
 
 	RTE_SET_USED(key);
 
-	val = strtoull(value, NULL, 16);
+	val = strtoull(value, NULL, HNS3_CONVERT_TO_HEXADECIMAL);
 	*(uint64_t *)extra_args = val;
 
 	return 0;
@@ -67,7 +67,7 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 
 	RTE_SET_USED(key);
 
-	val = strtoul(value, NULL, 10);
+	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
 		*(uint16_t *)extra_args = val;
 
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 094a0bc5ff..68f9b1b96a 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -9,6 +9,9 @@
 
 #include "hns3_ethdev.h"
 
+#define HNS3_CONVERT_TO_DECIMAL 10
+#define HNS3_CONVERT_TO_HEXADECIMAL 16
+
 enum {
 	HNS3_IO_FUNC_HINT_NONE = 0,
 	HNS3_IO_FUNC_HINT_VEC,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 8/9] net/hns3: fix the return value of the function
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (6 preceding siblings ...)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: remove magic numbers Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05 17:04     ` Ferruh Yigit
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
  8 siblings, 1 reply; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

Fixing the return value of the function to clear static warning.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 290999f594..974219f9bf 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -154,10 +154,10 @@ hns3_clock_gettime_ms(void)
 void hns3_ether_format_addr(char *buf, uint16_t size,
 			    const struct rte_ether_addr *ether_addr)
 {
-	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
-		ether_addr->addr_bytes[0],
-		ether_addr->addr_bytes[4],
-		ether_addr->addr_bytes[5]);
+	(void)snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
+			ether_addr->addr_bytes[0],
+			ether_addr->addr_bytes[4],
+			ether_addr->addr_bytes[5]);
 }
 
 static int
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v2 9/9] net/hns3: remove PF/VF duplicate code
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (7 preceding siblings ...)
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
@ 2021-11-05  2:46   ` Min Hu (Connor)
  2021-11-05 17:02     ` Ferruh Yigit
  8 siblings, 1 reply; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:46 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Chengwen Feng <fengchengwen@huawei.com>

This patch remove PF/VF duplicate code of:
1. get firmware version.
2. get device info.
3. rx interrupt related functions.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3.tar.gz           | Bin 0 -> 203522 bytes
 drivers/net/hns3/hns3_common.c    | 338 +++++++++++++++++++++++++++++-
 drivers/net/hns3/hns3_common.h    |  10 +
 drivers/net/hns3/hns3_ethdev.c    | 314 +--------------------------
 drivers/net/hns3/hns3_ethdev.h    |  14 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 326 +---------------------------
 drivers/net/hns3/hns3_tm.c        |   2 +-
 7 files changed, 362 insertions(+), 642 deletions(-)
 create mode 100644 drivers/net/hns3.tar.gz

diff --git a/drivers/net/hns3.tar.gz b/drivers/net/hns3.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..af70a374b11a9054947c9c09210f25dd39b54fe2
GIT binary patch
literal 203522
zcmV(#K;*w4iwFSmfP`TH1LRy=Z`(++o>%2p5ZISVkYq$kmgLQu1JD#D5z#Fq<v7O}
zG#H7BiRc!Qa-3c4{`RfvW>bBmoB_@}92^ITE!J1nUDda$>Y^TYdF!`d{@R}={B*ll
z@Y`v1n$7aJO`n%Pzu0Z~XE&QI8|Zek+iLw{UH!%VqCcm+NRF2E%fo4#?JnS+qyHcM
zdBE|<|HyK?di(H~w1ETM>9lLczuUCCEjs>9m;mjz1LN;>oaQf9^DpU*^7H?E{C|68
zMf3jMn{l>GcX|3ISf#rnTW9I<@77J!f75#7ZIV--zOY_d-v038n0<LDeqFw_oTlA-
z<1`)H8f8(o$(H+_HO{tKk*?kX__r4?{+6wGt8{IV(KKoiZ_+0t^5SpsB-^F(LxAp<
zo6{<_{wpt5*{*o|@ZT>gC`W!E@g0eSi9cJ!jYbRSjsfG1eK#Z@-5{pehGRs9cO;nJ
zj{D@M(Ws$AD<#0z0Hp6n9&yLPa60j)(3^Jix}&28V|PfV{v7~rg7{bG<%<`2aXc*x
zi>|nb@9%UindrV7yJWhUG&&LotWmN`^QHCA7mX9x$?lNC+8>ttRr*eNvfd<L#LvgH
zcuY3Zll-y#*mB_GDk+kCa}WM__u^mgUMRizMvmF;3-3jzjUu31WVKC5vRWNMwz1o<
z@PCE)@ZEYvEphJM=hK?x**_$msQle&`_5uNFmboZlLb#cr$=kQwxCxObj%LL{)jX1
ztlutuDoC*>Fp=LG9xpd(vMUKav<@goiXVqmXbi<urSUnHek@XwAF|zMzx)bJ`0E`<
zd;9G+*{!T^r}UIk5?vAvSS5L3J?^uW_39t{UDW_pC*AIkKP-HVV6=J)>YYsp!+1LG
z2y9rzDM#a1Bj(@v9*Gv7=SL9;``v237O2x1aToE3H}$(^%hVWH=kr+@`+cN3BK5<<
zU-)FO7>`Tdmc$EloA_Z^Np6eO1(5wS`FHC|q|V*Ym3TWMHT0v!_$>Q(t1D8=UEr)y
zPo$25aWH)^@Lua01>><lbjQ>hlCfZ0fOXv$j3rqsoQ;S#^1b(D;09wPJKFl#W-wJB
z(<M&Bf1YR6t8!()M~hKOcKl{sUdU!#am)OhwzfD4Wu4bc@kEMjo9<5qJiRoJHc4KT
zf4@^E9ot#xO28h$937^+^q4KJC7a(lT?o`Tv$=<+4L^~=M{?`)VP!UKKEY;P*%6`M
zU`WCU_UJGe4$o)?b($h{cr&KZD0bsTq)2rnsbvQiQ%^#dP)CQ(2Ov81)V?|`9eP^>
zZA*RiW2zcX?uiDy5}~x|nDl2;U$7O2!eS7xs7yp)pM_&Y!?q-AF(_<rMyRbrC$48%
zdJkF#YXKA%<`9ns3EDDBh4XQ&No`AdF|m@!Gq&B-d%*NU4jF2g1<YDHRMM+IxFa`x
zx%D%&r9p#PM7-H#GMjS2CA6(Vqi8`DYid%j>Y%m;?WoXTxFG&;A!x;+T@@P6>pIY@
zgX$f)R-scb3dGjWP*;;0dkT_6Z&c`fKCgj#npE$m2HIDl@rOF8e%%l_8gyWouzmlQ
zM04MZWb9Q_UbG;yAI{W1Fl^@vv9P1!@+)^!c{BB9(?Kw#3u!Xz`x1Lg*-RPKok~a!
zZR=};o{!oN*=lwTQYY>m8H5uO1^?p<(4GMbHu1rIT+HPTT$^{2cshpDHWs0_wB!X4
z@u!Mfwrm0F_18&t41FE=CcD~hIV|&dZXOmOs2!@<uk<qx;nJW~&@OLj;Qcno5Ub`;
zMJcG*++9TexmhZuYiMv#2X#~^lN!2e-@46~S*i(Ym|b)jU{Sw^vyhHN3B9U0Q4G+I
z4#h5*q;}0vlT>NW&clGjGZN!Go6m#kP*O{tvok!<=9cnPLiv>O<LI}1`H-$o8;D5E
zgBefAe2C3r>$nO9Nj=$?0R0fvLa!9)^aDbH;f&<ajsgwqp<M-vK>_*b2g6Y;Yu%G=
z$<$JS74%wHs}Aa_QbBhWTS9LPP}p=w+F<sYo&h>HL;Jc~s!$H~b*L(oLkA|i8lmzI
z$fQQzi0&b{5=E$EP)o&@(3U;~byC$ycr$0y1w7kop_EW*62kPy#bh2W*_EQg=&>80
z{rL*oR#&Nx<WSk69-5FGDy;%)|Jn{ns{qXei_4qFCaFCY8rDM9RRD*GA5Pt|*arr^
zQs+Pg6-1X%`+`*N&y`R|@=o|H90wEhlHJ%BuwAtWFt7@+g4*1XNwUr7{gVX|ro87(
zZtgI6!kuiOn8l${Av*?><=2#^e%7#iCY#NEnG|(rBAf#^i@^XRjF}pdUCU=8o&#ZU
ztKv(jV}gDhOM**iOMyZdK;lu@7qKO@ZGb95Ih4DB;Hz4oX!0f9rn|!Idf=)-pH?}F
zs3f;CBucszp2v4eBu)8mnud@!G(&C8J)pLLp3&Tj2$duG(B~=$zzXVIfWo})`|}Fg
z;<`pNv#EdpvG~*v1McvhTk_-yG7K+3?Pl3h7)3Q!1xhV{Uzv*l4W{!2D7Ki7W&Qig
zT%^!`5R%xv(V$%w8hfgj$)P>IzK;8CmY?>g+}iF}X-&+5u3k8s1d$|<it?)&cDqS-
z)_%R-?2}cEQEtZ&jL`iBrW-$CN<jnJC}(JBfI51Zq%?&tB$eUz`-=K@v#A9X6dL-I
z*{!cYZ6h@PG>6&Om!Xak8cZWUj1{RZBb06h)mB<U+bYzLN3?lCGX|}uB?`MV1cP7<
z=K=BJa4ZV2WxI&b`9N|A0IH8x3BA>ze6$9e{dcRM9a#?4IMoLI()&1ftrFzO-2*7*
z)k>QMv#A8N73h2alei8=sG~q*&z->E;;P}$mI8JADzJjK6{t5`;2|vGODNy%y-k`N
zt%u~e`kow93$w3vE0PAbqmOhWmP7k)6MbN2@9em(B;_>*55mbuH}r9{p1ZN=AVL_4
zj<+aix!)DX{l+>x{HTe8N1s@hQ&_W=IEO154Qj$@98e$<-^cw%W>;os1-%O*#j)%v
zvy(%E>0oAQ(019WU{|Ea<LPj=l(KYSy^#<cUG!OQeJ`Gcl^FX<o*I3Bd;!W^^p8ha
z2bh+q-^0qZq9M1y^C)V-f&QlNdG#zkM{+tbA;t0Dq;FXUmg}CzB6LjUDp{oXYCd0(
z3G5;@EwK|^&h2uRSv-PuqcN2%w#rh^!C92V57ndU*Fee)@*y)MDMB}*9OzO@$zsN0
z8}ig;J_>XEj9G5QHsq@ri_XDWO!@dIxHI;wWHGpOtQFWwY3I0rGm9aeb7qk_IE%qz
z2=>EJPpy|MhV%|+QI>ASBDp*~4Q|K|RxCYvp(4vOOU%}DB_F&gnfR0X3FFEZ!$daB
z#AeMJqcM-Ny_GEXWfp0|&?LM`3xTDLEdMeU7|^POU`k68nlEeUSYv?zyAD9h8p^5$
zGvZ@N>8)A`Gt_~B+I1i{B}&xQOGO=FfssitE$3UqR!Ta|sJ1SvT2PmTnP6?DYY=bJ
zlsQ>UgSg>bb#(G%F(x;k8VyG$^)X_VNK;I$V^kF0`snUsn`bH&=R*AIhaN3Rv4yf1
zByvs;xNfSZ1nyF7qbHMMuSxSTD8~nd8}=2}E8Jv-1%G9`RYpVgbeDYIq!t`>yM2M@
zo2C_-f<%o*m)1MnoYodrd01I)opx9_WPSc&*-j6B6=|+X;6Z;F-O_IMq+9diiD2%4
z(98i|b4xWcKs|gdDB@mG_Ya})g9|z4kN2iF4aG1=kbKM@8K2rL7P9P4+qxzxCI>e#
zT_L|%fdU=ql&widV3+F=IKePKV!wsvblT5gU`QcCow(8aUt9KT%TZUG!r-7#yYmc2
z5DM|QWp^$MwNYsA8HgYgjuoqSS!5GMHlKkABD=3G*zZ_<1KVZXd4!k55vy)^(Xd`w
z@k45@_b`dR)1r#xkbKTIS@8qsdHQ70wz4AI?;wso<uJslRRBw#Y*Q=A;qQH(QbGGQ
zC9F%2`Yk@>J|As(z-v)Le@OdliM2O~z{{f>=?PwdETR#`c4RF0<H2N3DP5W8!yNc%
z#arK31wv#ohuB7b2(bpXAw664LCRt}1%KCz788X^x7Ud(JiNoe>6VP$PjH^luARLF
z*0%|J+GS@IhDO}t8EgSy!`lJa{E+UjF45ZWs7>bsG-Wl87>E9qBbn{2ujz4@ZeY7w
zVe8^p^2S+UJdQD{r8+fVpQ~x8!tOjkXw^;W;b83Fu}sd*7_F!+{L&W#=-8hQ<58p0
zlJ=o*r}X%PJf_DSG!i!=TIt4Tp;-OK!%y*9a>xi+Di@#O=X+xx{&+_#<CGCwrH|RN
zDq)k9;2GBP6j6^E+#AVk>eC8DI8jCY=qCGpBW<q_*_Q`#D}|x1-=M#5aF10htGL)=
z3IE@l`eEMlA&w)(!*Nw7kJJC8NTy(&!0#KK@jD#7#|;`$9B*m~VW_F0R94WLtMKO-
z`GKeQ_1qWeDNc=#)q^#-1(+1VL;wnv>oco@Pwv8EZr8K09rP^9O9ARENPO(P7HdW6
zW9EsxJA1?!f-~<#mwNVBR5i~hbG@Q@x>+j~dEBh!@4CZZR$R9+b61!@W1JM&FaC$A
zks4KU=4zPMW_eG+SEq4)(oU&<4vr|Dozhx7KjAKo(=_=s<yC!6v)mBIHi4)%dVX}d
zRq*3!PK{RJLCd<E&&U%updG6r-^`|1B<|F5!*~F_qX!W#+Z50>X*8c&7n-NRkEvHL
zFQ{Z-Vwx&Uw}Yy>(k~+!aRk<<-LfnX)lQX1^psigXnJoHCOX%LHA4!Iw#kxYD|xtV
znPs^vNVX$@l%HcM`1!%3`hbpm&9LA4%<_?8%sFi$IihNqjBy{!_OUn&H<*37%Wd=Q
z&C_ex==R`E9O<KAhTDs@fWdNUu7@e#4uT%FweZly6P&sP??^WpEbD~qvZaWCkJtu$
zJeHNngjLE*F9GbA>GLQ6?7#1D9vF!F2F!}}AH~ODoO78zt%yhODuI3aX_-RQXE&X8
zwXaitT9>ce;<$gf*k3v+apY~&$lqQV`CHS-vv@%qw#T0yHh`ta$8`1QhRuM$L6U6y
z`0TKP0lFpwEGAgCh;_Lh-S0%rPTNP4AC_?3NWn8MC4LvLEYtgzbdu$V1ZI;k5lWnM
zZyN(yylR{c26)S>M{xpC3<<CGl}PKz`{<9FB4L3lhO1pe3@kt~a5O}~0)pmrw3H75
zVm`stSXUrE6XjAQ#BB66oT(`mR}e~guSMeYRu{rUx8DzIj9rnna9M*+{C?mPh)m5o
zR^*@1GNjoRK6plZpAkQ!C9OI~HAXdh3IL^lCRO|Xz{R&vSY2ym?4gXAT+WHGw;m#v
z7_6JGoc>(a2EnXV_a+zz@h5#-(;@2aronNOz!)@|yPjX8vy7QMKQ8#1kf^tzn-WA+
zoh5A~yz6=XJSMR_v<)xtmDI(Q(^c0EYYl>F#Q3S#skv_g#3>;yz0cFYBjF6q<c|^3
zuIr|Q)T{b#Qo3Sjcub;EFo@YbIqgJO^_=~Qs72FA<q9Zfh(@!I7fis(HR|_+$a7&g
z6a-w=BDjnW&F~BoS`~20;pi{+7Myg;(*^^w{d%3J1q~5DXT>%-l=&abps2}UIIwXm
zonvu>a%a+M*Fte;7ok1n&8zhna!8KJR`YaO*AzEH{7BjE+eW{G&Zb)&PgdbVZ#SS<
z;Gj?3xgnSRc-S8c@>nEaXxs(8QjX*jut|1EmHl9;tJPuM`9nrA1K<B_2meqH^`0Sz
zA#}U=U+T6arOLsoj2oJ;>j;if(O#_vvI;0<ooyhzC(Giv(KMiq;G3b!v$f_PIf}*A
zI0qb~YvXjmL}Kau2s6ZK)^-%5B!jULp;^^nd>$&9IOTa_>{+c2Qk9Tl&fA?@jUF|P
znCpuW$&Tn}ABgb&GkaLAP5RNGv*N)r*jm^2866CZ0A_wQNsLPD3!=^<`W%8>)9jKG
z7)om7*@o76O=CdI(`9W(YWaX>;^Q4PyZTs+If0`cqh`%T5s5<3Z94WVsC#E{Ohl^S
zhFvq4MBC?!e6OT6@O|!0$^tqdZu6XMGkh)FL`a@~D#?V!rTlDGd+_CWp$AAzcWN8P
zjD}!A{hnE{O5?iI>8TC`kVbgfgH>~UX={NEqG-&4J|FmJn(ZYq<=Uoi!SB}Dm(!75
ztR$N+`(su-Y*_&+9`mClf3V)CKVFw#V(@oXGplAxj$rXG?9F3X>nM|33>rZhq>}w>
z?``wny|=BGudN3pd`*9pTNzN=K<U1$QVl(N2?8J{Q!#c|+#I;9d!xGLsAw7&r^AM(
zh#^$Z_B)yj!a`z{221I1DrChSlj0Ods3>uX(=T0MPuE$xS^d;X)CSTxk|KhPG`CiS
z+<ZiUa}hAcI8iqa)(sp>!xWgCmu=BC+oIwjlt<h2@Y`I9l1A_O-dSa>LhIkn>Yfi;
zcq?a|Q2P12lZ=^T&gZl#$isb&iT*I-H)ed@z{FmCLPVyEp=(nQ<4Q1#q@o)dTicf*
zOt9+YizpOg80Sie(4{tPxoTBViKXAIK!cGh(|TFb1QOjE;BU5W<!R9~O$)%{mZD7t
zfp)3t1J_H>G%CVtvScyW?+6t7<eYL>Ips9sCfj{A<kWj?{?adEkoWzT;ru_)g8n57
zSR}_!@ioiaFheT5tn`oX*coLi#NwDxz+BZ}eA7M2ndXkijpkFgmcH<ST+cp1vKprg
zEhAaIGG-PsILE>_<fta&In<`+(DM`i`~?}j1^x{gEX_I%JU5CP!uPC97UP&dtV%p?
z!kODIAGQoP{_IOkZv82Ki2)7KsDYI^NNWN8Fr0-FO0i>A{Edmeei+<>Q%iA<eA!c$
z3E*AdAt|&lm_4rZeAqsVaXXqf$GVC9bikM|UA?xF)nj@rvK)&saDi_QM0}(M_}Edl
zifI1IZcfOkkFIyaSh#3_S6H=%QNt>-)xFDvufS?~qYf6)+S1`@n&WX7@oef3&u}%D
zCd1il-e)yyyTXJ=pC$qe<!Gxewp7*6OB>}ma(MW`_MDu2UNyBTk{?pM_0XjD@r@^z
zU7+4@HHB8_!#o){xHTAyz>%Da{Vo;PZ(2N%;y|{m?8*F;2J_+tB1}r*V{uG&`7+HO
ztD6)G0!{Hdd(vFlkfnPMKEtIln)AdKAInqTu%(Npwbeaqo8%Z9=bPj)Rl-?`q+YVh
z*$AGza_+B8M_&2vKF`-_G=2^=x;hOD$*^EjcQ-gSWK>6|+E=|EXKvMyOK!Dp7gPH4
zIT_DOze1zJ8t^&UpwhsLc*_Q*@SEUhMIksjak!Xz^wPg!_l!`K6~$q|8oRE=V7|3!
zwESY)hrJo2VOl`na15r5&3$qlCCp`^5?->a?onAigXI;;imaD8+3fcRIpVw!)}HSb
zV58OMiAY6qx0XCKUIlR8q5jo-71g;KYH`Pz+D2YO!k$sDkZQPjsro$BlG#GTl&r?l
zXS(@zgWnESPIBFi6Wb;A^(7D|jkBLA@~C?`zwcsgdn0!`^tlUBH&5v9O<+sb{8CO(
zsyCJo$?gk;py~3b(-j})&<lL2l^q27^u~_6Q}dmMKxZ#N=)R5unMCjP`Wyx0jd7_N
z_MH-gH7z&#g|F1v^Png?sL3a0Z9K#XoMPIlw9s8mXbC4#+|)};lE3x_hjtV1OD)T3
zF2=Q(yAsm|j9m1#K0x5S-m8Z@OB;&m<g(5I_K%G;^ye>=RQqIzV*bP4-?z1qD+%N9
z`4>J#59gX3n=!;Tgk-`bdlN8;pW$t6lbP9U?!JuOhCVU2<8A{vJ2{{IsTWBtsnzW^
zn9S_&-s~O*T2iT0DwV2Ar4n{0wP&>(n~p^a2BA;$luTydlqz}Hd;=m?SIXXIE0XET
z)wkKIWU4mErEEnqRr{F^+g9HknCR70LHu_0ZN0Xwc)EZeXDgnL>RRpRbE#rr{-T`0
zaw%OB3WPqXxPjxGIXNfrLiHuqV)0b*YA?NRF9tQv@bU2{lu;b7Jey82nEbG@&z?x5
zuFx&@isGBNri-<?V+<P=yeI1r3f4Cld|$+(J2go$W<-G*T9x1h8Hv?(&=0$2I4q22
zHVhn&`I_6mAq5rY!a{A^X<+J=$dG8Kw&hfnWBvHvUNfX~HOQIe6z^E}X0P37Is3uV
z7N7tU-E<(y>D2v2TeUsgUnImYZdkTYAYeTy%lVQ*<@jxjqBr@d=#5*R7!~mksOJ<V
zM#To+Yo)vYZ``6pqz4d{j*bq_0BrT{#fx6gN=Ay>-{sVgFNUx~$FO#+VS6k{&27dy
zRU=XF$rDzcX-Nq{BgwxCx9Uc9RWcmcc8n4&%9B5UrH1y4ecI#&muP(Xnzd$pr&vM*
z@#vN+`(fYjYIhsd=2<sBgj_l0^Hn9v+ib(xQo*J6sSXAHf1WUI&PYMi(**5<?zP)v
zXL|IVr^O;445z6$OD`y+{QY5SNg3s7bxRh@2om$C69xl>%NnE>e7|=QjfXQ3o>1h4
zeL4sU@h(pod6R)5AhGeyAc@__Bo~L+#;!!VQBtWXuOWu<KL{vvaWkL}4M#u0Pq0Jq
z;WVCghuBAg)6*LhEt-KBDF>j+6s^2}oD2Y|+4-%K`qui*0s!Fs%OQ~K&V=yx2<ld>
zFP+qv<}t<FbsF9)Z_9D4AgdkxmOgpa3$>G1$HA)zb#5FrFxz=sM&01mShFJP(lpMr
z6{L#vlY+DngbddtE2{1+&|B9lo-G!!7d2knk)RbGo2M1F>P4MFZRqgGab&HR<_6Sh
zH8CR5zE`W49^289hG4-^6cO+X7FRg3g*dX2%qh*h4UCOPDtPB+JneJrH6Oc)<QMju
zLJ&R7LurRH<BFjmgYKvg&_Cp{gc<W<2sHym|7usENY{aKaZJfsX|Ue;gXuM$8Ks1f
zUZ~rw7~PQmOdEYIwY+f)<6RGSPgX0`GS%}ART4?p?|Y*FX^zTBIQZg87|HEV)$;u8
z0G4irTOM<DaccmNbR(t*$Rj$>bO7KyMgl-9xE_P%+x2LhhlbPf3@EGm{}g<2fH?a3
z{H!9eKN^oe%_eg}WDp59dtYe|$qmPY1OI%V99D-%r@zuAS0>fLfj8)e!+`gL^L-D{
zpAL{?6`I)iIBBfW*=&4lHcqQ+TJELOv$lwwrqmRckT}n-S##)stok)O)ogc#tWtBw
zVUi}t2_b)#H5}dwt|GT-mxGmSygy{|>2PLf6|56vTmB`r&jdKfxU>p-aDD31gt3TR
zD(K3etAcWWjF@FQ0fZjmuN)lr)Jw_X?hcNkB-I>uW5x*K6_U89E=fX+8cc)F#<y<&
z3%+qdg{B=1FkK36wz5g#=?%^Vx}Omf&E=GW-|fZZ3Yf;5)<Sy3sbh~GUqZ7-fH#u3
zg|*Wp1=HSzWeDrjWz_R;KEt*|;UjbEm>12=3dYk4X4mx(HRp+ol~P<Dx>?uo`T^e0
z33`#AK629ztJw`e42$fXpvncHtl9-CP$Gog9apG*mkY}<ipu^T;w7ZdLn{;xx7`s&
z=S1j1Okc{YnTX!`@wGpt^D29jXGhO;GE1LZ^u&s=hUYryg6855X@5GN;BCUxIhfN+
zZ6|Q2EuikgFp6e2%TDiNJ3P?5EH#)7hfahh7`@~w7=LyTAP_@N2X}N5H@lS|$iDU1
zIpZV0bY(jl18TP1HS3P<*%I*Vf3EJyFt96@s&`x7Pe0iJHS2_uQbED{I+dlnx;spF
zcHC&U_ue*a^c-jzHIFs44h^(SfEs!V=cBq4Me7`9f``>~P?ru^Nx1~DvK@$C_pf35
z>0Yu6(68l`S<x--5M%6v%!0JBVITJNGyP=z4g=o6c-K6uzCb61eM3Xuq2g>i=*QZw
zR;xnOtL=R9vN8glcJ_|w?zm`HtG=Ly*lZIM|35p<Xezrrcu#(_y`;bG>L+TG+2rK(
z#6N)T3!7H&p1)8nx2iw8Tgn!ov^Ft+B_NFm1HRj;@v~aJs#;saL>Ag_{j!pF&rnGl
zOKjy7?<Rpli6>XBgWp|e-)4;!?NrfjTTVCJKmJ9j#+Yr&zR70SVU^U<2980sY@EQ4
z-%s{Sr~;O~|5{xsiC>>2we);pu)gU1EbTcXG+OcLuTu7-V-@dWJRW)>24{Br<y{K~
z?BBDAf6<M?-dsqlK&ln@BT4*wsxMe3dRL>q0iGW~t9W_HBLwKthJ^`icrSE7bX9g&
zGid=m#?$eaJh*0q*(e+I>fd3w;Q%>YfASBR{Lg;+@PGgPO@IHh-@Euz-v0z4U902!
zpIi0q`p$N}O7DMGpZ)LqpWou&H+%mR_rKKppW<W2`=9dTTJk>anze<{5f~{M_%H#b
zJ;Y~0S4GBfepknlNKk)J2O~tBM|Z7^dNtcWE;R$L*=g;awEeexXSl(?m|v5gDFvMp
z{t@EsGxQ!F{Mu@zRS=*T=I`Hsci>}%Ow{#??K7%|T{LvRU3ArjEpJB8E=Xq`w!?Qx
ze6Zfn_kV75IFXrEcqR%fuFOz)59f=28z7_Dnj;jOE{p!{bed8mT}Nx5BL_&bL!o3o
z$eK&Lz0AV$@}5WrG2J(CLsbQNR}n;0*Jap#;y<tm6OWPZe5)XjIx@0dADf)8-8BFF
z(pFCo`S=oU9<M=NJ`F)eldeEVx(>Z=+N+q9zB3`wAx$<c%JyLAY1NA{xq#yqj9mr$
z)K6h*u+kN!h`cxUMXP=-ITqBXW%L=R1*q?w6)1JhN*X!&Op`GINC|z0gE)1$SVt=b
zmDX^x<-b9Qo|kieW!64wzjMu)tZ;6EtJTs;Kg{X~&z6r`g|-Fnnd4fKSsww~zH?RM
zP1_!Dz3NC;Vb&*zJJ~fX9P5B%-45(9>m$T^4Fx@JsfTn<G!4ALFt`gZjN5|a0p^CC
zOz6Udx;q(;JkX~H0mT4~g7|hk{e+N$(Ixa)v2I$*<O&Ew0izJ}AP%OOc^A)&C=Y|Y
z`vJcbyt|+`i-S!{^UK@jF>SKMif<4*G}HK`3bB&%-<SO$*H;jfl(u>SZgKn_<1CC4
zKnl}907^CdF%3S?!YL^r8jA2aNgR<LS+wcB8{Y;u!L;JtUIlcfhLlMvAUp)6!Rd=k
zqmj%rs`?XYH8;KHAo<uI2hr#sDsBq_Vk1RzYYLOD!PJ}et}w?aR1s4s=Fhu@X+ucU
z;3mW_@dOkTfb+!ObcZwOc#0PlJPq&La5%(!jVh-`a;=UgQ>Oad^iFwX^t?lN`lXT#
zC%ha1BSxyN8Uc4l^cwYbdPOElS?x15EuCfTuw$E7auo&I08J;V(H^nTz4B(@EK9_6
zbMics`{f)gSnv2^64_B7eRr-4o1Jsi2N&v>55oLXAbuabQ_D^Fted6tF|!fF=7OgA
z$iepH^jg0;^WU~OJ;ch&mYo>=%x|B+p$g7JNwZu#liW`4Y@#EE^DL|E*idGkS#hfu
z6S2ozK~O^5OEZCyWdqt>PRBFt43B6CpD)7LPXf~9K?Trk+clvBJnTtze}~5&@I4jV
zhHUTpo~_k#Rvh%PrE=rQ^Eo_Y{m_Di&h{8(*y4Eaq+fzS7p?ruRL{CDq}RkJ%u}m@
za@jn^Eea}O|DL#|g`%&I|3AZ>w09NsK2dZ4LG%VFrwmS1$HN3EX8=k^t2-q@h60`?
z46MW>*wmczWC^QtSkr6^rv4B%x1qAzP`|*C>-R^fv#)4In_lu(zmuvLoVJXcsag>}
z)yVf#Q$_nHShDRXd4HIN!69Rix&^>vN)!`aD1}r1f`v3{p_=vrdsDOJaa%JG8k)>h
zlk=iYBGsgw(?pk9(s4$q14t7pq4$)0xgbF+xM7n|du0VAA`ey7q^jkLDlVDY;@|(y
zK>q%B)G-Uy1KqOBeWo$IRQ*QNo<vaKMwOBZSOee`!e>Puisd2&f>XJod3n>a1Igm_
zgo6qa#hzRV>vEZ*J6VCjF)202fYR-ECpdBI@K>ryj;A_R56X&F9gGXXB}t9Pc(Nkq
zd%;Vp{on>2{Wt0iKo$%*--)*_eo6H`nGX|Z$ts&DxDyv(K3oT(hPe}17jRBfV$NRR
zZu7aaD)~V#fvxDX0e&{=gNh(}p{=vXG$#BbbrcX73@Q`3<U%q4knAL~G<~L_1$`VO
zuzvmkvHEE2I?iAZ=KtK|jKu#xi6@)AN9kjZ|9^XD>pA-WxA8gi=UX-M|L^>-|Noo(
zdw~DHUX%X+D8v6Ro%$eiFn(#$3(>Kkd`Ec{j?>>z>vJ6eFdRGuunMNZW#srg9P?*d
z`;;(=7e9c9S-+m3)arj3v0<YGOj3+xxFZUGtoO>>sIeql<;X@%at)Objs`Ti4DmXC
zu0$p|X;om6OyYR;zs>ypx-bMZ0LsQ|yk`kNk+A%t!LHecr5MzH0)KA2zQTtcaFA2<
zEW@t@uk>9Bd)s(Dy~DVZP4T8{<UR3(E=<?o4-bz{@oInbxY6$H9iPE=zOurRZeA5Z
zO^G%*jC_jVz)Mf^iOidbT`8HU@-CweeU?#8WaTB8PD>!MvF(}&3nm{C_v^LpJOztA
zR!<Su8Um9eA+oG|<>82-eML338;3nl&AE(;2}aH>gHHZ~QECG9P?~iP(R7~o;}3J5
zpfV7*lnJbiO*WAkpj~!A!xIi9P{C~&o5VM$E8d_xi~^(u^tJJtM+bevkN@y$-b;Ow
z%`gTWu>f4tCnkSdzK<|^DT(s0cntgd{(p_us514u#){1vAh6aCBl?}HmUoj$A|id&
z)+E!$t&HKM*egIqSEBwaTzNDuAW#OQ+kAkvp|ilEfQ}(QhKj+Z2$z_V?GJ)=I|Z?c
zNDwF$DT@ov-~WA|=BTER+Rd88;$KF+0t!_=qZ&bI4sLZx7Sktznx!hA*e|5GxE-t(
zlkbbOG9@s_IK0z?M#9XQE5{t2zI;|!01J!pSCrKTHhPH`2=iqn9cRh5SFtu)#N{H*
zTIpuYbTE~PI82O8f+AxD_3kO8(f-g*RCv!7y-4!X)k7-uP=jnnQR+QpL{L`jxXyAS
zm<x-b)ZXB&C0=p42E`SUibwM9`+g#cSPsE=DRCV8#ALvv6%QXG-=x-PdU58PYmc_`
z&s(4Om5UpVlhaQ7{7g19iINhaFx&_X%Hg>8317MR1nR);#%uhI_a8OE4q--eOA1;8
z(rn~}<=h|?V6mtCe|9Fmd+e!5)P^~8QD8DCkBF``=4;QQkZMnYp0}>rad{GHPf0?2
zAHmE<cs_>nD!pU0!-7a9wbnmr)8%`wdbf4R|Na~XP}T|(ISP6Y;sio<LOOmzTu|_x
zLr3I*ny);79ZY?oAnZg@$!=a2fPZ*}=z(Q;(r)b26;Svuz({68m<1yWQjxP&V!zxx
zK}jqTFM%aeGv3LWad$<^TZ-2lwlga1W2PYn_55+TMsWpkMDk~RJu!Jkh>$qq%OVfp
z9R?xA0L_P?q{8SaG25HH{h$3#o2XFsp5S!2sU!Ah3HKEq%V|9~Pk_#fY3Fo`{ZYr&
zvSep_UKKkR1w|S}Ol(`UNgaFV=sne42|@hyleYzhf5;V_y<Q407|eGv47yX5114!E
zPx!qkrc-=nTVxNR-S`D_@xmaAuSWQ5uJc-3fl+D`Rh%utA>Y%3pco_2IrZQDT5>Os
z^0K93E?exMw_0p`;j6VrWihXRz{E-<%B4bW-zCg}h!9K6<8KqfNgKP*m9^1Bge;q$
z`SZ%hG2du*d1hjedhv~Ki8>;iC>lMK1<)YJFeA)64P)w!XXuZhGvqE^;iq7m&0<zM
z-eB?HRjhpzP%JCEZf<k1#)jkDdpAF_n*#$BZ{0fh-RWaUb4<7Y&sh}DVHr7N{a_e(
zQ~NLDtM*HK>uvvj{O0rsugr_Q<la_oS$t-5F-TH9$UtqO4`8ek-i|3}Nlzlr6WOg;
z+`ND#Qn-vqQK^)%?#f1M`FoZS@O}`Ju<OQ5699x-p<c6?1a=<We$dU5eU_K<IL+}E
zxs)N{y%MTzV&pu)e6k&USyoRl%JFo1Yk~yiVi1l2${SbuzF$`EhD<MmZ7Dta`A>5G
zhnJQyL5m;V1j{`L%s>CzuGXJzS?7P-&z{%+_x$f${CmjxUv=L7A9<$N#e_RI!TiHN
zaZtz+r;D8c0{3QoMy57y4xPQN?fA9&3ra{C-P~Tmq8!HlMQx{4HDcDOV*S~UyP_UC
ze)bl2T}REWdI}_LF+1CKy`61>Xw`Gz$QA2WMMuwEaoei6cXT8wPSBA?)wJ78Zw|z>
zFna7Id^~J6jt)2~PP`OSO&1^4x3*>Ri*)gC_=u+{t~sFN3n8+2CtVB*fhg5%a8=6h
zipUBtR#(vrjhD~FMxw`)4G~Wa+7U@=-#3!m;Enb^=dwCFJv}pGTgSu2+g#uazEM!L
z;a5-9!H0!-WbIw;pogBEm*7{$&c<(mMB*JFTxiDLi;+1PYU8a>?_`LMrnljVt+&3;
zNirf)?!v=c{}g-?<!Xc;j`3zli9Tp!*D_PYlm_Y*9ioU$85Bd@<1i+(6jG5FdOyMM
zqqv*^f{#D^zz%#6Pk5N8Fx>=23WN!&cHXcHddklB1}M9vq_2oEd<Z{oyoTvw*WW8T
z%09+dWDn8bCEspBJoN4UsypfrVL|k9vPwuQFM(IV%vT$)jroMH<ab)(vV^O`k91ss
z8o~@_>{BrOLaG9fXhjkR%*omey#yiFUcrd`a71Z?=y1Up&7_OB^!SeXD>bbch!3h3
zd@RYSU0F#XBXF1eOV}}Go1@+|xJEw$=SUDHkR;}37%&~WA^Sy}TnEfh1F=uB$o~A*
z&|Nrj(^s2yQU6?(=uf7>0BT-w(16XhoPlgTx}_Y8tTf&z6@4-t)FPa_2zaLE&p?c6
zg0PYp>ZrI17$2%MF(#Dy!ceva6lmP{FS~fP1Y06wn5`Mdiq{6~<mlk2_H(0gR=jE5
z(KJO*8K5S$?;gIpK8<3j$7KitpA_|Jh$28RPFf-ul@j5ghxQpCnNF}oKo$0{yU{1z
z>?7g7ckur^Z+9@R+Sp%kMe0SG^nVMj@b1X@3;#cx7_V^9_zmbs4}1C1i&FhX#oO4{
zZ^HqqVIOTFWZw~`4j=oVzgRYf$z5n$Py;!~1m&aEhVwB@@A?x}AL<pUk4ed#A{Fy0
z>94mD4N(x%>+e>2BNp;%ajlr)mztoRjKNHiS4g#bcd$~0`ToJ0kdM$Dr4y(OV37~t
zA7~@m?;;foEEeRBm!4SnbR!6aG5t<rqpmgDN&%?P2e7R*dX@sPH6Or^*64W(!1jCq
zFSJHKrT{#f4}jielSHglEC4$N0Ms=ATQ-2_1psVo0G`<ZUd#pXRq~Cvd=g2vG1scb
zHChiTW`XtsEmysIx?bH?Z!2AI%T;eXU2oe}?^(LuGgrNxbiEx{z31tA&t3Iir0Nm1
zqZ{;T(2bF;I&Ddo5iv)9Ot!XUt;ZL`TC%%=)uI_R6<r);G_GeiexeJL+K#rfDwZ*O
zhe2pYQbl7bchh=y(<d53zW69lM(}MiAlL>u!@zt*BbIL{YN+B%NuP-5s1?3BZ{o$o
z^SA!#Nr?sKcu=yo!U{cTflH(8efNs=-|VVlL6yB9!1UT(s25Ic*$WHwk|6X0n1V{9
z2D#5VHU9FG+@Sf-A70I4pd>8SqdjhZ3sz_~eG2vW-tb=);O_~kKJec<{}(hoROENf
z1~@ZR5r3hYFts)DU-&zzt}Hj$*@j50KK-b3Q>vd-rktCI%<P5Kbx~LLuEw{(0HZIk
z#d@^GzNCbEUX7P4v`|bZwX?0dcnBN05SOOV3JIU}GE$25C!v&JHK$ctk;XMS<*_fp
z;nC0^VKe_<0zQsS%?0PAZJu<X0x-X~0myF1^dtv-vDO4Q4Jfb@v};1zj{u|SrW;M6
zn<(jqk=83?A)=3v$`x17Wo0^Gn6S4^^9t-0CT0WA{DLYqFlb_x<jz!G%@oWn^@1rY
zXD>?DxL;@^5wuLz0R7RWU#j^*R;DgS;}{15luNuf6&oHD02+)~8U*~;0YcO$Gv`LJ
zMlVt0iLMNq4fGQ4>8oVEUf^`u6NN5m=WH!*0FgNHwv!pd%atNRp6{N=(=lF0$7IZG
zsUs3&ygx^2zQuEoD=R9jo|I{^&?wjS2YqxODf$leXsU{`NmFkT19rJv{0KkC(sbee
zEE+pUDXm-NNh!!ow#Ovcob>?Ub4GKFH0Lf*MBPV-)I|`BON?laHA{+&hs*9ux!H`K
zic-0I*$qecqBU`p+%QafBMXs?hq_W(MGb&n(Wbs|3s^QGG<T&%bX41x+*#uL%p|+P
zby19ChiMqdl`P2Z>|I%zo60X#p}kZWJaby=t}l{93$zukC)~M{LCr3_-n2&+2VK!N
zEs<_w%c#k<H#XEs0fE^C?w_EV{>#u%)B79NK~xc7xxz9>ppX!oyp2j-2|)z?D-o9B
zD`A6g<c)~G36R}H0i>(ty*P`Dy}@*RO*)MFqDCz@($qc!1Lxt<=0{}68K^P^n0<w+
zwM@u$wJ<VKhDI7-Qb|(t310z3xuUEG1vV4k`+%)$ORIYmWXv|RcGT;}apI-(<tn$u
znoxKVmu$5?@m-fSl~`Ly3-ngMe{b5*1yd61S$z3eM35FzMJoUI8~^-{aC_KP6MyfH
z<`dc+QT_2cGDoELNvxoJ>6CjtxSous-C>D!C2>koz<~fY4JV^KYjB=1(GiKME^$v!
zl;p1%zRdKgh|w9vVyu)54>HBvB|&#)eLOpXZVBz|GX+y^Wen#X#W5+^tqNwa<&ZVU
zV5s3g%_TAo@&eZ8CwXQf{m8UjM;F*3^}H*}G$*!RMgb^x`D^L;rVIHvZDo0sqgQ*S
zf?e>qMnKFxtobbPa~{<gCyct+ztz}l9n-k|cBjE<eYTyB_~~7cc-0dxyiOW=njzOG
zue;<ypL8^Lp8{a#K1coHufmHS$_S$55D!-(t}Re#Fqr6KHvA-ae;>bs0z{dSQQ-?F
z6=UH^erWyni_diFylXYu?|_ZHsyG|e;^@L&5HSJ7dv+f;Ii3v$M3c}R4#z#81B!n5
zA-SI<*vdX)&BXz$0Bbp>t3vD}$m6b(@&Zk!gJKq?1T5rbkyEkcNUYsy9hV<xuvx{*
zFP2FKHMnqm)BWJ6My4zkRzC`MgWooBMmJv59t~xxPEFORW!9;yI`zytTdK~MtBy8z
z5q`^_JuKzfQuXlBr;+a4kaej_g-+kke(ul#{JX~9LF@GNxNP+b>j`Ju(yOcPeKcbW
zrOm@MF8f4V%p7C7=%A%5rX?}G1oGdae}}zYk@P4#w+Iqs$~&9M<=PHmHO<*1teSG4
zu(zm<xt$wf$J5}_A5UUNCLH@$bk_?X%gvXJv?n=^xKZIyC)_M>&BJQijgaQz)TQX*
zwy16&ai=0yjSY{MmU{B3@PV<pCCjiO7NDR|N)?DxQelV-om_<SmCM_!u=mL$r%M=l
zP<x!@vq}zy<vqV_^^mV}@i;}S%-&J+?TLQ~a;sI6hx~<<$27wMue_c!$%*oo(lJn*
zNNvL35!%>?;gjH7M>y8rWQIf?20j>m9ARU*%gd>--yHQZt&!-{rtlNkNlN~dS|R?M
z^H#efHhO)A#liiGJjKrn<<LWtDn|4L>fAcSavB^>NE8Lv7eE(mSkfU)?<!sjfT<ml
zAkqU3=ycLk1AYxkjM@Ul%kVJ(XH8m0VKq-Ij!MyIH-kD_q*fMflr2JNeuU1I28REf
zBqH2FobjdZMCH$-TB?t!$XJ5iq&g5m;&>LP>;1Ci9!q7;TG6Ah=BxEFzK|INKKl`)
zlwKbzF&CS9y%Gld?;86*TcSXV{p|dfj^0VO!51Pxb%CRASAW*=u{s%4pI?ZRNjwZ(
zG0rMMhjxnWn72jU5O})2y5g;Sd&435QX;R{9bv}ZX)pv93Hsi6H2i|8hB?133>$?u
zz2FJGP+J5!4JYw<8ezWVu6NOmF%9rE@OpTw4+E!H<n!|Vu{RuFf~+5Ur!6`=;e5QP
z>H<Il_K%3q#)MxOTgoF$p+zD2=t?6G2)Cgaxh@vlP^`-{L}G*+k*!XvCXpXs!M=GV
zROsAk;Z-3!o>!Y?M{+1y+_f%x$Z@XcpTbgq<LNYY1WQcBYl{43SK%P`h5`IQ7g>xm
zO~LT!j|XdzW`(Ci2BfO<<jf=9IVZdw{e)LSD}KJ4dAyr_x+{<K;)@}l<y}uGvFcVG
z2DLHljwtu`3-yN>X2HW)=+_|<M7RAJn3%FdSWsXAhD6+(?le^I-)0<>iq$;-R2BuV
zs7!m7W;Y8p02m4ldqXsqViK=&WNA1Y`d6$e<jYc?`?OY?L}0sAP$^Xp_BwmW&KQA(
z%uV;`<O3p3X~qg@_R1FusKYf9--+L3d#MSz+9zo{S;CTA?1IiqO6qN~gr~hfJmc$O
z19dad*JSX6#iM5IE@^&bTY1u!6@fA1ffgcDq1?b`Q<f)uh?kgT)kHSvQJ106K(tND
z+@i!WM5uH!(g{I+qeN3!8aDOh(sYD~R!R5+@&ibBmg{nOD$6ms=G9l*2uI)vafAkx
z?NpX<%Gn4=s+tI>uMb2(!kLEv9ZsYWkcWd0ML-+^Y6q^gCPDnDC14$E+mk5kX?;t8
zc>9xVwZ!k@m_&Wk6UPOzA2ms7fRcPbES8v<!pbp2IndP%WIzYn7|_$yp9g%%mnIST
zzk=yF;V63heH-@^@8Szi;|K#qoE$bXCpcN^PI;K_4so5|o#H1~cO*}8yHmW&fiIYV
z5Z`c+tCu@c@&K7uW7(7#Qw&MEM}HQ0+I)!M8L<BA^lT((nr{yNfp2Gk9PYy&E#8u}
zr;3#k$H0`hg^dTqt?C>P3Poqte?OOf;oBNtpvR1ZLd{ENFO(-S8SwhzgnvRPv%Gfo
z{o>!XXG`lmzT1>fiMw#HnO4W6w)5}$*1Zs+j@-zMXV}6-Nnv9;MO`@6xBtCWTQ*LU
z?iW1YAN2kHc;b(T+r20UF}2$#r|Y@*i;@ktkM0FwboB3p*#W=&gmH7DxL+#M-#`37
z25_8tFNrTD_3!j+NsI`miS}r(CkqM{7qG9!6UK$C8PyqkAR_x)ES&%5H?cR^?F;A#
zD_=d~L&3|KK@|Jl(U+2OF|z{7M%mCiO>gMkb%<H`?t;GM4@o&iW6deLQot!18`l8~
zIYkW(*R%32CWYlVah95C!lk>JG6V@-^`cLy6TWCxDCy;Fhbrfx%aaic@1g13L>H6|
z+?W-^*{IsSQfGA3xIefP+{anW={;|le*GYhw8pRcc#M-=FY%nk!W%D4S?))Y#3}?s
z&4#tBQ^B@D(ArS5$#fQ+>pBxAd<((i0mOHTc7T|Io*wNhyBejJvL|^%RogWV5HS6E
z+zp3#Xuw$Ls&?Y<;+CmH16n4ILxZ@;NkP2$@xVh?0((t^TVBwaYsB=v3XYMjT;A4{
z4@dfVrB^jmmMAKr1*n{#@!dz|_k@3{Z|PW#$&H%0RV_!W<{4EjQ;`vBUgNuOk_+Si
z#eYfukHK(!`#28(<mUgV?L2$_yl&<H*s5+<|2O}~xA^y{@BiwlK9Ie%#2)h>0l20J
zmxYpmsC@r0s)JzAoeePq7612B@P+I=O_5TsfnZ>r4;4O$3ysygoddkO_iT@T(sjQB
z`n^t91fRXZpVbEb+(%by^=_N)Htsx6Ds2&nZMvhlM?YU2;?Fl#YH&c8CifXC!P}>w
zdj$14{k}zY-fUBY=g*T$^#cuRHK}??Hz%w6)L@5TZ_}qY)Od>;zo8!X_NgkNeYhuH
zWFpd-ukVm*gC|-a-k&u6)0W?X|H!+al-sVN{qz8i6Aaqnd0?u9zx;_{=qcn$&<ndm
z?=T$FU4uSr@8i)1CZz&4?RlIUf%3dwf}*nN9gOi&#@<zTbSWQ9w4Wu!w|5VlN1aB?
zZyo@ps`T`-tin%#aklC`@o=)9o~(Ix);jH+YK6&x*ZIjw<49{OpLI50Mbv7&|Lth+
z1fkUGZ=TJm=D$5_aLt|Unr|B?jrR?L_<X;XUGL=m+ZI*ZdG_puntOU?Of6Sf%-5WB
zVi2NAfPY7Fk)Vokcy#)!-|RGw875G!;w)&Mz2D9(*>RV2_Rrh}=LZ=D?fp(hNpt@=
zqlC!dE+U${i<rnc&2XypHI+rzqq<Le@;u7E&qO7kw1sfkDu%-{CnSgLI9G+x-Y!VG
zZ!nGVY%~gn#qh~oBsj<V%XkC`%*<foUym;7O}woB*Qu^JuO>Iku8y{TS~Ut{etZo~
zv#W6wYiFr_ym-rE8~eBj_%pv37yc{28@Tet2>#QV%?BMXl)(pGk5T*~{3vo0UeKdr
z7@vbjmeU^RqWLP{Lhf9J5o|Xje*GAJm#^7^0OLCem%%8Q!gkQ5DyU|7wM}m?@@@m~
z(`bB)sYLXK(S%*uv_(W-_j-)aAftZ_fRIrW@w>W6PJ{;k_RgB#WIDbHL94(b%_1bC
zbKhV`K~v~wisT;l#jCj<9{JOmg@6{#B7ErgC5`JTz1jE_XDoUO>c&$x1hqSph`*!&
z4X?flWMTXWv+gh&%Lj)e9)ff-oA34x#QVydUNiP?yOF>ryq*lnB?kn$_~IQNG+SWF
z6WRC$XO&1;j;;%kfr{u_1QwzO)7dZ(@GuPRO3VjR9w9Md1zI!;z~WatFE{E{aMtLo
z83#B9W$zZ_wh=hJ;~7TyYV|CPu3n1H_Ay4ZhBtxHmkIcy2NaeQ9mq56e+Z&bH2!O^
zT1g`2Lh_YUsemW{xd^za_c_LsjhE0(1{Xdxbsjg%c<bzqKyF6%@dX@FTynR?g)ImC
z;bY>D%k7E(144+_YCckUH|>>oa(;BQYgOe?BS4hjrQ#d*lz0;fk6Ji1q&EPR6xfwr
zZ@ebC^c{O5NYL%=cbcasLI$23sH!s67rF$@)~_;J1M`SnT8zACwW~W2Flytg$N&oE
zTEHI<RUs^B>p)l&*@&*FsH1DPedTW3c_)z7sD>_H2fC}`ZYdzV@fxWv{E@2VlPAc5
zT(+qgU8YJy7uC9VcCXbDqwozQ29YgSHo3x^phr*Y8Wj=1Jn_QK6B!fY8}>n;vMvX7
zI6!Sc0QUlvupsSV>0uXY?id7SX(lfox56$&BS!J5J>j}b38>)+=Fr)mmWVp9;Dsyx
z1S@m=X_oyMfv25pEaeT6dHHcoTt&|Rqh`C~AD*@vd;9N7@U7xK!A!Y&UGxWo!jiBv
zRNHus*|S~|>MM$Z1QS`*ps3>oDoLVIa9e;r(G>>083ZFYt1YTTbTj?un^1J#qa6;4
zujpYfGb<0V_K1STM4T+UFApA|Vlo}y(R?tGyg&Z%^glsP@o)MxnFPZpno9Ir#S_`7
z*<-7ORHM~86^5=5uluJbhg=C+hJIPw7vluR5UN#0^i4)LSmPL*9`~;JH9f*|8VoXz
zL)0S%xbI6Mg0LV}4G-flgmBTz!-&c^C{U7Cx8}OWyI53_GB5)Zc~58(tUS&0snk4G
zhruo)z1urEIBHag{Z+*^@gjpjlrLm`w^mN(9XtFNd$UU9r;?S|SgjrpO2|WHe55|%
z16+mJQ8CO<PLCVMg^*Vhi@5J0Qr<PF7`PjnW1#6&BEh3q%yj@=K%&1ElpH8Oi#dny
zHTmf(j3aTdMDnP4(r&ambPcHF5=SJbNG9#hdFoCsBiMkZUkW{^Oe*v`{uD<!wv-`I
z4A@)$+{>u7bXl~hEP>@iTO_QA?hQ;7MMhHaF>JAChaS6FX^D{PfC4Ox{F^~hMoI+5
zLd)Q=AJQ^KaUcv7U=qOT{h{QfJQ;}SpkBizhD2O!CD0o(_gThWbQ_YXsf12{O&&0&
zMUC7V(x|({kGkIJ#(IN}{c@0%A(4c$x7I>gsV~<}=ToLDpL@IreNMB33sZiAKP7kJ
zCyJsF)vEe8>#}hEaum_<-%dBW$4<T2cC47s@t&Z@GRabuoze5NL=9tV)FVeYJ-Xc7
z*ho6ngy}1JuZ9F@t8sk#zELvdB(v2t2uOP{^fY6#l2~Oq=)rInT|MgacMGeo{v@7?
zDZ*c&B`dPcR=eZaGH|%!C|tB~5(^752u5v$-cq#3udXE^@<$8z5E(|f@0HE*74UzJ
zKyjuRh*_U}B<uJy6-mClO)3vR8N%SY_2^iVAWo?MD=)*#VL~nQpN0ucMff%`hH$-x
z)q5+k=4-6%baJgy2HHF*eLpMX26ai^EL1<cBM%JW3rtHk@YdM1vX-o5Zph6>Vqe`9
zFLro3K9wwNc9*ncrL=RXCm6(AYmWHVi5w^E0c+|u7;wqPYc~5yk<&5XmF0l8aNF@N
z!CwV4in}|92NIFJ{r$#S$3NTK|GCkbr>Z#?hR+^@{P+9{uaA{^>tp5HuMf(gLw+;q
zo>JUg<efhX_@Thad5_q@r2KN;IB$Todka%jURcY^=C_Kc5qa$-(d(qMTlfA5iwBV{
zeMd+7kw2m5sKx`oE}ofBJXU2eXjf^D_0QgGT1n`0qyvWQ?p>-LCQis)|IXS!c<yep
z#K$5lcHU|=NGMk-U#?f{75#Jk2jKRdICMyAtZ~}|?;7*h5(GZ9P;I#6BJhadD9q{v
zlw1Dv%F_wDsU(9Iaa)rSw-%*j;BDd}(nyP;w&;kkzTs6eBzmo&YeEx$i%@eVE%>4U
zejW9K?=<qj=QXY_i6kCc7|-w)rU+2p%odj>GdTsOO|%DzPd*Df!%Rogu`PrQK3q-N
z;&620h^jB$(wlsO7O2CKP+Sh}q8ZlZM96eX$QMq>laK>-u-*Tebf?{Gb!-rhK5Aca
zEFZ?R_#>Z)oHX}6489nI!=6GAlX~8uLr9`03N|%3G~W`?)BJ5B%G(->AAiW&c^kx^
zpgaj51N`NSv)cUn*WKwSZykRYP_LDRrF^l(k(vkL!6!A*ZHO0_&C?n#>fv#j6A<lE
zFNH|(%tu!YrI~Cn0lMNPo4AU<<(Z-56V1D48Nb@mN;Xaht<y6`DR;eMwPdwwkmZrf
zJ3OLjwcGz7FXd1>=hU}Iadz^{qGu+_afvwkxZ-nI=q>384`+?jm=f(FzLI1>Y3*=_
zHsK22V#cnllXATFc4Yy)_`>b6dUtp^o`#q4)pc^(l1*l4QDEYwQfSP-n0YbvykM6%
z|Hpf+p9wQsVXx%jYQB-etFf$@U#NAA3>K2Z^z|!8sF{gpF^iy>yPl3hb&9Fo@fgu<
z9<UQaF#4d+dz-{oFQP}2{t(!=&X2J3y|=I$ng>P6iVa?-drQ+}$^Gu1o}YAHigRHh
zWeZNK5Xp{N)x@aBuTA0(vI&Fg4K6p)YXBu5q{L`<_TD!9+DF9@3KPi{8oWP)9ZcV*
zF8YM?-q@Dr%??q#(JDGY?@yZtFO9k)I#-H^MV!;QwsKNOcudbniBp<s!{h&I91Lf8
zH?M-;Cm-~xX%-Vf5fCm$FVkFgf<qFZF52Lic%6A!j_tip2UgX|+g799PW%Lf70f?%
zh4DQ9AT<~Ra@VAzlhFwlz^1@C0in}yVxt?A+^dC3JnfF6K`>n|GM(1mN&B$TN~5E&
zLFGtxZs7#l9c+5>m*wJg)@q)%nw{VCNF;l<5W1X>XOrb(^R{)WRdb+1eXh+tpW{re
zpt<LTHBr=JWsZ9@eK9MwtUTYx@3RpePUnO?QM@FE(X69MfksTG=51D`L~MNac8Vu$
zGQN;A`dkFkB8$hp@eqyo-lt7<0*9bBUehDW;w%Bfc=#)4xJn&wscVo)Emp53GI$=V
zigtx<E(>*ioPD8q-}fSnODxR8(PS3mw~E(1If0G1(RoKKzz={cp^s^NDbNUkZU%I_
zp97ubo@xel)^=<Zgn(s{C!9ib5rBbV7;5QB(k7br$_t>~Zta6Qv9GYc4z7EXFC`c9
z02%t|Y1dgjqgzVS=+k)@AH(q-07?#d)HqpmApIy_WFQCaPSJq?<m`b!VZnjmmM7PM
z;w7;ltZwnEG5PLU$7;!}yGKBv<WzV`D{BJOns?)$16xu@gKg1d4(tLl4e#hbSg6hS
zNau(p#K2ppTmkcCm{wUzF^h6k2HGeE>ySa^F85x07@_WihKreOQIlVm;)2nV72?9=
zJpR4x7K~eZy@t+f>g;Cz(*?02s8bTFQdklApx1vZTQ!5U&~r^xD<m=GMAY;QheCQd
zrMJv1QDfolmfjZH1nsLA3_+b=9JTtQsMQxnEs<qvG1$UvF40$0NRcEl>6ML=5POUg
zQfdyo`XcaL(g@?Pb*m(t+-wtJd}ZI{NGGZeB1$$=28sHz@%pMi-HgX^cZeA@E<pwQ
z;}6d&7S9ofeL8QUdj)2N!L)mcE-mrifdd4-(no1p!<!%r3jB{p8L_P_=%GT+#oruE
zohh&p=$|XFHKNZK*wzfGv~-K<aC0~DWdBpQ$kNSHil2Qq@-HEa6|J1I_`5laC0Pr}
z``nB8W3qQNqEJ#z+um@0BbrI83N#?^i3hq0EP+Zqjw(bqbO7VTNKb_rk+n)tp`x5g
zi)qfyvs`r_p@x$W%`?`I@X_Mt!N)AsA9LGeV3mhD>T3(4j=J(3)Dh}KP*+&xp^obT
zkG7*=if=V6Fap4<bK1@wK{x^Iq6FjozVpze8;QhB7*n|rl61*=9-7RjS%@0FYo>=1
zg+*+SY);IcOx{LqKFl&1?hjpO6&G|lk)G8qJ%bso1%2)IHen0cEdXKXPu~W2XlL6g
zwhhY4-*y|^`5(Lu?qqL+s+1Y%Chl=WJZok<hI01>pIxMcffP<77PemJYCHkW?K+gH
zhyMIcQ{OOmlxu$_b=x_6uM;uWrSt{pvNd`sQ$!0XJEVW5P@gP!iuWlcO-7&j;yE?N
z_*rsB@!h{%boVgzi>yxEqPK7-rY7LvaT;Y|aMq3|wy7QGHZ^aCwS9{{b(s^K-l({N
zHNS;A)L5!WhXzO49nRm5bWnnyidn32Z?b^F3bnm;*+iME@`E59TAESt8HJfyLQh42
z#8noiS*#MwrW)d3;?UFCa(d_AhNE;lvQ;zM;9s-p<o=c{0QeTiDf9MmH6`<Rabxz1
z?%~!-oWqJT8&7BdEMw<(RQ}6s+LAVNO;^XNQLExFu?N$iuq0p}EPK^jtRUyG?t<p(
z*=egY*I*?avQMWn5YZ2JEcpN;azR{iSDK5fgj*O_g@|TE$rV`ChT;z0J(=5(>?v!L
zDF#WyxsZV}>;EOB8=&E>!;b>eO;vq->2`kbKT*0#+Bl_~EEL>wIqhBxo5OPzu^0HS
zB<WyI)(qicqWvcdx(r0Jas3koT?QhWpp%R7p@L4rdAOi6AuTHCqF(%PN%tU63}WD|
z<Ie(8POJR*at<@b{SOp$iaJh7r%E*&Ve!i`k0!^E=4<5)WdB4dmW7Ef#;iJjq8!V@
zBnR8Ld$|Z%VVdw@J)f-D1HjEW?QkHW30ox;7L&Fvcey0WePnJicsh}t_$g{+kU{gv
z6B(R$vG&mb6L+UBf&s;%P`<|szrhj0?^AInlCDnBV;=HDg|6aJ-WmjER92U^0ByR`
z6h{1HV0=6FV6%v$m)>;{cYS(HhMt|9O@>sR+a5z9zcd4)FY;>7=+Qw;>xF5NF`b@_
zb|~QkZsiJ!Mj~0MMjr%F91X(bgZ)wsix@f8ANR2J0$%~rI~d14OvA=?w^yQvb@2IO
z{>0tv&^LqypP?uJW)zm{+o~pSH2soj3oK&5vS1?|tP)O2TlJ^4x>n2jgtc@GJQqsw
zIFcQce}98E3)Li?h!3I;5)*?$bP(_PTU~r3f+BBiz{e6jn^)e<yYR-upRW(B>gj0i
zd6NwvC?aOY$X0QQS8j)v)PX&M-fS~ME#;GKM%ZGx;GN@wVPLEJ9tL|CttG@4xPTH+
zC4u}Z96F7Af~7nWDr>m`G9~TldB+hC>k=*eV2>3PEAJ>}A30_D>WhN2j-qzwj>tY1
zt7eYKIN+*gA)2ZsQhG68QMBPAjHLqEOx99CWRJ;Qt4cp29wXdibor*ajE6{xzEt=a
z-V|VIPA#Kg81(qvPm6Ba+fICmC?g;(y@_dUs=GR!kGAGgnRifY4L8ryOW6L#@d@8z
zRfm)NENE$1EU=*MXol<sEiH^Zb0vQbXFxDan4-%z!8?1|YGzU9qP6N6OZI4c{({w*
zNGPGp<qqe1B)b!pH`j8Ui>I(b7GM(FY{_O4!*<D%`La?zx6A`&*h)p&CK*XK+h~rG
zOt!J=e4S5rX-pL&yKR4EBdhshGLg0FWF*0|gZb~463zc0hcn^et<!&s1oZ3Gi#cSN
zzb!-8MMIIsUhMAnV-~x*?;|JUF=fur3amD}aKCf0n;S}91On#m|K^UNWJ+u=P%^ic
zRm~kH4aH5{WeQhz4OtTQa47VgbhgGjAfHls-k&s8av6#V2U;SY_})Ff!xAS{!)rO$
z6Jso3=~a^VV=A8c@=F=0%1TOBQ}t#{s_CN>XzsubTBT+Y(Em{VSbXmR2KJ##x%K2+
z0OM^#*wJ8-S~L@0AB$Wp4|6U~Iia$1L_l={Eg)e>H<#1kPnNKRgSSrqDIj5u>WfI&
z0xoY;N0ff-x2;BoM0VGge(#5i{UQ>T-fAhdWBfa_?Kc&~$;{b;IAH;&AWj<MZEu0p
zAAflI_n!aBkNjzL)35qBMK7p7L=pwlr;JN?=#<z*VkNOV3rlQ$aPeXiJJs}0l-P3z
zZqdq~@AzAZY@2Ay5!nf6E2u7@>2VAH>tX|Ejqf1CRI)}bdVm$@=vS!fxdXHT@F)`i
z1-2o4YvpDc`_O|nBF4g7=l>SiimV39Q}>I=eSRJ5zNW%AmG~NcY>}_g+9~t3rl9O#
zzRC%`9qy0)9*cS00gPG_`#)dy^AwQ^dM|C=9Q<O!Ki&4PuCHs<O3(ba68|Z(El2)q
zZ2n-Kz37qD5`?9emaxeBe@w3<XLIj~*N((fXSX4pJb_qQQxz{}F@1*_piG!+^6s~1
z4FOOuIb_#k4x&R-r}FsGl1PS>j6scyl_8nYG4butN-#5dSstF3bIQ>N^K#Y5`lmbH
zn1lG>GRf#C6N6<zCI!w3l?~1NL1n?<1S=GWe7IT`v!$eBGLB3f3CwtbdN@ztiOjXG
zhi)hlqWHsc<m?(#wjDp7UU!!%6DXcSd);zf{rdly=va95H9GH{tcuyT+<dA?3mX}Q
zvAi-Lp0(<T%!$<ZLG!p|)Gf52-m`pgto`hz|ILxatMyJKDPu%&B)1koa_b&Q?qngk
z^H)K#vw!Bq5icwiM{#=r6t@>e@%+GzBHlXqi=c>St4<s#VE7v&`K`A!-d~I@ZPnPw
z96OWDZ%*hh7(r!kKi2M3Z2Jk#&1cw+3O+PfkYN7NUb|y&HYbJ=h<$pKF=B%ODN}s)
zo_7`dS!OlDP0sF0Pc*B<{^qG(QkUq24>e=|k~zN0VViXc?&5DKED|_EX>8G?yAGoW
z!w>PhRDs;44ZZD2mr%n<s6M`kbIg3s8@FI}*L2QFC+fM$jn6rii&P{Xw@5`+TQ!ao
z&&ry&ORYBr<a5^^=w?ALMxFtgq9Rcf&N|!cfT4RL9$!YG^%7R;Xd~854EZ!OJv94L
zMsKRHO%Ya!V~`a|HNd!zS_OaB<@e^<&Gt(X+bIJ&D;S_zVQ-OEZ%5WE5%+J^G3wQ$
zJRB+%)KOx9f&D<>i^EN#LuEN^X}RSjtR3YvD4k?(a*-2Z12wrcg}Cf!3;H)u7T>q?
z@g`3k{PNOce-1uQ7xqi^LLjGrzQv^P#AIbfR1C#Hbe`h$JjJ=dA3INhOizInPsMP%
z*8#pIkz#{1_i!3!IbKTsFMh{t`tosYOdl<Nr(Ep(N=2W=nD?Pt@wTf!Zi|;EJWM$)
ze#MmXo;D^}sDp5Njal;5O$X~~9Cs8h@33U348ma?Oy|8k;blEOK|77{Qg?3kthXxW
z1o@_FW$#eSd$%IlM0XX~%nfvR^?%HBl^JhUuC7@7A5aXqD@t@KYtPd(Dy<&wO1udp
z`Cduh*!8r%Hs`%@td+e(yEd3p@xnllU$~*n0=hP7>PymGmwJz;RqD?w=sK9h#NJ0W
z!!@~~X_*4qK8Kb3cO24lAv!m;+?+W{)#nQ@T4u|%H;LUHI=WAsq{>6x%q{PF<;L;W
ziNh6>yxhnlY8XcGf{!<<hsNlX=b-T(^NzpY0|IqU{dd2X+ybGzYdzN}g^?eiKuZ3k
zR~wD0_~aBiM7SpY#kf1F($dB^i0O4+Abp=W*MN>^Onc3vU*x-t_<k4Frdmi4#8o^6
zX|!a9<i_GfNJnefDD_4ad{%xM$|w9{@m{0}7>n+KB(a1+kIZ&h%^I88GIwyYb;UCq
zWem=OOl6CsNe_$3Y0PY4Pnc|wJ03AlvToKK$#QO$QOJ{57|*ZHd^X8je?DqP`7ex!
z7Xhy)Y73uV9bJXAl(A25FdOwS@i_LyTk9&m$MY+ybF&B^0!ESGb%#TGqlcvl{)P>4
z1IB3GP`m?zpsBgYfCk%S`<;Jye!|an9Pj<Mi5lIAG%|wTqjxjCE?W=X0dNHYpkDD&
z`0nV7dUDL@w;v7$!4zhTeWGD3uF>huH@#ETgFy=3s`1DkrItiM350}B5YUkt4no+$
z-D5du9PXVTb@<Udi4(oD2ZSUD7eRa*1S9=vIO+igy1BZdloOmiU<`!t>Qy%3a4XQ~
z3bh9|#bj8kRf<CraR0;ZB`GU|O3wzK+EPjeAUvO4;nuhnN7%f??fLH~Ed3E_7@iM`
z6UA!l4Tr%EDD|pe{`1Kbk4y0c5>qs&a`{1nki4>}Y9*hj-gn{vS;4F%&?+Y2va1Dw
ztLU&vt-}Wn$Ai+k_Pq>qYoSnfA9ASesyCjf_vDQdZ+$$A#oC>}a>G%QT6vVv>9x{H
z02qBPC&`aT<`b1hO&*S>6DRLTYke3eA4#{)W(2m!FO-(Dhr$whli87g;;%@DO~EVl
zk$$JIg7xSt{Z3yM=jeD*iN-G`383_=j_0O)Ls%S&Cv>SK4OzjLte`%Z>E^A@1}5Q<
zLP<wNNuwL$Oi{ODkam97Gh`qRAE3*-S^}rEf~LRgFrUeAdiYu=NwGt)HJWF_B1f-b
zI%Fgsqhv+*!Bdq103_$IPxqEVC=j5lE^H(85Dp5=@euk&R~rK+hg3vj(c7T(#NJ_R
z@2&R-|9*0MlKi>j>A#C2YWXIJ!alxHf!+K(8%=`I<&X6$%V>OJ^4+iVuqQa_5hU1C
zr|7uQG2iswjc<Wjr_>d}klk-p>GJMiMlWrC;;*o2qK=`Q3JwbLHkO6MjROa5Pk}j1
z#B)jRDJY(gwkd||^yKJwprBQPSA4J}iOMk{>D7TJq>L$jC*Ri%M}zSur}4v!@Z-UN
zl71${mT)t{is_^iDmuF`t_)_Twqsvp=L%*QC5e2$P=<+-`GuXzJzr=P-I!ib%y!`<
zy6SunPOe90U3)t15j`#Qo`H7nLFzZGt4(F5>&B87bL!FHceO`E@i91lbDghMsmG~D
zIJYN_-#YAoI6V{(ui=Atnn|nLQ|M8I6oF6jc|ElRRBX)B4i7S(Os{xrqp_#G8yu;_
zCbb$}o3Nz2V<&!?cglX=IPp-a=bbN9!U&K{eJ{A{1p$bfHLK>u47F?z_de-Wvo1}N
zGit;qLL=`d&m1j$)7?!;;fK*jsEphOrp37D%h#kWU(@pE%|#EGHyP(Q#P{szRTzU*
zgk)Fj7hSKjZ_My_rku=Dh&8ddwAcAEI5KfbqFu#^nO9!%S=eN@Q6l_<43y-$G$KnX
z+Uq%X$s_Y@viBh}=!`dZa1&wD8NUHiT|BSA*i_n@gHf+LiDpCEP(0RQZB4_(Gcj^J
z<L~cYIm81hli!lisH@5a5!^wY;TLba>d|Xg$wi0n=4hgzdE(fX7Mked^(V=aO2$Fx
z(7Z6?J6UFRMQtPaNEIC_h@?CNQW(**OU=+zsy&L_I5{9iYr%a=yxTheWo(v~U??DU
zBo9<PP-BG!;@ZT^<>kssYkM=p19*U&c0`3c`nMlOcszrcI&2d==nf{K74RW4%GxV@
zD4PF7>c@1@0}_~JbCnZgByM)3#x%enYan|#^{GDap;~$AP)6$VfN><2L6C+%OV*n-
zKv7+hr7$u|=ZuF3rVFL&cC;rtB`h$Pp*By^;;EKC07E_~EB%i@Jfnc5%1`2rUD%H>
zBYL~}pA9W4{kA(D(P~{g-~b)ZkOV+)kOM%~HRZq6x|K%|(G`v=RY4f&sqQWRr$g`N
z=fLBuYbT{tlm#l|)Vosr*QGOI#Y4^V1?DNI8VHf7m(v*Q_`)$kfOeBmN>ye?Qf4{_
zG0q9N>*pYtXc*vG_w7{|4?C5C0`#Tl&h_5YOeoMv$9$zR=$tmrj+&kSL=?2HwTYnm
zdq;0iRo#N1+s)&%qlW+6X{!iuu3Z%L@5jfDPOG`U5dLPXjCeC*9*}~}=knp|<k@-P
zGo=sHE?)Y+UtVJ_O6FY?vWe5{>*~t7m@`##Zr08#KH;FDp@6=xGzc$K#v&H+Ufdg8
zdh7J7d4BGYMq;y;Fa`eR`K7rkvBi_5N#es(&L+c{+)S2Wo;0?kIm&V(Y8ppYi}GN(
zR}iMrv9QL<oCMFZfHxCb0w&R}fgj?QlwW+|2^|oc^v%SU^?nmylPk|B>Xd`pN2sIY
zY+nt$K{p(NtoXjaR>9%vF2bxx#@U3=<+ZIa$B9wE)MrH`vDPu+=p#8QR3`%ai{S^g
z@|!0Ie&@{*Z6j!ceAMgzQ+G6kGFT)W4lxoVtxKTP6+T(jQ^iZM0F`k=s*xlGXO(PT
zgK`qKfl5Th`)3kDnY8U=RkDI9juL7~+xef~_pdz8<|Ph|l-J<HKR=>@=CGu-ETD?T
zq`h1EepaTVJJ@{ERAIZ&Ta#V^-4v#lDRX#pO{{zqvx*C^T`dA6k)oW>RLyqy5h!E=
z+f7G4$R%j1dlk<)mkD{@$2GiA7xMX;PCv`7#><6HS-buIQkKdB0T7G1|Ae~_SI*8h
ztQ=bVB(V(t9C4twk>p4VLJq$P&!T?f!}F>nvT^XEm8H*rv_jW0kXD>^8l+Xx4~165
z`Aiyu_a9=mOJoPGmrF<vptm2F&D!2e6%MA3mF({L{7DKWoPIhA*W5CL#9@QNDVYez
z@D*+*wKww|QQk}0Cd0}RJCxS(cduOV)&7;357*<qI5Sta_eB>~T#zhR-DzKsq^z)%
z;bpWo4S+lmjQ?fz?)x?Gtkt~R+4j~n7o}bxPP80IRW!~O7nsGaDnbqhv!P957wujd
zD}d`Dog6N5a)samS6<HVc%Deb)WhAXcI=#P8?%+FlmnOWMyiS?LLXoyRVW0GP_e}A
zs*Nx?ujEefq;Ca}n+|47CUn1IV8wVKBtKmR0A9Vq%)}QM)Ie4?2!GL1oUuu&7-y@|
z)p$1S3lkFe3tS}J?kVByYQ)CuZdQ4czfz16<{6<U0U|=dr-%|64#FK;@PtUpbZ}}a
zzn12(4V_KzgtuRw-ywKL451x2PxJ`5(S<*~^SMFA%bJnIMd&K_UbE7bT6p`MY*F8*
zBk%hedA=@!FXIvWQlj2?5>P7WDU2HT?=|OAGVr0UkYL=^arX`(kc<A3qFSJzvqMP=
z>@iuiz?%$ZmBOW>NjL&k;FFI(I3fyvlcQEFsVxzQ5=-%oPYjG@H)iDIB_=pZRB&8K
z<_waHBeDPJpf-^WpnS_XrGG?vK1&Tf+l*62kwVSV_?<YV%$_7_L~?5$*u;}#hzfym
zI0|DD7nZQdqfQb7rUJA^!L1enhJ+czs-__FTU4)MeUEQ~>9C8d4%1Z!e1<JnqCB1!
zA#taz#@_xrD?G5`x#A3EK;EhyItVrSciO;sy{o9GRdZx7Ee4#8QY<*vo}yH}1=Pd8
zf~H408hS%#<dX08{N9MOSbCVGm13FE9>F3!@xm32!^4maIm^5|8jz5UG9Y0QhB(ZD
z6o_1!f30xUWc8(u08QMuSx@=O;U95dI^5l+AD%d@$iTgo)I@RdBLvaPy~RMrB|or?
z6YLBFT>c{ble>idOY#kGci;ClWscj*g0)JT50ikTG%m?>fN6NT>%6j=1lWPfIGz>>
z(|9aL1#Km+U|C{&ikIq-g9vZ(j{-KA1=4D9B-d0j+*QR+U#q*8ZJfo)dN&n1xp14q
z#6ZgNH_sOS#)hy<=1~V}H=-R-{Uk+aAWC9c&DmHRqzLzClVRAC&N{<y3|64#q;tB9
z3(XTFhV;swo$mB9;-?(5!o*_`4(s@HPJnpEJ+lRGna#i741^WEII?a%Jd4xGdFnnm
z9g2xQH<QC_f&8+u5NEkrcxWf50u7v?W#iE4wA{TzXW_*x4g>-Q7t({ESc7mfZVVYO
z)(n!%z9hZE$TMO}5E@<lZN_{hk01w;i2IygcjHa(V2l#+a@L)8VLh?cNzi)T5o(f?
z=@{SVyQT|td|4H%y!&<2dlU4!Grn>>RrN<>*w4qa%PVg>9$%|4Q+WwF9o|R8mG=rV
zWm^{i+pB7UHMP)+S|~;^xzwqCGo5vsOths3Pr1NVi(pV!(lXCj#QjRVMK<b_5X0m~
z)9z4=sbmAy!$I7UmgfC6iNdN3iFl%hmlYJDDwMU{WEmH8sk8LJ^-j_&fo&p~iazY+
z)A1L1e?`Ca4mM?vGRBQZ8gB#l_pZEadhQ8>%&<@>Rn+iTVNDGKc|OeRhJA&g|Muvr
z%N3e*cqx<`wa09bMd(Bu^#bfgLR748@shW$Ed)059=Hq&FM<V@z@HK%o2Sai-**4B
zJB)=wZBvttKeKQyDle3{<ORC8$Y7Tq`?NiNJ?&rDbU0L^07P0uYxa_sgD8u~9HevF
z3h&K}i95#ZS~=Ia<)O9MED!mt6_2*WITtT)n2PcA%bKp%2`}YW^M0axWFD5T8J9_1
zvu%%40R7g3MYGWyv3}ptNdt`tY<~(j`mS{QG*8-%R>#Lbie15^AU(x|MR%Aa+D?!w
ziElUJ#8VueSUbexN${Ppk{s?u;lE28<Y^wjQ!%cxrn?MsqWVxql=ZsR1PQA@ojnYb
zMFnKIW?J<oHW+=rl^ISfwQG);k82(N%K45G&r8Ba5|gWtZ%?G6$>pXZ9-mddrVD1^
zjAA}gQdks=Zz3PDw89UYN0_V?jd5)i2uA<<AVtNDx4EaDl5#hXXG&F5)i>!)5P3$}
zIzK{rvG>-e>?w^_$`4PDKA^=YxMf_b+U@pDjCAdd;?1z1mGMDGL{L|PWVfvYmJ}-1
zb$Ew##k?C>V=ZC#JaTL6O06n`I_Wi)c8}RYQ*Ecbh&I;@UzS=#at#qSi90~ap=8c|
zVFjUnZO*jvGSX?I@>GaGmM6wAfQ#`@;pa$ztY+*&2219yv|@P<jD=<^Mn%>cW_pp*
z+FEFtITR#)UoOb?a-t<`PJvOnk<fTtEXsX}(*^gIyfMX#lZBGVm{M9Cy^vA_{lMaR
zxq6>82JS=!sqNg@&B@mB4$|fg9p$5mpJ`PKn<(3wa4M$-^Rqrw-~X11dXflEV{h&E
zLi%{2gPz0`Hx%O~`IB_L5vtH^iHk*HL_LX{V8$v=t?b<-kXrki4yD$XJ%*~-(mz|G
zd+X&y*zCIGp)LSz*(lcEJdtQ=jYXujQ+X^fF{gs$MW#j0i~4I#u3bu$h5OZJX9_F%
zvKx+)ci9&ajEhUgZ<irQ28%dj%r$-OrAt%KRJ~IS_2}n>--;>dEYHCc-!AEoJ!1={
zhAk|!^znOUZdhUQpbSzMnatn>Z8x<yS~+YL@|7}tSpW)q>^`}NvhoWVjs_JZCCSL?
z!P1+%u*Rha#<-dQ8-23V4~NNKA9>v<8uvm9^raLzUCxa#R|m+=BUa!|@%wD^_s<Xb
z-BpqxFlF~p&<Bvku*R;~%V0(8Wpga5fNJ#@*kjYq89rGi8^;~$XUS)t0X+Fm+Zd@p
z7E#R@P5xl+<zNzHNZcUCr9~RZS9v=nm6VQgOtbDUvjAn-$P4bEGDe*wuJ}y;{EUt6
zp`jMb@xV7m*O5uFQBiKsz2`GmIW_e~1&c<?T;Z*M?xi)x?~*NUQH61?O@mi)*>@uu
zSKNZwl^%@w*I`vvc^5+6#?v8ik(mTt2ZU)XUmAikyDsTGRQYqymB+{+X&Gl(bC(&5
zklBn?B+{Bc_X=mIEPyEHtCe8VhV*w%kChNri(Vz4dsA5P{#tTVI(_|}1(oiQ&B+pF
z5La;cLh2gHF!|b%^5s5}uuLDLG6K?8fGdMl*_<RzeOZvS^C(-8uwM&Y#WqfH{M%`F
za-R!f#;IRkZeQcnFJE*Tr+$S6rfC!}oP<;pgp>FRX0q>J&*I=ti%!PwBVWcSKkz`z
z>_m@1HM+@)L!Ezsn?I#RgBcdiMZI8<&|=!(gLBN<XP`wVTWHLwL-NO&YsM{W%?g*=
zocYc1t9?tlKX_S52coubE^7@rtdzxw`j;h|Qj#BwSgiFtgahxTJpYg4+?2kj21UbJ
z+RV5qIi5rsF8CMSy4+Ohb6tBE%_tChQ=B%WC7!AwgPj~}Rn=h=FU6RuoG6s0nJN#X
z@sQErLlL|znWU0|>5^mfFO#GRi{|7*(yXt;&kWw-+yVFEAQ8qbd=@^=SAf^E3DQY(
z-`_tvZ8r{#<f$j8&;|Cn&U5y}n8aO6snhbd)22KMGwHCzrC~5E?tYlYFOH`w-5z$`
z9ikH)?*)(rQYuRu<g9hNk6j(_wSG^Ao?2%Fmj?6%e|7f@dh{f^>P~|`*Q$7Dop-Iq
z-U0Q}z>BW$_F6#V)G}kp<{|@gKz3yfo*m+UBt{gHixl<Kv$ij~Z0{X5c2|?|mS$#x
zc4rO!dWN%tC`?cLY*cjOEul$2cXKE0m3z{h`zAZRlL*Pb(Lb#El<l*-_|CrxdYiq!
zE%{#+{_X5+!++~rJJqWAZ;ifJtF>p_J3D`?ZP&J|&#SfPTkyTM^}PP<Z(eoTh`9dE
zVBt?a?{8PL>u{7)Z(jNT(0_Qn^6cQZjiay^jG|zp*$+lB-VC3<^xm`&HnukQhZw|7
z!L;MamuYx;6_<KtuU@TJH{eIjdl$CDVF>cuI|{GC^5}Cg>+0XbQExcw2i{M}z2SKC
z>b3R_76GnZ_U~d*Qntns98_WRYRxV{M$Pz4{0l`;Ht@jE4@V*^{9bGS9sD@n+0JU_
zkAm@tzy_m!IMDVoDCdxStR-yuqRSb};=5}+0$3OSg<ZpvUwoOJO0`T457m%lv^Rc-
z9av$GQ88zjt=HVx(9Izn^7L-IOn5A1YUelq^bmw9h|=RX=ZF5`Uc2KTwi*rPo97X1
zycW5HBi*f)**XIYV;_}CEqFTafXDpFr#Qm-5Sbogab4TcYp*Y615h5I3~TGza4zUe
zYR{EW5Z-6oeU%iJ<*&PXzKsj0A@56y%a5`j^5dzR<dYu-xBkU!8gY=7`b)cyE*e)n
zz-8k#bU6j74|`;EW#5A&f(*jDpwB>vE(t}R2m*W{6hF!%M%5>QWAuM`C4HKrcW*;|
z5e`uArv&%Zn}A~02$<s$zGP#Z-hK9=-SnC!$#fGcIzuI#qQCPx_Fxxp9s5V8r)Pe<
z(>TM6J1g7f1mdCG7i<_zaG6b!auMv^;pp-M{Q<zaTNL{7N6S+W8gdU?_p!CAkLMIW
zc#h_~S`wE2b=Svd=7ebyN@WY|h451_{8AGB&B=H?q}6ya8-6Mg&}$$ye66UgC5XN{
zUJ~n`lGORF-|%P>$$&}?dWe7Ws^#PmNJt_O<q?k;SFj)UKW?&!0Q`~OK4<yi$T)F<
zRj7F!#b>=7nTrEf0lsm}4vvAQBBR(NO1le_<61#KzynE=i;B151f?DMO{T#hh<jK5
z2$MbGbWFR$5+eCw`{O3kCOOc}srzh!x;qQheXiA|Tp5zBL?|Uq9!@3frZ-(*c(S=|
zRcnic#SdE3-el&-V}BU<JKH4*)~Gza+q?h?(#5xhIeiKzL0JHYnvFwk5gcku!J%&B
zP+tUx`ciP%vT@j21c$8*99YDr<q$5R{3R-E2uIV`LeO!_6BK~7Av<cyQ~*ZN=mK|$
zIh~7R;@c_chS2U3Oy!u73CI2w8h!AwGDp%m6oF~byRj7kpDvnDLsS9e4!CMx&=ZP*
zS(i3jt~ysyF!m_gE0jWzxt~1IHx!o6^dKED0;ty?_00tOL=(`*$K!WB%-w*mn9@`7
zm|TTonDKtuCy(~%F!F?#?Ww7dOz&himn@mnpOEWH?)I#G>>V}Vo}m4F+Dfz#V|ET2
z?ftfY)@YHWRX1c)yzzR@q)JoOQU`G3Pi>&z5xNN9TpCZLTuoNhR=rf4c|XZay1yOx
z?~e}rH)Z32imFYUYALNRXfp&lfF@!WYgoH)!}@(2CK6~>-$ms_|CCy^{+shwyCe2W
zodIR;CgLZR_y(6=qHF>J6}5)ss?lQTp6CF}X=ubUQ50NbhAnJc(t%CyDqadeqG}?S
zlW3GM5nWRQ2S%(qwQ$zHU0S!BJi8gh(Q^VhNb_WxsNhpj!M#zE72QP|OZDb~{g6$q
z6#OKJX(dfMO_SF(cv*6fMVzyWExTZP=gzl{ZOOcbniBy9H`jdAU`6Hk^CspoB8hm=
ztYKS5*Sfb!YA<iWRqrb$#K9*4g1*PQ!Be~pMD;fT%_z7;X;|A;A8Drt%U1Bp+0Pxa
zW8XFQ4qB(D$4Nypn#Hav)NiqRNn?N&+#AIdV(^4pRJ>YQ7~c548Sw2!9A1O96im?%
z6N%L7k|KPW*n2@4{z>E`K5x#ODB{lF`llx)Koj7bK@r$FpKahM%B)R$*)@|6DSl#s
zK6r$W*@Kv%$Ls=U?lIvf6R}ae4_Jyj_neH!?L|$<<95T7vUne~wqWnP!Ayx_jZLB6
zc-jwe1AVD4uO6mGi>P{tDf7g`UX)A@wG7c5G?3{u45lSIyg+ABl512f?9Bw~u27sw
z1mJN%*d2x-f1urZN$Gv-<%xBGV2H&zve4lO5ekCa7m}#_q<oH|@N&dSJlK69uSPob
z)}$p~E?jlqP9s~wThH7`tqum=PjUj23z%k!m6_S;n_%#iletU*h>Ui~>X0IYf~l;N
z%ne8?qw<vxY|hNbISy0!>V;XaO^VJqqeten$^-W9^iu71lq~x?98vp=e&o$Dzq}tv
z4{(!7*V~gx1*&QtWH@MD?Y^I{DL5dZ0BAQl{&~A`P{N_w$EX_F9_ENwH;BCTfrx2z
zy5d#6-4uwa@a0c)efd-2%TG)?=@XY)qk2d$@r!r%&-|m-srLs*Hacp&KiWI_^A8BH
zodz}PQD{{FR{UK~iviyuC#uO1;)7<(KR!KZ;8TKG2La4y*1^IPlb$(E)p82~M->y6
zUW65Ke;81!7C4glvrp}o_fI?jg&lnJ>M{D5bN*Z3ezuM0zqPIH`tut6Uaf6a>pTB@
z{`)QdJ>dMe_F~@o?_h-Xm(OmP#@n|4&R54d=2yHP0vZ)4VwYir36Ur<Sns<389~W5
z)MWqo;1@hk+&egE`9}z0Wu<yoe-5maQ}LZ%aob(-pmEkQ>b-E+!}t%aS}mhrv<>xY
zu3lS?anxMhwjATA_1qQhanxN1wo>D$XCP>eqwYeldD3b5?M^$XS94OC>NQUEYMJ2P
zn)UXHN!|y&cs#9ol;wOno5UVA@L0Ex#<OWJP)t;6{aQ}3&-=!H=d@Mje()Jx?1Fo!
z&hG#eIj{+m4o>HF(An!~J#4SK>z;PrHCi}oMMJ1xeE}Gm^;>&w|LicM`Wt%zU~MS$
zPY&_%mG;j_$-~1G(Bo!%UtmJj-|V#;1aR91n4sHGvxpUU?1}^ubiPK%V2bK<yW-oU
z(>HrZqN=L4XIDEshtAp^7_z9bp90i6ReXgtUR2Y>J3IFeTBm3J{z=l;i<C4#fAQYI
zd;e(f_tW!^Hp~|&5OfxiY=G{07Fe8XKZ_$U9W0L&r|!*426dSxdc|iM9Cq4j=+$=I
z)tbj=dadU)24d>;09wB>r<YzGzY)J?b2!Kbxmp2kEu#`})N#A{8*^awu0|Y)j|a9p
zE(8!$vDz~GZOgIL?e%n+unF{4P0R44hX1D7Sy_P}rP@w8V*{G@E>c*uuq~QUuuM$Z
zP3p{?%J1~bHs{I82Y7C+co}QH$gFv!aXr@Dch@{_wB9x}$%~3tM)%3KAnIjwp6m;v
zUPjl4Zw{>C*c+0p35Jf61EOXIjsVlB&6P6{J^Q)C2*83l(CcR)3_`p8PRC*^YgP~N
zDwt8zmhe=ylff<9F1VcxZrOH`qT}M0Z5JJ&CRm22t!C$U9jJ>0sN(GF0H0;x>0qj7
z8Ccp(^(+HNo2i~<Aed&VoeU(?Otq7NV?!q;*UX}121o5=VB2u9>+`JHPjS_ACs&yZ
z|Hlj-wQ6My$gI`R>hBG@ChUE+^UE1Yc^)9ac#)QbvKBrC$6Iu2gT^ZOQm+N9mewv#
zuwLWj!2jjEao+Ho2P-Qzlof6%9)F%_>YOdlu~*VJmF^?3bB%!YSAio}uHJ3s)ZOp2
z6yIl5d3#h<#7~V?t5r+1o19v8RckA=R)W&qkC~N#D}G7p1=+xidV{=91qbb<6i}Ma
zq$<v*y+~Cd#r3xiKm(OLQoYNn`>y%+U8-^|tr}|d!(9D56^D&%DoZEl%8I?0>6Ok;
znjOD(-exspt5(h?jqJ6tpGUsEH%EyoZ|@#@RfS$wonMSPq>pL37%iLHvllPsXku7J
zsA8V=&nEF%=ZqE%nX!#_n;H2>$6WlzVB3vfng`Hi9|pTpa>BrvjJv8$RnflFKBLxt
zHNXA#y!N&H_AlnOujjY#l`{xHjS&jiE4dK1sy2xILy+pt<A&e<{bb*Nmyf_Rn}TNR
z<2kKu`kAed=Crn{XSQw~{643Bih2sb{_p#+V)C0mPgCw3wq9zF#@`&uJx`6@Xgz1_
z&r@SJTA#G%H1Dz1ayi79AG&FH6HMvZHuZoXWw)r%GuG3PGOh&O-j!E_4RV6E>Ikf^
z`YcMVZ<Jl_2ENjag1scVC<8v~cklIU4+I(@Fnu5b+YSU;CIV9pfvJW-y-deL?9j(E
z40K{UkA%c8#svX9_`rBXiX&UcrsZ96{R87e3=bt@_-FfSALC!*|Cje|mfuIN{~z==
z{D$|xYOphJ)vD<K->UuZ{jYEG@0<Dm8=ZG}I+;2FNWN>A!^CY+^Tt^8C3=dHQFHE*
znb*!ROp4+>(na=-H2fxCopW7C>s|L9*UqjloR`s}$ng~qmK~qbtL&;CU(;PS@;HwA
zppi8XbU}Hx-vmYM<lqz)X8+y!-mi@&Ypy>A&qPvKybA)&(gGG~4z1oc$fCR3tJ`|4
zs8E0QwjpcOGHbv_eY_{D)t%LzRjq2<&T1e6-cmJCbN68f5S4e_UCYW6=8J5Y?+<0A
z#+;7N4)>`xRX!v_0;xUma3_a%qzQ_%(Q3SJwlU`u8Zc-|zsRkFzB@2nSB)9f%ilH6
zsxQc70#&(|TkS`GPZ)i+-hD`ZXMvJgR%>_AA*#x2t2Svkk^>(j_V-Uu4moawZTPL!
zJlmDYIB(NMEgN$CSHJzPdD!vyz=%I+w)gj12NVmC!tq^pO&jR>$x-tdEUvTGDIGvy
zEoF@uH8bmZUJBE*#(s0}h=&De@BiFBKQ^0Gb6UJ}wn$;VkL*q^Kcv=5&E{m7CA*I8
z<vVu3uxjj)bBR4LJI|hNJxiCLV8*icDb~aI{<EJuD|SCn%c`-mvz4xM*xCb4mRS79
z=c(}=?Lj|#(jAnN1zMoeA;YMr+?rxIXM4X>g%WyzV3(r*Y<RY@Ezy1l^x;mQ)#}+*
z*cG_4;uzRb>r~Qk8)29=FlOiUeWQhrOz*!|S4tv~2a~#?`?qld+I#YCzqK#ErRf5L
zsavA}YNNv+)Z*jLd1>+~9tNW_D8=G87<UQ@2OXfTuq=#;D$rWa3_@6`J*!sFkK7fs
z*)Q2G<zRFAVabP%A@;Tsq^+%Vr627|KU(wgrrF`EDsO)8G*;{-vF&&E(ay3M@P+v7
zT0tOCi8JhVaen;X@4Pt@tg%&no*^HxUi)lszroArkeDO|!Fy`=Xj`iA6>Z%&N2mKg
z%TDXgDtKK7AtXJe+RE<mYl{z+kX~)OQ#lCXio&fDiD7R#<YGEMK_}@UJN`SZ-^q{h
zEWhGG<7n@9|G2&KEaeya<-FMu2gT$NvBNI3as{Q9f^v3xM90l%rzZ`pk=jI%;9z>T
z=(Hp?$!BlH<ZrK1&UjYqdOpRq{r4)zSt3yYd?oo4525w|s`jaq{&dKX3&=kOttqjN
zxxwte<G8u@nY~-8qJv*sEf|{~DmW3Au81Ukfwv|u`Feu(chtM0(eTBy>Ps)0?0U7A
zUjKHQ+%UtsanHX9WB<B4+0{Z*FEA4dSOL36MQr>bk+H-yA9rbF#vS`!3Pb$VH-Qz#
zaB``dX5luQ;GHP|io-x~^fv5d8sa<SUp)AVJ_|5y@DfI6AHmy5_j?y9tbsKE=&t!;
za=A;J|5JK!@fr+Id=IgP?=;?=G&&n^FncHru5S%OqaL&0M}5WsRp{zNns@En?Q;6X
ze{F!Sc@Y0~%$(}~>einO67ua0F_{>8k0;&Ury%zF)A0nK-@`nZM8+@@bWDZ-?Sm0D
zKO6MCV1$v=ec1?MnUf;sz*v7GFh^T~7<qHvwilxK3W`!{^@$=7X%!b^QdqVz(R7b2
z{yg#7B-j;m+xg{87zy5BI==Sssv><fu4iI9a*ipU=#1m;5GzL3GTSx$>R59h?|}w)
zRF9t0Wt#0;^_l}kZ@eQq;@sLyRtF>Z2A9^#0}Ah2IAfr<{e61p<Glt@K#Z^Wif{O@
z0C?k0XV|MRGE;*5bRG1=u6%exeeCwA-iJh2;`8&yiOzq0zIP3Vdk`3l9dPVY?sZK<
zVFRk@cQ3*r@RE-2?D__vbbCQsE@3?XFdTj2UUWiHS9;%s(`+(?+3{Y|1v2@yJB!Do
z;F7;$4=_V8NFF^Ux5r6IxH_SVV(a6^L35Au&YqwAd~*8hNhMu!*nHDyIlk|oo}D=h
z@SNcc^v;H(jF(Sp2a;+4Sa_}9Qzjec#C_k8g*B6wIOP9cc$%Fo;$S73C7u4b4rD0(
zQS;<y|HHezqr<1T)qeC3&d-h-zZuJo0O(Vd2C#SD0jj)xdf5D}aquzSTF9b|)(0?a
zPtVVicEmynckQa>E8BrR+2FtgYV&k`b%kCMy~ZbMrq|?W$2&{(NU}`ZLn-ue(`p}{
zF@t)PzHifOj_|4K5VIW;pm^-6SMegF0|A$BBXVlMF~2WNjR;b&I}z)uLfpOqG#tkv
zzqM@?j{4qVW8b@`rxf_9RDK?q;6%YN=!rLqv4?+f;z6AKe_%d(x~0Ug3?sXpp6&Z@
zG1Bl5&o&QFF}7`!0CiCM(FHCPfUt{*SKWK#X<rQ*MLIrpj7ajp5G@AqzB`-+-n2Wq
z3|`U){+C_@Pg9JK)v3vbqdLzZQG0w5cSE{(74d!nIBoJf^^(*fl=9T{t`L=o-;jk(
zjLAhs_-1{C!@CG*g#6AqI%6$FY$UVr0PvgMUd&qv`dusdoGsFEGzu^YT^C3Nq$3#O
znFc{!*|$WKQ8ZYu!Y}J;#INvRX21(wF+wruVr(V3ioh^ui6^Jk&;&o_bB(r~6TZ`T
z7M0FhE!d~)+QZt6G=;Cvrc*pUHzj-msN2W$vM>S_Q)vP6n=x+5?)ZM)5Hzc4Y)Oxa
zZ@`)h2c!*w83m@sEJh&(V0tH{i*u|B(QQeP<a|eMUEW-aSPz^|yCfkdV~V^X&cwzT
zVaoOB$p_gwF4($bw$`&<5NakCC$sAd7$E?1b)9M)=QTEaPVI=~?4vVUa^V~_+h`!$
zJEK*Lt!Ud!!wI1L7B|E0NW5NT=$w?QR99UlH)!Yxo#Jd7UgOdfsUl&Ag=+A>NG?*&
zbQ+GR#1khis~)|V{lkX&?+5(&hj)I0*)E%VN6r6i9C&~HWY<VFTUq%7zOVeTDb8K#
z((8)$H)qAfI`3DwavF#O5l_d%b2rnm`^he3tmI8S5>wE<K$lSAv{;335|scg^mjMk
zo@1OGptX`aq#sr!bwJqR6k-433*q9L1X1({iU~|iOC2!<=C@k;zhZRhk>_K{)rVs~
z|I@~a)c5|_$oc2y3!8I97nEX1pM)HyLNq)u)><7&1HID!b++`xq?%+`G|wa*^#ppe
zMeVHmiq2|S<4Ix87K0+nW^neZX(5=Yi=~l(sf*3^`id@Tt3s_v|E#gF>$6!|(m(ah
zuExYO05bR5pUj5*0GILU1P$~?TZ*|BUA4IBPU)6Dkbv}};4bLRSh~@vuSqbvp5aqn
zBp052!wd<nFAAoVIS)fb;A0G0U(^dwVphC<7?JUex(ub<5La9F-ZuOLHpB2v1wPg!
z?toyPfMGx?3Z*AbU_=4vDNuZk`ic$gtkw8+ui0UEO;V1$=J6Tsf1HMkpi>}?-L%#C
z1y7sk6Sx1h%ON+Yi>QbkMi1XCWekH9pag+dkmM>zAfyO@2dF1W8z3LlBA<=GH6q<i
zI3Qd!gx@=-twsU?hnk)i{Ho21V=7JrjFWMUJivqH^<h^|Ok0~lhQUoROnga4EkRVN
zqwRU`54}k+rP+bv<l4`QJglQ5Rnbbe7|ceTKwni?#@ya;2sKc(MxO2B!)Fq{*^14Q
zpM&WLFif6D!=z8Jn-4F>cR01IReJ|#2R~!S@TEWI_N-UmpjktZgbl|S@wjoS@Ea(A
zDuphP@)P$db%?9+46G_?uywBksXI#woasaW5mc`f8m=PeUwouIjviW)xWt4J4LVmm
z?v01o+u42-Ob{FozCDdYpuX9HhQF9AyAeUU4S*zFE^D_ony2qUl*J$^Z2cYML$E^_
zY=hSmna^zW1h6y!L^metj>cdxfVnv3_tp}$oAk0CU{(<%5rMyq5ugsh#nVO8U>I_i
zi}#2BkQyXYg6V>ly0o1dup&us0L2+eZT>(Hj1*S1WKE_ZVB>L2&J4*MUGH)@z5o*l
zV_`rlrq`VYP<Q|W50^Jy{>Mc`{D8Re(pC)mRD?Yyw-KLGdp@K(KGSQV;1Fz$;;=i6
z#_U@F^HTat$j2d^A|oOa*r9B__XQ=Sc+nThvx*WiXITP+2z6GFP!@&s0m{8qjV_UI
zMLKZMKOv0rB<}sjA1pb03p*1E+u1Nyau&B8+pS68U}HOn{lWOwKHtX&1dMMOIeU8U
zI4=`Y9|MZd+g^>Y=@~YcQVilqT3VF0V;aCF6wy1myNQop0INV$zkHQjX?PtZE_-Um
z#OGE?GbVm^tMGavn&<}t37s8HP~A~&H2knSt3t3|T@8f_oEjKyms~cO4P7l!lg{dL
zAl{Emw}J(D8OUa;6@4X{dlg<@*~7$nM5hVH5Yj0}X`R!*B)XN4OQc*%CqyY*ehXqa
z(_;bO^$aZ_YyE5E3%MRZU~o=nGPL=`M!XlE;$;306g$!M?5}C>3bP?TEh4cjtqay<
zEvQ^dG6IQI)1`G(SCa}^@3AKJC(~d8B8qz}(tyS&)j!OQ)c;bX*_5<LwDybDCcTl2
z(<1dr8!R+zQ}jeI4Sjr`5J=qKf7dv`2eid0q5Au*adN;miuxp^5ZNT^<3Z!F(IV5x
zJ(ZH<+$IS9)crUTw_T|R<C+5Np~6|oNYS7TEe@3?FWo$bM@v}=4C!2WzI77>f%UHY
zu&2)ma3aeU6j2=mUl~rvQlKsZY$-4Z*qU)G)AUmx7Jnu^jcx?sr6cW5K-cKU5G4~v
zUINoau?Cb}*vX|oP#C1vXaEzUTyPa;GP<6`?Eh;ikv1b@Q%1F?>gg$b{aHwN5Ln}x
zT~%5i{$w1*`oRsk)LAH_BI3|!SS^z#A}A0-e?Zc}G_v|dHY&oodpf;SuF1~b)0X@T
zM*Ibv3H6K;poz(bh6Kf6Aw2RSkW@2_h&bVtS%*#)=pFgK*B!)CFTnN$393tjvcK68
zKrjm)OhC}57q0a)nCtHJ6KJjh0GU!%0%D$FaBos?q#Ym)G>Ke5f`YVWGttMttf&Tk
zlc%33sr6T<EE&AcPdd4`k#+TJT8v-aN*T_gs@sRH1!E-msMEDyakf_T;z}^(jHT<U
zp%Q-mV7O$6h~sSOI4%idN~5E&vEx1RE#YNEztw*4gA7j{MW-t69UY}(zWAo@>E2PJ
zz2BhAPk5)Xju$sw@KQDDil-CkFGsYu@U3Z`05Y5;p0X#37m<=z*WC$49wkSSH_oHT
zTxvYcB!Myo<)L5}2-VXe2q-!cRwvCMyOc|46vVe<Skb}g62@PF_1nWsBf<z&K(uRN
zu<WLIFi`>1m)1S1zr)~~QgospO>TCA5();$1v2HLt8n5;Pd0x+1MDK?t*r|-j1Ysu
zHXnAQSV2iBeM8Ay$QOW1AJhraG1gDj+oUsP1?CzUcH9?=UxYHh3+669#-|1k1Go#X
zVNVp;+~UdZY%&pMH2#AT4l%1cjiHB_lWa|{uO%LPZ||&`*o9&*z<<KI2Et#Vyg7fC
z1uGDQv*QEl^FW&w=>Bvzf-Pu5w6qBU0}10RIVe1?R)BOIkR&3Y%RXEc6YGmqiJHMa
z1GN#U_x7lC3Efl7UN9}2vrS&jq@UinI}D;8Qk~!sV*iLNYRp|lE+OzVf8|@l!uydU
ziZK)l6U@K&%Tej`tP5&e{3RI<<6>xB@L&J)kRzs2LJvdJ@d5%~Eoe8+4^I7e{(c*y
zQSD3K7{l(YXv?UxpF3^NiG<GeHieGXQt({0>Z!mU5b5cZn{+jc_Dhilm+hBuOedUL
z;0~tSMY*EKu!)N|vZ&%=Y$0CgLgwhf`UED#NDd^S5y*D^8C2WP*4}-6fl1AyiHy&Y
zf0ME&l|%dht1w8xq)4r9PiIsNlmO*iy~z-Hbmk*t#roshQK?J|Hsoa;^f~ke|3ncd
z!e&5f84YI>Xa>x!4#rAlLkTi^uv7O&7=F?3;;Z+<v`@~lRhd%RaeajGKl+=g@nWnW
zt4iv(U2!PESJaNXJ=UVUKXAp%Upw+w2LS~@^_#7q-TBuc+7Y5&sQ+aoQx(s&Yu_mh
zVsPt=-N`r{ANV%|KOCqsVl43oaS|xnuw+>Pv%na1djb2~k|2TEwSOIjMm!`sF_2Ob
zMMMggrLSI$d0sh{@1z?_e<;lS*<mUWG-<B*9*w9>5K8{rvSVr@BLV3!q+(&@L&*r*
zRM@=xRr$wJnzh<(9XS&~5(}yg=W0CcV^U%580yYLD+B6Tu^1RR&H03PllGKe7>9x}
zA!vKtx%$So)46S@c3V!V3_B5J&9<p0)()6rU38^WT4zt>*ERrjdvgHvHZY*WhG2_K
zssCQH_8Wb0T<-cPlx$gtyM*qJK@9;$jtCu$wVLuO7idTia)-=IeKV!FX224s)?T^D
z6O=9)f5D2oLJ;BK{V<~USE+mHUw{G<jhh~T30}(YV3l`=5&SKbl@#ZJB=zHqA#tD`
zO8hDKBEF}>>^=RTaxNyMml5TieKWKg>@*Siue&YeZ4TiYKs&Q1?i&E?LylTZN>O~%
zS*J}lbuU2vV)r8UArU2(e4&11>=-@H4b+dP<DpDHnUd8;bh`X2D{7yEog+%vEaRQ*
zk|Yv}8AjZF#l_EShlvXsHz@uAtYKJGbeg7o59EJQbWzZIgG&@GNxyl)WrI(j*}|3+
zOMzI704o(bXnxdA3NR^+Wz3gk2b2KX{R0-kfDc{JfVC&s3Are<rMBvmv$<VE7TozU
z$RZBY(llETfn*DS*t-PnSy%|-szee(2rQ)pr3l&U+;N;`I1Nbl>)N!+3C}M*av;7*
zTFu<V9|=}*G%jXjW@(>Kb5+ii36cdy_0|-ZL^y)eG$h>yq%=OY!%6%XjR&zXPJyJs
z6iqUOakNdljyehCn>}aVBnoEzv4;<m>9!f!g`mClX7t**vo^c-BeBQOZ1Op*0z){!
z*wZ#y9_1VaQ52AY-gA*tfU=NO$dLokq^6=`GLo@qz_Grn?=ZFvJYX%$xTF2A5VvLC
z4`+6xOW}vjba9HjnSdV2vq9D!$202|weoECgE;812l(uL^FWAn1qW(ScVt}C)9C~i
zBOR1`1lw(p8wBHwg)SIv8UqUMx>&!W_mA6fuPY+o@!`A41U?cLahF0Ef>AWnrdlC+
z8xDse9DsNZ9k{5y;o^v{!U2yb1iOjE7sj?CNPSdYGW@9Z1v!zak~-E19o`DQ`JXd$
z8h!iYATn4}9*ek%1-K^b>*;CY0e>gwk%rvu{}XTN5xsD~AAwaMcf4dM3X&W*(dEs7
z_V+9vV~{%<fgGo<iqt$@d`ZToXnuiIMe7&UCFCB?a^mfc#1)7{E`XFr!xA+eo$eHE
z*7dGYG29q-zW}YMZz%xC9R;R4edHOGk1Hh3vM9@kLlMg68V6E>-PS9%%v~89c!j6G
zr})FwI74c}UQQNX6f68BeYM*PL<>=_51x)>G}jo2J&Zr|q^AxT81-zL*zqjB9Fq%i
z+8qqS-lmCBKpqQVG`p>skEB3O5FPrUHf1i$L+*{vPcUjmTv5gNB)k_Dg>+K@cr?AP
z9zr#w#?>rF&x1iOYGKiA(`%0v-H6<DDJhG3DS~xeR46`r1&3DZ?RfML4#F8vLKYF&
zLYdNh3F)d!n5UUozplz<zI?7-@I791WtRk-4~6*O>3@5g?Q~1cr4xWgK{1!)Ed4Ya
zO<)`Qv0mM@CYmV3ho{2n!cH7xLZx=PiMN+&CPlWQ$ZMUQ^F?3IWK;;t`W!5`Qdk<O
zF$0hzC_z*BjSOTD<qSK<ml~ILKHwZ03f=dI!iy)XTmT<h^$hi~-L^rT9d3H3{AR1d
zgTlxX6M$=3tY`6<ZVIExL65tF(sj{S4gs{-U?)m!VT^TzdK;kbNxMTko1XP2iJDkU
zQOitr^E6#<q|ZsKYPnS%^6A~LD!LA|U4=JtQ8Wp9AxOaUgEPV1;ip7CZ9jkUV+DTx
zSgm+F)fY8tf>ep|ZkuQ&BoEFY{>?>+P?7s5C~A24kHUl=5ygZxhm`U9{G@S2$y%ii
zhdL7rMbunIfu=h2SsWQ-fDch30hJEbO==MfrI%awoMaPHDNtA4n?S^}f}rk;01w#w
zubCD=@dRtKMnMvoCWvlm@E|mT+B^*`=TmLP((^Av*<S~j*iIyk^RH)daObn@B=Rwv
z8!ZL&uaP$e&*t%K%8x?teobe?z#oPYx94y8C&8fh_{qa+9#wO>%Ld^PFJ>fQ@S_O@
zJ#E=QsL^$Bt%0ECsn@?K(trXL)FMXaqG#-QzDz$KPcl;q_RB#43>l(c%Xd4WkhM6D
z^Xy^??7dNlfrRn`D5$_OU-rD5bwMh`K_DP*AjFt8S?s*q?~CwXA$}>hp0_6gw4`5a
zJPG6xZW7JR(Xw7BqBQ~;aop`uREoS1`AIUAp1u$7MB=>b9yjy0jPaK<P=q{8^sD16
z?(k^uE&A2yE}u-gvSPo1LABnWG&**@I$dEQbC?~$+C5l0i_y_RFB&sCyN>^Rb>*np
z#vDAI*6$@(m9mGgK}$F7m2j%Eb5ZkqQ3LJf;CpsYUpfw2TfZf)CmX-%oqq$ZWLgAv
z4c{?3!j$mEaR6RQ5kWt~2RyxFGKh-WDHj?>Fr3Spubn065U2)F4ll9ZNYvBq>-p_L
zc-!s8I%*CQAOJ%%gDNaMF=nj~`%FJjp-dFo#DQ4|l3i?UT;n+eK#PUMc8pWl=RW1p
zum@ojCKxJ2bnHkwLp+E$PkD$ce~N*NTB;IdLYMTB+wPahs~X5+g&NN+f`e{$wUWA3
zGM}wFIcya>*a}10CNWXVIw+Qt$~CaNn$&N|Y`Bt9csiWf$b^)J!!_nZ!YSHy09PN`
zv`+D})}u7O)BI=wsOJN4EC|UiBjK$PE`wXP$`TKba&pksYtvOD?=uL$hQSs%O$3GZ
zaD^To{M`!h3Ln!KV#b?_TrS$Ah{GyTViSih0MVec;MCo4EE*Yb>}Won3A4l={!UuR
zN)`vlvWB|8$bqXE;Lfj9G|%=otqd^u5bb9x1<V;;^rO3$e(N__K(D-7#V!O(3(Hd9
zv6165R8M_9-uq46C<n7zJ*FYiG|u)X{sa_(YcteYM_=Snz(dRAQFM-^<(PS!EHb86
z>(NZp##o9wAAY;B?{UuCpMx(XHpRWiti~sM#|>|71pB<eb<Nu0kLs9;50kxFxdD&1
zWI@f!N_(`ORdSjM?KB(QX*RqwPR;`*^=CUKyH1eQiKd_(KA}z^pR<;6xTv@b>9#==
z#VInV&C!<MJa~GvjXzKMk5l?9am2Ll9NSuwmST(0_+XOlqkd90+}5jXyQ<Jy^$Wlf
z73V`78^BK8(8dO!Qyo$URp$}aqgm65$BrXKK+>-hA2sdb<YZG>c%=UwjjZHWpa^;6
z1de-WZTktkH?+YEN1QwiH_vNm$izAyOa}Yt`98gS-UX}9?+z)_$fXctG9*52{^g94
z6*;r{9v(G*bJVgz$tD9^*s3cX;up28;tRkb=o|xGu|*mx7YNEDji^FpnhYw^g9E=4
zfo=woaVeKmwDG~W^lm2K*vn^oMpkl&QPC>6$e`@_jXaVH;~Q9SN)h#4?Z`>`K@)cm
z3{6G)K;4^eI3&p+^Y(byBz5{_9(qNIBd!PfKt+#g6+n!Ga_&~U_jn1WA>SD2j)cos
z1|M;giU1>$|6ubJ7JMWoV*z0U@h~Sgx>FqZB$&vn5F*>+AiQ&=M9Q3wl&2&W&}$AF
z{l|18cJxI%q85<Y8o!po5e%v~9h2YasQCu}lf-NYOgKlZfFS%xf+;Z*)+XNVnMNG3
zJMM>rFB;sgbv-#$bACJ0gO0tZ2T}pF_DCk<qVWQM4Tiy;JbMD^mO9}zSA+CNvM~7+
zQzRG%W2mScAQGM&;#YQZ(e)KW48?a=Lkblepv5Lz(Ul=BjDy<sZ_IWFH+k(eadAE2
zn49D7or=Z47OK_@#!4j~HIgJ!q?~ZICd?4`)Cs!s=^B~hFqIR9!eGQnsySzR0w8vx
zOe>jUPWDedQzXZfU~N-Vp5R%wyeq>Nr^o;WUCAU+iKQW94i5KaHbct86=>G1Xin#i
z7??yo?CR9MMTb$}r*w-}oEMVA^_^mpk^-x*XfW|9SA-D@8fZaVGMGx{oMT>~ha-5B
z3Em{0_#%<!s!R?t4LJ8%6nC#DG%;PeZAM2}eaS7bgajz<X4##u8rp6<Wfkx*w1Rep
zR|k_}m)MnaF|0T}KxOvaxEzAyuB0$9{4Mb|vXxB{^8@CAq%*qI3PPl!xgN#0vZwzQ
z*}cWr92hA6t6jB}=E~Wje|Fw}=O4BAQ8n>TPVw&c8G5FZ>@IetxfR4M@wBN{KyTp8
zD8gjMGz@~LC$s2^6QjwvJoZ0=<a=+0>`n$g*7k={5A>pmrVus<1wdjh1^7ZS6&S5R
zNA&Vexwz7C8N^1*Q0&sU0Y_d*Zj^j~4^!@m#9o&{nWA{`#TL?6=#t)Nju*$d$FOkD
z{=%+T6g#qSnr2<bi@T&&b7M76#>1ii&+!FEs$(`hAg}a>VW9_wbk4@*E(=>u(tq2|
zZSU$<E=4@g8H7Drxj^FaRL+W218)Y*?HFMS`})~og@RAvS2=wn-0Gl@6-(75-Eqa@
zqZ|DA)!5NsMU!HA6^`OvbHCEQYa)Pd?sO-pqDG$#Id{RrfzwgrwR56cH)O+?1_^b%
zYs|8E85m*0DI-t(elg6})Qu(CJms7d@9_Q#UQW~VLm7qd8~e`h?e`7$_vZ20k-KRB
z^!WJn#Fa?){a%Y-^p$m2)^tLzIqP?f`ms^p*#L7Ck!eJaC$1SYlhNe(&2Rh|8^=o=
zw^!Cu^R{Nu7P}GB%RktE<G-mm3OEt3yX;UtY1(SM#n)Y&mFPJ*R{`dfM>**%Y@Qr6
z(9eU9YPibz)njLoZBM%DKmiQu{NPL+H@X4swJG0-8~cn#?+-a!;vv2sae9E2bUxx>
zYnV`c|4oSA($#In^GDrl*em~Qbwxc7cM--VC@XKg){}~+di?v}sV)5HP5J?Z_o!dJ
z-ved6gOQshA-$-h(vy-q6G2(l+IS7!=Yl*tTo~kJkPq_x;vjEaAm9Cp(Dn}Y&S0*Q
zjtC8R5=^f;^~VFEy8|>jo69Kl(eVqL*$}~6VtC!^2I%0(>#;g#g9l-jjV{RGX%Nq*
zBkzf*j<f?AnTOg<8nyS|2DKYT&0usqnIvyhX*><VF0Obe!Yb@#ub@AICZ#|2{u}?h
zBC3_WC$GHHze`xTT;4T{{(zzqwfyNP&@B*B85($8n<{@r!w@!`lJ-`pT2-0&Ft?Qw
z90W*uyHR$O9v`k!3C$XpMFR=B0*Kw!&X4o~ROD~)3pRHkp6bYy77O%IUbUf*xVaBq
zm(o*I${{#C>xuav>6Wk$I>rSaf^T?&LFlio`o_){8YEp|HDZH3Jg@;SCWssKR3BH_
z+1@~v2^!&1p}dMp&I6I(nPZPI5N}nejceSVk8emd^j^R6Zo|H~xByzm8t5$35jq%d
zIbU@*0S-DDLgFqXeiBfU$QW2@gyfLgR2e8U;>SgI<bU{`Q!qp_sZrh7s_DegJ2TqZ
zosIOF!$+D&AR<e0mf;Vx*groyD&27nu5xG9;J1d3PEX#hlze(x=k$>N^nIX)_TuZ?
z#tG^orK^fJl<VZ*)$=3fi6Qd?exS8tK*rat;D4p7a#`<v3Ukz-O-gqa?+bAlV)_I8
z@}*4gVU@k79{gSgJn%neJG!kZTi#&<`p@@NRqN!S`QC4xo}V1}=Vv8YHht=8L>=|H
zAMB=|aPb=vF|R`8#mTZrOQN#Rfr$g#aXbt*Fu{wsC?HNCL2<`rwMscc%z*r8Y-Q@B
zKsvfbPulQghA+Gf1K<E*_s}D?7~Qc-DHoi*1_N||$v0~ijvN3bKm$yGj2#eYgr-9m
zX;LsOh7P09=O+Qlbj$Ao5y+yP^Qe_lBo*h=BR~w5udB*P8R-j@5D^-7^%QXqw0bJS
zwTpo}uozyhk`IvcnP6pn1K0J<A5UWKJH=Lss^on}5><HRBTYo!geVEBjVe0oDx;uC
zD$~6Lt%2o&x%pC*n~91@dv!tX=fofjF15eN6;GQmP7XEQs+VjYC~-B+Jc3Rw0F3D*
zhN9PX5I<m~qbfwtw)}v7l*_aYGdJUr56}hl|9@#03dmx!xdnN<KLaMGpi6NXGkJRf
z*+qoS(QT0sU1Q>8PE77UHm7`}>tZ&I;(rkP{bMsWzKtg&XVvu(bJh#e7pK}L1tNTJ
z@_I6Ji>+BHcm_{p&M$SSedyAL3Yye3=1gSJWzjj53YNWgOA>53t!^=ez`7`PE6i^^
zK&2-nEL!S<+AI<qfL?%|vgQHRZS{b9OrR#<6hR!&G$1F9-@u^jG>(1PUGPDN)00xS
zhYxMbg-34RvX}8sXoxG~A8Lcp63AK-07#xQj9pnnXn;^-<24;?zIsJR7l%iuzX~My
z(U|wA&4V&P$3`mx$`3#6s;)#|qATc$s;GXxCRpieryBe*J`9d~As+f0|1h;<@*d&2
ztaofz<a(>gLg-P@;3eivyAGsoFB3|w$2Y(k%B!O_!1YW1fa|DuBhd@CK?FEcp}j<~
z(JEUJ@%TFI`7x%UM19rB_Ar7Ks<>ZuMoU+%9FgaYoVV!ChDr7%REo_Tm3XQ9{$A(w
zn38WF?fup`APq#QLZ}IO-@Wpx+A>0rsr8LRG7y&v{X%#v1P4LfyYk0Vfue?v1K%R(
zP~wdTBLsq2VD#^WQ8H$irWK&w7q2A2Cgx*!r4xwfo2Duod$vqmGtWLtz#h>cT=_7~
zr+e1!l$)w5x?||%0Cp#2cv)Rb3*)WB4@v;$c}5mC8K=!T*f0qjK;}SJ1RX{qK3C)c
z%**_!T44f^1==NoVKxB`EFk|kd*W%bf*aUqUHQy7PbnQn8DKcC1Bduh$_BAR0ZDnk
z<MfZ9QxHW`^w9I7CBNGgM+bd2xy3J1^TFfxbgmvg9>SkG{y;vB5F(P;Iey1OSYnPH
zPhDBn`PnXmZj<gbqV2aky^OM$$c?FfLX$mJ>Tp)4rMeP`ysqcj%j6jWtse|?;M@-g
zB@eWkrj}6_ugHct2Yfm(8<B#U1WontDxSM&0@xU{F%7QAH$eexbm;n6aQSKEq!Y|s
z(U3JP(H<{mt_p2I^*OrmuY0NWA=ArF;z{1hSM@p5<d>1JpX2&cwa-O*#j&>Nm~@?T
z+iIQQi8Cf(nj=lA|1YDSIGxT}2k9mv^~yqRSP9j}oj+Vn^TBIZp!&#mT%MfC<3kt*
zvt@T5FQNM!=$e|BxtKJFkrNc_{<*MH(tIvZzH>eY!{mf<7<bbeB+8N1;v3$oy0sBd
zCftFCw@SeLz*E&S3<17_ZjrT-^2%8WhIr<z)y=G_6v#NkK-Bc3JHFx7o#^|T?R6)N
zZ#Q12?}csB{T?v}>{LFg*!c}iC$L=h4)}1XdD3pQI>s>OSI5+6=?cFzPkvGG(4fT8
z5AcMS!@Hn59RbjDj(_`;{~;-#iV*0{tH<dB^X>2KY{P%+TRYXN_-~EA!@pX6yY{!*
zHvAvhWm`2UhcC}+fAgx3gO2%chJgv5_qVIrbvVkYH?RDE=s%3DI6L@l<0$L}qbS&D
z_A$HoAPlB2y*KTHjjfISA-ZqT$Fx75e4#^uQm^dQtF;#!^=iH5y$jpnFa#;*9Z_n_
zK0BRO{~iuTn7iMXG57C$Wt;2Y(7As^@ot>;X-s#O=nXr($!jMqOx->Z-+d0LlPTB5
zr5Q}pJRWfv*qO))(v`1j2(PY6TrHB8$t>S0`>M#K*x-mUJ_|`6$B@xwI(~RSohVM?
zCIn}up5DcGMO4|O)p&A`MwA45@s4tvXzG!vxXc63ul?mgwuL0I#$Q1|{(t;mBLAnr
zy1hr~BVYbM+j?GoM)JS<yjpv{RYUo|^St`M^8Z`>dsO)^?pORI7CbEV&8yee_i&v4
zc1=De{GJr7Nk<AnS+fg<<I4y?YsWNK-RR2u6nx<$72H-ZFQt0XuA4d^VMSeKha@Ev
zU|{OW4<A9Pg<Yk3w{uYOs&~)!=;sdpJfPp}&*;k={8??_&;5D@8*JC`kDcd9r7Z%n
zy@fyb=;w<={Q0Iz4GyZ*nxPWBefqgaP@mK9TU6)GHZ^$uJgHPa(4bb6s)uz#Y@ZtJ
z5bSOG^oAO5QR6q%!`?nsCA1Istmji=bkcBWgLp!*dG>zW$E<Vwnyq)(Y#bdVk3zND
zZJ$2*vZCKOq5l{UQ)X9d=T~V0pt&{L;*Bx-jL9ep;fld*&>sJTxW35fMyr;EtEiHL
zYf{6&wY}ddh%DAb2=re>x3-hfl~FSbV_7K&Wv$9QDD>a=jg~gFVxxk#C#NTet-ZH|
z3BDt^oza(BH47uCrJ&8PqRqulQ6As1d3>wx>}Y2`lkd!B@*Ovm?-XV79h=Fw-79iu
zK9}#z<?<ajm+#Ey@}q_TkmB-fYgM{yW??*+%Xj8;`A!a(?-ZK@i^ZS0SMJVy{@$6x
z+(~&`MB!^2pU}>YV?!{j=!W{P^^rD!-PNy&UzaxqzA`H|%l}s15ki7{hL!(^@%?Da
zZ@2dS)03m$@gATGvzoUw%ih<@0(~5`I}7)5;OZlp1hMbke>mFOy<bm-2c^l8`}DNE
z@R&%b-LI=f2SsvrZdWJ}?>|$T;JRN=g$Jbx(fjnYz)a~9{eE37Iw;y?=5|H9!TqO7
z7ufggtMIt={o`JJEihf?hIY^179JUIv~znq?YwKW9wylJ&F#MZEh6OgO*d~Z*}3<y
zc8YCQjt&ZrW2f*=wez5zYG;9+Dx;^uBPzaAIeRL+pmrA7sWQ4+bWlZhs+|YzR67go
zR2e-L9#rw2%GuKbGqu1@mC@CrgDSF9?L2I!+F4|$%Id4|xE9!{+<ncTt_;)bp1sW*
zS%yhCx3`DwR6C1oQ<<F=p0(5-wPd4BRh?t9RTi+A{&=VnXIlvQof|vT+`f(7rD$!j
zLo8Cgkd^iS&4GdF%paJsL(T2m*ky{=7CXfv)r;xx`6Dw0`rO`4nOwNK6swChSh$Dx
zjaD%=d~xNzh=?exp65-8p@GlobwOo1zuQF?@6JMt*VbDXsa{A=%OBVxi+5+C#cQj1
zi&QVB(&Ue9p~Y(}R9V$CwUosgEP_zM#k*5z@!I;%Tr8|*EAo2M?ZgOU(?`J+Z((o-
zGx@~5yscL8#*^N-AH1yIRS&8)Je<WV%6)#w2A_Dl#1zI?*A+b1#pKfT6(Fdy-Z4E>
z$j7>vdQFBlkh+8I@if;N4{o0Ru0u79Ei`f<{M`5*qx{;94kp`L*)mJ<^E=F;fz{sp
zjyI!D&s&)5JCz^aq=VnP?tAOgz<#k7KGS2Clp<2kIFk&X2_f=jrAOfRW>YO)82lyL
zsqCvUUlaL^cSnj~Sw>to`7vLW_9(&URkf1L1wPeV{det|cn=0=QC<SxwA<CJcD0><
zZ`F!4tXmDY>i^#QF{|Oz)fJ2bC~4e-cbar=`pGrbdW|1`C{q?8HAR$b-=~}RG+m`9
z_*0}6IX&B_CGxg$(r7jJ{e4&;&9@?I-Q#pcbX5l@VdFK$8;I5M$1A!&hk>o~<;_hh
zM>h7Jcxw3()9oF-J*Dh67-8!IW{mo$pRDHEc;7HS7*wm%=~W(=V}$LBWJQ_i0)b;K
zyag{)EgBu3oF8K%#+8*E$T%7ilk4n22S#`&Ob*qw0jy`WVYtwY>w7<#>ty9Rxb989
zloFCcC0=(>FIj+c7FGB&^Tw!8Nl^q()M$2)v`~@xh#4uEPO0A7zIy5%FeQmcNDaCn
zW^MhxzlJwPV*+CYQm?FhUB&-@3L=wkz;H(It8QOBHi1wmhbFzs8F4}_k(E#k(O@+>
z%1U}NwIJ@Qb~jpz>g2V0M1c+lVKoke<f=5{L#s9%O=humN!b$GRE3Whi)39<uhp*0
z-+=pHc~A7Q+3!8jXVps~am-asF*-*ga1%=|G*8aXJAUUJ6K84CAVVUjuq-Ell~5)|
z)#G$fj+hs<ceYCjb(k*PAi@_~l0P|Hw7g1~&De5i#NLv-SMyn$#v-_blQO1QJattd
z(IoKEb@6b3$b*)zOg!Jr=1>imc%9j)MM#GURp(AK@4(T0zICc;UGQ@<Y-%)%s06sP
ze-8Wpb##GJ%klN5JJi$9edhG*$;;st@1KPff($fGoq#sjkoVOPwo?+=PZJ@sfB4qN
zT-qo|pvL{S)8@%Rv*mX%wj#Bcirr6yKogpD!JO8Cy%K6Wfa|&&y9Ab$MHgX=&uYB#
zQa}^{+CiJ0<GnNgSZu~bk$*Bp{^|XcMT&n)Qmo(vL3JYchfMTfqx$DZu@49wIh(#e
z{P0io=Mk7EUiA){g5V}xB8c%%7w|W~`tRh7sl+q5A@AxyI1fXKI(hxt3FU}-ua$X*
zFt1H^f8TSZbf;zK5U)OHgZYT+jmhk=6+V17=G%O0ZG3-=MV2inl+0o_|9-Y68ck6*
z7ixifr`EUXY2c7RC{Hr>=G0=uRIw~=R@LoZ=zKgV$yJVNf0UYHY~IF>%NMrtMVz{M
z&QfkTv&;$jAeP9#IFh%trr<-_nz#|1j3{~aT_CCBUGb`NS0TW!yb~}!HKC#Qmy@xl
z_u~QO#?vp98~Y;Q_rdWQ*fp`Pi3A&slhfk{YJp$PP0l6lu@?YbaiX5P^&$80B?z7-
zgMD5aY8~Bwp9TSr*0l$w_9Nb^FTT(pR|D6cv?^|;dbUIts>I;ZTNhinabj>a$k?tH
zQ<jXx%%oCqN?{g>n4p>dqC1fMd>`h>z<ffa9f&t8jAY;8LaNszC|#NR9r{}in#Uzq
zWL#O>@Q_zZOk@y~&N#a8<EA>HDFf%rtNR5i|F;sFx+cgbC4xxlgLyEiF$*$%`hNJq
z5N2eV|BC6L$ih%B3bLueiRlMpScSJVwe;`}&<^ukU0;MF@q)oX<t?`AQideH0Ugof
zv4SncQ;Axhb(mrXg3UIa{dS|5;sJn+b3k{gJh*d}Zs)e$HrhUAQDLqH;2@s2xg3?u
zv&K(Z43(VmIoQeKr;NI+H>H^=%|*P4XTwW4>1#^jX713&25rh!v45g?r99_6yM$%r
zw3&^K7!jblx(OuM>Xnrz3QZ=90_m-k?Gw|^Av<?69mnI|co-SpO0r4*4?msM4{kWw
z+S!<%$3QcsfjJLGK`h=-6xF9xU)pc0@;MOec{Mh;QIDW&FKGSK21{?fu~@|<E4)Ss
zFpq@cRq0)jS&v^u?|P%)vWrhZ;*+DJv3T}`-e0~Aqd-3RY}!kBb&}W-eI}fhBR>y}
zRhYKqvs0|XUoc|;Y2!7@W%vo5Pp08b`gKR%63Hcim)tSMcxr>Qw?*55pqa>MF*_h=
zh!0%;2Wg_A_h<+r^Oc%Vt|q?QNBFR`?V4A*#fMH`7c6tPl=tPauph#z9Ck0ux=z$Q
zdB1l=+^s*Vi9bp-5d2Lzfoy%r)<$rd3e`er6sDeZITrRfE^3LKpxef4EZF2l{p5+F
zfRdE>$_FR7z@=6Z`S8<f`o$OVqQ*^k8qyaO!8-bG-Io*d>gd||u6*^-JLyTRQT8&T
zHvR_Ijgf&grY3QteRcbfNIv*t<D8|Us@`2@g0z-d@Mq|;`6D(=mt@=31TZCqBnLb@
z|5%XlGp#Ptc#@G<rQ12tk>m>b&f!&ddQgqKf6%h@{j7`<Djb2>3j5MR6L6J%23RP@
zcZ?c0ESq7BGbQXB5uZ;!b5+eosdc6ADyy>T%lYlx?y|Q*thNA@{(?=J^f*bdN2ra;
z*hH4QKZ(b9@Y!GuBWqJCupi}ZGeoTU3CI3ITg{w}V!jBrHUlaB%_SzD(Lh$9r{`e0
z@u5VOj8(i)M~b`DPE(tRl5F-ag^8gv)}}l>v72d9D*KFK#oe2uv&Gj{a%v%5FqDhf
z;f8^39<&aExT`G$tyP?(vr#%fTC6rok&X-j#}&lDTPggp>~Xa_LgAj;9krzguy?l6
zi6AJ&^|c3R#327FYf|%^o15zg#h1;K1Ldd11LTiJE6lk@dDV@tX&p_C95+AbUhOc6
zP}EYJ@qk78a6JArn|Sh+MA#;M5BJ42BJ~>D>Z5;P7Rk7Gr9UC4l6IpLO>Om}6#=Lu
z^ONltOKFy=)tVM;LUN?soO84r)BBlMnQ{W#wze9K?y2eDp*P-pnwa#B&Yu6ab$Wg#
zrOyiI$;WEn=T%eFiWBhxAcI{De}16mA5oAZ4air?Du$Zn`MbZ(3H(4|*e3-@ghQl7
z+?w!m2Y0<70K->*){t5%$0@e&dYygE$DJ__QNb}3-5ai{TVGe*v>`e8B+0igUt2(T
zhqd-XJo3m!skn#NsWIm(%nwz~vNoP&>tz2g>_wD)b%Cssb9bWu5gSp~mhz1^67R3L
zll%o_e2yH;*$rNa<feJM7|6Y1%I^XZJ3T+K%6cLa${nPmygvNe=G?<Vxes`*ea_{G
zW4QV$lY*sCOP)XN?CbA%iw9cC>d&epAz}ZnI`hu7cvSrIO6uKGOQp*=UoysMo-OHs
zad#7cPB1(6z>jaoC4FPHYKOz|Wxb?-EW6IDtU+sQLeY-4*6+R}pW)RlA>5q+JL7{n
zA*oR-l7zeqoAg*oW{Qg?6RZ=3zAk)z2bj`>+DXVq@j)ezFk;LRWwc+_PAo73J3sZT
zba?;)lBS6d&v_-CCLG*A!&mM3&8Rd4HUu2s+R5Rp=Ot8BZX}JcdX$9%*?uG9Hoezg
zwXBrD?6Ih3Z5aSD7kL>7>-=gDK+Uuk)~d0&U;#UR28+r<kS%Z|l-jf?Rs&V4xK}u;
zObE5)t$@UjZ6+?vi#xQ1!}1TOA9PTr1t5sipUlHCngz8*w1vy49}K#)A*-vVrWndc
z-9u6r`6(mbE=-aliwQ8kp3r@PaL#-!h)fqBbCqRmFE}Zo@P!?S0g-B>ZWcIv)EH3c
zy;2)K1rOuvqx|5>Y2)mu+4)Zks0_H(0(eY+myuo0?f&8<LNZ-lkP(5TV%jz7=Te?n
z1g_3iCWLyUNU3QHjDVg#j}G5)DBc7%FMZ~fh9E8vKxg?0s2@W$rV}wqWZf}poQM(s
z*O1<n=1!RfcmDNf5?P-7FLPC**b{q9@33rB)S)M`Z$ngm&5$j{O0+uh9p?;=;#YM2
z-%eXEaTU9x|Lp*HivH)8xR5WVK^I>f&g<s)<KspLuOvtoUbs60g5IrI<ck7K)=~oM
zt9r0|#QYb5j2TpvElQ$CJj2eOi>h*9YY+X&8GNFsar_IuI!w2hj`rS``FKu>O~hD;
z{;N?W*P`QGKam^OEhN5j@YImo&Lbnqp4P6WZ&6m~#e(XyI@iPL`FJy@*CeDzr#;Ad
zY39)b=7s^`bZ2llPWm#=qO-(1+n;m<YHJ1A9wliFrRb~RX!t5<re3n@uJ-Z)M5`@w
z*j=ONo}`6p#LU=)c)7abR+|Xos&z_F6Q351@+7#L8TOy3Fhw>XQ}uA@aSQK2wnpb3
zZqc9uL1sl|se3I>uCEWtk$t7|Kf~~*kCOm8H~(|J_H5_b7UzH7dbU-6{`_y%+E#V@
z`TypB{uckfS^nqlusgj@r+V&v>7gGv_5B;Ai?%+~8c2Vh2F}`;l%H}=%WJ^xUz?r%
zcX-FMgAX*Gw^wRa>;3rsca8m@{o_XKZNuL`>Ch|C{MKReAme`tDJ;tP%|sFbC`;%`
zlW6lgm|h0>Gy%S>Xg`%`q=@0C##j!4j0;DXiKDC4025y1epwp~r(g`O-3)xxQ^l_n
z<FCPNI26BL4#yYWA)W=TX?5gRZw-`D{Lg4S3f8g{*9d8ghAK#MdKqdE4#s{w8scoI
zyfi?9P59ftrf2TZ@l>TpTsN;H)c)6k%bDK;f^h4g*Yj%^VT@quv}%)wKMZbyp;SIk
zPEQ(40H9vQb97Og)5Z0?F5VuUzS%p<@1&mUWVq~cY|ZInDdX5SIzd8#Lb%*<Je$+S
zQpT}kbTWL5aXg>X#Zt!cB8OOGP?IS9_o1Eqm@|^4byCY)>huoFbT)c;FX`1je1u-o
z%l#2LF&F&uXQirv$J<zimO{ZjU^1Ec*RZ2>FGl!YCT#<-Z`Crkg6iF&_@@tf3P8l$
z*-Keaf5L$4{<ItA?0?oIYa@oif@QcgK~me!>u76<9X-qIXnTnr?c{azY>6G2l78B|
zz=sV{1zTbtFH(I>m)^&Zu5k=5`b$)Us;*%KOYNeT9z`@Jqk4&*)Lo>)I!o?n%SEq8
z=*L|BF&^6STB$CvlV@3-)Rx$Zwd(u+#VmR_RC9^nPL~38%UliPG0!M~_4`2_^x}tD
z1GP-p*Rx?f8UD}OC9k9KE@zvpTcYdE|LjLWciOx1ufr(1CmkPiq){~U)k~&*G{6@z
zgs0;kEgVesGoHm1G>_1hspf<Bc-xHwe871W5aZ<b@aK_oGMV@m&lDyk2q1bzHtt?7
z)s29DTzvQ%PYGtDZWM)=Bba7BaJ_#=kG=NnrI)XqZrP*+X^ZN@WE@80QRWcwbaD|d
z!;}CA4+Z?KX*Wk?S+XAtHva_-aWwV^!2?KVvLR|d*LX^HJpn<OZ*$IP@p?Aw?%h(o
zKKL&CZ8zi>vd6Q(qSOgt*m3WgcGY}|V@?US3!z~_#cEN%p9Eh}rCM}iB=~}s=b~OR
z3BI7cIUoFwDe!%w{dKUs38<wfSaq_rX{e>Axlhx))RCkoTXnL$k+`S4pymJPE%@Gb
z|1%O|;T2B}M_~_5w|+2*uO4URt8U^Yck?WBG;uc^K8_&J2eZsxe#{)pRnRTyg;-c3
z=!02mHyI27qv`hh(?^mD`e>Hb&10_H`16GHvH8o^bREccy#bg8H^Jy}7+vpW++P}N
zyl{6CPlrn#%a7UJEO9Wkl+DI=RMZ2@O-}9dm+ka1`gv@XbSkZ+h0Neo%Wpn9Gs$}U
z+&^v{`;Gm5ztL)y?#kYOt^POs&mP5Hxk6vXFwm(2JM^0O_d9RRnk}j~$1?(Tz7}=f
z5cJtF4)HjFxT7k`?HmIU+*wk~EU9OfY-N^gXO=w6EZNB{d7fGFBD3Vj?2+aWA)5-d
zY%<ic=}^liL@k>VwQN$<vT0GvCPpor8ue^y)N^<un;P|OYSgo-QO~AEJ)0W!Y--fA
zsZr0S##S~p*q8m^o+W5J&y+Oqcdn>e#5J2<-C0M|X<;g)(6UZvAKMF!DYeI=0_u@D
zN_5dgv+JdLP0^EkeSsHJmg=cuuwnn<2R13N(;<|1drOY1l8~>)(Zf%~EbaYM<Oh9V
z$;mhhDOi5Fp;QV!a9w{n9heF;x$BqQ!;5qe$b;jD6aPmy<T<X`KT{-N5Ya-a<0Zva
zfH+v@QE^5WOFAfiO!}eQe_<C9HA0*EFK%IwBrP7cmFAY40iU;Z`^uHJoY)nkm)Z4=
zf8FbX@VuOkXOrc2RZn$=r?17`u#0arS|3Y{l-SPdV~J5^&$9YhVnEqWs*hzemlfZo
zWph|+H!o7%g#CEQjP+wyA4_B`%Uz>&vdnnJ^m)7JWSOyw^{h^o8K=0F)yXnr6t}ZF
z*?GLs&ZLv)j~CXNbn@cyLOPR9etf)`PHi!Y6+ibD!hOOzwQiOfcbB>7YfD`9c5tWG
z%MzEp9o?z*vcz?7$98JHEOFsmk)0HBMjF_1bs}@+v+jj)V_kW%dAZ%~IJ%qin?cL%
z$dm(grGl@SkEcS-Sf<tUVs3BCT(PN`NfimlZ|W>joi&9+=gvPr!|YNMj9(YILzXsg
ze}et9RoMQy8sPI7gYjcpKhtO!Q|6)RBXniOfSFA5SO(DHfxmxJT{>HCr#q=Fy%SS1
zzHOcQdk0JH<WGpl&f|BJs9=Bl%e>w3ECn5~kAu4<-2hA5lOPs>Oqg_ju*9o2=C;zk
z3uWl+U!Ei4Yd`8;E#%x1O&&`GF?3RFqO0!2k7gGv_im?47DL%xO&@-?u<h*X(w{7S
zP|u3>w1hG3Wc1Wq`k0;<>uCvNdg1J88a~2A{aCQ8C5*}ru}S(`{#@0Z;=$3^GR8GW
zSa1%n<qd6)z|gx}#^~~e#<B;OFF2MxwtV5S?6KtwkY$f;ju2V);N}RDC6BH?N0uyk
zboDvnWZ9#0N|fp6<&DQFLu3cb7=cr2jFvb8r=S=uaRg4;Fdg>-e>Pd(Fq|^M=w%sW
zamoU`>3#799|>O8V4O0*>}Cn0*>bLZ3^Q8lXttbd-t6Xqqj^jt>T_?zI4%-sfsII@
zT~4Yr+@<YC1-e-V2WE9sTk2@G3UsrC(QIdRQ(x+6o)ze338UG`>Sk-Hqj_GSn<b3q
zMK(h(SsD1TSWnB);WC9mZRy%+ra-7IeN>r3p}zD{WeSG+(npmk9JZD|s!Rc~we(S?
zg#>N3l!<0(<4KDMtCI(g<gvH)MI-;z2p{qI1pB~?^vmrd&3S{1$Bete9){uQ({lSr
zOYmuT*|XsgsPXk=*=N;R0uB!@mfKN!=5fQj=uW4>aLHYzSpavTN9iif3Ai;pMpyMT
zKcKwEuDVO?>M=##s27C`%Q|Wl-~H8toY9OlvuG|B4^J0DV8hD2N4dCR27u{4$TA??
z@%8A{!1($H1Kx6?jE|`(gLjE$mxPZ&#Y+KiIj-(}-BMrfsq)ewKeut74Cpj@8L(g2
zST7N_C2v9KjR(ttY}rcJ7j&6wIiSroiSOUdM!oT5N&IKoLkPYH6_!PEOGS|2`_u7c
zNgZrEJGh-*ED653Kxy&gLutzaZbcP>6ki_f=WfJd7rX`?Ex4Y<Umo7c3+Diq+sBWo
z8D1)U>+lGZ8*&nc<@RDO<BRU-Q+>%j)KfjwmfXWus)y?GdU$LFD~RzH&E;axKR_E0
zg;)iX5A`mWs9hoK+v&1k*R$}B9}asf3-1TQe(X!7m<4~)2S51Mr&7e186=BweG^m9
zU*eSO;3?z(gW;!=Z7z*4+b+oRnSv#%(}E^T!TTGg=7o=so11sxq@I{;blJ&&(>Jb{
z-o;jmOsMf+hmlY3$UnS;bQ1F=cknDlq$PK-lOj>H+zy_nNVMb*UZhC0<PPi?TnwGy
z;n34NccK+M9C~{1PV|C@L*LHP3?2mi5v46Zr;T?Erd`UYPcIbfvKA|dvn+)QIh3q#
zV%W{&GrzOX$%C3F9lzaa^SHT3sA6UAO$I!_r<&f={_(*tDo>HSD?4ZCB7N2EQMC^I
zv(sk#^dx6oMiRG0dfU=_>-=&?ePj>JN~*X>PuqG=$L;2CIo;^VG_v}r&!Zitlfo{J
z&yPAyA65!=R<*jy$mzC7uUqqbtrhCEwn(qrcCY)V$H%}VjaCc0baZHDe9G!;Ywk*W
zd!EIKoI@rH^7g!yb#`{<AD<oidv8uoTgM=oxEq^zS=mSy>36F@zgxxn-OB3s+5GXI
z7aOnp(X2)KtrzIG?zi^rDb0JoYLWi83iO|*xBC`aR=+#*IJa}`xA))qt@QFpt~X@?
ze?AZRFZ(C{Ve|0R1zvahFVaEH?f@lA2K+h8`p0?rpX|4rN+h?=>@M_^zeU8pQ-@Gc
z@ymib!}3%H6q;wJt&aa@uiZG1g43}G+?L_J6$tE?IOX(xqjh+6`fG-~P8~+xTaBPi
zsnZ4p>1{?|nqMxfms*jHp#lHvoE+tB5Sl;e-dhj~khJ{B5MPeRP5x8{Mv=w}&RiCr
zOY-BreSeR5NfNzft5Wu>yUX7-P?;;bZQ#KFZ1GW$`1h3`4stkOeOg4>v$+4v!Tq*k
z>v$e%+3PK1;$1J|JkFd4quI4S$^JATGRI#g0rrOM%BDuE1yIbtun;6hQl|cx$4=Md
zzCY?-2l|KEFraS+LuudP>+$Kq`B8(cWn&E|pVtyHIh(#|p0<Ua?|`6{&I9z;g~8jo
z{R;{2Xe&zQ0XTAYd^Epj)J|MPgU|Dt!g6u6gs<}&g2Lr!2w&$lZ0*1CTfaHla>3l@
zoqbo^&i=fHAdnml;p@DHonuG4&T)}(cCyCVnLEzTZwJSFu8#5hyvE0S?M|cRXw3z4
zQ9peLHJx<klC^^S3d<UEqrp#x97sN+07GvX$eB|E`_Y(R+Z#_c)Qxtu&8OP&yW)B6
zjvL3Pt>4ovWipbyw&-|jvQxoqjNT@Zf;XpU>E%iHEgd|$?R9@t3WV;8${&NZaizy%
z?N|9@nhP$a_vFG$yf!8j>8#10otA4jxC7?4LsKBt3@w1%R%{@q_?GO#ymoJo-lUsd
z4lj~c`Z_~3g;tZu4@L0BQiHORz5=`b?j#PT-a7nM@h-;Wp%;wGtAK*JPNBjrbovDT
z+<1L;yK9zXtPH7!_yfwI7jGKGfYQp-b&t`QO#>RgC(gA;F`kl6;>cTny1Jskfc}Dk
zG2JNa5y;XL{8?cy`RUm{?N`h-Clznd9Y#SJdmMNrM0{lhtCKeLp^EZj8V7z4-^(5Q
zAi=ikC3d%qi4cIwi0PCxCk>HNzjSq5@dN@j*$vdgeyAc0f$FRcy5Z1^$KLmmdyo~6
z!GGT;ZEppr?EMFD%m`Dwt$8oKwSE}U?^IJFG@Fi?kYA12<z~LL1;xZp|HPRE<)s43
z%R?s@bs({vA3DXPPN^B*dvnx4AOQfo4}^neTYy;A8rO<;k6Y@`3v(Gsf=oVx9y}It
z58|^GgU>*cEIMDhzv7`2hH$K9S(w^p+ef1K1~NJHv}}@#4|!sn)-ll276zg^8mk2a
z!3@f`>VAv|Y)cXgAL<`-Bm-Cp_mT?0DiuajF_iecIT&^?y+3STsO>N>>>nTahevyF
z{gcLT9c(tQqnh0j^8<YHUcE|q9eoA>yGjfOzc8~1Ca2#Of{NAg<BFSQ<%x;V%n)jo
zdEN$8TNqHy4QP8lAcUi@zZK%n6+tI+U<-{)u15=2ZBbaYY*_WVu#C|uC|^C?6}+4|
zuRY$J*OxWtTT7g<`VuE>%OLeUc}%OmUR2dGWQ!$-m!V)4l&QKD)x;p9;}Xx*DpRls
zDX&vN$5i267;?>m>>Mi{VSFP+GJnTtw?U8W_3poGsPW540yX?^v6U3)T^Aru`Qct&
z2(X6n5ZdyRtKKO+vcV*=74u+i&xHk0K%+>*`6{$GLk?vqa2Z2Wg2N?)79X7(Ts<Ex
z*YFBzmuYF1uV5nQLq|5}FGa&lEiqv`EN7KzM%$mW(6SJiv)FRx-LOONv&I|;TP{HP
zYD@a0`(caB7!|Rx_XjB&E1u`&qkhlDn1%hl*U-Eb#6wINd%6VY%gs3K8%{Mm6c)$9
zrSv|Sy-(&iREnG3cxJr}liP%o?H{QYHpESc_cOxt<`>BB0om_4tr>=MqWDCAmgS76
zu&=zD!+Or}sYSP8+`A%+g+yDg8wI-JcdqnsArfCovMywDr{s59T<;bDoHDWJ8Bv}v
zC(`i}XiU28rR+8}qm7hYTe)qvoNcyq+tfuHw+WU%CR!^_b1Q#b?soOLc)HsGP5zie
z6xEP<wvNAEOoQ&H-7GFV?YwKW9>|A@WLtz;aG>?wRo9j~r;!?E_RzlR$Wmu!C-a7t
zZjl;OKNxgp!}z5oaY>l2HAgqyVc17>OW)7RD1h_j(xwo@D3UZ4bfeKcdB1n$a&)>k
zd*G`qBUP8xOEOZk4R(E7u<h!Uc(sl8d_^D02LMcE{~jBf+mpQ5APgS9-!R7URq$sG
zVcrPl;ScCP{IG7mD=EJID;(2xj=lE&yN90Ai6C&v{SVPVHBb*Yj?L#%G3X_q*w}Ra
zW&gy3DI(I|gP<6ijyIx+ix1yg7IYChQgFMVVdwX=hRe~U;G`^Z3lJG?mc=?(`PYV#
zHd2>m0SHoG2iJnu$!z}DXo-jGN%Y8Hz$LmgUyY2FksDWv(;nMblZU{)9i#fq#rwNj
z=vLxMbAK+Ft+~h~7Y^_5TE);U6BFgBVN)AJ!`iLA`NMuT7vCmOZ~K8RT=yg_>~hVR
z1vi|nd~{sX;0CmvBh^y#pu5dH`j<N)?jE1zqwboKMLcG$PQyQF9+&V#xu|SS#Ef&d
zT&jFU2ijji0E$3$zau){+kc33wVZNGie1t`-6tBx*?jrFI3!)l*ZOh^A#Tn<;fvuX
zkN;!D1&f$ud2@>IQV154>;>f+5pxv`xU?W)SbIJc{lwJ;0mH@fA?Sy#ZXD)8(9I$j
zgwF9C0GdJKYA-H9<ioIZBo`cv1J4Jd3jzlOb$ulbKooKCtBQIR^;9VN0s<zJ@zyy4
z9+wS$NCb-Xj^AE|P+sDC8?P;7S)<|V8CA6St`&XxS!e$%-28_hOn-{Cf|6T3TCNEu
z&mbK2{j2cuDu~4Q9O5uRdRJZeFbytgUFYQgS%?2<j&dAY6h}l_Cq`awPM_WR5}zh-
z6a;;S3WX$cwFv<nHeO#xms;cwevuhEo+u>Q5lubacBdnjb|B^8{|DpQsPBE?F(QR$
z(W~m+_jeyz(18wswDDwD6$O+0$Er_#u-~Qfet1uwtO|W1Rr~cTol*kT6_a>&BkFs_
zpbZc+pwC}d`G3$xFcM*zR5oHxbdchFNR(Mauy^{;vtatghl%$u`cd{NSs3AkQjKrc
zG5-Iek1c_~tYIaEs*LzbeWyF2;Yhagj6Zj+iu~2T=?<x4^5?G3spCm++z&VipMNi|
zWFS3xU_4#i-qT{semQTney1CA;-;_v=D<HWKgJm{2P0d_>vnWSvU#G_cUI4;E#lqs
zup(7<5wui;VtBc$7m7V*lq<x{!t?eJKN0aL9lrsO0@qUF6c4qWps)LhvK>JtKMAD_
zH`p<$W}uYmIv>JVph4}U#NX=XCyU{|KmPFS8b$@z;8~(w^l|(z5g<DHD;_pdf2{Fo
zfL_MGqcxCPOx7x-w(0ezVU>AMpa}uoH0@Qou9sScYFDgUXZN_z`m+&8>o9^%u4HUw
zQ+g}|DqM9(eb_qIulhqA0Er(}*y|357v0_`e=zcT7x1&<A$)Hg{^(9G^%y{qeZ7%T
z5OmSdA8Xn`8nA{RVjz1F@HOoKw}q<M4CIN99?XhWV4vA&?7iJ<o`{NP#|N<RnjQb>
z^lb^R>UwL3#O$clCtYj0yyASV6A|#y4~E?@u#XC}^`z7C&re#7xBlT?^T<DF9PObf
z;TT)7A1k{2@B?tDvt6sv0THx+(lJhfr2OWYyo5bTX?VOPmz<J$oy7pQegVQC{}R`v
znK@NKa(~*~R~Wdyfe=W_%q|7J1{K4HtGIn~yR6myL2Du$0vZM%WhjPngi&_@tdw9;
zev$&To7?YtDS`BZF<{L{i_1n1`D^-08LtgR`W)3UXEx-b5`hmqJ3HGrDAF?`RU`Ly
zdLXWjW~=T&lC%I-Q<fB3>XZ4qeU{q#S!qP`RMa#hX`(<zaj2oFP!9dx{YzHWgc#Iw
zFYM;*;rmC8y_UasbYyJMsUvM?Klkb;uNN&-fH@j-Hs<uADL}4qq&ip>z8ieTDY@J}
z!8q!J#gOo$@|7hVnz_q8UH4c60qJi*DtL%QzP^Q2BJGHMzFx!!TC`Bn;K8H)ly0QF
zf)b6qBeQtgy$PmK5P9*H7^fGb9qfT%@h130XcT#r<HH+|^h!urB#6_lQ$jCubKq@&
zTG@L5SzTPB$wax)a(l6RK3%7gu6roy5jkBd;Nvdik+8Pt3`LGZG_pp6BkuP5USe0m
z)*JSsP46lICiv$piml!dXoY_3_TpJr*w6S!h_?Vye-$l=4zz>?O*gsVDSH$?E3+}n
zC&1naY0(NYCDtjE*Z3|7wX4kNZalsQW<>&BgmFprTJc!Qm!&F^n4#>P9R}U$`~@)$
zW>H`-1?6#FcnzdhfQCl03UU{~+}KgEdrHxoyMNkyV%pl(EM57lvUcy~DqnZ{%2^U1
z(*fuUz;8StTWNrN3|~R!-w|!ZBE(5z(wO!?5|yS0CP7F4Nn+6FizMlKW`xL2)4G*b
zjCHhc3M0W}%5cC_lH<MKN=|ahBO9Sh{p%WdVcaW`*HKU!*Jk*yU_5XtpI|Ok<(L={
z`z+IgV;f5jQ1nE~Dv_D^CLCSzpow!T)G?0qUo$b(LMWw)0aGk29_01wF4(|lhdis=
zveVX+tpgIfvV7I)C{#H^lPNgEHa?SqHu7}%hMeQeF|-}elwlrRgX|HKzglq0%DX9&
z+?yH>Vmycz_aX!Q0-6gl@L(DQd>-f)OF~upt4gJOMcPmRKykyyH$+L&^iZucBE`_L
z1s12A1hLI~Pm=0rkDeSh_}omHb#mzx5{&?+sANRlZ8?Gwrt$wJxrkyBhx|>XB2MVi
zgrYE4?k^M7u>TB^crQ}8CE~pakx7F^Wub6$q(ma>=^#xmr6&RG1J^kQslobpOmD{r
zdxJ3@9;(06b@e_(1Nj?D*S~}L8IDBgIUeU@Y#&FURPUZ2W|TMEMAg&7Lp)k~zRKbg
z9bJe_2-<5rj`7J%I!&yQL85)eKX;Qhe2}4kK$c)ge4?q42YZ1&LuCPz&!$A7{Px5#
z9-Mya$l2oc>%1W%KKh7+48sT*=?v16m?3K<19j95RQ9E^x|yXIQSayF_cNVl@Fy)m
zo4TrkigFXg`^l*3J$WK$LY1(GE43KtNRo~xD`@zAFIIt!!FLS$19$mxQyO%xlxw1Q
zt&*6M|M1q}KNQA+I>?%KS<J+2Hu^Lg-;TsF_lNIiA3b64;_nha#f99TgUYxfZo0!+
z@RIsMabF6_neK%^oP<HJBB~c&_`?rrLRIg+ufDhwz8KZuL-;X&;S0LuFMI7!@?tiq
z$m3h>uo7SFLD8BDUvez^)F(?J%9bfs#b|b|Rn-65HN^nQVfJ8X3!V^9GKp$!5KMBI
zs^oyt-z%?_jZ66n5aa{H{^197R|_<tnO>8H2zQm>m#So-&O3*y3oA+cD}CIqI3?w!
zkc~hAySf#fY)%7EuA<n<ry72^8j~S?KVx<mm;hZsS^1DO_^2wE%@7j&w6T$dEQr~7
z{VHK7EnGpN!qw=qPH@)?0?<UE{y!qx-SP9L3|J7}uLRs~5@{m6G6ug{(`xc!dRkWm
ztE4uEgoT_dTCHOqUhddaiXy6tZW5#jkVOHF1bm5aCB0BBQaDy}c~v>ZyfkT6<|!CB
zmuZ#3g$uFG%8DS-53jsbjYK^1tbTPJ>aaBe3KcbD1#O<ZOCm7x0wNMY$j7sMXm-C#
z&+Mqjg9cOqIA~yLVE_Yl2Fga1JQ<fVk`>F%yf^@Dh(&?`)|Ihk(FTw-K&eAsOA7(}
zlJ-Y7Itdmi0@d%<=3c(5I*;~DE<omS@<9H%o;~AsPMqxN&YkV%$>Hhzxn>ZBP3H7`
z(`qX=+wQo#lpdk9tDCxmnx^+exl2GK4TBNrb%}T?>>SY#r&kR9#9Vh84V}xM)=rv~
zhDqgg1FW$J26V-u&HyDX3pxe#*%KZCEGAPB{qwZa)?DUq=Aen&^H@m2!pcl?Snxbg
zY6Z_3r?<h}eb8v{gCgP|>~;41Bf2myXW4rtC*OOjRi>Kf7_`xD{%1qdU6(XY;!8F%
z$f|_O;<RPK4$XDqCIn$22%GI9C{g|UAcGBExL_AlHSu`#CSQ`FCnrEs7%Q|~W`<gS
z(z?LyJp7m?;He8XE>?|wK5b7>_#;>ih6bWs6YvpX7$dS>7X$}t$tiHSHiW}NC^asp
zZ@$B~$h8ZeNGk0IH+1+K%_bP8L1Ux?_2aX$HoXqn2(oZj7Dv6SfT%^9GD7AEA{7vm
zah67YCa2DBHc9;4b6aGff|OMIChPOzD0C%)Ap+v8M3Zm?bNGoXQlI!I-JetaXFLgL
z)PbGml3W&8;<r0{Z~5T^qmmeiu-}sJlYkwj_ILUjCndfzi{kM#@JA($Na7ZUPiYLQ
z70>tgI;Y1?4B9^0`>k<c4(YZV#!gA43Y1FjlAfxT?lb<*0iM|_H@b~F?#6+~Y1_$z
zoM2&UO(&<v4Gu}oiY2sI<6$f4>AKenB*Y}JKm|l}2M8~k_3*F34D;WFao8P(|LW4w
zKYCzk6#`*I?-ckDsBD&aqYkzZpiOh{2zC*X$}(@FB|a6rKHcCa9~vhI&6BsnigeAq
z=|y+r^jgDd|LC+0E$x$)wxk815_hLDOkQ_-jbV);x+A^OIQArdeeVm9N|Hd0XgKcn
zvj&vH9O#5&QUh%@Kml!cOw1k*A1y-F$3f!|SX6WYOC#tGeHy0U>yCODgP|agCy{h_
zM8WhX>_Hzw7zrobf)lC6mpzrM7E;LN?O&Un{dfNU=}D*YTgN|d0~!U8bT1r=9+fu^
zau<;FaZ8H%G!E$AD{X<+b=+?318cT?_%Hl<F8{>u<zlPvV2mtvg%VKl*ldKW3<G$k
zUT-+YP@a3NGw+W-_zpv%bs!^y%_VeCp8GD%bGTC&EWIG#$QfW~r%M2&nI<)B_h1^5
z(=tT5#1Yq%?zEeBK_nZ_x{R64C@vEK%d*m0587f)V3Sc);PhIZjbBFrs-JYZr9U3g
zbtDGV8_!1Z#)j0#`P)?hYC&&&JsAcl%$Wx$(hQh+A4`!ZaZ~8crqcjyxH!BHlz$5g
z`au^1L;`LD{Mz;8R?iy=fQLUSSi~RtGjv8WUvI9;&@jYYnbxGPT%ulZje1r|g~U;<
z*Mc_C4HV+_13W39i4<Lvx<u@s!T+x;{)e4K<^uz&C6~GILqa~Gq6mdhtL-MIP%Tw$
zQJL>T34MaTJ$d5ky}Xugmo!6jHM%HFHyY9$TJeN#ZY*Y=bm)sN0uvA**lZX}mG9R*
zwDHdO_Z#i@t`-4q8b#knq_z+jfP(LJ>8u}=LhbZd^EX@S<wt$>Q9Di;kcCdCdE7WX
z@9+S!m11MHf+!6KUj#Q`Fvgd>9Eqq+nw}7G_QQUPOL0pkBeH|?1$2G`$#m9vr-yV%
zz$*&I9~!^4fAw4V-r>RTyV|WbuJ`1X_itxKL4ez7NS7b-u&BsEFl{Vr0b?P-{8@(T
zD7Pa^A5P{{pUm@<pHEJI6?Z|Ltyt`_z;oBI7nrz+n^|A36UkM=aQXcNHp+H(FJh_J
zGHW<^RcJN4&Q+U>oV>{CTFNeK!!Q=;eobPcE;J(o<+1}FDJJNd0>xKF!p2u!Gz$XU
zyJECrZpYJ4sI8C;QvtG$6)2;Oga<X{2-Z@ZV&toS;UV)dz!?h0dtflV48;8>L*B&E
zrYd8XB-M|vC;Ej5OK4dsE-AMMvXP3(7fK9cj^}u0JtO28x{~4~#(?K8>|j>Iw@0UM
z_KqBFd9lB1?EmZ^H(FqN@1Jx^0I(?F<aTp$u;~nhI(l<RkU5fXhHL_54yqa5r6ImQ
zECf$hTXfja?(FbhgD(brIb<b3N5z=HsCy4`EDd9WuJe)3o`!Eu>EcKiX5+)7R<U&<
z>&=0eI1FDJmzEL@RA@$tZ2m4sII9Q=nGS)C$+eR)Wn4gyT7T>f$G00=E(hVM0u_~E
zitEGpR3d=&0PIWe`!(;Z)tv2Ydutry<hcq(cloL;*U21$w~_2a^XeM$K&YAO`Wm{}
z*?U~bPjS5Wn^1G;LMyPBw^dzTK$)9wC&@Dp#t+X)^sECZGtAcbx^Wy_V~!(XOxa{X
zfP71L*JcAUK*S{{49UC*dfgfD;3&97CuTst6KQ>}Ne=|Dfb8?-GUiw!ST?cG_Ml6h
zM<l_ZTmva`&~Q!tO;PG6$FypP8de;Ug_3d1Ac#}WB5jO8<zu;^B-Il0Zb5=c2xT`F
z(9__pd*~;}gjlNM{y1Pi>vhl_vEE6M?m<i{Cm!&?OjBE73<Se3-fYyp0Z3?iRlI0S
z2eMHd4mnLrgy1iN#C;v~Hwi*3xC9M%h`#Rez`MN)D5ET0n7a#lGkL#F^MKQByO?gn
z5rhFqA|ZW}CfBnl#{PQaQ5=qDqPO{;V&jY><>kV~M?R>sI^m^L9r83J3-YCl!%{~t
zj`fzi++@v{x)>F7F~5`FWzD-BjxW0DCgJtOSzR0*rRpP5oeh)()vFr<?4{t`d5oL6
z$homystr2bG#RzKu^4{3p*DVZOG$`yQ)91jIJ{&aJ(wlHyRdbRE(1P-LQ%=5K47Ww
z-O&Y2IpHdE#Px{HV4A;m6}_8-PA4?x<D1=7zMIq`W%`sd^VEs^*|d%$D_+fgz&PhX
z^x*W@6Cv#k`;)xQ(CI`vo8^)2O4{XFdJ^9#m!}FNvKJ@scu^coY9KLhN3=d)ecvZS
zz50IG-~4`aXV}*=MWM{P*^F-hg`WHs_RpRkgDC=yC=PR8hhiBxJM?n8%BSF2tAYNB
z#BVugaz%YT(V0bdc3N0R>G!0&Af`r)x^RjF>>K@dvtV`nIJ41e{Nlg+HPK~?I>dy(
z&vB5QAtlC9v6DFA6{cJ*%|;t_p%qYZ7ndS<3P`bPIr7C5IrfTc$B9~&OxeMB^bgc(
zykw~QDF{g$ymK$k{ZMmR(^wQXc`lH#D#~4V)@aG>RRtExLE}AzC?tmqDl`Otn4uvS
zz-x>Jf*AmFB<NG1kG?oC`eqt{?HC0<){N95Tgd~VpR;_;TD;Q$ht5840n|W!HgX{U
zaGCndgC1!%<bp=+I1Hj!-&>1Wk7c16Ja8EoHg_2(Jw1E{3k;mLm1AkQJEyIN+h?6V
zZ<l`RBB22e4|O3H6(|+s&<u9rogMS+K03psH-jBdAn@pHll1hB+2(*lzKTugfzrH$
z_IZm28SPh^#(5D8a3E}J&~b2{{+T>rlW}H15yWnzcLDt`Bfx9{SB7RL2yaG_Sh~4<
zpHeEj(>SG7K8WS<k7+c!zz+r~xi2h+&vFaR^d_(^KMEX{qwvkS&BqMWQMO6hk6E^(
zY>+k}-Nxe*oI+{SOt%%?Z8d{2(^z!3)GfwrYjM8&(d}+E=a8n_@St92iJU?NOt`Pt
z9rk3TN5WJKh_7tdo1uGRxbjOCSdWrwqk-C_?V%LXke93}<D{Vc$)$#h9U{G#rVpQ0
z;AyelG`*ejjjBu$p4`DXC7t`}`l`3?btt<NpXH+Z74?EqcN&f(uZx)@hQsk~^b#xn
zdKHYcSWpr5h*$ro<4gD!RUDC`BpaelY=6MYZK_U1h7<8up0}$mgYR8+N0&jrvMTab
znb4&lE!yQbpKe1;=aa4nxOOkbFb93aB*i2iI*WbzyZFahtgyPpLE^oO-{7A}mCV_u
zrZM-bn&>qgO(gPGD}0qy)}asYns47Ft!NypxF4oGDm2!dWGU|CfokaYbGsBVn9>dz
zu{hJ$V69ar7qLRpwWCUzrX3DgJD6*)a&1s;nnfkz9w5jZ9ZHdvUqec=uLX`zviIs-
z$(^hQ@8XMxdDg_DyU%!YWbu6iPcov9)1fd@UV2_;P>iNITQ{x}Kco<-j=NO_J&C$I
z#PB#}L|91)ZfrW76*ukeS#XvUTVPA-Kcr&w)IW|pNO<P%=LRZ3-#MN<>P$u?Nt3`N
zaambWbey#aU3HRf3o<^UYfbuNG8q<KVi_DO#-^(`^vTw56szf+#(L1g#*?~i#nrWw
zY1cV#zH7JOeXGBslWMMEwNx83&rtj}795@Z{SVdtb2MRFzwC~@@o4x3&ul@Dx(-KO
z+%@@F7uh_z>V68m+c3UDAzLD`TP9^S8uJ-7%3cH`&!ipN>1aH~TWDW4Nv%ub9+_se
zRX@&IS%|X2zG6xg`{kUrWaKWeVYD0=1=Tp5D3zW)otj+(Z)9a({&}Q*0c4S@Ohwg@
z4CTYE^Ey($6jJ6?xP5YgP;n&l(@RubovZJ@8r)ZBIIhTf4$@Cte39=AXb%?z@fC_z
zy#9ZqU3oEz%Fu2%gL%be^Y^ehG~e%a8h+;#G^`S|<E+S-HTedVx9~=uW6wW~0WsO?
zXxG~qkK~~PX+Xh8ey^_4dFMCYH%>bIB*0O7zrr`e?HgnyJvFjq5W>7VhHT$zoSn8h
z0J#C?|4K~-zX($s6!pPu#MzV)P0aF3_in&)4DMp@x(n+2c-WW3+eG$3bDDrKLLTm#
zQ_%5aSX011V6R8xYcTjHlVRB7>zbg+T%ompF{W+3f)~!vB}-s{Yc6peA_86?C>~7z
z5qYp|@CgNIhe&jLpJ(ATF!1oYm)&rLK{o^jwpfnQ!>d71%yBmF(D!f~co?unB0^$~
z_hX5>)O8}+=BfKmSBjh!&*E0hrf`#<yYZyp)aA$nS0{gajDOhMQ&wDh7n{9D>7xq&
zc6PSmzxA!1YE}HVM&GNo`tzNw+TUv1we9NjYVA4v4&QcawZD1QN5RJWH^ar|d4Ic_
zf#}PrH?RDE=s&!Qe0K2L#u4mOqbS&D_Ja{@e_=3v>Ah(mY;0}p4>9@?HIV)B<O?nQ
zQm^dQtF;#!^=iH5y$jnRtbADZN8xoSTw+gGSN|T4dc#>i@P48<V8)wQudQ#eAb`2?
zds4vZG=}5LX!B~#{wy1$3Xpl>tC=ja{caC$$-Zg(=XkGk<yls7n~LjIRsQBz%nplp
zZ1+K0udLLnRjJeQBERZRU`xO|Dx_JyL}AvO4RMDErykwA3{azziE_CCw*NmNP_~5?
zIZ}{c>O=`i7jns&a(pp~sIKUT_SKgfAa<{8dcoyOic_q36956b*LWJnUn-dMXC{1r
z3J4<gQnpVp91px^E5T2?Me$M&jOQhPT3Knf{0k^5)xG}<_5E2H{&<0vo2?R}TZTP$
zBkP|B^}PL~)BT@IK*=iAC#ane#Cigiz7o!?Prvl4I%Q#3;n>KEHwrFcr@0AUlHEZ3
zW(R!ObCjR(E1V{8=;%~eFSQtXp)}Y`#dYnAzAFnJ1NPcGKZ0!^*lh)*Te536-#6Q*
zEr0*$=am&A4$`%pD#wOCG=w_!9dvys?aHh2aTvtEwu5(#fUJIZI_-Y>pmX}sdy455
zuZylAocgn!3Jwm$z!`DR7vZ_1<58@!Ri_GijmznHHnHoy;A&Klv;?ylI+De|Bu;rO
z#-M$bZgJ|*XtJ!tjPO0OztgmVv>KDjI-csELwat?$Qy+;5#fpZ2q-4j6Opp|jH_Gg
zCe^ZXH|tF)Eg!7kORySZ3h(WXT(C;t_sc?)Hh9h1uMy{<Cp#l&?$mot*1~o74qrT-
zqW0>zQj6b>q=C4`p^c{sSP_%2p@{@H0p$q8wPE*>i51cHmCl0t5I^oF0ognaDAOi*
z-2&4ROhL%J@_@xF#0ogu^oj`1KmM`0Vu~juwm8rMarzRAS5|n1)JQ;KeZdS40fp6I
z$#FAg2(Kmss8y?yy$HP@yb{%Z{o1Qx+AH|+R52J&i)j1`dKWLaBm!dNwHT;FI_w&^
zEG3-R3JhAaqaN^ABu!Xt3E-9z1;e1nD@LTxqctdUZz_O@7~Tk%a97k4<3kT^{HftT
z6~hO?UGskWDOsJIW}Na$x`vC~y6$B(^?q2DzW0(Q-I&HmU+tsmy_1;)EV_(l*TFPR
zl^IiIQ<F7pnIH%-lyOyr*RyLuyjwJ!BrSm3fYMaTTuEQJKIa%vRRK~`Sp!9*57qih
zibeZ9zJw6r+raETQ#lY5gmo`c$fJe@Fq<$4JZT{FjJ-+-j%R;39#7=as0J0$2|mxd
zL)F|`>`D3rB~2A^al*xWe=7<>!9vLlIG9M|0B%&a*shc`H`ZIS)>e{N_hd7KN7j4R
zGF)IC>O8ixv7r#<oTTcdq>eq4=3Irs?!K6Ud3Qw@O2m^#H^^Bd%JYtQ+@ehYHH)+f
z*H<=7xoC)o*f8(^3Z`RvM@fJ9NN@2<Uolzac2I+sp|(_iz`S}1STzUc*2|Fst0{me
z!!^pK$|Ek16lHURcn7dj(MiKQOQuHmf}YWxhRI*pChVuu&A;0_I`rTC-f8%6njM);
zeml`S;+{Ah0{en;C~l&T?Z>?j4Dh2A_%Vr8qb4RejeEwucd<{Z9gzLQ;z3F@6{H4F
z(F%j{Z0cQni31S_F$kx4*#|#(!usLcNvc^@JTk_A)wmfwdo}g8FG5PAF%r*rs9Fqy
z*Adnqj&F0SS1aV#382<XzLuo0db#ok(YfaFf2-aftIX-3p7xC@TcS!`RDl&THETQ*
zHMT_!Bu0E?RCz9{>~IxW0PvTX7-G|pm=FVI2H3t-65pTTX1$(0`{lVjIGbQj#JJ~Q
zcPCj1@#durmJI5N2QTUGvdW;V)nc^G$Oi>BnwL`etkpzEXJ;SG*|RfDY^K5*g`ZxK
zg`D-`cj2)|1NgiRViACx%0lV2*G>_wHHmAGmY!I0_L*r`qFHTF>CDECX_#E%G+-w%
z4}NcOnJW#THfH13sR|5^O;hug03L>;Pl%GY4)u0(XLXTD=^XoKZ*f|1c8;1SKkJhM
zJ=qzZTnOpBLX9?F(-5I8{dZS>Oa_WY$zQumqI{7RV5OW=uK0JqA{F)y_Rczumbi6b
z419o(p{tXp$-pkZ6#2--FUcyY@JST%-DI%wI=;g*V9ZgPWXeB0+Ix!&<IP^Xfr-2P
z<I{tNTUy%(S}8F<xzrA{(7+sA!Ze^Jr35;VYJ!?6?b8zRSA1leY%cu$L-=vmTw`fw
z$7#Yvb}3&G=_!UTy5cgjWJg8U6}cLqy0x%U)1N?myan}3dw~VzLddb8XlNp<C#JxK
zHp9TL?UbmXtSvE~Vp?DFD?z>)_7%VHzd<A=hW`7b1OFJGgt_-JM6Ll$Zb{c)c%u5Z
z)2VBwBsioA|Gw;b`nAz~`>vx;5%=SmB^?=ag1Dr}9LbtEV9cR*%RyKVAUarfxcwuf
z46<7(9m%KwQNtr&skzEn`&g-Mo75J4>4d;fMP|l)!=(5uH9GACS?wA`(yu*J4kXRl
zaz+H8egXZQoF8k#Ghe(zg#-(ddHgFUtWHr{*@55DLGIP9(Aq!=1ck2@mg%DViVT~j
z>hnai@e#lYc@5=c4df!I3v1*amh&i)^+tk>>VcXRlRS`pQSKEG8j12bM`%d-_t>HX
zMQ2gj;l#-;L6iclH0|X}44C+$6u&G$@XJRh_1of<zAQpxOErBEg);~Y3SOTyykaz-
zXQnMqF{wlP`-g^^CF4j^qJ;23$&o0hGP*>;I{3BKqGX!tah2M~)ONR3FDV_P^BXok
zpoXYmkmMGLK}{G{`OboTC%^@lX|*`}OGjZcMU*!GinU;J|CF@Dor`34&{<^s70GwU
z<hP4RuMdA&kF*-S$bq8YTpTcj5j)R9&ioSL`6oUsgU6EeAPSC?YK#XKFnM0Yo-*Ub
zRI{dHARIczN)5tb*e@A%DtP4ihE6&zaGDC$Kj)K?!u8u!KPp!LO&jq+`WCL=uJ8<K
zEMgHNOD1A`i|_{KtyrE?JRwR8LJ5L;Bl&}WAvpZY5{aoZTl>Rq77tk`i?fPgStRTn
z9nAe8P3mZx-W|d*%DcN>>L?HckzldeNb6DCj&ncl@Z3K5=ch+rn$L-*Y{kW-AO=ez
z&ZetrMW2<_29lmca}yChdVAoT_<fg(XBovaE{-yaBY~MND{{n@nsc82NWNNT&6SKc
z$u6d76Iw7jU0|0qC?OC^No1o!SwBvtKoZJubrn!l2p!&#OBgjtbm$T$Fi|axfJ77Y
z4aztSe-*x5SmbynkufuLBY*?*2I2IY^R?nP#b)gA6>Sn`i#EMIKtoS^m6Xv{K@CQq
zfb;{r6A*dhk#v4@e>cz~9FI1=H?vqCTATT|IAd25j}sFKdI@>P2{g1!E`k`>1IAN>
zn7Rmupg79FK*tObQC$;5GD^zLNTf+K0U)I-j#=RCv+yRHxZ*S+I-B(IEWe-}bqgk!
zU{<opx*%c+8bw};wj>q^=z6A<GxF6jC2g|a7)xn(iUl*aiR2n0QTt-n`-J>X|6%39
zp<buOy!M?!92|Og?q-vqF`o2L5v4aX`S*G1IoI-D39P;Uu(iuGC09L6d1)8#tK!`P
zGMjtTmDF4bZI9cO&(;z#ReeYC(j?sFBJxeiHiG0F*L>-w_=SLENw*xyrb)FVl%=?2
zOG!16oNx(}?J`rY$#9>?7i*4#1|f$Khed4X>_xng7U)p+4ACLlnR=cKFw+z+`vG~U
z{)gzMBf!qyCMw~Ql|SPlNO7$rLkrY8&R3GEblI$`l%HJ9C{r)8cO+{MP>&Lz!Hexd
z{JlBf{}~eqGZQG1VccedI}>>x)o3|+XK%fI6&QPe%00UFT4-7_b=Pk+KWC3JKW9sr
zpWL%BZE%@ZYFbT@r<T?^=h>k+;xq)5>8H2l2%jUOYfHHvmT;blA-eK(lHe|Oz$rG0
zjFZdFi(7w)_W;sIn6@w%XP7FU^!|sI;w-F~572cShK-i&68xo|>k|BH`upUu*@I6Q
z7I4R^(5xjN78G{K%3~Z6(}jQkg*~z|tmffU^l-b%c~W!_%gVs!+nQFuD7m&3l<UUT
z@~x}X*mKP*`?ShcVQCf?z<Qty$sXMQ^ByEg(!Z9WC8nvUr3C_VH2(7~t$SKjt>&Yd
zRP0axtD94{?9a2Oc&fRJ#WZ!kNF=m%6(p5uQxzoL{}cAq{0TaHv<b>IstQife1j?x
zHs9Ey`c~nfac_>bq{R(oSxXLyoMkR)$%kws84Wx!nZ^{V=}RYqpF4+?6(s^=EBsgX
zX#?3<qYHm}=YLMkC$>fey><F+a4Dm$@J|uQtAHQ`GC_e9aZfLqMfkQd6w_sAG1V08
zX12j>e~gLul;%OqkysjLUA|2z$LC*n@0`~u@A!%}-h;Z}OVmhXXz#oNDlS#>#U84m
zo;%bpTJpj&@TsKH*>x}_&6-IM!E-!TOx|JB5eIKI`A$))$e?K;N-65Aw`h_9<KvT;
zQ+)qwHjKl`kZv^r6)+1&PX{9hFM6+NsAr9rQZvzu_lg@)sj^3jwNiw!Imb+sGQ}*T
z2rju?TEUbe@=-88XrpQ{Y*1x6pGu4m>JXIcE({$0$LSDR!vt+Jh{8VJ<>@DBOEK5N
zG?l&dmchvWf>AV+4`Wi!B1{p7or$+IIpqp66J8A)LudGYYaH+qgQ2<hJ;rxP?=R8q
zAjya!Ysro@>8z1cg0QikS5@F!@Wml59hvL#c=;HyOSrOF==<@-kmi}CD@iYwAF7I+
z46I5qmtyN(3BB*VG{Y3xvOrc7oA}prtYuy7#V)a@AaPWy{4*ueVojtaSNdIIP(}B~
z4uKat1fB`s77?jFl!%Be5fNvIi1?d`h`6AL&{ltJuYR4#SSv-r6fueiG0T~i+nW4a
z-0P73r*u3rUC0(pFNVgOyM%zRk<-eT?|U0%@#jerHXPzHXKG-M7V;tD`IV6@;jVQt
z78A$>F(+c87a0Wyz$iQW^lmRdH70JTI!2N_f}SyyY7W+^GMOU6smq8(BUbj^XIj+A
z4Lwxy^OrSNAB`7W)oO(<m3zLkshEyqr%S1XF<wk{686cHRW^b}y`S9Ge()TW*M0Qi
zu1d5gzI67hxSvRdpcg#F5oj_O$&Di-pSn|tLbi}znIUp5g<q<E=~ZQlu0)e-2_Y6q
zU5;MuBSkK$)Y-qM-lDLI7sIM^FRY4-O5K^FYxszUR0_=iAl-B@T~E$EQviw?P=;~H
zx>X85F@9jL&fI-?nb#5ZTe-<r>bwcQYtY!m^ctykQf1SeWC0-)M*htJD_jTHy~!6c
zbH!Elit_?{#c|0uefQaz8*I++Kz`#ppJdlnyifPC;YrNNgx=PnCbq0)o{=`?8=k1G
zpS?A-ZIos}YDy>UI0t2)ojl-%Wi%exAyrsS-9$foi<>~%p=IPB#oB#~TSc_}|A$xg
zURs&Vb{%b!8%%t%5YDNT9E~|n#`4-qSBF?0T7r=zVF%7gHNBf<flO|_3ZP1-+LgA%
zC#L16EJw{JVM^q5K~(*OR83J+?0b8|p?7{3saw9F4dEW>I$L+$trzBuGtoq-P6ln3
zjC+MxQaGFDv81S`STfN~3bCc(^U88|;jeBMGb=5|V%9A@PkSaQ&*R3%p>x`+hF`9b
zS95qXtj|64{uW!2xcUyva>^Nk=>0!-2aZuS+jv9Sf@D(kDaAfyhL^n3W$XKsMrZjK
z<{i;Q1|7-oxr6`_n4+!iKX;B6a7@3-bxddaO0pNF^OPZj&<3R~r6UC>6?nsrYUz4$
zgiqvmQOpfZ7n6$2Wp<>yW6kn3&W}Dbn-;uFlkPsnk7oZlz3VMq-4_e42Nu9B6yGYC
zbDe!&;tl=AYDyR_#;6azf-SC<I<H$h<c)bBTAZ@b&D;D_menMNagAOtpgeP00wzyf
zneAQE+$2$nYkJ!-=QJjb?dQmWtf`jFJsdKSRRFWlT*<|-_?h1#47O~UONWCZ?&DF;
z1RXq;T3D&I?KbB42@yJT=CdK1w1fROWvxxs(W#x6!sw6RX*oSRIqkI1&(4@H1Vx1I
zJh=4}5;>m&8r*u{4`-X&|GfS<i168AfvbmU4?!_aSW5Cb!Mjv9Nkvb>3_bkSf8S`e
zo2Ms~j|;R<`4p48xLv*n)OtSD`u(8R@}bu52eq0HwF*$>9wYSKuLVW^<)5|?Qwr+i
zg*TfCnC=ndEMU-1LXPXSlA0F78P@m`RM&Y^mUEl$GD`quD>tIe{j?fG)E84{WRrXA
zG4sPo7Q61q?up(eC2>mKeas=8y!u%9dbPv$(NQTnUki7tT(ypf9O~AU84TT(pe_{4
z3#P(>lW_Z#bQwvI3nT{9jzq5~{^!V77Qfk<KTLnRS~!mU<QJ54zqE^_6?2TnkyUK;
zIV)q84C@xL2q!^&JDz^>g3%@BilQf>rol~!n+AfY-qmY(mKk}~fB#6Kx#IzkQ$?_<
zfYs0F(hvKaUVE%ZGC&2`g<{o8q}Ik4T1C=LbS{yqD7JS2$b0S8s`YJta)nyI^#1T_
zn6$ID?fn}H;WzI`_^k>WE@$x6{yo)x`!DtTe_7R@8o$}~1SX<i=n~V8njKsH{vo*l
ze#6Xc^6#O_A1eQTW$)FW`L>9j$*p<dA7MDZ(2-L`^!}9Wupq#9*#O@$Ky^ODVAK-G
zz|DbH@}Pkn{z7oy`HkN?5={ZeS*2Z(<VN@+p&m1jgZY!S{D%fkE<Bkn?;$bHn)E87
z_!J1%_{_<Sk{ITS_fONfaOoT=b9c^pFTwaH!}w?FjFt{#p+Gr#gmlR`$^ECa;nXpd
zCDW0PEV}18f{Gb`xV3!74*pET?{UIFg^Kt&@-|*mprxMTv(U`z^N`BADRjzkt~IZk
zDg;mquyg?T)X5>>2tG%~0Ngw>Poa}rU^Xg+^to&eBS)Dt@-oj=on-AiqUC98W)j@F
z-H}6Jj7N?O_NPRhv68Y>H02a!-RA1H012h3)4Nc(*&LwH$s8|+22JRs4p^BwZYDTs
zhgpD%`c?!OvNYLa3hOiI_T)R&$^^AlV~2OvCFSsiEWS>VsTn6v^iZ<zZofZOTd2B4
zM{we4cNF=T-HE0@>m~Hoc<Q?3;L=0`)lcn1zEZuqqE)r^S|?~zvn{Su?;pPPkN5Wd
zv%S`yp-+prg`^)c!F-~V$3Mjrij5X*1P3kusBuE7MNUgUxQp>FL|%KNp)~{OMK-_W
zHNc5+DL1LfyH~0o0z!i-$YPQROXd~L08=B<4ghpYX;S9T;jiS))<kY(5j$IYq}jpE
zExWR+#t1_S@<Db`jF7=ODXy@k3gVkA2~A2EFy@G-oQ)wZZiJwb>59+x&Os~cG>;qp
zLG!);=J%DltL(UW;)9NK-dL&LZLgZV1o#tUN@W**)p#dGPh||BVF?cukM40UWGrzK
z2e+1>4JKn9cGfXo7QGFlKxNyx2(G#};h3W3fKM=xZZ_gE^z}$~4b<!Oz-5qx%*`t*
zwDwNg{@cAXWTCVq$!oF8cfvip>sL;~iqK81;!m%Zgrq^jG{_CFCQ(&NPV$&{(pUy5
zcKiQ?X<~1~HcW`dSi4F8yj)x(-Mv4ODFw>CoV0CbRo)6s?ZXDzjunO=xK1$26wepq
z@z9I!#4ppkWu`nx#2yl(aiVXn^D+vQ;yZaMzVn*_1#NEcC0@<=187s4s(P)AdJnpU
zJSadzB`F3J`E`wxvnX9H!?8#G(H1!9rEceI#Sht%&JNvk1MtZZo!((LJR&c76sBBw
za#o7Z5A})Wgx+I9(1-X~BL8CkTPzrSDu2J6PRzU!S+BBOOmt5LPKW(vo`$=S-}lWK
z`+XZ7*ULF6WGt>pBWv=GT~1CP;kVg!6~piJ=q6WUqGeS~0wPl@J$WHy(J4;ew?-c(
zaBEBqi>0$DTiUHtHTefIInV5E7=!U8-m?EZ3viF{fdwfK4{j}VXMkNY`}DLuX69gU
z`jrueseiec23>p`&Hw=Gf!4wtAo5O)6Gq1cL$)Z0$Km<WQGR<H1#yRB(b0d+-=*fc
z2ZTtaxuZVxyg9wubQ+9eoGzaKBvx%7Zw_|O+llm1J|Y+25W9(Po-lXl+C^%-_HgYj
zKD7;F2l_Cwcb-S52<!mgloqM&R32<5C)BjJxd_BBT{qA_(&^D#bX_{{5m&n+3i23x
z7v0{c$&{|Ff==EKZ}5IA9zM~t!Td~ch21RtWH82bcf(PHr3t7CK0XI^@KwtTdT4wa
zAXuO%-=Nhu2M}MI&gY&%7S6S8c=s{0#k0h`Htp5qD!DU!8+M1ctuyQ1mbRr;yl8d-
z5}TsXRR=PTdj$&8Cqn8<h5+6?@Q+hp=nQB@0MCcfK7W(I(L+hhvbORshsd-5mR$V_
z(to@XFGq@A%XSQ1vgy-m>yg`9wO>N;gPhqpzRY{Y8fxRv8E9D{$Hk=WH@KXnd#+vH
z0D84=pqvuIKFe`vAF3EaVYVmPLN?Q>p7VX_j(usaLtX111Pfa71ff{pGC2NV|ILO<
zzyONkjXdX$=y;g~oJSH457FsuO)wEip?mtkfIVZ+DIDkly>p1icSUJzc(c_?vK-mQ
zwOG1_H|kHvlk7(>O+!p5b^0eI?u_Ry$JW(#IxwYYJI9V|b4i26*0g<M>bh~09GH^F
zMclRd=SO-f7_VXTxWvuuf0jk%6*)GLihO084%d|0MJH?4!Ki4GOK(^^!2LXuQkFQ-
zWd*ACL3~AxVdLg(D%u~Gbl_Q2(&6e>n+3Xu)l0%?)YhlNma*7iz`##ncl^2urQN>x
z-R!*RttTQYPJz~(=a#QNy-v_05v(KYZjvnV6YW~8dgB^pMgn9q1YNDRsUQ6$g+HJh
zDMPT+T}a!|UD9ODd-gJKGBM~FjjvlDq*k0-Yx<V(km<#(VmR(~hdz@_cUc(Ig11<E
zk!Zmy;cjkaKChFpZPmxSZ0QWxtU53HW!)2#w<fFkb>`h@n|BS(bKIHCY?OB^l4whs
zeaxCYy)=JuODCc#?*^u=5tsLo_{3Eys)*zw>1)n~#r10T{k!DO21m18AeRH`9W5UY
zW>31NoHSh7Smd=TGmcmaY3#qx!(Q7y<XWOVqX5SL{P@EU5)6;u#pDZ(Uta&jYo^c`
z&*>?)IcIJB@2$_gTc3sReJ<tpZq`PX3TMd5exOWulFuSV040NvmL2~y>ZlAixe+@e
znH8*gHpunxl%Q`UQePy3hxSLui!}NcnJAGWH$`UNzXdl!Jt>4#DpQoR>c)<`b|R)1
ziGSKsZo_Yxn!wCz^1zHHAWoc#OcqOG^1uWpX(Zx8NT8a)t~W5|F!`AbQ=W}P`hf9_
zt|Ot8bO<k)#d~d9k_j{`K$wHl!%mb)c%_ySO$q@%s$4M>LcQ`bo@qC9PgFBAS0DgW
z@!x+HEj3Bwop?$$pQ-2crP}RiU8N2UMC;UdZIJ>+64TU}jHG1OG-HF2U6sF@n)Lk_
zer~Hdx9#~RpJNv>0|4jx7ARB?n#_iQc4J@>H-k#3Z<-H?ORqcWaz1RfrbP%Ag?Hnb
zDBeXpZFLy0hgc+OBa#&@^-AZ8V;X7sc_2mNUez0;M~LoviR}FD7Fd9zIBJ~KkN4U?
zm-1{GwZ)awX-sr>q+LA2`;y_eParx@9~_4dQUbYFj($9abDE@gD+nJC=!$fp*Gtbu
zT7ff`tai&$`D|x{K``|xt7AF_^m2@MTn3juGPCRI*MdGr_BGCN!dabKe&SVG@^Uqk
zSS}fsH4nO!bQ4txtZc&S;xDD$@mY|fSt21egzpvQ$MpZt-n+lGaU=`F`z!nv6YmoT
zIf5X89j}Rf4hCWKg<FJhysuwB^9X5xS?lJR5r*C5{Ow;|`aV4uVeDkzvpl;oOm|mT
zS65e8S65d>oZgH}vB7^si)X=Xit!y2JggvuK<qtOp-bJQ0WLh)w+9^hbP`>{R(2f)
z94i-!kXX<iU;0=(++y2XrRhXR1=f;X$Mf=9>UaZo*~-*?NzK)2OobSxw<ba(ztj6c
zYtt9lRf+yjIjLXME!`U;4AhodUg!6+XHftf!G?ExZ&@Y*a=p@pc5!#PrIRDgAMpZ)
z4miS?6XIha;6|ItPY!p({iFRJi2tJ<^bg$Wte6iGw+Dl1G8AF0(CYG?z>!2x^j#1S
zF^=&?9HCpPdO?T{&XfLRa79q!ly}(ZCK}9zM_??&Sw%Wlq~Jx0X_ex+0q2@SCMze-
z*bIXuGI+>n#KG>I5_HJK9{p>oG&o-sLW;350%x5^@Vg9ZoF(z)Wt8C2mm?ixUwk!W
zL_j7ORup8qy~ZO*pCp+i6%(KtOfeGpG_^uD6Od1scjP>hfu>CtREk$@Qd)Tx9PRIf
zXGb_^``ZWm{|6%||7(HW*S_d0^Grpr%B@A!0Q*{1Nkm!z%(tcQnUo+T$`{)q{NYlN
zXOXVGD>FE|i2Z9sA~r0XFmpI@(aj)2?vPA2?%%{?ICtcr;7PF`q`+1ne0n=;)CBcL
zXO#iIs3;!pAFa4S+?Cme9{hcrrBvT*Pc_0k)Up#fNEm6T@y98x5#eTOAsZ35D4Za1
zYA4QzBY=)Ru9kr{Lt2oKSb<YLE!g_ffbMMb5zB+u(@zmpYjU0-ZbB%ar5A;P3X|@a
zM+$F@@WK)W@zO%Z5-{oXA~S=+f5Is9+^Y~qVgOtnt@0P}ErtD!2EfQ;H2Ucn#wcY(
zZjtfcTWj;AwWUT;w#aJk{(>bHKi-#iMn`{Xnt;>Q_#;a-`LAiRGmeQ^wkGO)L93u+
z1Xz(?MGc9bKJgy@f?kMt?#07>MJS)L1zr{*)-&5Yw?^IqcNy1CmU+iFp&9`^ZA?Dm
zZy(b|EX%g@so2+wGuBCNksF}S?I^rXZ6{MXL581c-Hp`p@igF=?xt0+WZg1&y#?U)
zYQU3js5R{YK4;Y0Cw=>ch@3n$0rQ5N2IGh}*mN+Rv6Br*I?fJYq?IQIa;6Fxho;g*
z@psRem5;y_ZGJWA@GmMx+Xd_}<d~RDM|5xnDPkR5DdF5CA|)^$pnu}BnJF*jTyz(M
zK;*Yz1z|dgFdPi^;W@i%lvZ5xE2x@};6Kg4DZnOdl$E~~3s7}xIO*=c!7Oobba?&i
z3V=0bCD7nnBoiu6w`4#$*(-r^fA-z!=#R7P8aXYQMc9bKc0Kvg+$bzv+E%XZJ;G<9
z5qAg@Zq6;iH4`puC9G*L^S+U%4P(|9c|WmjPFHYEUuGAk4J>!)&@{amtXUMxiF)=<
zG^)#GFONwcNo0#6c|lv>mMM(Dix^myYKw;tQ?BrvbI=|8B2Kh(>SHxB5J$rNU|8=9
zE|TdOBmN`>8sMV#Od%8N7&NuJqTj4(mzNkfjfGv)teIyVgI99g_UtRzK|R}vazMTN
z7NS6?jl|hE7T+?|j`44?VJsl{@4C?}F0ymnr+0!%k)^5%ai!$LKAN=$Su@D<KIlFk
zdBjIX1jA>|3tPOzmT3cpu>E$*wJQDL;!-^ix`$htNUuPCC0-@Vgq#`_h%&4A>q#<K
z;QZz5{2(oV;FUCtleNK@=wlszo;=xvf7=^R*4M?qE&9H`{^Q1v>l=S*ZMIq)o9!Q4
zkD*>`W4+b-OR)YWka2(JFg-~S{N-v6du&O)s`7u+A57nMvio-R0QRLx8m;atTmG})
z<>~I~#_G;U?rS^K*=>SBPge$wpuOIDy4qfEw}RL4X*`NS00jr=Ifq7Uls3zMjVFWA
z9M;NDuot1=7nu;RUKmBVRbBPdEC1JUkPPxA@ihN!Oez3=*98w)P*CS<R}b8R(G<2=
z_^e`BkdS(FuzeKv&}rlECmoV*OH1ozRp6KQ(o(CUN^8jomQhe8Y%gs%*qrRqBdw(z
z4qR{u1+O|s<cH91qN9V|g=)RwD==HP)|<hG(;PiB7`vA+Kxc$Uo!+m<-JiJ<_p)AI
z<52guLAcu0_jbb$RXzO`pRB(`c)1$eyW#G3ZyS5tXnRY$$0yv@SGeEp?DWE40GXG$
zDdQ@?@KC(4f3XMAYBhs)!&eb6P<D>bj(V8rd8y?ECd-e`4xz)=Mpd0d-S6L;LCc*h
zZg7Nw7keF|K-)_KtnqW_?=(g)0b~VZpzX&n(3ZEuU%O%V?4T1eMZG=B^3wu}%W{*l
zZG3<3or1H@873xug^{p{OIlAV>z(fZpAORa$9gq2rQ5J5T0eRbkyG<}|JCad4)9A}
z;BGCzw_SoS2G5l6T3%x2>LJ9|@-ivJ_M$~q>GknxkG?dQm(1n3{QH*K24It08n!V0
z237u~_d0C<9R9k$3%_ixufG(jVOvda)t0Af+h284R&7^8ZF{N$)Z7@5ZPmz)Z{$M<
zvwMPtO@CSM?Bt;1fqB>gX@epMfu3w*&UF@v`?~;X|0LY&0y>ACBP4P6c&8JJPL4Xf
zkl<I6^st6scDnG_X?G`lBj#imrbqtXJ3Bh+9E98l{Ec4bs&~dr9J)S4w;Y!AU)orO
z-?H18X%)jyqiAxOU2TchWKHKNVJ@g~l=VYAqlNO*J9J%#9{%NwI(YIsVD~R;=s}CV
z>G6vXiU`4D`rD*L(56qC96^h}Xrjn3HfacU<$yqmA4U1W9G~HO#4g~#&<r-8QV0AM
zQOSQ*`}E!^_Wi_HblTZ*iqK3gC}Dm+Xoua?H_pd>3^sDw44&HGPP)gvWBV&&xPJmW
zb=&xegUNk7*zk0O%>`kfH~>7K4>lQu1sA3wd~>u9v$yGd-8(q`mH2}Z-iIm66Pmxe
zgyyf3nk|Kg{k`pc&ykovJ0#|hHi^|Yi^Li?gPM96xsMKsb#sfB8i42X=}zwihbAB+
zQ%j+b%O3^QLFedI@Ac9WNK~tgWT8=^?UXCgAuAXgrG&i;8^Z4C5{Av{!cGN>%gKt}
zZ}5W%8nE9x#g|i*eFEmKk%NT=r%Nj~XgD-LRa>GO;sjSD`m!jQM*>9th17uK$({_=
zDMFn0cD4^Oae8t~VJ9d8dLNF`G5KhGck><IA>nc5yW8*B$!Hi4(2mVfCfKo%ZX+}F
z%o)WWFe=<=`so=qTCM!STE7u8H{#!0j5(f0{X~Heep>`qz){kTfBU0P{o6FS0^ke7
zYB{iIoWXbN-vx`qk}z5}tkzv%wH#RSgr6G*3&QH5DGaaJ;>m1I0)OR0gYFH-{q)1i
zb)$(P?$I4<&>s!vBf9gxk{+e!x68t91pPChG{R|LqDQI!18^P&*Z4PH`g{<7{GfOp
z0fsj#H_hNfGq`R9D=Rk*YPdozq3=e+u6(<4t1I79WwY+GX-2)kJk%JRj!b!Biy}uE
zTRb_S8T<RqZJ0(Q;{&C#aPn~_>2>Q}3tvTZG)fMLJsCzfMkQKJ;q_=}H*CNA@%@(h
zwiuA3IC4+lZ<+dt5Bs)@y>8v!tZu$h(tQ2BjpjQaJhH{g(7iS&=kk#4hYrYgyBH=}
z8pu^gLN-WClhg{CqU>tvmbN{mWRw<dDW-dr6qL7}aue&859^e%MomZ%w}P**CNNe2
zQ9!Q0G_c-}PbTPw7|*VsgrBC#(7r0=(qTdAbe@&8<<g?I#J_Eae_6M~<!*o1N~|ce
zn7M#!`@@=aAyhUBmJ)w@vI(C6AP0J@)jcxRV3IA`IWdI0j;SAmScDGAJ-gC|fsA}P
zmRmNZVLu*;O1T>)cilZoqK{kU;TX*ea#>y(qfed?cY56eE6y+aYps-GWXIw&ZXYTm
z1AA^CUP1E<8C1L<kLa%9dASq1Bp$!@;On8%ceMrL$2UXlfT=@fJ#qz7L5;S*2C><r
zykIJ*V+p4s-f-mS7vzvvpl5C$931a#_x6vEYO#rn+`Tf(FY_q5MRw7>)MpxZA_F(T
z^hSGy*vYMk@N$z}-n#8;Z81Qued~$UyU7Pe|Ft2s9SD`HBe%`f_dE6PkRHC2l`bxW
zN8*>FtMCP0#eNCS$0OLz@zLJC6}QyG_61`%*?vim8L-AHOu8t9Ht=ap6upy&J7LG8
zElAC!y8l(>vRJDcsBbeY^;K5#s2*l*zh+{z9G16qH4kd(QCZBEevQUxS=gsv+o6_P
zs|h@@TmMIa;ClT5zLRUn#<uEH4nWscKo*XWZwt0l-UXotzdZ9jjpDw@YyD!l@S6SH
zh2~$%{s(HNQbZ(iSAkT9Y!aD6*3QR8ZJnUE)fV_?;w6s>4C4c7voGLpTXVKtpWwQ7
z`PzLsR;jJL2k_ZMN8HQiumVTHMLfcJjwiw9&yNs7oIS9ddQHD$i|<Te<PpQ~Hl`w}
z{kL<SX}M(1^qYE>A6IO;cawasAT#7&?#jWe?iY0XCvTo`!V)y8g?KTQZ{*6Gibj6%
zww|xz!llOwUP%<NAFE@^Z3Mp=pQXi?LYCvC=pt#1wHvV6)>ECWw031S(iT+aC<AVF
z`YPSGhUb^UNgbw{&zR5nWc$<gs6Po|D{G-EAKkMA@hnV}0sb>gGxAptf(P)|EI}Wm
z7$bA1!DtgJQI1jk9ct3=FCGYQuwefJ4Vd`WEP%C*#zY{lGGNJYCWH(7m6I!BKp2=Q
zbITT{D+O3H^-tn&&zF}R>IoCRO*~=2=h*YIzJ1ByG!T|<Ukf!8RtshJ_camM5VA$?
z7Q)xY;6CH4Vmu|QJbVD+BvH(Ovxq57aAxse`Bp(PNjpdf*$jVs!N!fBOr~M}kZlSW
z1SMm5J&EaG6l`HUB&LyJZ}1_T0GT2Ok=LJ)qgWPPU@+E{-?stKYl3RjO=r;{zPRPb
zar03mJOm4M1hKr;-JB$%bv0+LJ>#ygV2NQL0rv6Cz>)WaP&l0vP5A}p16NJSpNIAN
z7k+XQ8;6Ooaw7W<joPJ+(4MnsNB%bL_oYfjo~X}+74auTJYD^E9*A=k{{BLk5OtxD
zTe8k`sPll+k}X8NeDyLC)CS&O2sqKo4wsZa6kg?HCix7|#VHM7KM!x3)DHMgsTW2T
zw?`zxsdAiRW*H-g(h^{c7g*uW;Vv$YU?ZoN=I;RTB-+aBuX%GjR&1A7+)x!a%8s7z
z96a9(<#^=AKB_pCzFU89A5018@rgc_E{SSu7o+|qzJ|%APow6D2Sr6fmjWeEN;+=U
z>$r9A9k;7GrW0GsJ&5~fz9Fe2j^a4M6)oFl%a+-4qoU=8*|PoKuzG!LRUGA^{6^}!
zv_gXa3R;+QMiLBHBB(bjTvy#xHT}MS=pLv5la<?dqJ{ORYpFXd0|Q=uj0Q_lSemT<
zj7Xgo5iuEpx?&<#K%^CPikhsSjre61ZkNIL&v{jNfVPW)w(ksdqZsH$A<*ATPWXJl
zcNTo<abLvd#lCW9ew2#%4-lR#08&6E7@;2}rWA@>l_ov&a>gr=b3!<OwS%Mx9`z}3
zK+cGeyZxzQi$*DLUh@PxYW7_Wb=$jn+2C2G4w{yEPMEqX7fHzyb{44^TC>R0Qzb5C
zx~{(Xl*G_4?c(te`#v8w%$3jSDSTj+_ow%(nXO#*C3=wzDnC!o#j||OO>Y?A%f^)R
zCKYzBI*5DxMond)+!xiXNk;JLWjmb1Y~@DN;MI#dKL&w_ZZcT5<aGjrmnQO<-b}}n
z;9aZzH29yO{rK^Fbv%?HjmjL=zQj+p(WpbdymzahpBGsUIsm=D;9N2;ej?qv2fLip
zYd!QlzOn*8xpaT}>ABf}J<Hu4%Lkgh%$tfQ=_M{7S&I4cxrpdm4c%~47Z}%J$lNOW
zrC<d~N;m2Z)$(Q6BgThIf}?8UXF0PQSQYui>%KJS*1}jj!Q1FgfFDB=fi*E!uJGQk
zKFU%T<d=kJ4k^zujFa3eZ2A0TQ+Dh;)Lz^KFZN`-Tpao~WVXfA7F>FrHbUPejJTop
z9@u!Uql9c8EA|=3NHv^(Fb=nYorL(NY5#p|r3=Z%GWC)-e@{MXvk`I}+KMPkb`?wk
z3je2w<HBi+5P1g;-jinZE`Hx6hcWo2p{m_dwcFxqzdK<`azvv0a1{rJtw&8qFNqV{
zDnZ+T|C%@HM4{{c$f6kjttrNdm&dd4CbS;3;-_2tli>qHf5ULhiwHtZUpv^wyJtcV
zeNM(9wq#Ri9kd&*3G=ZqT#*hcE}iVk_|;R{x`MDxfaU!P+mP^cFYDB)>FH5g1M7^G
zjIMRM^;Ng}whhwdeb=OKA!ThdcX?mZ@L188S<TazGW(ZzrmX1|y;=22x@*_#u3fXc
zcEQyXXf=U-kMWG-z7=;}n{oUs^ZT-tUSh?ILmf70Y%NQfCDy)ENOHuN@)zWj0EdpK
z>o<FQs&=cq_KO!DZ*bB0wxp}uTvxXxUEP*+Rd1&v>8pjX+N;<}Q0-Mqb%idAa-xFt
zw^g5RLkcZy&C{rCp4>uld>0rzR1n08U;N#0s@{sKw@%etuBz!oc1V{%B>U^QkBR-u
z-1ftp+?Iu3Z%cPM&(Ryo<r)xI@Epk-H33H_pxA1>Y*@L%(*++Bco%D^FyBJ0;WVn^
zK10M4x7XcP;ZA5>d#O8TM-h@>;7~2)Cw$gAkS<q(6Uzf8ApLXODA^wBcP*}=3cHr&
z6<z1{fB)|6-$DI*n|~K7*e?p?y7AfEvHfb7;8s$rYEyduqyQj@5D%&2*}MG{Ry6Sx
zu)k~G>iB41-Jl9fzSypfCGy%rSk`M$NlS6VTc4WZmb8q1vPv!H6_>(@fP0F7&*3rD
zfPd^0gg8Rj<>v80N_Ikk4+e(u#u*apf8z2M&ko+IhN`HmHgspV)Y<Kq?(FwsDvDe5
zXZrZ`$d~{x4&s*DI20G+AgY?jF1dx=H+T=9vQJ6%(Ab5e>Gs2)Yv5kp-a~xpjZl~J
z<V{dT6slC4+6#j8Q@G|Jq(4M)cd|x3f-eHB$hl0rs+k#u*bQU~ipaO~#)BsR?L?lm
zl@B}JCuvj4ZGrB;*sVdCRAv{*-%6>vzM!0!rUq)XlCD^e70am6wBm$Vf1NhDGmjZ8
z58#aj;Ee=uodba8I8XmNh6sE));?D{KdNry27S$&prluddq1LlIpII%eqvG6EU00T
zvFuoae{Gf5w#q2v0-YSpowqG*_ZrM$8BNo`&Lqa(Sg6n&AJeP&f(V>$xd)Qmal~lm
zwWnEcgPkO-D}L9Xha$_B*0PsGdM(nimo(1MjVF*m{C-XQqiro4>Bb%JA=;2FhEmX)
zl3vE_RG5h56|~q{1-ZX}Zqrz1yHPlqeoKszBCxa&Y{{=rL+zqOAIUshftDiTl5Cnc
z3Rpm8KBAKPER}Pp=mz5MLBN19$ZNoS7$VhY;DS(f$%eoEwl2i5?HNa53mH1tl}(x#
zOiQzj)uQItm|i<OqNvf(tfVG%K^8H*;D|wN!R(dt>xRg@kCExoEa!*VG(}F;*w{J1
zv|ls>W7(n6W^d26ViZ)-f=atAsER7dsAbauJzL<0vV{8gU1M{>Pd^#55IZDfit69y
z>$4V5mMVs*tWsP;Rw>b$*96tDTij|`w{D4sbz23C;)@2`80Zz|CX2|cf&>1abIO1?
zyVCxWR7|N2NGpNAFyvZrXq7{A%4IMN`WXipJ$)G@(PccHH0{P#Rrx&rz^FZ+klQHD
zs|;Ox0sq3cbq@CCx^4((1pr>0{!<)R7O@(AnO7fbQ%6Q5KJa}scUEQ=EA++tAPkWU
z`=j_0W^84%;ncrfpgxHTCFSWaqf~FPJV90JL%e1Ar-*dHLZew%=0o}*?ToU<ty|-k
zYA8yHw@o+3w_EY;)_5zh;0p?$(!$Rrw8BD$O&%`=lE|wfP6!}N4e<sxk-EtTuW!6o
zgV=DOyOu&fXJI8LC6?8O<y6RPMK88kHPo(cKo)%&^v((JC4=z!!r!%sciBcnzAbq=
z;G<En$}Zl%7&8S#UCx^^l^!ohEp|s?yAxZQ7;ui?&GK7Mx$7wIxb{+LUi7zWiuEP^
z$Ax)Gy%R2b%B!#284JE~r>pk4e*PvcGTe{!yQr6+%!4)J<wyD^k8}mfH+Mt1!evj$
zefEd&`s^)sNuXT#R8R%wy|V`Y8bVUiL*5tgS4KpKH{K1mcknGZd+?a&4hhw8<v|fb
zM|oYUoRmbiO8MRJ^5Hy{I)$bmFfm{OWSjIw-Eb}SWlQH`olh{R(dbst0R5X&kX}Rq
z@~k6&X5nnpu!nE>^>~JF_>f5ifWjERVvP{>4BG~n8@2^;ec?gu?e6cAH<*McyaN?_
z7egkYIC~UTGr7maT>A_e$gA0~ynUoeMwWVfA{9mLR|=M&E3OfX!<)fF?IYy(k{yhq
zJ_W(2?$W}@9dwA5Z!K)wlA|NI8?bC-?7wwH73_USX9ov{)4eI4s&h*jVuBwx<<lsB
z)+=FxOyL3_>0b?1#k8(S5+EbUy2M|luVYXzy6Pv~ghCom`s3&wx-7lkK7Ab?Z69{f
zC-l9>Oa(ul_3;rGzRNM1(??wYI0tJ8Od_P9qYPg|fB0Al3K_FQYC!sUR(L5(C(AVg
zika8MAxlPOwhQ?gH)t%#F;Mio%}q9|xZEmr^`>S`ckfjxDi4ldt#rCw+|3XQCDeco
zjR4VxRxe|<OU|`)igH;<1Q@3J8#7@p^|tp9ejx-_9$Iq`zmDRRI!Pz91crRE;><;m
zn`%J*+Z3=9!(J1a#h^06G2j!BD>$l+BAfaVrj~u^4nk6`2*Pt(i^T*bumMQaE~cQn
z3Pd}i>I3_o^#0MC?E|)XyS;HL4Mg^z9Fu#6qHSxq50q6#t*A%xOA${}%?R~`hHAZD
zG+x4>VzAr%XfVR$Q&Wt|0`g9e93hy)mXyCpqNsqpHhqqc4?BlGnPytGwNRT+zPeZ|
zA+dp(RHi&67MlQ&#!D5ffh6&>$B{@hUdFJxgIcsNTsNvO!K>nx?DK$E_1=E>v}9R-
zx{3kHiqVqs;>O+1;qjY}zjZS(8Z`qUkM;8cXVcVDkhV@`)iZzy;AHUC>OXC;y1LqE
z?WqyCD@rX!1tY84UOX8F!ooBmOA#%Z41?&A73#m4;qliXSPlM9luXIoG@GWePVJor
zn0OMQ$dRnc7DBwBxs_6@>0J<;h_I1H?W5z)QBT$u<}AFry8zX4=r>Q9i*GcYewfel
zGRIjzn#AR9Ote^u15-E%Wgya=z#{O$*-KZ*A56$Tf}!5OWoA{zG(=k<eJEHC!oLjq
zsS`ITo}_ppHz-o#7nUD;5tZu6ml|$iTjkVb#rt8wDlwhC?o9UnkgbLb(Ov2<pgXVo
z><6#aq6seMqtSl_Q1a~C;mWsZ;~U|sPbYC84wOujl~q(`O0*eU#=e8n_fj#GvRvsg
zryabMg+CUQT$Rj}z;1dSeR*ceueiGV*%w-x!)SE>JhB_nT>#0~58|0+jYx5}d@o`S
zkE&_#jo36lW0zYl+JNeu@@C2O5~P0R-9h<1KKs7H)O=+HYQh0#t1c!C#zRIxJZm4U
zT^pcQ0+xb;!?w*^dnzmMkhzS5M|?XE*k|$Cw>KQ5WGQ&S{(<;KzBPCT_2gRs{9T{9
zxQT<F`O&@?FLjVCdZ@5a1Br44Osb;Rl)R}f5^7{ZR$|I^EhZ+fu<hpbk5X_-QoMNX
z7ZqsR9mT+HbWs@Hz{;eIkr-wLrs0|QJZzrhmX{_XB5CgAMnDjy2hGX@T0^c(bvm1f
z^m6(*R>X*Xc_!2Am``U9N)A_;`iZ^bA7W3&<}dw#%TR7O&+a_RkTca2JI<RH-AdX`
zoTy@w0ha7VfuyDq2kkYtg8eSgvad^<iA3ld9VEtSfETeSH?8UgR~vdp2J*%rCmOU!
z;7CRf>PZHlU|3WxEGibNr9w@iu!4v8#+^liX$+A16Gn0(P-Mu;WZGC2#g1X8A`PgR
zQDr_WQnUUnwu4$bU^*WR@B+bzqkwvj^NHDLT|`a07|lT?vPnhxaHTqyM0kH)Xf04T
z+#U_6Nd`>ePgBDlg~lsUdjYdBA@OH1N7PU_lxk67jga*Utp3{fO-}pw-<$iboO%9w
zzZMK(Ym&V6!oQJ{j;*yKT$W@PlypP9qcjcpBH-Jhlz-GtetghWY~57cY>*l@-ebQ&
zFiukBk@Nq?Iww6GNNn7p8OpCpnjNRX_Q^i^J@v`CNEn!CHN$@gASjdDV1@ziQrOFc
zbtpoSF`v+uNRY<!6p)#YhLi^wc=N-WOv{~Mti{{&2<Epx#1ga{^#>p4AV#P*3Y9dZ
z5*96^+u%GJP-0o&M}otGhmu(a(^(3<kwAw9P{`AYviJ6HWgUWI<90d?2s?(A0Flw3
zp3G~ao`xiQf<F`_qeoPw$j&UssM3Yw#l|e2;J0v2|ExTe;E_FN*;N8<!tp$dZbDtI
zf$Q6lz2k0Yd*}6vB~=O}j}$iU@g}d$6c}=p43Qd6nTk^dL#aJW%#!kw+Z0l(otI~)
ze`o(z>EO?PG!BtWGTLOasGXxVOCvy_NCU%Z6hgq3K*jf4N~{!|uqo99-nW-u5X)Bx
z6y@j<S!;cs8D`>&FBrpL#stAANoDc-U5xS}k}6`67e-Jbr`^wv{oe(ikpX+^2mR-y
zMIujx$mDUanW7O%&i{<IymamAp7IKtKjrzKTkRj8JjVRbo9nIC`sQXE^FOy+PyUnt
z`D^@q(frRBu%s@6kQN+fem@Oghbljo^BK=V#DcI<4w9*vc8e-v%6Ji*E}y!#yUY5Y
z0LOK5RgNh}j8SEidhPvkB6_BqA}vy~k278sGBFQH#AI+DW;bCHPcFmRhYWPSFc}QD
z0)#Zp`m6;`FF;uJCn?YaW0SMn7j<9*N@@TCEhGY6qX5dIJeV!FICF|cW<3gGjN@wt
zr)bDevv`oIc(L%y2s1OF<2T0%rj(7-*#Ip%@$gx&ezU&5(RQhZ5p?oY!>@n_{=-@C
z9XzohsVIl`vkNFs;&mKKd6iamm3DQNjp{0!)m0u>S9wxh<;S8bNi|)PYPuxVbV;h|
zl2p?rsisR(O_!vaE<m~r7gA;UbWl`&Ih_tmnxFT}N~v)%Y;0UyI-kTPpvUu3R#twV
zOiNLlgJe$7x=~UGPg@mL;CCEBNrlHD?C%woTJ5J{`|;z7TJ6VA!pE&vMXkrJcGv>_
zqN>aF_GZ|6+<ID7?{VvIVS9bEY6wu}X}G!mx2i!vl_%lT*53+;k)+q_o_5fr9sUip
zq6+v><wu}r`)M`J+fSc{ttT5#D@lbUz=r{foom#UysfI{S8wUkOe&UUQob~k(xsV{
zFU_QMX(pvhGpSgbNyXAkYAns9dTAzAOEamnG?Q9OGpV&SlX^=tskt<hnoBdOxiph{
zOS9!^S8Hh|b(dyRdub*MEX`zrr3uUUBI#d_;T%x4fxwBVq{=_~=jV8rUswUo#$?|t
zu5pn}$6<dqtJ;TEz4BFGHLj$3TuIfqu$w_jV=JzK#)Hannf1yQ4N`<iYpzh1%IW}|
zL6($BWV_hSWs0INPSa@UJ2TDZSWZu129wN$ou*EaIGnKME7j)`bdXNT2#U{8rxzD!
z6pkn2=*F1LlgK@e+)z3BVuzy9zl2Y|^2Eo;Qg6k%aQm<mN{4)9661zjR)ThQD&>a9
zdwZvy-pWNI_`l0bE8M`jI#MU2W^jSYpDjq8Za3UNk|)@`{m#K|9hk^x<21g(5KD;#
z-I^P;pmXV#b1d#a4~uqcfb$Kd`!;;Jivv3DE({su(=a5Dx3sK-U&7tJw|4+OytpX_
z+q)astO6`z`*Qnqf9Ed5Alqmu#&-gpRf66>+&?|-?A`%qQwj*k$^^}e@iI~-XtcIs
zdZb}=9Xx{ns0V_wKv-tTnvTCVwlp-TFW2`XAgM|4h+EQ?<$RLTD{S&)oD_7ym&yg5
z6r)9=CoM!yd9r!2q{b3ehGewh7v$n~zBL9^4ogrvzs095)hG?7lQc6f1LC3Cy>m(6
z7IDV&aztoEHPBfq!)9qw>MfO`xZrFnD`Ea^8egqIW&P|!*Y-U6Q1un?`E1ySzGHJu
z73U_3Q}zzQ`-;DU>JVR`G0`@(;{IsZf3^L8e15Yw_#!sua{K?rlOH#pu>JqX_12FY
z@V(W3@_6$<_W!T(^F{6dlfh^{i~`JmhwGlN%-6177)7|U;wgU9A0M!0Lygw19=HWb
zbeVcSkEY(ws2BNw++;WS+1~W<f?)@9q4G|Lmk83worRBBdZ3_8rYIuF7*3CxP!W@V
zynD~@Gyk>T4Ay@Kk@K%sGg$4Mbh?N1SGy^nt<ay3n{;){6{+U-tL^<G{#(>N>~Pc8
zlcu<wW=K>_Zk+u0Q?7n`vO|CWjbN*^rtpo`cImdiEcH2zN*L0xR#ZSU`ix_8o(eYu
zac*RP7vUsj5}*<M;P_7EDMpVSooB}O3uAFZuE`p|UsE{YExm!DeogGQz`rL`+ueq5
z%I#ot%TfxW_c<Jg;&C*c7hjbVg|Hvv&vbsS$c4z`eLn(3JlDqkY;c9QFzMhb!dJV`
z*>Q}|5ij4ODt-b7ir&ua{i9dm>CWrUAu?ik+}(e*f3z*VXHA%+X)1iB%*$r>NP4q}
zS2?30y@i6kHh@+u-_D!g&Ktp1)E{CX!yxO&Bl<<SF(E+u8&A~1$)0fA<Z+7OH3JI=
zgynofsN67zt#QvSro_G`FT+~lWaHyLi(gjG4zlOFOd>~-R8fG4)i~Uhy*@C(md@|T
zv-#`xevhZ~>~yKMzOG8oI4sKH=@NckHx?D5iYyn7P=-3b6sDt>bYR%+ya`|b8upIE
z?cME@UZ=Z4nuFC&j-T{~IcU-HgL$_7)Q>ajTDV)1CL!+}RWuDT)Zm5YSBwBdgXFw9
zaAx-TJ-~!QuS6@5pb;h{TX~MN8Qlz`Xo%OnH}QBrhL6LB^b!`mHA_3QJzoq@cAJ*y
zC?W^jAfGh59FEVhx2c)gQcjkdFh4odqs3Dg_Ot02&QT*Y>Q30jhg8S4VVvUgE_4=Y
zf~LORJ3fSSTDNns{kF3!g9tefex{S}ctYqwvZh<4e9)#B`dNnVfIZ|jHE@4mk0pU;
zEEL*shHBx2^I%FG%r%-sAAum3W*p1U!;+o%M7J)U<gdh7s?z~`=@Rb(B7&>Qn`#)1
z`nTacUCAvnesNJt<Sr<48C`J!|J;F(qK|<x*qjgyzAun~(&5zr?MwrI4`~Q;&5EVS
zMTDC0O@m)Gw|@UTFNJ7jRL(Sl*Kl4u_p-fzn?%lVrLr;6z5T-u<G>1En2gUUw1Py3
z97YZFq~MW%)2fn!%n0=FEw`i=MNU~Z(j+QD{!lmW4~H>2A@)ZcD-6??D)F9svsR!r
zMCgoq=M9In2H^|44<|!7(qYU$!NP%HVG0<Ts)hE6{8?$U{4kk*A~%ibra#CCjA$c6
z_K}(36MB#e$67pq#{E$+yXvPAd5Kc9?NK@<@7g4yC)dY6qcdV$g;R7LA=v5s@`}I!
zZn%LfloUEw@!(44qL#j?Wvr>iHz|HU{S>sG1iwkTZ8?o`QKC*nF9pu%{LC0*bPqHi
z!#QWp-n0A^9i^43Al{DuGh!E{rMx_WTBLIMr45A;5l-#}r9sO@*|XZUt8}ie-p_f}
zink0_Er*{eh+p|$%8sJU&UEb{1@N79CvC3b%wJ+cbr5CzLc2Vv923w62>Asyubjqn
zeSv40*+pH?RB1XP7pZG{O@ag8VxLuM`nTiR<lIm59h(lQ{Az_<yR%Qz;QTfd0T6I^
zOi=#gPD<SUP!drkNEBoO)oaC?!o$;7G<m_Q_wd@tYh&tQfD=p`H^3IosQ4T9^6lKz
z%z|0}7F8QAlCQYb#4UtRp}tn%9~irOvxiFW$)54NguG(`DGtUeghGBsan9t?(ZKv9
z?BeDRK;LwBddJ;H@Y`?7l9_LCcC>JlSDhX=;M&-yda{>ClXo{UA_^j_C7t94j;D+B
zEAF(OdpKAG!1hhXmfjE_s=gT1d*TJL;>1kL7c_V;cRLweCDX|i<PWitWK*?%rJMgp
zmPhJ4=GaywIqGzFSqQz{?@0yE<1TNgPV82{<lk_M^bbTrOJ1);-f|u#6ghW0j|Xy_
z&gv>Fw?(fk@<YiVl`iP*C7p$E&(-TRN>lV+hi~#wzNFm7ZNG6=r;PzwC*d5Ogr39G
zZKynp48#cg2OQG(vdEoC{AI}Fdw6AJ%UV`A4w8>yG@fO*J}bSQ91NBH=kj(G<Ml<?
zgtc6Jzu>JXzMR2Cz@|pYEtxe3<Bx05CkGaUtz@1?UVRfb8gWV*#gh-=0RFg)Le#&!
z_9`NWyIIX>v%1#1q?MGD;Ifv{<UfWOS5^i_rcIc3^pEm!0`Hizy-1r8&gK}mMkUTB
zS~2Wd#MT8Vh4fcc%n|at_IveuTbI(4Z38{=VgqOa!@+kOttTtooL*Tj8OTdj5)f<@
zwAp+wb6Nmp#N~_88BJ-PHjK771{xibJ;tE~BJoJ)QEiB^K7NnUz+3ZN@3LJu==17z
z0XF<c62Tz-6koLCzF=Kwx$NPF(kSMT2#vmm7r+SEZWI{5SFngW<DBeaWRrjq1PzD{
z1#mhUL;<QOS7Zjf#Dj-4AMl|jLyevzN@4UrP@FglRWke}RjMoy%#q>IC+5=-_I4hD
z9wVcyk8Zj0TCjbA=C$mK0-^T@A4KoejF#2BKca_#&|p=Znt(CY>BS^P1wXPukBvq$
z%Z1Ur85kxcG3<tVG^KOX0QFF@PsU=r+_!j5q@Xp#NrS=h3m=$@d6Z`AnJsJla5Nj@
z>rUp9VhdwqONRp6fm37anY0yZ6JMXH$(8}cN1x_6Y8U+gt=F4$*aC$5Bi?(UUNaa@
z12mMZuF6i@x|2~q&2&%0IjTHxbodmQXO<>3#Q1{dF%r5P#upb6Jr|`Y8M;GY25!OK
z;tt8_O>jd|hA!Ew6;ezuII&&{D#to2h=8mFp+vxYim~jrehW!%`(ay#Fg&%S6@>nN
zAqr7ZK?T!lfgiWD$prbupxiglHKxk&$@R#d#apcWleHj+Tf5TC)epvTN{Sb+c%DYl
z-O9H&@*;xlhBNgse_tUlDrCUwJl;)Xg7q+)fxeswj6rBEMv?4$qui#SP;l!G8QD`W
zj>~>L39Qk{A(xF(55`2@7?C>|Woi2)ENupJJf|k5`-bE)#JMt#ckyoVSzIk=Qk(Nk
zZT=e-3I{h7vYPqrI8E39Ktt?LQrvT7La)JehT@-O;ddzmP_5D2m8E*c<MV8FGc^|v
zvt?~=3r*;Qc(G1!*Qn?RYst7a>2GS=r0G+*zblkuKR7l<*M_A}A-J0`=MG_O9H7%@
zJUXA=D1!0m;-LtN`nwvHb;Ob)MSii6wQX0Pt7ml--4OW@4Wn(&NQ*&MWc^Jm`(f3s
zk-IcBem*;#d>{V1dvhs`wH$f!Ji@R5@q}3((8MqX6Vw@^n`ki4P_Z=`aX5{LM_H-y
za%Ck$UVsKP{gkRm0MjJCjDbGV)C$c+v;;#_xx+*(G!6A8!E4_&%^uRstG>10OKruw
z)gtdI(}-WTk!nuyIA;B%K(1LQAdcN3jq@^Juv4TG2dfbu?1e|i-NWqzOe$z4NHnW-
zJA2{I!ST+|;lc4~&y#<!8<DyK`tX1PJD_YAtFI8~+ta<1u=h6H-9O!adC>7dg$hA-
z!}<_iAP#H6+<tl5Ir3qN@Bmo<95gT&z2e-8XA``ym~c!(B;&Jh=NS0Xp{)t*ci)`O
z?%^n$GZ>o}`Um?*Ka=y^ne_1{?rzx?_V8qH*w=!fy{uw#3I5GPdasgnxSUCmy{v|A
z5AXG<z&NM!nht>?f(9~zPr-_ihfF+Bp2NIz3OU*fKFg3GiF5L1pIwNROI6D_9)e;N
z&aPwjYmAIz;=5eC_rZTHi+zn!O1|7a?Qq_>&Ji-Yv~xOzVi{~HVZAd?@B}crZR!&v
zN@BdyRy*C4u7^N)qp^O}zs1+k2o5g;&>BvVkX*xH$~hchC{Q=~5JVFYz)@3Na(yC&
zfv@W1>up%YDG2J|Q!*7NT3I5FvZ!9%&LVu{AdA-ICPRI}=J6p)CUD+kA2|Xd;?blC
z2x}q*2_kG0P$wS9bD286a+JC0h1xxmXw=7(xN5;6c5ts^;B=7)TULB=OO^O5Y%<J7
z3J~?pVOi!0cSAG0h9P*2mIP0?rFI0s(>935<7gQ7>DUfks#`pf-Hhf(Y<6fe=-m(`
zv=el1IG0+2@qE^Tm-9?sfPRW6L)f%uQ4&vwObRvuAVT<lKNeA~j9HTNC;z6iBuysc
zfcLS}!C;=qEmvL?I*SbBgK<xw$=WMHdwLbNahs?Uh*;71u8I@Ga3#8|k0!#M!YfLp
zAcd-MNE;MN0euZ8Yl@3F5_iToOF91)@0~^A4}cv#lZ2&)u>?}w;8GoEz~*vp&#W#v
z2N`=l0o+p3s{jo1<aep!Vitv31$PZ7j0$5QZ^$(oS9s{dUd|)5Fg(!O<pb648gF(u
zPn^R+3~xSFce6$z&Ik>9fF=x??55%fh6>GeP6^a~p_FrHtikvr-2w%V2FXWxwi0G#
zk8@Z~b{AchJ`#7Omc^kNScYn4{N)f4rX3Ko_fUGrMa|?(Mh|$km%#pDcPgB<%zEGO
z`Ih;Q&<8?LQ~cwdQT4sJB=X(n+O(nDT%Jm7Bcfm!JJ$Mp%I0`+LEbnxV4o$>kHs2R
z*D<cttqs}+vB;s%@mcT9!EX4H5+5yHPVpvWfLU4rq;iBR=t&|j<M0)<*430Ec(R9A
zuc*kIw=+I-flyxfWJT+rc3w)@A^?*=37IdEvjYyP1sgGL!$OFQW@Il}<3Dg2FX@4~
z+@MFtYY*3!92u&hHZNH$^L@~21m9YhFxZ872uTT2oz6%Cn~ccvg_1sbx%zcy8*e;c
zHFI3tP^m$di@e}!Ed9GWiGFF3LGBe|I3UVu$%%r?U^z7^hMES86H2diFs1-A5M^6l
zX`nd3N1i9$;~n_V{^54_?|fa)^86cYCStn9DNEW$BY5~QAZJndbbTS+eN=b$-exG3
z{mHH1=2R*fvm_q(6HeHgMxfdZ`#OqYBur0iTH*^$X?VGv45Tff8Kh_d5E@v-;d%8!
z5jk6N0_9ccigL5U67MQz{4g9L*$zHU<T^z2H?SvYof(HM9HpwaV2W*IH==Xtjs_UQ
zKiuVPI*JFkq{MPd<S~q=DQ-0!5TM3Q;i${|HR)*SbR4Nl7*O*n=%>a=&Q4#4#+iyq
zD8@1wDGHN<rX1e1u)%93F*7ovq-cx-{1o$WaQGvvPT~0Icz~C9bhx6|$8tist+uv^
zppMw9<Oil49W2TbF<HVIif0-ng_<G*im+q~E|6SCwx?7|U*e)9B4Ne)E89six}@f&
zavarRKz&e>+R(R(R2jpo*Xv^7taQilCieVqJQwwNMRjl9+4a%W__6y%UhBwhR)3u8
zk>58h{X=D5TtE>qRRXDFi~H~g__TjU?@~Egu9R<zam9GPolDOR!KduijV>hw0%XPy
z2EU;Qq2ro@D|o(IO%Nn9oZCr%p%7_V5>jk$XoV!>*_HQ!YJRPaNADB3Yw&CtdX}WC
zyL;fk4h7Er5iT>mE6^E4$_rY7Ut?6#z$wU2SlZS=Eq9*PR{>Q3RmZX@Wp}vqdi&^A
zM?oxeZ>a-#`xF!0;DrZ8H^^b?`b5-$>FzeqEZvr37fb$&Q?XO%1MNkejLFnQ;VYzS
zt7?IC{jSU?`5m4_$Ng+gbqBjPd_p@@Bt0eQSSc=_g6n<~Q*xnfD%w<Zpn?l46G~<(
z-BqSmx!kLKVr!9^EO+}yd&f4B$%3FvTX_@FoGfPA+@<Kum=;(Ughiq0n5EPdvD*O&
z8b@%+_h_P-ORh58YHf}KrS)+Cbf=6OWQ_0<z#g|~S8MdvxJAPSNAEKxSyt`VduRB@
zWr5@Qr(Vg-C&ES>@kP0CVV3)b+BWQ{&CB)WX0_N9Zm_?S?sSg6LcAOPLQV=mzu7dN
zP@v}h!xN#ZBlC#Q{HWk_j*2C5ydAZqPH15L{-57Ze~CBd<?sL3+v}}$eE;9t*lhpU
zdc2A8f7e@&|MUL;Yy5n*_`e6ouRP&@<=16kaS%v4lN@j(9^WaZh7MU|WpWk%au;Jb
z9rqJp-nBIfOhcOQ^l}9c{ZKCq{`%KI)XjmWT)ZodXTbx66Fm68lLt+Nu@rJ%<FE;>
z5qKky!`|7^PT1>i?{rogHfFn>muIke9|SL6JZKb;jU}f&y4~&@Lb|*CD?6K34AM6+
zDbrzSfiXHB7@m-%NtzQBn?ntFtO_Md4(E{YAuOp*d3H5T3qUJ-{6esQ-R>TNdRGHJ
zURDjF#d|n9?(Oe%YILCXwS~arc3uPc@ceRd*n;`Iz@3;dV)Z#8VgB>;zvxHr{~QtJ
zOY~8`|37JMJYIL=|7<}0|Lp%?<L9gG|J}E}xB2~Fel;QjrP&a6%6ycd@%bE1k#Okc
zU_lH<cslMM@%y^n&gst5lTD`-{m)eCM*GJnPwj9WyPdu5vxA<l6a*NA)`qfuu>b1F
zg5yN_!xC~lp_)srw$sbYvxA?Z?BE!mF`n&F1_A(5fXdr&uiNQ_z1Q8&>FZo)vRbcp
zweD$AC4{kk+G9Z5c=T985*Fh1@~nH>qbh$ztCqJoco96=1eJ*bIR+14yCN{p{J=P2
z(@)Q#4QyCqm-6?Iq~}N-2gk=JOPhAB(>I->nom90+Erv|lVTtZyEpNe6YZenq7?Sf
z)hImZ94(b}1H;4E4+}vmMyZro7<jVV+3p_7sej_o>umq1_Y@ys!g={=zNqy?l(nAZ
z3pd)LFvr6f=lSJsh&+zYo=fnzU7_`}Rc@{|uF$qCU<7Bo!lqpTLpQsDSwSS2ReYGa
zp<LhQTi6{reLx9*C9u7}pLBp2>;4)P(^^z%`KwTvYEh-_uR;;3MU{<w%+<Yv?N@9&
zJ3+hW5lqhdjhiS%R6E$%hx5wGn@z;|X1%=9lch39n^5U&_oNgM*6Hn>2smyf&}Au(
z?oytBs_>Aki|aQV=ojp?YvkJy83>>&re&cYAh+`XBw7%_&4NM+@WKMf?R)??CBUZz
zg#`dN3jpqQfzmIrjl15k^t9JK0kQJxg!*i4l+`%&QN{p}4{!@;wL7BoCqDYf!XJHO
zm4zNc^ty1!MlVpT(fV7y!t3LGZr%2Ajw;MC?{0Xkuxfkgb*#{8dua8ld(4T+h?=hW
zvTI0c+S6!2@XRHa?(M&YnMM>gJVV18ot+~t_bsVowWd6+kJXyW&GT{LnmSgC%11A?
zsPYgC7uB&^RUQf+t5ua-1ILA{>R2r+4>KLBW#xfbw5(20;1=P?g%Y9-QZ)3f)R(XK
zdFlIBDwX=B6F2liJdhAQSW;;b#DjhRf_}NH2JT@XQR=0oZ0Qxt%+Wqt!XC2Dg^%-v
zowvQt5x4b-kUg<feUkL-kjp%>W2d`wB1Dg8hzA=7n_S%Tt*_px8jX+UxISsqJ}r=m
zs)CXa7kLT65b{yK5xbsu!<1$D=~k^8o)()u?`|o}3ZQKkK-&Nf)i=%DNESZM7m}o)
z!YBE{-sv%y{ph1d8?<HL!q<iQWok6^4nu-;=TDawz}zT=xhY|~n}#k`FwYJgato;W
zhR0>>a9qp}$3+ZrtY*T)5wJm=c6NB{@k|qJY6T+GEY67ztF3R4#S+OV^@1&sNIgSz
zcrZN`DyfH0PkjohY~$&rSbX(Nspw(d?!H%iQPH+vc=1~KyI4rAR=#u>&YQghW^K>>
ziefJ*WmDe-9iE;RG9i{Jl3h6Kg&O+#T1pF7M>}Za@i;s?;sfg0fm6I;7PoW7n{Kg>
z3Ve!Y=J5^+CvN9(mj>0cM#OGWUUs7f`4-5Co(2*N1c+4xGIW#U;t~Ajc4U6B$K&bh
z6j_vaoY(t%J(POOI@$;3eHpbga;ingAUO-PvVf2~+o!#z^Z5|^^A^199&hjZ3Meet
z{w{~9b~@j1I|tcybbQol8h_(y)%knV{2LF(-8Y?GAN)-hK5TDiM?W7O|9aFkKEXNG
z{1em`^Uu?r-iZhJG>84Mi~g~Tzx=QX)xw?Av%`D=e)aU0%_nweAXlxv@NZP}_m52c
zsn(lUU8@=;O_fP`)RVb%77YUO8b6<7Pz~Xr<R;%CH%JUCG(jgFbSG2U8~Vc`rjFMi
zFkVQS^~V(YQ@WIspPYJhf^FEn&HB_LHxKm9*fP6vL6C<z`QT*eWo~|@;2{`lh(9Y3
z(%%OCUx4VaoM4Xezo6mJAM_7B`}!>a{UrEJ)h78Q{vxj!<LwMy(hgGg2g*{+GfkeO
zHp)xNPu{J+Wfzay8i4+|;rqC$KmJbt{BF}>I?tjc^wTK2_7EpHX0jZ^vLzz0Zjc-D
zbVLlvpaF+)oJNDPF<T9EWux3T>Zy0wQ}4JfHo`E6fYrq?98PDjS~mx&Gx}M05rydh
z5E_O_KTKk~e4J8)--GO?n14s@jZL~Sw%d~Q5%_7ARNSb-#iVI?)laYNdVn&Auq)zm
zW4_GkP-u82fO#Ptj)lwGFuXY5a*H#YPi%(rb$UKzH@M24&xc~_hv9rUTX%bgc^J*d
z;UF2zU{e@v&T{?#9wav`4t^Ioa_F(<(8*X9O|s-R(9dY(EfdB`pI>-0oEb@ztORG`
zG3b`@iGqBZA2_R(7p%%3WdQ|d9;7f*+0ZE2EGn56H=4SweB-l|Z`tUyJwOHTmcgWF
zs0itLI_hWWxlieE9>voTUFI;Khx3MLM)RMM1M4I4$N6Z>o~UR%!<R)cS0Vo5fZ!)c
zA}_X6#`FFt{Ui#F2T0_sN$W{JQm6FV;xUtWMUFn%>D6>JRN=>9|2>CoaC#BE+)XKF
zlz5}lCvR@}P41oYEjIxY&1A$?`C5cvH!Y7$1SDREV-F@k@y=LB$Hh#C5kG1oabY~T
z*Du!a?Gp&_cruJ`5N|94&<OdQUhj;ep&u?Hx5ceRit?&4=inq!KN%yBCE1pR1tNe?
zy2a3wXtj^&7%$n~)DLEIE(fD$A&JKQc!CWDwK#SgROeBV6XzzrnUM(q`S$Gq6w~nM
zPUi%zL-M^pzN&8q>&D9<i3n~lAc$Ce8{xZ$@c>_Gf4Yjuhd;iYOhw3P+G1H{pt#xc
zm00%%$1YvMIl=(@E5BBZ^HMysa^S?qi+_FuBz{jhwoJq?ndv<hC6481|7vpV*ad*}
z6#78nE}v%;7}5w&f91nLxD988-Tl*@?JgYOj(0mv^+4;xd@=(_!Qa~JYr*zJxW6Kz
zjLnrw?{Tgk*$c)&%;&RNl&n(Fg`hv1jgXLl@LI43Ly#!*+NnaDQGQ*BvWUFnpuMr)
zWb&y8PQ*IGRbOBUOocIcn&`7<hF_3Dee@f>D4}Pr2ys<DO`pP7_FIR^@7@5JGT~{B
zPsq?wm?JOn^ZrlaFir<Bau8hVr8>nvHdj7!V!r+}nX#6NNs`jXK>hIIV|EqHL-hoA
zMiUAV!%Idd1VvvA9S1R?HO#@(Wu$nll8TV?_`;0C62qb;jG;P58)hm0j4L9Sa=j*n
zcb$%|RrDlWz0-sotdl7;8CxSafxV+?FTPX9$G-0^see8nePI6*N<d_iL=^@6$OtN=
zOpFrE!1#S@*`r?Irb*Gj!_?gS><Sp^kjp(46k0r3k8jC)5p{fb@2#0d)fBEdW)*y+
zLR%n(3pEw>8*Ph0hg>}hdYbU=R;veB1;PAHg`~Xbf8gI}*6=T4ydu8SA{qmcaP%zN
zTsVUP2}7Vqe;^)V3E8~=!!cl-UC}FC_;4FY88jR92N>f|q&b+Vh@eWvL6vu__@%a~
zOC|Ez!PRXV()kz%)qTqc?cKv|I_=`)9PGhLNG3F*e_|4rN8^85+)etIqtqasf!)Qn
zMNhQlgPLf#RUjLHhOEmOkyK?HLWxrcp|W%Vv&Q)f#Rkt$`{{4q5Ev2=7^8adcLhQS
z9YadFsC09v7=p^xL9@H)?QHQ_&anz8Ib-G&C9-hp`{xt1fQ*EeZ!Uy*vMgTI_HF`n
zyhc`9;|Dyn+lk<<#%>o3`lAttb;CzUBKstcV~#llwomp0^x3AWDh@Wr7MYE7pdnz&
zK3P?0As`@bO}k@x^dg=6gOmn2xMdE_!{Oh=3fCHm4hKX*z2INo=OQ~kZ#G>frDUR|
zfC$Yqx<${y;Aon`hQQ=W*~FyK2B1h9e&<$3mSqmfSV5UJ{fvsUGuYFJst@k%6c7>L
zP{aBQaES>m0QU3fx<3&|J8RB?OPcCY9Ri7NVippk>2!wbS1O;uyV!9=CN&Zangj@=
zlE;+m-!?hd3UAk9qH<thX>kYumo>-zTVjSt4NS^8B4e{^XcJ?$5fG^)^i2I67xVy>
za`}LDLcwxr1wmiP6?l$H;+YY83Rgwp>XFMWWsG4BKBExAtHBg{NBMOL9Dv*9V3Nt;
z!o6t*p!8Yb5-`f-%X``{(bsFQi>ba*AFzi*p|IsEGejRhu8Jd?NEvoMtm>1i^BZM@
z`A6&_8=Mct<j5EQ0!&{_AMKc2k71_8m>|8=XiVYb?v4(vS;9%eQ1AK+aUup6-Q!su
zVQ4&!$9iayo<yT6q8Tj$ZXvqnz+w4f2?!O|XTkLi8l)~~AiyrOSu==d@r+PBJUKYs
zKSE2l{*_`D3h)vPDGXR+HJ+?uo$lUF@Z;mwx_H~C$Hsf=#e6i%k7qEQV~A;*UfLS2
zfh=UpFenGBXuwfJ@T=Gi6&s8qI_&qwveeB8L(<Vd=)em+FB&<d@(iPNf-b?K6su4a
z6U@sADWeg9!#Aeqb120%-IU@qjAzfF3H~KaLk+!}Kqg24iUlcD8|a0&0iaO8`I7qw
z$P?HUK~73#Ze7OS_Ge$Wwswzzu&i<Z^;}lPTxe#!Vn#P>*(~GQ(A@dTThcPalJ*13
zR8TKbsG<c8Cyic|u975%tpPW5QdlM!?h~^G@D|G2scVUoaJ*);Y*91X<ecWkvYF)!
zO?+Udy&t0nkaSXty$GF)+mP5zjAM4r;w9}`nEiUf=aB-t)<sNqE!dp2x?<=eey|+i
zNt?TD;}S=1xC8j?MsU^eRvgxByCNFfaPGtv8_cN|CD^ekC1Cpb{O$H&Spu!&k6hVe
z)r;L&AZo5zYq9c<&66P)t!sy{1%TuXD(T;ZlPTYN!Pw<-8#7J86zQD+l`N>Yig#+7
zblUz3=P+bu>R1ds!N=~;=!1?wj6OrBzlJ;82jR(S=WO>ld`*|8Kd92zo>G+wPo}ae
z0;77{7jrPCj5<adOl!NPBU{oZ`;Jt(h2kLrrPGT{80CQWpgs%b`e2h%aH)iKGz~i^
z!7PpD!>QPx6cpZ<K~o;gM^XXL)eZ(%(cnYMEG@N0)aex%!U4v<<|RlG<vaw@_r@Z`
zY9(?CP!W;}IXaZv)KpZ|BQdNTX5SR$!dWxGnus--&IG^Bhck^xEyg=N>Fn$ybub<+
zQtD@*4w)T)$d{j*<vCiHSM^Z)^{*s8am+wZg*VxNXVCyNKB98N!K~sBno65LKK)x0
z{`<G}X7FVFX^WcRG8D=fwUTEjU@`n#C}I+X85I?y<B(~)*I~2N9zHheogH-!Km$Mh
zS&9=B_{y3})1<%+`JiQufiFQ6FHAuy;x5+LwdfR)XWHU9DJG<{kzMt#BN5Im8n7xY
z43SI=pt#05=HqN&Gr7siJP3oJIX(oQ3#q!|Mx!u|F@+7;%E<1a?7UL!Q+6O#CM+m~
zfVz~R%O;^2z>p0CO5r^Qo_{HCCf)oFVkwDe%NB>?82G`w;NZaY7pUdE+%3GrphIMT
z^r?TF(!GGZ!}ui5=Q^%12Iz(Dfb_&gZ#8(;=B@}9yVYpg`0();FyL@%-a8&W{5>aK
z(U-o-u<wKTBFoy72>tXbzR1+D48;5MY&yp9w3z=$uhBvS@>J0!f7v0zGV`U7ysDs{
za~B(d*o1WCl-%-g0q_D5jJrpHdo!E`aRJlEF#4<tOA}mEXqRM!K?a86b4pE<$~!NN
zz6fiXt-8T6YSy%d<U#t)!ESIKXL1=(aw2KrK=TnCXBeazW}B5Uqh6{BiP<3n8PggQ
z92u1;eiTj?DBkjZ(AZeXW{t-SnkNhlC1-_~y%8y!kVZojhsYj{a{ZtpjpNpFp-36U
zs(i5{Ek-yvrp_vgog@{yrjUh4N~7auN}tyzI3=c6sSnW*mJ1vBsoNy!-)ej7jI*ZF
zB%l{S(obTT8EG6Boe4nt1c9-7FiQ(N4m4S`6tX~GFEB>uyR&(OsBSqILs`kikXzAv
zwesh_vB<nP7QN5CvG90d=u3>+*A-c<>x%4aTvzm}t}85OTuc`WiqbD<owH7OLXP9R
zc%`?J-F$3t5EuG&^@ToX!|G|l|HXIXWZAH-2!f82iz%fop&1!~6oEtj?JN>r9VBsa
ztuWFsO;b4OW3(7!9=R1wKbCCSEp<9RO3)^os`-qEH;$8yj4(b)<I4$gGKPRf-H4_=
zM<t*TD{#_lgH*~DTiHB5>vg*5<H~h|-;jL1D*Gih%F5v25}tNm`HBuU38jYVoy!WH
z2-YUOb9or(pNnD0w7aq>=ybc7G+cWbTi@HtE11UNwAyq^?Y2+ZcbLNysYT85NP6Sa
zrSI*8BQv{^jC3umf+8uD`LbnL`*<?KDbvxd0Uln}GbIr0iq~K4QF8N<GlBED*cG?Q
z&Dbc;yI7i8Nc4*@Ie40xrInZay%poZ7rNl{OrqPaUAS3NcwE|)pOQ8jA|Z?juDYTy
z4IUOD*x)$rBH!H2c=g3}L?lZwm$J#~UCpK8tK(yI{I^Th%wuUjqOKM9)x^w0p(1<=
z(0RE{S;k;GS6`@&ZOwL5q(qcP7U8<EaWIRGV6*-R6v+xku=yDyu%=_75gf}&$YV6k
z6SY3n1qkEF5<hvSKKdBxE`(fwb!#QPI3MQHj@TlhOcHoqjhhw10bj1uGjm#Y7_Y#U
z3+<A{tskh<0@o?w^py%I+n1N}`f;4irQ$ib=1YyqbTtJ<0VFHxWuwa}oFlKs&1D&f
zn{TEkbZ3Z%BxzdN>!2FnRGPlL4&od(aXMF~S#hQQDH3`ORmZcuzGtNyp(s(NOFX-!
z!c32Mg37wZICI~O&$tgqSDRW`Xr{kW47g&>jLU@d1WL+0C82`V4!sJ>F|)<Z`B{V+
z`z;_&7ItV;n35na6cX)@Os+vptvry{lnXSm^AbgJ$=9-dqPeO&7PaEb2qK;!H&mLi
z{N71R0#|^++(vfs^{xDplgmME$7rQupX;)9$68;0Es3?~6ac0`S-*=H29%}3();rc
z-lD1U^Ty!iNKn)9+km?f51Z)AuFeOH4t;jN5(t$(R0EaCiP+OoB&5MW=cL1|Ol4+6
zH51~Yzl=|=?Y!noe`B5%?xM$c^xyYl-U<6U-HM0>xi8cgk)j@yjU1E>3B?aY&#w6(
z-hpBO@s7s}#2t_tkF&ZB3Ie&<v6JZb-joeSEwVe}D?zG?!+OupvGR2UID(d|GnF8w
zei#lmFnS>d@+djTSVbldMow+mIrwNOe4l#4Kzk9vkwF9yr*s@5#<RRoiP^3<q3pCD
z=keeJc`i+-$$11adgZ*IY(8!nd3Q`BpmZHT69WgG$57O1up&%~&tz}nSS<R)99$`x
z0r9Jec0+i)F*?Gx$3mvPQHIP9g{KFOnhd90bz|*yLclxgkH*eVH#H=ToYb$B?HL7w
zZ8IkpgPPPGoQlwxc@qsO#SG?C$neo#xY1r=z(9M1VcerP48D+X0F%4G5xIfnh5WS=
z%%QMttr#j1I>e!g;t~AE$kZmyCjicdmE998x@Oi%=Ze5U8+CZ(JoVTn`#4KiitJ4}
zl(B^(0cH~sbLP!eCk!-ZzZMBS?duJ_1f0k%a#vC^HXdSD4GjJ6eN9YiiiS*ks%!O4
zmaY7Jh?G-y&FQS9qMl_~s=)i`2U<uF)F80I$|JmIKtpY#Koe;SkCle}rJr2p7(}o#
z9S=(R%0N=gA5djJt1)r$@W%K{Sg)G=^f70@lDd-vHn~B2Wbg?8OHIA6+h!)7*&l&t
zX5b0PD4A+gjt&qjJSp;H;W8mMtAV~=SH(*X8S(Q#Ws9Pf)q+(EEgO{jECl4>8l7m;
zkgt0k>UxgCScVOn%hroon0Nf@??9bBsm`K(1VO!CXc*VgU_toOwpYJ{FulGHLYbn0
z+@k3g9+lfNDTes+gX8&xuB&pAUe<De=q_N%a}Em=1G>TE(XsATvcKB2nI+MTC)UD?
z36zx(C^HCDIRiK7A(`jYy6_DnZoO_6guej(nnmjZueH*w4h$Bp-ANgXW`7imI%obz
zN(yR!SUU2gWk^}uH>ohVHswjFP-(E0ktn11<)M5u;cX>;ftKd85jjP8ZmohKX-FI^
zfY1tq!Q;QVc^}Tl<6B0JIup}AoDDzVA;y{sb1CGx0Vln%x*19$4JTGTJX+g(HjVV-
zjFnY5V~9JO6}>6RLPs-IIwO}}j>^+Ry9^abFVM?TXe%c0fe%0>y(M?)jko?9&_CW8
z`bQ02tw;n;PZNQar-@Pu3Xes$j)wb|Z+As7W-ol59bP8>G~J#P0;v7jG>NbYwXRa~
zE0T#<v_@;CQZ6{vTAjsgHACBEt;6JEo1`f_7ini=`H|b0nt0xBnrnj=k5U=!=efLG
z;3EVB3?6+HmS5djcHf<4xz7Az#V1i<xm)Xlj+u1yzxi0pSfE=Z<t>~OYK=aO`4P(l
zM<Gt(XovDy791WLPA3t+J^*HrTf1q1BKyc-lKD>h$;}W>rq|)9e><IL6`hH*k9OD+
z-UK<FS4Zlhx$qoRieO|VFiiepgBfnw_2&b-75;ZM8<9bxR;yfo8<Ab&KlyEne~`#O
z2-Pb~{)qf9t&L6i-Oc~DvGJe$FJI&5tL1;$Kk9Y!`CsH$Z~hnk@d1m=><Sk8+SLQc
z6YS*VBs@IX3p+b}`wKwV!_E;V8`u*+wHmNf&;pHGi}up0)eE-a`UD^IDy*+>RMcaz
zg>@Z7+5&T^Ta9(wz`9n0jYXhuxX|6S96RC8@!{d|kwujCo7Vb|F7do|6=4b*^o|ZR
zsb6)Du=>j1n!$Rbtge7sv;NLOHwWCVy?=NT_I3_U!Whhja<Wc+leheB_My?Hr<aYo
zm1P&+2HoB8<aqxyH&^Sey0sN2U<<nmWk)^Q-zlI`t;!~WTz}GEPI8bDksRoJMZNa&
zU=L6C--f5%ZQs<c@9`E`uZ1FwY~?PkGg?~PFOQD9hua5Q3`)M+Xyv)Is1<j%Xv@}}
z`fJ^}KPkpGfbJU}S?X`0Sa_jUZS3e}&APIS8ud3Un*CUB;2SxTwKtkU>xrkS)6(kg
zvA?%`6T7d+9szcGdKR``?)P$RUN)x%jjEXe8&Y)X(9`8z8`kR<+QEs=vzS}!t$MW$
z8RuysHn2KdQm%USu7pkK{UfHT+jWQV(p?ON)zuhY`gR&@wzt1`93H>vboUO9fAvid
za;y)%qK0{X&+nqI&Wr{a@J*^ucmmlguDrW{%C%KxcfYbAo6434DsKCE4X(Yt{j##M
z0Xe4%9qpX%yKvn+V7<febmz5igU{9bWk+wkBE<bo+s!k;)o4nLURl5JRz2(-dN$|W
zwuph)dzjvSr-PXRC?iI0OT%1u;qG>C8w2(%<@39AUg5JCQP_U`#MAodm;oFR=DEa=
z5<X@E;IwZ`o926s@pMS9Tf$MCQlR3)<K44^jtr(Q{(8B8d@2^A{`ktMK-}}{On*2q
zOL1QHU!WrEKY*h8kM7RPu>02dySJnNfR&^F=pEXvdPb|>+ug%${U`8SuhTWEAHPP`
z)s4W9-mP>eBME^Nz==M_w!|Ou58!~~?%&m)sN(Ijj>pBQ-U$Ar52#NOw;11YJCJN#
zRG`&<(P>wgb$X}jce#e>k5>mT<?n8^m8(x`?s2q5907mLM-e}OvL8l`)60Ae7l0}W
zX+yQiOOC@K`>s|46;Af*QJ1`BVILoU*7XCsl4lhChYBcWk{z{UssnP+qiz~oN<mMe
ziF6R>cwlC`B)xvuexJt+;rZ~w@9|J|!vMLnARbzvvAKzo2oHuB#S_`44lYDnG)(&t
z;%x95Bce=9ueLp-1t2C$@|iPyhpCGMcJ$mgPD`j|#C4A@-?{Say#ZgsRq<UsTy;MB
z;J)V*Jjs4l!qUv6&l20c%HtnK*G7Ksh4K8$z#je$$LR+jqZ<6pyvT75jo*v=(5WK?
z-SBVqxJ-ZTXMO!Ok3rt`Tn*w8|HddN)3_j%LIbH)MJ&1_u&mbNG0QlOZx~Jq2=(sn
z5s@VI0ZRJm=fM$Ih2#Dp%qHj{?z?6%=RSu*dG~02H*fK?B%Dtq>#pS7%BTVZhUUYO
zxK&j}(hV@Ym;{4!_^)*LgFjr4zsWR<FKz{g(UaG*p^<ZM&I#4L!zjAV#Q5e4F>zBe
z>nHuOeP1!SifBu)?mNq!T2-52gmJHj)omU0ljtLI?4r%YgP~%c(pQ0%E7`qAL(krG
z<1V#=0(8s6LAJwDu@`dwKB-ol+{KVEJOAfm$hiN>#%qHw(?{w3Piy^gtG$W$Kbz|t
zk2l&s{`i;mR{QaK`#<+TU*qR9?tj|rRrf#gN{8H-Kypq8<<~k+!EkWy`8t|jrk>Bh
zzIZWI_S7vKhZuiOdE=CNr7i!<h`a%s90nJr=Z?4qaG;IZAeIkfFcegTioj(=4>AXR
zd=i6IIgX5mu6#1^`3wGIp%knPIflN`0^oBr8VvM7?j{Wi>p|U!Sjg&HAEDF0<nzn?
z_*nmyzu?2GaWuxA<DvZ44Az^JfM|NLBEL28MGI|vjeKV-<V&L3V^#4Qie3)yA1N?v
z)^M9#zAb`Xa9(>nyXj{yYU)shDR(wl{+E+R1|#WT1kdGR|4n$(-G76Rb$iF*$sXdg
z`T{jb_%EP0OX6!*<d*WPKmnB3zm`BzI<h^*;+>qA8^wM_&yv1TbVkn_>6?VQOz+Tm
z1BcaT7ppG>iPk3Pup{>`KraH78M}ZEt&X;G_06iS;Cme-xwnG{68KU9Aie6(q68I+
zix~CZB1nj9Z+rjX7ubRKdn*r3Fb)hn2sf&F!gv|(_>(Ctljp(F*#SPYE$S^Bs2+-{
zut!t@9?%}C#t68D+)|g@6$aDsm{XoS=V(_2ygr}&TXDN}+#b6V^~nA^U!SP;Nc?h#
zC4kk7r{P7g&M$sHT_H9rE3(Ju0Z;$le)qI^{>7_t!7AO(;qjYJQRQYJU^jyayGbwc
z8$fgcll{`y-|+=<Ip?Tn;sxw?mvKqfuO5`B`B@{f7m9B<v|zvC6)WOTNZ4*Q>ZEwF
z7ZA%~#T?CCnWB$9g*5aDt7>|BS{X0O?NTqT?J7ki_sK}2P1QEx5oHy{Ucp}!bO5ar
zO2pxVKm>CgC6o+jjBkJ2*?2{}Op1?G)r{By^Ktm=c9%p_?=bA5bUNMHKIkmr!C`%!
zLn)5~$~`g1WJI99y_|uzAwhBxd_6p$acnZ7uB@y`L>qSZ7*w#R+sYUV?r^hlTS8a;
z1)`EUQ0N8vQvKfRKqZEa7143<Lveo%dx&~igZ`|44%&Yfm#fok;4uoFw!tI#%U4O*
z>gb=`miLFLW`Hb46G5?qQAQX^@xdRtgsQ;O;dm3M_4W?=?tv2@<8_LmiX$})CA^q$
z4Z;b&tiG7sL5~v+*<vVK%G<o7<6X>;@rI)HzEzc{6H{=+bY6sW2zDv!RFw;<F)33N
zt(s!y?$CnP9W|0MRLW$})u+`LL?W>k6>Z5x2i*@~%NQonq(HAW>ZUWO4p?9`pIFa|
zUFp-s$M92xM`~T}jDuszU=oA=@E>!0fdwZ|%|X4_l*nZN=oMX=zwS^lrV0quRSAS}
zZ|Afqh)ji=x9l$n)2N>e3Z1u&w@hkfIso9@`DHX-&!+5ZtNal;sA@Z3To0D#kG<n=
zXM5-MimL_qbOu%pR3M`qrBD>vAB}aP$+@HiRZcnoUC%!2R(|pC03~xczo)5uK4*(G
z2?znC_?C`G@2~u2_5`6iN_weN+8XcwNbD*he)@Ww3>e+xz5Rm@c?9hDdYxU`Nw+kB
zag?V0ON8-29|ma;CKHc*Jo%tBaFhpA+$}y6Q}ltT!t{L3DI%b^J0U!a`X7j@!HZ>D
z^$W}8I}P%rv;A|)OdwV~3E6ZSjQYuCwD5R-svb(~3nM=U2~UZ0F!mhAqi&(<x5!BD
z%teG_F#{2fpUpe&Zgw|Jf9{3byZ_(WX%8KP3edH3B5`M9%-3`$v<Vo!p1vEx+dDsZ
zdKB!v6kB?pT@yinh`2)G-X9LDw(sJ-+w-QpT<R|-^zTO#sAILlE7XMI+nN)+;9;PK
zjp8{=#>(S%J#IQXqTCmI`<-1s`=H1h&p96*f-Vsl@X<IYm1qETC!q8go;VS43t$+O
z5%kQNEy`6%0-x7vL=TRo<SuJ&zkpT}!TnuK>X>H5q{@v5dHJ7w6SnfeKfDK~MaVk+
z`Rg}~`s@DDdzta*_^@-BC%Z>c3|wWBL$kw4buhbKdFZxRGp?7jd{68<%vv&_VcO$Q
zJ6+7$ynj&7h*oSsD_uk!C3ittIE+U3Eern~@{QT2h6wwDi&b^}g%&Mtj};3ykJRdm
z1hWK0lYt0zbr<Z)QHv>BVlh&S*_8`dLy0lDbfK)S)-(z5P0q6UXN}{(b@rz=Iu?QU
zK9ca*c~$-T<rWNe!8QSX#RG5)E`Le^i0c%$wfJ1~N-TH#@$g~bep`LPHUL3JW>rls
z*TzSjins0t>$xB;9+b8UbuFYWifqG#DEFdMg->s1%P>$VBG83L2`1(}-2EX#-U;RS
z)UcLJrW0iuUBFgi?-ROlD*O*qZ@tp}r1nn09r%=jZ<M&pNnkQ&Ghy$rP4Hj}JElvo
zs!hX|%LLJ9a^J;+Rd@UF)W3^(WHomxRU2n3$%}2t9409R7p$4KU;nXixf1PP_kIa~
z?d-pLU3N5tN(-G?9Xuy!%GQQ#ocPwAkUa`dPf!dWclUeyol`%urze5v>-N6Ru?wxa
zq7Ym47NM`My%2FF-p9gPkoGmTB*ETy;1*()!MHy$@ZUMyJ|YD^-0dEp)Ki#Dq_KUG
zEpl=hrIarkx`dAl8)i(jKVhb`PZR;uHx0jbJG=KX2@arw)e4n9ZzM2@I2IZZ5GunY
z#&V-uoNW+iLVV}=sMmSh`+|s1LJ#WcU1d!k^#YNz2;x<;ruNqE)peKjS1AOIio99)
zF3AhU(N{TQ7HH??8Wr6rGb0EB;0`V(m8#)Nt9=R-E&LN4Pp<nT=z#R;xPmQx#}=9}
zIZweueeAdg<OEVdf5dsjao?#jDl=;=B2anP{d>^?RBX8E)pR}@;_bnDISR~*MXEp%
z7ObiGaS#yY?M17e>=5!oY@%KvSFy(kF(LNHl6?`A^DMGG+PYL|Vd|4<6?h)mm==h#
zJK$-r!57b6le6t4W*CDiPc>}+Woe|%zjm^WavjYJ!7q5}6%YX^yQe6$Fqj$S&=-al
zdMzPat@3?I(?rfZAh9>}7sHPSWa{?O--Cw_*(PgN_IUk}BmSbCTCltm(Ac=YdW`r@
zjuEwU)9OM}r)pQAR3=2r{oM+w<9eemM4Qf0uN)z{15l>%et<m`<D>n2y>|*&_P})?
zGYcC{eOsVlm0c59<`cPmwv6wNeN_01s$y6%(Zul8RRwo85tQ2q<n@G!0Lc;gulF{>
zSmX`YA}V~1ods7g4kThhQI1sgt{{XX_1)xKv2?Sg3C|MS(nQnRQt+!dZvJ~p(%#M=
zB}elcx+O=0-+to($ofB(@Bga4b^sm;z9jy%?j@Sq$O>qn4-cFapx!+S?`*KR=r*5E
z+%sBqjozQ!2ECn<8}xr)*=>l2`w-zvUqOOb+$I-4aq+VZWpi{0Qy|d4>h7Q)4&7A&
z{+vBxk!|8XJ4M+}K{ribbF=t?-W5lb;!n~*<Qm{N5kEO@?kcIPvBea$y+=XM5%p`y
zdY-GBkFa0OW^m?)m5c8;@YSH&kG^@n$TnthJj&4fF#FJWzDr@Fpkw;DpP};=^+R9(
z-`_pHig+)5mRb1raseS<%OJeCMAmj-O*4|nc>}RkUD${{vV6I&)%XuJ8k@r{w;lT>
zv&~|zvnG%A^L#ax8~i<aUdmIyf?L<~(r+zOjG`|PjC%vQ0q3l8g-)5UJ<z$A$ouJP
zDw4el8--Zfa!0V4waB2KxBl72J9``^1Iq!p=r1oBJ-Z|_ZTQY=k{}<tY$r)#fnCHa
zt+vreP_U*?T5fr`N`!LdQTj%`CW{_W>y9f<X=pNCaM`}*9pCe!@p-t&G>}yBkg3Dg
zwNX1Nb~T%p_oDX;EA#_F98S^2G;%V}u(b6?<?`RW<yCI49@~&k33ce6_ovDqZEBxw
z(5J8<ltA$-e--pWvCTc4vIvu^EuSjYAe3B9cZ#gwKX+2szX!;f6`;!_Q55Pt+`+PM
zGD<WXn@bn<>->{nPuDv9{d=hp`tY#OJ$J!z;XZD^1IjT^r<T&Kq3E=64@eC96WpYj
zmqDu$x=svuUG>vIzWFZ3uRwOsqy>~@aiAAe&0_<_rLD}~=C|gc>iZ~8$$abHWabvy
z7hWO)jRh6&e_vLu*d5r!0{|W=!URCYNGl#jfd~-g=NLzE;Cp!1L<ap?T01aDu?5g9
zwV6nDW5@9L^Tg;-hBkK++{<lW@Qf|@yQFSWxly=o@6;af`Op<*omJI#yI#JRNF5po
zIp{fIHI!S4=H0UD!+C$iPom9+g11Xsa{LYod9hxr>fJ+qc!3MQoryu<y3D2KNka6;
z5Xn!kkOFlY`{TJ-Z7Kqh*p<;K-RJ}<aG6Z!Gh_ILt*ByJUDFMC;?x7thCtE}!SfPn
zXN$V}F^D{RXPG4X3>oBE_XW{+e2aeFEjG#=F!#CKtJb=;Wbe4r>n`*1HSVwHS+2Sc
zx~GR%pel#MWIC%rkSbd~)b;3*Z&!*_F}vGO7#3#q(k*?F9lf|gPLI4>Xe>*fz9@=6
zRZoMHS8m1E^TQ~bRo#iz3Br}9RwJ)^l-=<en^cABM!K%PlttO3cZoUzkpOVB1r$kA
zV;2{$^~_Qw?`r;}I;AhVSdkjExKOMi55I`IQz$p<TLk~3=hV}4B*hm{a28sE`KN37
zC<7%6tct(O*!2rDc&>_%UH^ppeC3SiOg?wm;{6YaY75tz?-pxViE3Jd7FQ7dJuN|X
zl!)AvXdR;B!mdz<@UxL765Aq6bchlFWh#Uf6_&FN(X}qFVqZd@W#fHXy*KIkI|0i4
zf;lI|zBk4UK^K<}Bf@9SCWZeobpR{EuPC5Uyy9=ieZUt|h(fOAgDr|*)>LFT<Pxhp
zgP99M1IvxtFec?-*xR~kkH%qBwutb&pT+|s0j79J2TkUu<C7iaDN2=huz$GUqxf=7
zmUW~cTwFpIE0rW~Aka0`x402VyjetI6WM$)n}^vHcq`m!uh>DAw``{d#&|L$S1o~Q
z%kfU2im)W9&V!47jJY_nX}~PU7tIK}88F~)hY#pilW%EGOF1_i6!LALvc}=XT=5O-
zg1k%@g8$n&c{n)dBq2Zz{P!Kv`2E`XCnnBa*c-IXy3FmFgU?`Xu8t$2(*cg;{`ox{
z1S{Xp8#$II>B<~h!Tp#Q&0+sJ48nT7Z1MkRUE03>RovH7ay3_9!0t(3pkM4TIezUT
zA6Z9KC(2hw<gr8gsHRo%d@P;jhezndi7rr!1;_cO{6=$8_g{~m0%(1Tv#aSm6YjJ9
zG>tDO;(l22gH&y4X<1L8U8h*(4{LaYHYijf@Tv2RVi66i;8nEtj?ITyF_4yC%)ihO
zOXi_oXdv+<q{x~1e#XVqA$*%_&4$;V*_wxMWZsJU(<j|rluPqxj;@wdbI}ya$Vy~J
z@$b%8ag?CWe~Xvw?CnsfT7Is3Nx7u*%bvSL^;)v@345;wt|o;BnOYx$JfXSDoS=Aj
zw_Hba`nknS`M7XuL#oFl`Ji_mUcs#lH!@5`OoLP*jNMpD$M!nEldvrqoO$lVT(Ma^
znUhdoqS-J>R{B7|T!>pm<d#Y$5nC#c^6-6s)UVzbOwt22YZ1Qc$fuX4y)ONR3*_+u
zoHmniItdY-ubBGde!R*Yjk@MFM;P|A=@_)t(X>AdCo2zetD$VEYxG~>zsqJ2hTFa4
z!~LDG+d0^N+u5!8-lWn`Y{<C^<1|p6(UilYVz2JYDR2c&M@W;?#9$-|i1AyH%C`aL
zx#nEfdUP+(PXE4DlGe$f2myzFq|!thW}r0A;5@pR!avMD(CLRLNb&oJ=+>x(`^t4Z
z<(%8n@BEu0{S}uQ^N+$n56{uY3-%Wc!dA@lz;JBOic`Ib`vJX>mUZiA!Zc<s37&Lw
zWHKWh-$*!RX36i%IsU7+YQs-Se^$fhSg?M--s3)F`C&)tES`*}gAXD8hgTK;Ch|~v
zXIM-x+qJBr=;^jV&nG$Hbu0>Os$`)KTs5B!%M4;w7TsD`Yj?0m+-?3UwWbo?rnaM8
zL7EdgW8B@s1Q)5W>;YOBMaLiK(OB6^9)9C@`?V@B=z3p6ll!^~9CNf!hod8mxk7{r
zN6BnOv)&Gz3>aaNuy!%cODvK6N-tEpJmj&cvp8`oY2zwczb`B~Y_U-pbKDUe_Zo}*
z?n3+i+>BjerXvrCHzN1wx&P<X*?bz<zvn$!VFoMHOwk{wZj|%bD@X4dPxbQy+57T=
z-1FvC7{tCj@^HB-V!VrQx;{D>WXVq8QM^uyPO!^&eT0>ZDx$NnRI*0yCWD`>n^W|S
zUihCEdLu8VtJUZwuc%(C5Y$V5YTeqiUs*Coa8!P1pRaJkW}jxxCN`a=3N`%wIj+Su
z_hMUI-kIu#T>;Q`*{eSsI*sxbJk7-WqT*&y0h<xMWFPv+A++d&pBxFug_XI2sxKcF
z71oy(u!Y~J&}iYWpgPM_-095M(mki;(Da^MRi73Y`UaR^uFd7&fxpak4NO!1`U?HE
zf=B)2^1hQ00?2B;q-Jh(Xm)&Zblf{VJ2}Cok5+iGF!GNY)K~D(7<5kNS$=8QA*{Lt
z{iLP?&p~$KQ{qCyDNBP<eA*(|pZdvUg%8@u5f5gVA1?~vd@%}gc7cYpN6}b8>k6_f
zKIE)D;3u(gj)7y$ub{u;g)o^A0(o_*?LHTy{$=p#Dw+gBlS{MdEJ&vSuAi}eZP1@!
z-nRJS76E2sW$o%yfb*4T?Q$(Zc>uy*taLJNuR(Qev46pE*oJ2hN1D@Y3}8fT&1=%A
zPGD3&;6V(biBm7#%BNWjz_3c%ALI2QY{39yI#2ZoB^JGD&?lb4>izTSb%gu%`6wD=
z1PUfn5)I&cB0IGDGB6}GfJ_Mb2OsxMXZOZ@U+-e4o<+d+cPqc@ktz)Geu?(Af)s3&
zS`0|i<a5#9@2$$`UaEM<;W^)n!Q?XDo5omi`S`mn@!7~)WTCq=Z&~UZ{dZ9rzFsKy
z3{T2>#wOvG_>k}@_DmGozBX7_*~lO2xE6o;&(FWj4^Hb3aKxNW*3RegX!s@iScjh{
zPd4G-_QsR-b@6YDzQfPPW~=>|)@EySedF;)`^O*uvfkQgwcCFQ*1rTY?#~>z!yx#}
z)qEUJO6paW|C|2&H8?%leY<)9+wLTdR`=;u;03JlXTi(U-PMiNolzgOi{-xtJJZ>1
zf-f3Y292P--g>&)UT?R8*KrEEJII{i0Db48A&ArqGEd+mc98rx%cyM;b4kHVUlP#1
zrs)6w-E=a#)h70UKta3js9HKdAI4~}m_#d$<!AzW67_&GDC9!i2fw>{`sBNyKN;o<
z`pNh^RGlcq!)*A0<s&Ng-=QUDySwu`e6smn;|^#-pU{+h#clyiG0y39o($-%5hYk%
zS(az7@1!%}+TgpU^L02l_k4vtEAf1W(+O-Pg$3dDg{SNSF!g;NO+R@)kI!#BUz6xE
z^?gpgUvDxW40<Ht>v87!n2kLjXBk&*EH4iuIPib}Jb3rrRX@G@?tPA9o=e8SxvS&~
zId$L5xzi&FucHC<3VmY5zoK3|Llx-sO@~z4XX1N*O|lLZ#h~)XlXyHI!>_#aqOOk~
z8Ru{)fprs!hUaTRjNVh^P~~sZ1h&m&&x!1Z+QYE*=ztbHy4TyMAz%@1?;Lc*5NixG
zOs^vvD%J%Q;g~Z(m?0b?=a_(L<-64}68Sk$_WJ2sd$s>PH2JPUM25O_Cr=M^qGSch
zPY|yR3<h{y5;M2D>!SL+1v9CTy^car9ct_EcxdYnuIS+POaN4cf+R@G6)ah!vrvj&
zk_vgi7o>%!bTFG27iRNG1f>nDD+f=cEBs<rVc}r>CGc0DcyV0gq2wH`nq=_8KR^q+
z6*DA?jTPbkcxSS>I;<Z+C7KN4D18>Z6P*eR2#AvR#ZBYMU^GXQQw*oQY?=@R@i8rK
zHb5?-z7)NhfuEn=Ya&n2|3PFmsjwE^WJ!OJg-{3>lyfmrpa1(u@5F!159xn4fhG|s
zgID+1N4fsjZnxSk*8hH7Z~eFd-&>nMZfyKV|N9z0KRl|b00xg-4Y0i~HNaC_17y3+
z@?YZ%kRcaANXO&u+uqyoO=l-O>Kq@1ufyfPLK$pxMa9sZg+}lb?i9?FFW~bm>0gff
z!K<B}U>Nr=C)1QJWZ)M}ee_`U*FitcRzJ@BqX))y4eqGM16$<t>}KT}9m#OJHjnl6
z!sZb_$1o1X<MTP5_djGRFvye58@#Kz?vGl0yRZbMt1qBl7*DVJ!S@0EjdtE}dO?93
zS61ZHoQ5tNMUzJG(@)~^`|WOc+Bt&%?EfFU8QkCNEie7P<@VSXJ+3=Y6^z}^-uBr+
zFMM;b8}4<&m%Dh=sJl7aKk99?!<YL4`gNMMK8Eurn;KT|s6mfXR$ugo!=y>$Y*bYR
z-EKP1q9nW?^(SH0zod3;D~cetYCQ>s-Q@<Y_ZRU^Gz`z@Nt)r@tgv-D1kDm=Ach%`
zZum0QyE`vVT_CQ^$SHdZCg=1y|MW_L4jyGUA9HVlRAEE@iX<rJ8>l5-XPITNsFGVM
zq~FAJGFtd{IGcv^G_pRQ3+syWF}txoG=o@Oz}|dB`iJMkkmCXV6v$5)&@s%efI?UL
z&8YYc<hzKH6q}O?P<1S>st@;%a-f@vn8G4ChXwW_8r`lKt)B<$!V7|$4=-+nlFtt@
zF6N_AIN(cG$9Zar#tHo!M1YT)Q0PvHFm2ii($iBOfp8K}F5elo-g7mc4p}e#<g2GV
zm86Lu-B+Xjh~Cr$6MBP}#4}KFQha}xW~h1w=TU}Uva=|GzsCK^067+bpw_8K6Q{u?
z&=D(USN#c@%s~Yach3mpQxr|a5a|gDc1Cbel{N_h2MK{b6^S9Q316y-B9wv>tU4S=
z-e(H67eI8LG#t%JOfS}h7<g#{|9t;_Q?4%YD}wy~d*SC`idIq9B&L_FvZRRrE`Gm8
zEBCpoKz{e=8N5FkB%IOp{5Fg5u3<h=uE)$w{N|6@i7SB?xT3mReF6WVTvcvpdW5Sm
zLi}vA(>mFw>oHJW4x*lOWK=9&Mb2t!RuQv`mWz_|cV`uTZ>`WJcS+&`b{423p;n(u
zktSYseoA7rKi_<Wts@?xVF6`NlWUm{0HWFN?iMdSD3+B-#u(`-h?_VX4K2~0DAArk
z7t21sSs}K?^!n?t*iUYTGfy(XAb_!6kA~r7KDGmjjoKTV^vJatOh@7usEen6`pdpP
zP|C-a0Rl)d;CrHV^K)$baJUSp5h4z3NW}#Ymx7H2J4qfw*K&o$8q6H%W2m?UBha*h
zC!4G1F~3n_{Rf64&*ij#ygb_r_dvl5yQimko_|en)%fu(Ef5boO>WlIXXI}|7`uk}
zh~*}|>`D$LO-~gNxWf@_dqXT+!Kp_z%_e?RPmgl#Qd=B)iVA@zXW+NzL2Hh>RlMci
zd6D!Xy3G264^bvP9VH9W9oP&%GA?<(Xw+KEN#R=N&aFkPy=Vq>SLt0wT1A7C{I#K+
z`4^F)fEnwlR8dQ`q9#|3si~RYS<8euijssvsi@UNEdUZZeI<FVpm;r__)bjmO;FxD
zZS?w9^^+T?zFK>@xbRIUE-woC4h*HJZ0T{yjk|7V(^RZnI4q><1t7(Z!Pi<>ps0b$
zd67)Vq<r8<r0I7l4qvMyEb7u0@daH%-%zIrfF&YV2*(tVhE5STa6Ad}{|)d3BC%~i
zY)g{hpHVVpo@=+8L3_h#f<Krw;$}_o9O9{@hy2Fv*P(r@DI+N8A83!al2%K3RN|&a
zmrG_dRh`ctgV@FSX*2j+GiX82t(MdDW-Uq65G}@5$M^wDs69FfiFv%i%l$zz2>Zi-
z%*juH4`g_!YJlaFDXv0Z`b2zV%_0OCR+9!jKSzjow_p*<fM@}|g46hF>j}u;6qv?t
zQwH3jC850DbfHhClU1m63F<C$jHUp--(q|7Y8H>-WE~}FG)UQ5L~tr`E;hk!;N{sq
zoJ3!qy$X+yR+z!<OJ}5YQw~8qXI=`5YkGOU0f+8Q6xj=Osn6hd@AK(`eM+ACoIYFa
zhT7jjcJL05zx*TxDF6Ara!_E4z;5Ss=QKoz<AdYl6C)TO$++^`yzfa<1Q{a`x%6F0
z8&a929HJ&T$vC)HQ~lc3zi#MXH_fK1p=zcYsV1s{u#}9?XHXmd+m;1@!ln?^bkp~*
z_1}#m^4A&9G!&GZurtan7<cR7YWj(@Jf05&&Q3<lNP)bDnG8YvMB%*kWQDYnb)l7z
zV<oCz^Wkj0DX<U;xk>@F$^o=00kq2jv?~E@lmpmMY6`xS2->tY0sqBXMZw8H*rTD(
zek3<xVA=N!%fRMp6ix^g(Vb#iWy}Kpc)8!BoTjURFe&bm_3NcGv?L;&X0R_K$S?)4
z1P{7Npd0+#ssta5z8m`4wx@G)nOQ=Xfv*1N`cjb*hHLi><2Hd34-^xyf7y>Gij3`A
zWCR(}7Nn%8q^!O&Ze*OnftVUgP`dW%kp~A1b6bTWUYvu@8xFF6j;M=9@PkVqsY%<7
z5fcIl2a6Aq1bBL6ktl-QWXW_CoJS*AdVKUi8corAaGDGw(&mUbqLI)9`7bz2o{yq;
zX1DKUM`?yTokMK+?^G(M47R}LDe4f<l9*|!NyG!LunT3MrYt2H77NVv_dJK~JlGW$
z#DW0KQQW9iw-Ig+jYj=J8thd)RN^a^s`hZ<bOK;f|A5;I;NCU|y|F;U4KZl7!>qxS
z3tAhi4<J1yU~(=*HBOOZwQbdF+p^oXYxUdm_S>%2Z_DVHrvT6Jt!6tA0k{G(KxX!N
z0qXEE><85$iR6#j`3ULzbj8@4eFp{u)3(21yRf0jjHoB_>Ub(nv#h_;2;`|oTN()8
zM<s%8olO?_ghw?Z&5Go}nC@iYAP|E9fV03>1+><J(Ci6-Wq|I_sB5#CZ9Jn*Y<~Wc
zM7}etxVuR5wO}LAM+$@3EiX3!FaXZB!1|rEi#lnScVh79MlJqsd-;2#7Js+B>uR%B
zzZ>3uH*58~;ayi7&CNyE)rNn0Y*enRO@G79ighKqFU8c1hG^G#3CaF+MO?2HuOZ)&
zgRj#hn{L&B*QyP#og?;Vtf7q}_TIS1HMCjO$!6sms+NIBfIG;*_Pxr$jXTRgME~ww
z*sjer8@0G_qc*%vo*z7V&+sK^Hn_sDx?vWLXVauVlG;Yu`Ix1oY4?-1-rQXTnR~5c
z4<YlAPFt+eyl+|-#k?)r>WLNl70XJBrfJjZz^acHYqB~zqh4RJNT@9YWkc5jghOE6
z1H9Hf!)xC&ybT3!nQj=98#JGoGv+<={8Y+8##xAM_0r-@%W!foZru{}18~jVW*G&w
zaLZpv6FF8QmTX8<VeUTEylYG7uI;bnDTfw9ztavb@ITt2=|4XU{b>I`bhQ35eU$tE
zwH`lt{Dl1fTCMf<jTV%*+M7@Q<Nx<nem=whPrm>u^8b?#eB?OXAEE!A{wN+L43ikN
zYP*QS0AwhT!;49pFN>$_3MfB5FrPnMJ#Y&~)63NJnI0nKKf^kJkIQ6-!}M6B_@I$}
zmc-+Ja*Gb&X#~R^;ve`9HA>Sp9I?1UwVnuaaY&$8hmxN-sI+)SystE=VE<$%5HUaG
z+uHx8Fc<IQ$$NYui(i7^M3`|v$LfG0nM@)X0AZd`L)mIN&)x^)^fK2>1{T3McKFUW
zo~${Yp{bXf9m=}!g{Rl!Svj7OMhK^p%i>4#=KaPDs|JtYKTS?nt|J6NSrUEZ8#9Vh
z<9h8u1wu4<#Q!*cd%Cy*;6<Pi<NYJ{X*_;J92(-u=4ddxU7<#k{x}lR#1BuxqwT|v
zYM{!g75z2BL^1*w36}oG8uW__0VC37h>!FZm#(jkxB%j#@zmU4jDVdO5;`ylwv?QB
zA3TGtW>J*nn$aWp2p^eD=~j5w&#qLDtS)eyb-ZRw=L1Bki8*znOW+qc6M$wqnc}s{
zJPM|W#HSb(4)k3kUZK)B#b+%JpJm8jVz9!AV<i{&L$MV9>t@6W0yFpl4aBTMOlE~X
zD5ZSgBM1JUroI|(P5L);<TjVFQJ+?Ox>dBo6M8mRxW1|JnpojW7EXRq0i3W>R;|Hk
zDXFo9A`Bhkl4ypvknm3~)R-&jY$q&w>}^yD<5V07=*71!2!wZ$o{{H42Lo-r!PCUa
z;cmEpwBLin!mE`|x7!RJ(5td<hcccxhvM7ceLxN<CS1eOc2z-Vk6T0=-CHz@pb(_*
zYyjjM^C`xt-YbScBXkECOGApvZs(Wqw71>u(GlU9i}wD}-m$`au0w2~<U^i*pu<t-
zC87>}idQ@IYUN@+p~rA4GO9d3d5}6jsfp8cHv3vQA)yu^Q}1R0tmrd4bFvGUv`668
zq=RQOc!<26Ylk2E35Vc{X4M2<fV}rJmf?InzGb@8_u>JFMXLrdj4t}~QTEJTZz_&j
z;d+~^^){ZtGXFS_QudOn9*2Joa`>z9`3h+ihAzc3!(vXYX&Jf?zEL<r7=&;rV_!!h
zU18v(+ZEjyWpG6@5JUA+Vrr#AGn2vl%>br3IS~Bz8yZ=?b;PnPtHP_K0!Z(zv2VXj
zru`v42U7C`yS8M#A1tx6iX6y6(VZ<ly1z|b>(gC>U#y*0D$+>e>4aFiSeITvUH<HN
z>F#d*(OdM$-N{Wh<c71dZC;n5TUk1b20<phA~}RC{-&P1h=Zj%W|13h0~rH-u}-?j
zJK<?(=lE!MyZd)$9B(vFt=9}DnJ1Q~a#FBkP<`WFDMWt5gI^`@kz!*$`7oJ&nkb%J
zQ8V}Lupxv;UT`!6x#ATTxNjH8iI2K^mab*jsJaFAa_Q|Kc8<?_NFY^f!qq%dgisCB
z+sR->^}xT(;1~T6NQKe$k6kA)lB37v$V)Nk-uwXD!AeakPyqJmMr4Je&KaMz$vLJ~
z$}swa{*pw42sGd!W0#Za*q_1@--lxuEy)+?*a*xygFgUy&wMR{sOyiPN73-h=jDW&
znWzTyoW6_SGaFQE#ae|Gv!gZ(^T|$bn&jk&>7p<LQY`*e=9lu%Pt5Op%t3Q3Qv3t9
zS$uQ0VhpBHEwAf}>7WPaBheDU;Xwu%_9~f9rt{B};v9y|lC>NJuS`Ib5O!oatx^B>
zSc4LVPWq>!#B_Eagb+GF!wEWQ_HrM6l=OfzdN1>7&!%DBJHPcAY<|eam6dW`ROZ-c
zlw;jKRGQYrHEMxTXWXD)crhz_1y%sjHvPm>*a&V<Rt~(OwIqL^4hQ%UD^7tgR%~Nf
z&LU%M0~nP~tJL4n85W~Z8n}sZ_{R{)lo@`Lj73tf9j2J5s`_V=bumi0)|0P5D|h6j
zoPF=ngG)5DZww6$ARmH$mP>DtpDj-+1JChnPw5!+^y9*3uXl4L3J3UzJvr>81(e)D
z>5c3b&>s%Hs$<KeJ#JZfFFga4Yy8f`b0o^5gZtg(D`}(}ctc=Y@?WH+`Qm)FFgNAr
zES;Y(FlWUip(y1!Az@VD<ASo`Y1uHJc%=h-4;3wJnJ4e}FA`bNi2p)Cyzak;s{7xK
zjrQZmc>mkl*lhpUdc2A8|DeWy?tj0=&sVws6<58pLHw2Pa*3z$Hdh9lIoy5=2VTsM
z2lC?R>~LvQ6^YNs-SEx!!C42N819K5Rj1o|g{|0GXaA^UG{>TY&XF!!aVrOp<h7uD
z^4VyZ2?exS7DHtK>KHz;I0rSo8GXd>^H5${q3~6O!Fc$QU||fG^c_0C{)=SK&f)Ga
zpr(e~ySsoM2)<Y9T}!_Fb#eJ_=cHFsi~)s<OJ8@kcMD3p6{vM9Q0tbX)-6S?TZG!1
z&JJ+MI@dbw?i94&Kk9YiByd_*47^fO`ihHxFP_-xc+Bc%ZfXzrPj>{S2qS#CecCZ{
zO<Dsv?samgh$;l8+d1v@azn`hc@0ni@1lyY4vt@L9|&Nc^1U;_;Is!I@=d$PVNF_G
zU)+Tp<v1*Y205(wFz5nI<SFdAh^cdRJe;fQ?2=$9D?jkDmn<(UJM45{bxLda*NrUo
zuNzsq_j0!s^W(iemqpz6m380*ep*gEP^1gWdo?DhS7VZT6_eB}nFJ^UCHA<x-}`%U
zjh;vJ$g+wlER@Q!v}6i<6;s%&m_i(PC1I-OxK}ZWRqHhSIHM4{-nH8M<%A{hPOp35
z$STo^s`Bb!y|PBDvPQe22BT3t9KHb+D#LU(kQoekP|HgM?f7IT+}#7h?H`|pJI9BI
z$C5p);?vVJl9B601ueH=|J7O8d3ELk);%czCJS=Fj&@G>y^s{UTc1x(PQ0~uUiv;G
zK}&|*UN%Uq3@50Lp%#gb+ZC#qtQNwb=W)jVMxNp)n^>GX8iS_Bu|`DrIKz;l%2POp
z&q9v!g4I?Ya#ScapkK~9U6LBO#F}IjauPK$n8}cX_H*-A#qG^6^C-Cu<k>ZVL7ZdW
zlJQVn5V!^hWoyVKe{_i?%x9wrJ<kWTIeeyfSQPC;Jm7LESKdZE+$v4lr6!fN=Xxr(
zJ74`_e@0K+;jerSi0$3&6Hu*;Jg8b7N3}j}O07lwMaqNtT?r`qd&>&>Wb;_y(8jE5
zo+2zD90$nYFO8LUU9=Al_?p{2;ot)e!8bsH)fadJdVzKqb71^rNW#qPX(fQgTXP#)
zV1udyM^jcew^g;0#`aWb0Qo(n7|8MxhFW<ZtQd6u-kN^+)4=jkfL1E#fo2xpqwu!i
z;KJ2#?#F4|fIr;>r<r9$PLFGYwB#F!gdB@KbR}2bOlgY?nf(-#eWA;ukQdVnB|?D5
zAFyTefs`C;51M86SBsfZ0yuIcf3^;O;4QUaVjYOzKX;ds4U%3@m4nO^);h<tyfr)h
z3_=2&&mbnUBMjK4fRBGzW{Vg=&xPQq6s<fZ#8%~^RZ?80QbPfba#q?@NTza>TH4dP
zy`yk<ySEKU22Z`U@GTW4C51{jLqWS>k9{OIS!;Vn2M%<?CdYiEh+giAuP8MU3cu|l
zXOw2}p&2+5m1mVl=Xj6s)scV!-R<tb3A@K<N4w$KiEi_K*|3ak-DNatkbfJ+v&0Sa
zpJTlE8?2CNY;~gzbF_;6DStIP5s*bN6fXj05v>MC$iU51r#AoUs|xBF(|mpV&l~a9
z6=SM$A#rc;fFH#YUV(vEJ*+Ihy3Wz@Vdqe=Z-w#%N=8n9(&VgGp;&`5u&C6dHrjz0
zBCAt%^eC7<a-5)1do?T9twb`Z_9a2YV&iUNN%1xMmk=%D_fqj9$uW_7O~D#mm3&yj
zt0Z&u^_SJ@ie6)l6^TKkPS;YB(WpQ0s6TL!+7Bumtz6UJfA3Qn^|FQr9D7!-KDyyq
z@-JfTIx4Tua+6ajAbEqiF98YAe3P^3t>p^HRt*8k@58+Ul8gR80qGxBPC)u;R4O2!
zZ2ma~B;oZ33rJ1QFCieGZ2k!aq!o6^m6ndoDp--Wxb$;wrMPrasMYo7ipwXPHO1vO
z^4oog%6O7S35iMICiGPU{$F7ka>)zL(9wisBpIV>n^FjIwhCaB?sZ_WDq#oT`qW{U
zhwP4slVGrqm`YI1xl_~wb};k|p7ZB~eR{)HW2?{<_-rG^qiGUf#uJ+CaF!(=otR9G
zB1-L&F(q2$|3mnlk?#dMEzY83^<+<<TKE-O%5ij{;ACe%(rZ4Q^#_q~N4pfWRcM)T
zkA9w+lKAE4NL&>6QDR<`7;^4Rd5zH;l&OZioT<2yW<qXqwrM0k7{5uxGa_LQDT461
z1j*xCP9x8in-E4aMqrKR_d(<wLGrepB69qL$?*>$hiP$vFH$IKKDVAteVm25WaS?;
z>?#76(SywjOU?yi{2uK>svmv=wJ?Q5z;B00e*0BTLQ%tosHM8PH<I~oagbn=l=nb3
zDXgjSYT!u4LhW9fRnCVsE)BR6XIDnlwUIW)_ZBc8Ieq_Cr^nYEc$dw0X_zZ$X|v=$
z;ayovD}s4E8Adm(wT1NimL1-lg?!y)17+P}xKu;?s!~H^Qw^o7tX=z(V@WDylym(z
z)?rY40VM`hnbwmP>0=S@9c;ti-g(;-6Ak+mddyQkgO|I(a2j#KMauiqrz{qn$sISO
z&qcIKRW74hh5l?B4ADe*J`9Mbm0j@vP7KRnPDK`E;Fx5@_3^}rQU;Vk?{Rzz6D8M}
z++Kw;SM%PYd4I0i*O+0=Q&2IM@nLa3NC_qtSSYKy*0&|K&gBu&dmr>p_a_u}{=K1_
z@;zycoQRjDioJ~-34Ya7u5mSezExg)u%@Ms%jSIOD6)KiYrCXt{neAp0|~JBLgH@z
zoNLFyt!lZP*Ev|qh4GONn2z<FJ4CA9e7nB+wkgls_NtL+iPdAL(I{mSc0WcA^d8b>
zt~oD1;Gs-$gC&$bTDMUW+p3XZlt;yjsdO*?GRqgoMw@%tYLz=NkEGrfjx@6#IbRkY
zvlex?q<b4VAHvy!NsJ!oyZeVLMeZ2Z5z7=m8j71rMCl`;b7gBzvG>MF=pKl?sbLrx
zn+s;yeP!Y@gKlQ<gOa|MEPXH4t&lH0D>%<{aYwA7ZsioH!YkTJVQmn`e~4z|s%=BK
z``nKEH=&$7`7hV4#{qsBA%C-O@(rV`X-j`(*kZp5zvv;0*TYo|1Q4t?lqhQZ?TXDx
zO@o#VX%yzb;<m*W?W;PLld6U0PjfbuUDkjjjI$o&Xw7Ayc8@|oEM5~O%SA+pw5}P<
z98$)l<rEKLu;Agi3}@XiFPjEA$vEFTaE-mn168z=$0KRY(*%ctN77m;!m)}ro}d#s
ze;n^KBJqnAISgMDAY4lPMgBo$w<2`dSjk`Jd))EMjAsH7&-<jUf=5md$)IxeX{*?S
z$6J*5<>4!MYw5ddJh!$@4<~XyP;Ui_7qXZ;Y|7)57a8>3yvX1xrfUErC<;EsL;CI$
z?pj#OQ^)aSbQ@qoP;CGl&c`!)x6H3oBR*%yYa`V&KAbfF{zjtWtY~~qDO4h;d<}YE
zJjLw^%^4S;Lh<3gY?hX}!DGoK?X}EG=)N)i9ABLhwfI$JT(b!8lKf3e>48zv3dq4$
zy#jK<8FKsygYf7##$JyRL@YNhX_ToLi+i<Re=KUs^6Rsf?Z}I6Zk*=DuQg6Cs69^i
zhU|03sl1(hVso+KOHj+EOSS{iCJv&O(?*y!V*kL*(%j%nJb(OO|D)f3j?Zt_uD(bg
z74d&J+COek{NME-*IPesv@rhflgI1-dH?w}e!l4Y&kH!gUx--YhcDlTuS2DySs#}v
zkd^v!e6n-A+fh#!@DsfpBMZ%X%gBWY*sr|V3szsi?$ZeRDGDbtPjWt5)qMN(wA1a;
z10V#{G@74K^Ec2Oenayn0l^K;0|(!voE`1&Y@hbbjEpuK*y?O2z$=M->%+5yp3^?x
z`mm_=n}h8mD;1=#HCD2l9&VqAmovxWAzU-xbljhj6Y^>{UA+c{W$N^QcH{+P1DQ|y
z<8m-KjFav$J<2<TX>Jw`V+Kk?oDSyGc^ZuIgq5e|_Kr)CJec_;rZ_qm@kl13(`<3F
zA0BmH9ryOPd!3>QnM9Y<EJoKHs2)ho(Sn1<`d>K0Ve!<UO`cQb!cw`2FFhdW!K$0;
z(+gr4%|O}BL3p`+y1x@znB*al(KX<slMA5R>1~%X7y`gbo~Ea#;m@7F7taPYJv|LR
zM7R0YFqib6w{US|YpCQ|7$<w-n>}3ECppsT#eEq~q68<A<9JcjYXF|7;4WR&loR0P
zZa_AzT;sDnR&mN2pU*EY@UVcPYjO}yd)?0V;r?zZ8Q`oL^~Zt8J83P6?GD8sDp?W~
zX|3;BO}*1&Xxlq2?K(@Rln*nt+aK&7{fzG}d*ROO?W0%bqSjL|iYFhaF)Zk-ei{s}
z`jg9O=;h*0xO058xBseHh>33zz1%<A#do~qrgqlxH$IOi!$3worO?MBfwhZ<8r0co
zF&gHeEC_^wz1`#?@D}6g|L0EUB-}pOf72-u2WbC+)fCNw{s@CRqn})!BXU4ILXz9#
zFnnURcjkx$4}@_x_sK+zUIPoXNVaN$7GwD0U`9ED%(Z=X`kHn<5^A6TY-~1jj5V95
zR~+;h6SxPM`Pm0X?m80Elco>O^@ZGdl!!C{0e9~nbWq;(ULGKjr=FdZ{4{?Uj3Q7h
zuRaBXi_0K8A9*Au?xo^kI_#}YFL|836nAM``r*(FRt2Qms3Rey{lgOz6p_ebSbp=U
zZC89FM<f52$R3VQOh1L$AcVfR^tU9v-ZD~}&o0mzD8A696wa4B>z{*mn8lpk3dROo
z7w|2{XN2W<vZu0?^ZU5|EZricpfRWWM3Vv9VW8=_KUk&NP3Pxm-lP#2K~T?c0LMW{
zslP=PON+!!hM4J$bdUYLzoSZNZk3>D#22@yz5yW5USmRl?aH$*pbg!6eyRtg+c`YW
zFLIIntS+2GIUE;`7|vlG2*txeBx->u9gG8^XpU)qamf_VG0iVj@y;>fvbTTG>vXNj
z)%c*eqF#I|AvNb$?BUMdtAgg)4eZ}TA!?=<7nF@Q52srNC#i&ka^mE;D>g-fitD@s
zW7}ly0FOX$zgw+r6n;Yn<&or_qwSXm9g{rnJh^mHKya$;831usJOPC6!Tu>I0|%XL
zo&^sK6ht8!uDnnV_QIp%?&0<UH@6D99iZvK@y^fT0jMla;oH-_6N*c-e~JV4m2SU0
z?Hu(OC+p6D`5FFy%C@Sd))RjPR5tkvld3(<*V+XfF~Tko;&31K(9@;I>+6C9&cXHs
zK=yWC<7RNW^ST3Vj`zaj?*6O&qx|rT>eHuie>W%4k<_U3hC=55i|=jHSv(m{2Oscm
z0sh$vC`9BmgIz{s15QcD$}r^@9ELG`C@B~Si#J8N5sdq60S?o_RWy#a3`e3VMw-Ot
zoNW)&IuE5!k!%)lGYVwKE_VHqy(wV4&2f4uUzq5?2T^}${+$6cS(hf$H2WNE=vye%
zY_-wJuh0{QOAln!-jEBBK4jIWdl^M{W8(w~7^CjlAJIPhu7tDRZ<+H+(IKe=x?4n5
z;9mw})SI|w#@;apAcmIrviVV`v&)@f;&SH)KCP@b@_Ymvd^QbXr$<KkmroTSet?>3
z0^9Hf5XlA2qGo$8k`BQHoZkkhr$`!02<Sc}h-voIGCKmEV8;lfLVL?US4N|E-o<Xy
zT8()|W4_Lfd5H0_X^2+$?>637Vc06ckiP+nPd(_6doY}uVwq>ioB}KpX@%rB_K?*s
zoKMNUGYc<A@^hgCB-Iqoa;Uv;cef8ktTYoFAPF9&LRL&E`n!RT_-c~}ab$O;(qVB}
z;!1ox6oSc0QjVPH&X-Z-%vgKly@wJfdm>!b?(tCv7s=9+To$sPmajO1Sq4M^MJF62
zA6MZ2jo|+-FRjpTZgNH6S4`L*d>e=oa)zR3G|TqQ@|F>P6K|k7lq{>hI_;Km4c*wn
zdv^YU2gZ`B?C3-+$gXbcPq9ODNE7_gA!v|_kEC>N1`g*pDWyc97PE$++LGAPjkPF)
z=77ALbCONQ|H(9YPe1zphs-)(BmijX{ZFgC*=|4P`=3^8eRH#o@ju(^oBz50`5Hf8
zFaM*6=;@FDX@6s{u7%=)76bq-3KuHlf(q4;JO<M&9*~iO)2t<{$<0S$ELSE^D*~4(
zL2sx^h#3Lp6BvQlM`2Up3Y^w5m9e@0^<dV=RBrs1mqVDn{YBXE$s7xZwa$SIh_)hX
zH-2woTY4v4vnACP?Lae}CUqNf<;L&w#9mCV>>lWqEljW8o#|EDQqW6|8m}IVQQu`~
zXqw6m2R~+PwwmEO!%bgfh{hGhO<?7#E(V9+lEomo)eT6{37-Cv>4*|&)xv6!C91ZK
z)MB8LLQt5_>tawJBdScJD~6TC>k9%jT6p2L7KYa<h1XsfUb__D#=`J6O5trT3~#d(
z-s6SgJuZd!WMOzuO5y#uFuWiA%c4FnC*{1HEX>QE7G8LDdD+v#3$HFOds=wm)#YVR
z3opF7yzFV=g;$rCJuSTO>hiLug%@63UiP%G*G4wY`U~t8R&^hw>0lv9qPh*~aylK>
zN6D;h!#VFS0LG~7!KU`G%-VTuYJ)K<+fe3{xc-=o$~Khoe3UH!$Exm(3Nv0UKxMPK
zJF+2OLH;vZWPDB&8{+hOQGjj>8{U&mnv>el?D`I@$6>4e<AU&VZETpW_S3Na`0-*u
zJ&kOr?Z;2T$F0_4P(6)osE=Fiu(jUaSPZPMl|zH|_GZ|6+<Lko6@1Mc$d6lp3)}0P
z3r?E1nM2|A&8Ok!`rj6uId3x?GL$|EpSJ$C;Ou#u*^r^M9saG|da@W~Z!;S*l>P`@
z*?zhpq5bXL71DnCG;BTDc)B3t6*Tm42tHg}Yy-2KRYPBBTeDjEVJC}e0d934q<Z_D
zTiu4V01=ZyEg)HhTuG4@kSwGHB!yZ)vWOOt6lnp;B3eLFqy;34X#s9^XH*Ml0d947
zWQ%D5z9u%r1+@TA3me`-T0pM818Y$&z}v=#xwsbKZ)8JVTnq3wvZ3BV3n*yi(BKYQ
zKv6RX@*T8*qGk?-@1O+~HM1e#MGGiuW<$P<7Esj8hI}V2ps=00Lhhmk6gTv6$bwox
zu30tog|@XCS^($@7fJte98DHbi`*8T6Wtj70~R{a87*vh|LC8eM@fBXc6}QbdfD_x
z3s^p!1}^2M<FG%QEvWf<n-xG_NbB>pviWGix%Ra1?A!I{+S9^@x6oYY>N{f{q%?i?
zhiW&lp^-Pnf^%KetN`*tYuneV;M$LKIf&<Ri{FW2%cA=|%%RPWH#<i?<BC$`q08OV
zi7e-scU2I<N;X#y$mM8y4#x)#W1q5l*9Q=fXGUwT)_L36so6Zbi3Yj$r)N7mozv5r
zAksO<7jU8MVXCisAjlclZO_TX>H!!>$z{Y43fYFQlhN(6dxH<D?sln;AzcVko`Ft&
z?opJWPPcp9JvA@6Mb@z6uJ@)G7=9E@LV4XyBsgd<3TD&}eHZ2!aZHne2ai5avpzrL
zyOUo5K9?_8MF$(<&g;(3&!=aHo)P@QiLX4^Z-j$%K6Z$(c{f;_9$3eBL~QEC?D&qT
zO<mkdr>ggvQ<arZ)$tn)XVp1+)q5Qx?^;W(S274VT#E26B(3$r?Y!MV?_Tmehkt=x
z7l9ky4A5I|guXnu%<91IcJPJuAwDq3%bNxIN+NuIJ*H;?qQkSJ)3XzNQUJa6&W?^c
z2Mdj6K2ZT=!fZa7L?dTF{7!H0?4Ul@^kOZ<a5V;;)7SXy0Z}{I-d&6eh|mnZ!Y7xZ
zmchjv?~Q&jco)&h=;t?H`DStN<?e%KQQFR8w6f1ZD=S2+SA<rt9$LU!Df;=dC(xac
z6CesTmXot^w|jhI&o?X(SQ5Klm1Q=^c^D>BQ)$3FgbRU5(;S$b7c-Ja>3b>$mg|m$
zv9SK{@=`%5<~L|~;IbO<)&tt3;CZ_6sewgZ8Jn)R!@NS^>(HY%6n4m~)!&&%o_o9V
z$^C*3dnFxuHxN&U{*9)Xq`a>D<g`|!pO*H5EgV;IH}0bM4yj%@jt66Y!aP2O1yknp
zJ}jBE!d?qJ84KoZfnKFZ@Ue<lRC&7ei!@J%d;4!W_%!$B5h~yNC4x?EuOBSngB0$O
z9!L9MD}WS7XJbwU(;tn<z0`5Pq?lA7+>fH{(=_=I?C%^<@G*SN-xL8E<KZ(57qh;x
ziT=p2F~q5=6N|@R=g|eG)S-v;-%)H}A^7^4tovP)5Woi+Nj%G@2?Cp_M0`c9g7G{R
zuX}<|F=&o5f-Su_)2I+`|2<3S;mg%0{3{4frtt({U}jUXKh2X!Qi&UI=q#?ijt{BD
z@sC}v-2kZb84xT|Ncw}II$4GF3zUCZsh)hPXfTML0^TSLVVX-RW#)}iZ$G^0qKqs}
zW|Afv5|+snO%iJzR@R#qX@L|?htPwdAA2=Z_rN>UkddMIYY*;{VaZ9~%ey?qLcxHh
z^-?RTnJSMPcSeIizMGArjF%K>p2Am~0%SjPLdPwhR7v7u#770CY;TIe5u-ueAIV_b
zxGtN(xT9Mmz&w!@LxbQaeBDW}0`D&`Qx_ET{qCu>UC6{ppOJ0}ARhN#ce)NlOpjEa
zYe|LSE6%gTU2z7CEekpR`*%ACtC%Dw7P2W!ft6{tQ5I1En?jMf@oytC6S*!+B&Q4~
z%P*YnAU_dRMp~fc4OB}(YMrd1Qh=6(mA!LF*|Ox}{^X@r`lgAB8-K?v<0z&+E7SP0
z8+{g-bt&L89L_uNinH(Q$fDU5a1MoyNT%2EP`@J<%tC-fD3Ue&<A>#n)RU&n(1G(y
z(ndBMlr_KSncaBvo#%Uj?RPEErDPEM)s4mvoA|f!;oHsNo9F9|@3usju?Vn=YxC)b
zS|(!DV$g~YF*%0`Fjx&X8o`SfLAya&bMR57j?=s1)O!em0si?ffbonr&x)AqJnSOH
z!(BIDY>nj9nZk(4`87`K`JrcbHS<-<=DCr|{aLmZS+VRrndLGxQX<*24_9QF5Iv)f
zD@4lz*#nByyd0s?9mhBd1dsS1BqAnyGRqut3t~Z!6n83#KGu*)w4DwnR&49cGcomL
z5hckvIU`B5ZpxvLxXMcqZm30XtYgLn7Zku6M}6QvXdrYXSk8DJ>FrSHvI)#6>{IaJ
zJfgN3h{cL@ELLD9m)|<$wfZ6(h*PbWF*?@@$e2uV%_8EoAnggK5aq-tKqwxItLeFV
z9ZZo=_!0KPe1%p^WqYEj2e_(KmY|M9^X-=xcs8`ySO#YM(yUyDudq%TxyD%6GwgiG
zZjG|#xH$TYq-qo^g?UOu5Qj194nvBV`CNcG`5AOmLR}m%j(0mP44wW>F7CJ^&wNsa
zQ6Qc9E*-ZUl1(e7oUH*>;t%6Sqb0PI*bC)iqKE}RljJ5hM=V0HJ45Du!8}dNW*}`k
zAW9>#m3sFxvNzR0qN?{oQLE_G5P5`!v}GZPFSap75E2^nignoaT9s#ABNxab+u}_%
zi`?VR=*hh2QcuJ$sb(%`(=5*R;0(}7C+F**xr?K5$hoYwmrx+rn*iVi*dy;K^%4dw
z&MRd*(e$I<fk=n-SEHM{Iu&RA#M;x;CgEJQRBUQq9?b5-ga3w{bkT>6VIfxP{qJBU
zlp0fc`Gk_BfQel0u_TRmZ<8Aq8P)GYulOvTBBxTQR3>-Q7F;z&B%kpsD!Dbr!?IE!
zc^JtB=2dtKtrldSRMcNu8b@PHahu;Jns}&?w=iyDqxwuOurrzH&(06O{Z_&c1+$o!
zlnYKkZlyg}{rL@}*~gi7Uogx~j$QQSI@?8cqohWo7B_lDVU|Zu=#)N%?i3bHGH433
zNY0$u$*!Vgf_Yt|>v#}-c_XM|JDzNi)V0%dseWMZk*HPi;b&#nD%IPpWmZRjQ`eM^
z&ZoZTdla58$&G6S$y8Z(<JpDvt(U#pes~m!`x@!LqC)C;mW{ndpa`h53(tKW<TDA;
z#adA|AvL{<qNviF=y*=pq%Am=91Tm*02d8jCD39P7~*9F1?OQWWDdS5+<Q_x8L>Eh
zIjl7~S2LCx$1#ldlw(6x(a6+C6?NJ`BU2yz#X5#<L4XF1KNSc|zAxW7?(Pa(!V=k_
z(2&%{o3E>WGNg1_INo%6k<lOVB<K(S(H~&=?AbIWn{tW^eGC|kVQXOsNV5zmJh=?6
z`$^oNpukvSbCfk_!W$PaqHaKIL0@$i5Xz5LOcyJ6P9@uC7Kb3Gd_XkjxQHJzKrKuL
zL#6SQ)T12ks+x%^&$-0Z@RwMlk}Z{y49S-&&jD?^3ot$v5-=D|LDdAJQS5xEG^X&j
zSIKk&6dcy%q0GZWnU9Au4-aLF@=#{;P_KxG48mqLCm^dg0aG;rS=j{SrIV$vEGV3&
z=E}djY?=yQ=6ru9LWb>k{~~z(tGPepg5y^X=eLXk`>cV6HP48RGVu^19?ttC0wU#5
zbOS(SaACEUc`Lvb4WH9U)y6VH%7g)g8pX2!{d_MlNcy;c8%zg-d6GoKwcvCbNPR|M
zkoMC^UUr#FM|ShPa)rJKJksI6Dx0nPnmuEKw=oM656lZ$%BQOi>nQ<ad;~Nm)A9NI
z!Yj40ASCCEklCjAoMp^xnTGQ<6_|z83BUe8oOCqJqGu!!aVt=4XzQSI<JOm}c&kC}
zIfn&GNX1q)l#d$5BnDiidXy!etUo>>L+&`dob;+ay3deZf2<Buy331uEVq)@7oMAm
zU3Z8Qp1nA^*S+}5(Lx^PU8SQ*Vfo?5<7P$y7gS9?*mDs2Si3L;^m~7}%FIHV8Kt~z
z+)a7>8k6?#qCm+>a}|}cNz3kY(rRjJ$~Vw;jJ2=6{MI1lY9O|*FvMMJKAE#b{knb@
zR@8inSnx>yDvr?VL!kw_z;OhTFBiJZwbI9}z@yO>vw~ApKc<P!JEj_DI<%qN{?&%Z
zSdQvu;_{<o=e-B84BBQ?1-ydhlKo!iP!tD2t8#+w+n(#g^xjOox|;%@cVi0j6cN@v
zUbrgH+n_%h%tw7Z!DQ@SCLFZ*(T_-;Gi809bnJ<lW6qsp@l*(*miYtbveJuOg>S>1
z<HJKux+U#c?|JI-J$mocA-w2)inoUK@S*^Q@p_@*!?ag|X|EE8UL_7a7l*rvC#41p
zUBIquDF}Au%vU)xDwB}H0LJ67Ud+%!cJ!!pUIl>64<O3{$dOwBPz}|cq;wt1LH<79
z+m_kpd*h}rFQrf*`E$}+5WFuwwv>}wzOMC*#8|!tjy|U#`Sz#G0PQnA)A9@+@hWW!
z=SEz;!K1-+KFPkkzacsi@*Bb}`)$KN4AZ7{ePGxw|G{e0KgglJK+pY$RGC~wt3U!6
zO4gD_&b;?UB}A93{Db|^nTGF}ZtvIF;nd?JMJw9?{C&ZD)A;=w*YJXm(SFQ-Q1ObG
zFT>+q8-^F9UbYDJdVdD$<(|KNHuZd~%zmi&`RlB7rJ<2u_60!YuN5{BX9X<{u2B63
za{9cj>YfeVL!0Qa@j2&3JvNXFblftBm}Ag_4c%bSB^V^)$|G)Q_-vQ=OrYeIe@I>_
z<HSeiD;J{Yy|GpHHQ6ew#a6}UvxV8J`1I-?D?Mzr@QK!9tE@g-^*)EK{O^hXaJB+L
z`$gHRKqeAI(Kg`PTgyH|6;>{iz2@8B&l=BC*$PqWit_k4>F&ST?sd@Z<MppAex1jC
z&3T8rabtKS&hI4fb%tQ#mV1%^|EBl6aqgZs3WhNzm5=OuUP)@T6&W+JWmX`YAe#Xz
zu7S(VjQ4&6Y!K^?w{zTBUePUfJ;!ZxcXYMx=eTXjC7nA-=rX8p>B`CTBFInOe^s_x
z^|azUx^lI|IG-19Aez}6y~G#T;1AzI{vQ{*nIm+w0-;-_4&7bo7HdcUPdG;KXdI2q
zk*=9%Wfxz26A7v`xmqhR^R2|95F>y1O8hwcf-A95!>Z8bYE}0Q$2O>a=3u^tz3THF
zC+W?TYey8{dA%yGU<U0Ehl%64u)LIm5Y#eLx<V+Ah!#KCudz(*!O>FjOkvLMg4`@v
ze^9ta#1O5Dv_OQ6fq!USpfQW7Bg>RyayNpWqiaw(ZZHLVG+aS{<KOUptKs?(PYRra
z$v1dWUt-3Yn{0#bsT%cztbaa=ut)7xjB(#?XA%4PDn5S1&7skGB-4CTL<jEA#6KRg
zM<>yd{gMN|x*_x<?0f(tJjaj|8G^*E0UsVt=#{QH)QM~z(G{LdO(|}8`bh!`+KRsU
ziAE8IAx;|w-q3h~D3<$*3)2{Z0#ockjcfAep3bZDNg7{HC~<ujO#W0Cx|T4}!QCju
zv-(4{qfcu^Cq@yaE!C&SP@OsMWGNIYl7y0wM$X#?!6k<7VLnxmi`0AhXWUJ%0My0=
zB#{u?3X14eLt0nQ+<kkXwc|XLTMqY;dkv$V#r5qsA1>-%tE<QcKdBfy_T_pGzVCM3
zzFy}jIKoyh<9MX}LLNEb>XRVknr137v4nh~WnP6IGmY|&bk`uiH+k42%$1NX(Rrji
zcj~f8S1J$vW?fYLi9Gd}eY;y3ry1V&e9C5F<niqBUj`O#yrwYtJ|`^7cib9tR5nF=
zhJLq4$f2mknOHBN`@M{FuJx@erDA*3Kj>&A4N{{1k|_|CdB+ry`6XdB5!M`6;1(>A
zh1N*<A~9D9E)%&_3QW6x?p*R-4i|B<ErIKtLMQ@k*-pKzUPSn|Y-%s}ZTcfMTIj$-
zTD8wz5HD`hyo(7Zoq$3x$u3q*RMn9V{}L~Ig-29jwT7to05SV^9)6p`wh)VtRi+>U
zP;_X#gPq|nN9g;fL{>zJlB0MjC93a2YP0R4O#4T$tpC>PD|4*(_N#Q3?ww)379C3Y
zb#XdWTSvYsx8BvMOj<upGe(ic<EvXV{7f*gIKayQ1AF#^2Q=&D<_|U7ix@AcJ34C%
zD@HBT1;?I@5(;bwRr+Z<AJ52*lfwRer&%EVj;sg#1^>W9KHt?)AjxQmz|L>Q=|2V>
zZl2K@-y(<@U-0~e_>Nyl%@OEq^PP|h29Zm#5m`1s&AEu9(U4;P`8f7Fvs(m@iqZ2R
zR^!F7>Vb~?AAoWnqT5y0wr2e};UVEmmr<0$0bmr}#AuPh`>r&`u&#+D-@?Wp!}h~8
z5f-3{Z{0B!aQ-qtrJur5LpFP)Y$4DOw^#O`HN3zxEI1q@RJrG}j+Tn!#>aV_0I#sA
zh5;G&8WUsew#@3oV_C@dvr1+!ymAEwX5x>gpRidH0A~FWy{m_wo+)b&buQFQ$u;a*
z;CdTFpRh7gX%rI|kgSuFd9BoP#G|PYn2U)^>(zi|Tf!mUS#}ERuR5TV*-f;Z)uxfW
zdZBGJVovjx8r5N;X+`Zh##up-!#Vr%%Q9jp%1#1A0ckS$z>{VX*PNOLog0g+G}016
zv+;!tAqAU4Eycj67wE0QF`?+~KX3Rb+wRLrzo>Dc-f-)U)*NhsNkZ>}mMP(@84B)u
zc1`W~AGY@EH40QtdcldL#-x8~r{^zAx?*qVGLn52f93lgc;*?n&r!K-;5nO2!L3(q
zeerGzPdxPAbWQkLij;;~pKPwELe6HRc+f|EWsUW<EE-`9*sFMO#b69<`9e!;IO)}N
zKEg-VJi;~Sl8f8>Z@Op~qRXye-*6(*uqg_ygv^le^=2P%AO%sQWe%P(EV=2cbAM;t
z+f}M$nyCLSnwTGntN8K?DRl+2#od#fWR><3>P<`v5ik>tDIkq`Bl5_?dPrd7nN24{
za`ww40qNMo93&x~%dU_HIC|8v5uhBH7!gk;9*8E>47-7I2OOCsnDh!c1&aXSTyQ$Q
zfrIaSo**L7jp$^Gb6BpTp5KP?u=t8oXBlC;F~Ad=sQ$)0WyI1~s;HBrq^^ef85g9^
zT`Z#(4yLo)8keZHW*buDEh7fhD4LkHVinA6sMK408!1Fdg~IDJY=~Pu;-8;%RWk;j
z)gF-HgS@<Sb>6{Rlt8K)v<Nt?;y<n2EMhXa8tfI&fsuE`YF(UuWlx2QB+z&bwtn;N
zgW#mQfAeHBcpySSO@RHO+5=@~e?Y;{rin*bF)GE`T8zn(eC1r=6DJ!3Xd2`d!!v<=
zV~|z&AIqd21`r#e{i8SA2LhpDmiWdboU0n>*(GHFNi&YdgW2uMLvBvNeIFVqD65BY
zT_L$ZH4#tatA=3kme(wbU=1xrjFG%sbL4V(0_%M{e;=$cAIy;t8Yo)h3CXu6^MPOl
zvGM*Cd^;!8X29Jzb5=5-{G`yuRV6K{8<U_uO0qUo(6xLdiKMz$>)K~(OZ&TWBj+uM
zl_P8|l@Lz%a}f^=l>TFA`j2|^Csc1LtZfwvjkweHD>YsvqR1Av^rusI1g1=e1yr6=
z-DVLRo~zQRoual<BR>`!Q$3amYh(C*QPn7v=Uz>>GWCdR<+LNS?N?Hc3`B}`BO};N
zF*P;vHZA|1lmI=3G9AEgS`oI7rq`kpdn}H+Go>|1CbHB68!1;isPGQ3Qf^iT2D)ny
zIwOD-rnncm)ctW;@9&+SRBm;sE;Vi$^U2m`i(aHFl}wGIx7a8?=i!SrifqAAWcg8;
zK@N@8S{&)n#|Vqu_~_upOgnU0*Mu{?Ax%Vvc4Vhz+jY@vR%TY_hDLYVPmw!Rf!KL>
zS~Gl(i{d;PX8%S(AQaOr7`lG_s}Wfc^$<diV+kcPg{3icH*8nc@cl6>b-=KA5@(($
z@c9Sw`VE=>HUExmc}e}@dq?Qq$&4zfhCGmIYXp6zO3;9PQ}mW{rX982RrFcB1775J
zK+!l5*sPW0Wp%pEs)w50_fXwF7aD5jAFA9gN~ua!tL7SUDWsmonf9*3tT~_DJ9E|_
zTg{;r0nDlZ=9q;67VX2HJ-8-8iiuG;JbKc|_vnQf8+C-7ECgo?%OVbMc;RGsf%E(F
zU;gv+wSJJ>eh^YTyIC82i9Xih=gE^z__w|BWPM%y+oJF58$UjI{AA-Vt<Bcv`j6|a
zA2;B8Yoi6#g7q(fjQcYOc1?odFIV$%JSnMHRsL`K0~*Zf$?n_LgLn{4(r9&m7)`SH
zB94-0!OPR#)s5AiQGcG2g=Ys29!Y$8m8}dKL3_RRbhW+SZUwL7(|8mQK;JoFPZ_qV
zEdMp03`X-I9Mn<Bp3l>8Hi*}*UN{99t8O~+e7^;0ndZM=Miab0&3(VV8TB17pxC04
zIs_#(O7bn@Y5v;;G{oFTRss0?MZi%Khb!G)C*1DtyoUcAKG|%z=+EYujn6ZH>uA7z
zM3Z5BVbF<H3`TnG>VaE83)J&D!cKCZM^o?T@eDuOp&obkUWL1z(;f69K+|PoX@&j?
zeh8jo&O#?LWcMvUwLj^0_By?t-s|vi`}F6f4R3TC;TDiYXugdoEPGlIcZ<$(|MDCs
z*%xcC{~^*5^XSSO?RpUzuE|?ex?a%%F#W{3QO?99wR)<B8y#%P<8X3rB$#)PcvO{-
zsFcgraISFs!}C1_rMIqTSSf>DkiycVz7eL;rMDrQ8<xB<wL+$z&gk6r3TehRy2&sn
z87y6_&(>K)${scfzs#uc96@{!QyzTlj`~kBV2>4vW82I}A2{m2a*|#y!$Q@^ix^Y{
zb3o)HO*LXvvoGQ#%@B&d$TQ*lDsC-{(OIAM*otD5R4yIM4pX^wvN}sAGiJfR7BayV
znSU*0z8NlK32y^t315+yCH#T4Z2FPqGI&Ja%B@|{1^uz5rrtP?6-YF!WZ0utUyT3R
zkoH7Si~l*DL<WCAp;cKD+_FGgCDyr4bXJdVO2=(+kTdSg8g~IZX2!U)vT<k5xU<4>
zXYROFbu9MOrO)=kw~Ro!8HBC<!=1RJ$V_Gk4gdDTrZk#hs?KRmX7L13VSJR)3jb11
z9&=312)hvG6E6(wn2w534qTzzjuI?fKOUO#RebdH+H7Ux_XXioa!gh^HAM_uH8olJ
z)MSfKO>W(N-qhs4-DPV0^z<5{tET1xwva-8aaPHFts>85qjlRbyjgsux%ZU-L{^X_
z5b_VL5*HsnhDfP3<KAI-^S)$1C~by9s-)ah32665VHR9idarokB=>7V|G9%K?9SG7
zrKH3Qq{}PHJRwq&`mrq;NR?Vc{S`5{v!w59$=Bzj`eMP)M_CmgWkr0HBS~4a9Qm`l
ze3adVkFvUal-1*-teB6o+I)oiqvE=Izs)k+(9n2tuxju~V(aCsygP)Mm>_pssuLDa
z+6-U50#^f<pzM3|f=g2K?mQ=}irSENT~KH!;5r=po?@`BU@&o4Dkvq**9PU>QOP12
zzAcrUk?NWj(rTFgt*W3^IfG^YRt%OEFj(ecu&kWHvQh@i3K%RW#EROu43^bru-^SK
znD4IMX0WW7!E$3QXeAlU;jI2>REM>EvQFF>`?!>gJUNLt6QWuad0T?a9bRslGf<_&
z_#^!9mf`g^9QQ+SfWP`CHF3(9eS}H>6QeKA&gbE5IvuH#At==GhiG)W!tKQ7?R6RQ
zxJz~4?vfV~q9=8%Z^W%`5Hp|FIrrypNICqK9z}FPu11(_3jS`wM!F>i%f>o`?fE0}
z5~hQI0<<)r{M<WydA1k6?riUNkB<+H*5_zQL21*{A2F@CRBS1$dOXy*{qi;yF^@}f
z{=@_fW^*(mj-v3%=875%VHQuX`!IDE{rQN8)X;`5aeavJ1u%mza#fO>weul9(*>nz
zaxo2bF1pe*TZjo>CblsE;fiuJl%I)T(J2LB<KH1xqg&HYaW=RLR#Zh~6?#wgxYd3J
z_?Zm?5xMu}Zg{%?e>x#l344D(>EJldlc@h;OSEmRw>PUAV;z6%&Go-MscMaNa;?P#
zRJCodZ$6c64Z_-_@rLY}#F^&(t4}pd_niLbhUSMIC*_2TFFtu;)Zz={tJ_pCjF5Dn
zk{I~UA7=gK_9?82-EMe*;eMNe;)aHVuLNc-Fs}*BvU0c5@K#n7#xGt38?6TZ(_&Yl
zYWTb1LFdSU?crrjszyD$cf|{76K?)y$F=7d#jwRG&kCm8Z*q30l8!-Hjj7BBZ@$x1
zmVmjJsr10FM{>tl-f%5FA}XL(2Ey5OJOninHtT3o<S63Fc2;<J@FY7c)C2G8|9KAk
zaX^UE;->gGNJa5UbV<7qN%`whe-aKZF3A<o$PIYh?a{=AZw|JP!p_n5%Y%+bkwak6
zIvn>4^f%*>WX0Fh19#m>l@aM1efXD`HaG~_Fo$tE=qF-4da!f}VRV}5PBW)d*XvVR
z9IQ?=v(xk{zQ}xC`p+zBHl2xB9^93%or*9RQ8S3}UW+Ff*Cy>1ywLGiM~1s8%;Z;g
zOEi*TX$WdEd7;3L1FMB|6D-LUBG(X$!r+-L%=qgT^$?iB-V?kmQUlTbH$>fs&x8MY
zx!+sS&;Zm+M_LpCq2Jxr8BOqUiAPnpG-l%dX!56AnR?dHsS9Ur$>s=ixh}lUl(8E9
z|I_&lS2$_f`$xN-6PV)e+lI9OjfENfSHW@weoz;Dnb|6HTV=jh)JzNxZ?k#0AnZjH
zObTH><zh1krYD74%o;6cAQ34@n7V@GaZ1;yxM9Zq5oSJa25}aQqdq?{6V2en(8u^O
z=qb!;%2V+o2^O}|IJk|nHPPmD+T<K0@~|r&Fq~tmmlW9&f4{&d9L%Mn9X*NqIHTuP
zeHwco`;Be}5yzEE<H;bRY7AJk>nlL?LQ1HW0-GO9327#0SSpY@YK1X@mzErn0DNHy
z!25vNW0;0R#6nEBteoqM4D`XO1oJ+}X0%fXwvwBIOk6{89>n{+ai6kCiz5g<d!t8b
zFk6`DBAIf^ZJG&S6$U`5w<-P?{MNgnfM?3gwidjcW>+$ZEfzryisgV$BNb0jpfc&F
zzO0hZuv91!vz9QGsWfofP~a_T2){iK{IXZ31XVSQ#dNWpcClzmc~)$`6S5n)t5|=v
zWw+nbCQbgH{GP`1fSO{^rL|wTETD8fD%YlPS>JLuL_Q`0NYU^-Kn<jX-ibqRYqP3D
z@8nC<JAZuodh{;p+oX5mrMI$rki!<KBrq}c&C>Ujhp6!3SFISZ#c!jEm1GK~rd&}R
zgPybn2j9+VN9|wt;}IvRNbn8#e71(K{dlvvoYJdDBp;G4#P<|ASuFvAy!LE|9F-Dx
zU49I$Y|-2r-&v+2YL42aKV88t4*()e3&zt&ks~7s4*ufieHa2hytX%qvi(7C4Qi*z
z?+-F`r41HP(2B$@H#c^D-XE0b4V_=jA!uW`A!tdQsCf2jjd-g8S4EQJ^@A#BdY<JY
zWW`1-tYY5bpy}oK>7Lc2PX9tnzWze1NNRESr<BD<U|MKN!9wfaaiJwe3$44@LhJr7
zSZLDzS+US?hfS&%nyOZ|(2|-9t(bT63oVbIf1w!;c@e!ur{k9ZLWZF_@1*YjOxbtZ
z{p<zgnvlGNF?V?R+_)5*yY8E=ZOJc)bJ$puLkF=xox1Ubb&cgEGx1>cM&h}h(#-5N
z8s(h!lx~boa`Z$q%wReusN7;O9%5c4m*?R#S(*d7RJC4ZL*>9pPF(=DfsNPr8eLe=
z5H87i5l$CttUSd33WfIgWQR=OJI9A%@0SyfMQIQTdgs@Rln=zdTWmd9QND|^Dxewl
z$6R||+VJpg_IaGGPz@%P=pMUdgK_w>DX0ji{T3!TZHQ;o@+iP#nG9)b6JuyOZ?GLb
z^Oq9|laqq!oI4`l&a(At+rtmop?F=6Q~(_AgD*6|yK+VS+2sJdp1Jk1mKQUVu@>Qo
z{Nyuu_|=$yM$k9?pEvthn?f0Id;uJZ2#6$cL|&LT%>XL~gXo#8$tv0uDPs}L{g&rE
zvoHeq{VB#FG9moAct>a@Uz~Lon|jZy`%8=@rskeWS%3Q1JoBGR&9!9BQ(&ZtFxb66
zyu|^E4A(Bt8{uFIxN3Hx=~|DOkYTKMf4aY3_wV81=~8=r-Pn{r_3_>qlacEP?oY{b
zqX%d64;}{4tUd`SX*LvGM@foS>Nk7RxGwBFQolc;0(#I%Vdr*Fc7G-y{Km6Mac{GJ
z`av8oP-U0tAZ9aG@BxMl2iFWz{QJ9<s}m%cPdt=h05%n+>~b_c?~mk>g~F);l%zko
z#8lq7=q7ntj}+F7Aa(K*zB@&s!%T<lhijl<>+z&|8%|}!`CnmD$hirDz*I9tHvW=P
zYSh0C$LWf=fIYxl_tTT(qYlh3!Pc|-y}G8gY6%2Pw#^AId-M-2v7}UI7QK9W)DZaa
zsOp&VY)QMp{Ek7GLFBJ!bbs<QtqSV$jRj1Y3vn2$o!<UoXZQH5x0Ra}Jt5e~be`pe
zfRl|6fARvrJ4QESU?msjG6&|+-HkAKb;3FB(&>d*jP;b5WgEd~Y8$SLR=GgBzLP*w
zQe~W8(hbeK_Iq2Xh_IZp9N0~xX2hOA$PIUcps|h5Z(v1S(x`}q4qwX9>cmJC#X^B!
zHp9QjuMJ+}O%Z@{y>yZ&lO~1E6uec)Q)_~$atu|WPzYsda9*l**3}rkq@I8$i0&z_
z)%{nmI$itx;MWuK+Cg4h1aYs4(A0i9EEu{wFHvi3HH<x}$H6jT>3oD~(3h{~W)Kf$
z2vB;|OJadP5C|Qe9pl3rFnFS45y>5Qx3%Duu4Sk51osu#_XvX6`(Qu&0A<%4*z?U^
zO1su4_%s>ak}XWLkLnb|g^{TXHY>^}BFBPhhDM+8?Z>*_x?CEC*B@hPL-QzD>*|>1
zX{AFaS#9#(1oxqy$;CrDI-sC+bZglZZ<Vg@<rx*X(HcydSE^F8$Yk<y=2P5rij`)=
zqvKw9dUk@IP)qA)zFOO``Qn~-dbYFEIXzu!omFdE+Qq}5wk;Hh<nF#)7?VsYZi@TI
zpHRh;+8eOgX!?nLA^Nwb8pmOG<unlxULEW+!IMWSob+SpXPAxvHd{OQK@<63M2ux0
z3n4sHSQQa!hVYN%Z&!8DPD(z)`=7m+I>Q)rwe)PHYOGxy6c5{6ES#gNHiBVpBY;M+
zk$u@ozwCsF$PwY2=Ouhqw$_YU0(v(CX9aybm+0m6JZ%O(-m3QSzP`g+db8(@XBV{8
zvPDv%Pw1s1f?H|5V%@7x+=n_*q)k{0)T(Mx`fef<@T@5^i<Xm@_W6j3rJ@5?-3JUm
zKEi#lSf1G1qbXDB%M*F_^vRTRd7@-PtA=dQ{BZ3T4d&q|M{9rd$C71XzCSB*v(O$E
zg4LTUWXLYxRuS2R^O^88)8sT?U@amjjm2RY$cYx_g_bQWU0F#M7RklpZjGl(;7Pv=
zONpyH!;cb}w!HjZbN7`m;HO_Cfe3=e;s(yBnO6j;X1Qfp*}E1p_m%tfelY{Gc(52J
z5ow(FWEu>~iRWt?mz{Ccac2(JgJ<;Ein_@IDCkdBxeuH6eHgXbo>kAR{lKJ3@NH^u
z7B)*(6YxRr<^c@kLHFiC-BawPS|E2ej90D|S?!Bk(7){B`C8WXKWOdTi&5X?{SveO
zSL6Qbqv>Z|3se|~*vGo|TB`Am#5%hg`mS|(P<Gp2<qsv?LJ@mq^-aw()If42<u?+@
zGZoWU<w_vQRL28N`>Gc^mlVSDIocE%khNlA+iFcUp~j^|sxKvYI`Y>Nr6&h>w!}@5
zJyFtYB+oO!4@EZ+!up?s|C7T6joiHmkK-;kBhICVXKS)(z09u`Op4dI2r;47y9&t>
zStY40xb^Vea4=Ph?l_E#PDd=}WTC$Qs3{K((%Kg>1?2clrmwz38Ol2pbHga&dFKYj
zMb~qOvJjGvh9o7O?KS`(6Z09965y)PxJt=A^y8?JXjAS_L|(B#yz^t<$cy+=9{*kh
zPd0VrNDW=yy&di!g`KyopX?v?y5asVpQntcgKEp73f;~tdI8E$vxs|4xR0Fb2gkpL
z$KBmdH$2|k136)y#0vXBj4Jy1p%DMzk!oN=eZBwcwS`Lo=x-MXogbya33}#iw>`yL
z)bZtLfxVr7<Ysv}g6}s*UHCxRylfs~EZ$-CmVepkzdBf#@1%XBdv(w%FK%P;@8-si
zZ?;ALMY(A+mY6jNV`c2_AFhbUp}}vzDU5+(UEty2_FFsBmw3W1#=~&m2j2&!Ys}P%
zWy~+Evj*+w6WD5`;G=GLj<*jwr#l_&{|vr_t+P`^LZ+Nl`2Lp1_v~n&>T6b)t*9#2
zIPL79n<Y?fMa`AxQ9Ck#K}q-VtHVJ_T@KQp5-+28CNC+PpKkH|<SOD*;ss{OqFUFc
zTB50@Q<Va8>w1!Y^I#zS4>1__XOsKm;^h8VNN&UK3ZDTs8s{k7wSKD_T=kP7nPP|2
z$a1|2emUT~#9t0j-lTF95Dq%CC>h5YI_LnYpo;6a!)?j`{vY!+6A1y$s~NReY~=KM
z`Q;!yvP{W^e1J*N7iNXRiTY@+9zWlGss4OV><sp}lV@@1I`j^2r+4>-6-}hEs_tUo
z?53TGvOcSzmoWyaPUf?WoxtLW@dYZ4r$bI>Nl$J2vpD$FPdUS*^GaGOaW@aMn_wlz
zjMmAxKN8pDQ;|YynJyFubmN{5q6wTEn(BGTMSP>ziU&i{5n+JYUY6;O6R_Sp=yGBN
zJJ2h?FseDZp7)ckFFrk@)ZgL(oFVnOQiOtfzqMGb0(A@K1cJi>pg33~#OXKjMtt2~
zt)(#xrOutFfw&o<jD&7BvofO9jgo6rpABL`ui%mRJz#C3(|b)%7+`le+1YoJY*HQx
zMBu7F8N$3jGXHoU2uLj8#OJMhdMk0a*`N?*z0<Q3wJiN)&v`3qrBe>MKlrd>jH_~v
z#9hrDC+XjVSmwP&N$@feSL<Wp-JL-UP(W+l<dqrB3>(+U;Vwvb&?5KFjzHz<Ztrwf
z7~z||u~>m=cppB2YHVM5d*ciug+!pd8u!u!f&$W!fyQ`xn7_@VlS#3;$w`DE%uSvQ
z7)}XARlJ&xhTayKDnx%SNa~=<Mt!%)WB?syOAttq{Uc_HVf()*@iUYYwo8OQ{aS2Q
zhi3|6U2j!RPx&PHrp=k2GCG$8J}U_rk)sz~>pU{<b>t<w$bWegoO1$5s%QsB+sf~X
z#kn=`Pi(oC&BBW)Ob6lhXc#7afFwpsRg|qS^V8P)jOxk6EP!s$hZHH{R^qCW!Pw6h
zQOyu>Srt*mHNoKXd=<*B3yAtn%z*CGH`wU1{Wk1TU^auY7R-T??-x@5EdC5+@;&jl
zd@cw*{zDmLzmcW#Wt#JfQ2LY^Pi%Dy@}!>5Cz<i+c8MJ+?MlL?^*wg10wfhMY{Pdw
z0YL5GV^-`P3*G8yA-x@rUSZ%kXeeKb;%(0tPV2Lnq2j%~lbm*6#as%yr>FWFAeW|=
zPr6}}rsxt<WB*bw$f4OB&j)E*^J?Ud&yg3}t-r)O|LI&f&&Yd;;#ceza~V`tx)AM8
zwo{Z3Nlj>MS*Reu+_RIU^7pY3E+l(#dIbBpV(+*LdF!1$^j7O_{UY;dytyxrN^Cfg
z72W<?lKdVQ<Y&CSFMhebh@89c=rP)LRp)<Su8fe9dql2uj7(2aEgrlZReT8|-j^U_
zZ|`!?X4&T`plq!{QEGSuk`;z?j*+pC7AU?!AaaUIP5LsNPQFvt5_FJb<A}|f6>KRC
zBF0VHA}){0{A@ILy%b#^zDc@(cyj$EJr3OEzKD4tDJinZc0`jPEmd{*Be(0Ux@$V{
zTXIN}s}!@W6f=(uGlNr5xS(R!@XvBE(elc4yD*}G;%Jm{<V!{H(7`!~)pFH2Rtn`!
zAeNFAD|Vka?V)W1{tKUXKTp-DjC@jrX>vzQ^KnSZX1ex_X$#FFQ?^_|`@lb%<C7B{
z&0<7fuAp9dUs^VUn8f(XWXDD+1e($>2#N*pK>EewFXw2>Yv|`=h;Gy$TtOQIMHrxf
z#y|dh)=&E5ck$#s#$3TK0lk-l#fXk|QFevj*PN=d7hPX<hAJ~6qdHaHVNTKu)l|0-
z5@9l({4+|XoY4|FB#6bB`{bxZmE!EXl&={ai~wDY4E!-4N0W@6e9w~Ubv%qL>KO0&
z;_OP%f;(Y2>j4H>oeu^Ps{IsW>QkIX)Bv3eCsT?>W$$xn>k(KN8b<L}9yhI(M-rPx
zfx_4fM8I453yjOY_lffxpfA%;J`I-EeeM)~j6}O)wSweAO`HdFhs9S)>ouN67<Pw8
zcE*#BA@D+oq24hWWf_Ud{lFxvX$$yB|K4MuBTx;~EHKa!=`wK#3djGf+MgzAd^y2O
z*9j$CU=x(I$04|Xa?<KBoen<W6&>LZqKiC=#Iqq^4-KK2pp4ns-g(^#5B85blt!W%
zNGJ@{aCk5y1ACMaPv#XE?lifjHGec+0~H)J6jV6Bk&m23S7@d*G!#3r*|vlx8XLFR
zK#(M!Wz!^G<72&<nhhP5HGE}@RJjq1a`-5TEAG%$r~P1rH{VGx#v4X4pz~;e`O*<1
zO!N)IlY%4VKoz9-4z3~)Dd*GqWY|w)SZ*Zu)Vn0YS7PEOZV0}Y+_txUcF>~?5NF-f
zUV}Y|JabFA2WXVQS%N=^`^BmtH8;7Yd`)_iN&TPn$5GQHmT+X0OlMkzD0ct$!Tzfw
zS*e6y2$MP-BXA3L54RU)8t)-lCGBxpYDpyLMGA>EXeK3b&suE!ZBW(K7b3fjKZ}Wk
zh(V&SbyTh4Ill{hpax^GZGcsS^_y=W1Rzsxo^0l(p&(_7bytVd!gKDobENS-L-n<s
zoc_SPJ7zAh1d^Wa`$&&gWot0RG!v+<Zm)9kX+M-dGT|p9zs8v)SuBZ9ik?uQe%Hlf
z5};5CD_JBwa~~k;B0=9<R<9oDN@}5FO}u#_=75h6w&addwxtq}JQN$`qWb|G2AKb4
zrc>;iOfR<R*SWQX^xq{>N&yh~(op2JYAPW-pUqJBoy|ruNNkkBLjGc5oav20v{Vx!
zJ~NkIaUx)^WfO|&K%uVu*ulc)ZIytF>nQs$R>K42mYD~#NS6|gW%7cm+y>@jkXM#Z
z>e7nr?0X`y=~jz%ajS0_1J;S0l<Vrt-4Jt;VNIfyCr2{iqVgk`t^i(?{v^p7NKJh&
z`#040GLODjW~;C+9WA*l?+uN+$n4GvVfI-HVfOh7VfHx+VOFUSW~B<Dd;9582$yu3
zTl<lZpi&FV?okWNK1&PB?nw))m??{$)V`S&X<?bt!sN;@ugwdzu*}lJ{0Yb;#Bwbx
zTT~14ch>lmcmfFWW@U<C_P;|BEWDIbxpO^=pp#nro7`gga+$lojzZY0PzW<eA<SHb
zFt_LW6vEp3K~5pezP3V``4mF_N{Q69j+nVRqW>z;&=Ip5I$~C$BW6Aw(aaQ<-J_0}
zRqBX~seU<L&pt!-D>%wB-O4@VVQ7qpeQ_`aIjV}pg-3}mfJ~+4y)i02Ps&vgJbb7T
zVKb+EoGQY}VH8Wr2E?oUI#pS6QN_U3fd8T#V2z_d*<OE-bErBjKA76t;>rVi)DKuy
zl&@Lo!InocR3_YV8p!+8QbNmJEx+oW=vD=NeN##ABwE!jJNyDz-FW2zZY>+p!8Ac>
z+qPIpUFH<{Y7nDCPn;!O^_o!nE0ytD>E>9|nMD}|tZW9{oNak3Vl7RX7xo~;6zR1S
zeF{IO=E#FpXV_R@M9ad?zqgCcz*)wS2(0iOE9FgEY<HaX=W5pfpb3Vl#Vw=&=@N61
ztr%1;7-KT(NYCtRNzW`VJ$?Q`#Y)&$m7ZB`>6w*E&+J~LXO0GC(lh%!>6v|&^vv>$
zEBoBV<!afyxH7r8mJCCO6rPzOJhQtAPuD^As|wGoTzF>ngr~^~S*h@>m~<^X|A6@|
z6rNeJ@XUO|vwFD{%T6O?n{xaNr%B#_vgG6}Ot1R6d*Gfz@6qO{pJLyHcq&4}1kHe1
zmX(z0Ly3NxwUzT9P~Kl<2^saVO~io=PU)lv%!^L@=N#QwTv7ZW52dN_<j@j^-{{FZ
zT^n`5m3H_+owt>3Z*^O+MZk1~^PV*Lagz<T!ZmMCymZook~bgR|Feql{w_-H_Dz0i
zUlb+sq(-8t{>^YKrX5x|f5O4rzJ9`Y<3R^qWF}E2f?(s6>a%g~(W*3)ePlD)N02Bv
zz79TqpAR+ZyX<5eYg1ooknME0bGjp~ru<_p<xp8#Rs=>3f6yKd+opQ0OPXE<Y23l*
z7H;w2vp;0;E?*ey-&gC|vX5}jmY2wg(J1G442hU$NKa$m`dv4z40$)xyklz}KY5dQ
z$j7u3@NYCVXuy;q_wJg~&V831Ixba><$NS-U9G@XOB{|o;Do=YKNq;^>t5$|f{IC{
zJIZR~?Q^IVdWi>|iFe7Hr$SwX@y-<9zA$>~o-`cvM}rmnqHl(7>W{`VLlJnSTi6FF
zH0NW1IG||tU_J&_AWUb`Al-6LOu{vZthyjIK24JkK{UC<0DP1sK*dU?1sZGy+3hSI
zVB`Y;7hectC^?3*mr{Ij5m8DWK;;7CAmA~H{4D$M_aGCQE^mTapX35w5cgFA%o_rt
zxAio-MCZ!B$cF%RL7}-!rj!>Q7F{$%*U1<c-yn*wBj|1zQQA%s-F?Ky+N*dLoWt;<
z2;(+KW6EZb1{YJ1sh`qkRGB5$jiMp_{aZkh;GoNp9_2!N^BZs!ph(SEeLug|`9{r2
zq;CFf-jGvI{PSe}=a=GF`K|R>w`&)+Yv<Z+v~;^xVY`i7yC)mE-Q!l<YWSN3z4o}E
z-47^_i1YbATX7+9ra^O#0|jfvLyo5W-1dKN`9C|j!j6J`Z!Q)zcdJnBD-_e=LxxM2
z#6g%$r(>$OGM+Vp)n(y<e)4ng5P`n#Z0~lDj}KMQ9~1IVUe^b|Z>+ga109dbCQ!q3
z=VvW&E!J|#ym;<XI~EQ~ONLMhJhe!~sX&3hJ4s=^Qtcz{lVLKSphYDlzr}L<knE3D
z3HO5VUP6~(1sWMXy9X5sRy6%CZ$_X@ecLj8pD&U=j6v{<acmlAb9otpZuQ4+I$dN3
zQ_7Cx2|dX_AEt)9#U|Rtz!AI@Sr!B<C<k~UmFn!qBKke&EaSLL95soWgBaA!Ft&{n
ztT3n)#Aeh-eIvW-PZY5U$oU*PM9Y&brSTe~o6{v{Nenglwrvdf#IsQpyxdJWBK|HR
z6%6_lL`VcOp&0pToXtrLo57pD(G#SQhPgr0fkEvT3Q_M<C5@(_0~&BXF^1<%NI7aF
z_9P9_V0b`B(+vPkFD}*|m?tRxcu%Sx2Ir^;UxRC8o)l-Bku|1XAHt>U?Jr@sv)w%m
zd#}5l)7M7OKfjNzVKSl{+Mi6u3V!=-nOn=^Z_B&$zCQ!--J5_%Mcf0VU{7QbxpOIa
zpm%2N>VWl<=;J(26yas{^Z4>o@)Y1J9h(8=XZYxrUX#e|MzYN?#wQe%)f-hsip>BJ
zk|@1;rc;EN!*5m$);41r?=WkKF+=AskzqL>EfzG`DtLtdWwTACZYP}~Y!`_~Y7L+a
zbZjVc#$V`A1?o_SF$^`s<PUAcHy*YjCm>zTxAcyf5mvsPH;@}#4`le?<hnnKWjZ@4
z#7h?y5{f+~lPTtSP%(9=Ymk%^#i*01)t`ES+Z1Xgr*0Jas>ITNfM917pmZ1*y{xnv
zi10;xL)zqnhGm{|^>dsrH6PwUxWKfe_kS1AnGMwkmQh43A*iCsbbfjDjo|tRz|Aqn
z6Z5oCNpVW`60YM@HeiD)Qdf$nLJMa)!lN@nG|WG8_3!dX2F0^YYwpY5zpD560-EsX
zz~i_O$Aynw^$PZfw)I7|l^%Te5z-b`Uu(UsW7;b3Ks%sq=V({P+b;=dYr0hE2+AHm
zimi&MwH6?q?OKGf%|)BlSg#gi?F%-m@hOTgn-{2yIE;DaBU!+`E@L&tvEjt)2;@J7
z08&7$zt36W;{!u8mlpLK5Mx<#i$cmavRi94zm<ut>!KN;R8yXK51sQyVLG>>H-ME-
zABr2{x-KmJ%3f|YUOWijwlDJ9ffkzU@QgmR;%dY4t0kve^{A=X+0FktVTR)lv-6SS
zSM^0!8J~x=KAr=wY%SZtwpcsEW3<}B&F>fhH~6n*vY6#dpXC(Zy>6!?bT{>&!uNhc
z>kC$irme3ToG-qqb?>C-Lu(!qmWcc5hOCvRhN=f2JP~@)-pgA(f~KBdXg5TU3%_FT
z^b;}6gQg`zlr7)ux$k?zY4mqj*L~n!fsJ6_T2Jsi%>4xe!`(4%U!C_o!Y;4}l%UBu
z*%KF*O+23B8UD?|_K`Z5z5X>keZ9Ze3%6l&-rYal+3xO!hsV1ej+#to{%g#{`U!()
z4*JP3<oLH(!uyKg9g(*V`4|pigDXr;E@CfB-`A5j`@5@TN<{^E7A497mYT^#ve0~%
zOz{mnpWaRmca03|YkF*N^w>UKMR;F@9<&HXKB7k;)Gbt;f!f6{V5f|}?VJOL51^IE
z{YT`PM45=kDtq2$Gl(_`1A@@V288M1qY*a1;anxCp9`yWJUXA=kkq}1C&0Y70@B3@
z&a;%%ohA}}W5erFA5IDvmsX%^l@<<9WT;zHEy7j?tUfK8(T0>Lo(bj4PEY3)^8sKl
z8<%n-AxXE#FFlZ-MCfrtku2=Ueym2j10zr*OS^A(!|mNS;lcLbkIz7E{TF#7gSfXK
z`P`N7>$w_g24zpw>UP26u;@U6Ud|@StEi8$5HA@l-am|@z=d!1FI8~;6bGa|p3@Lz
z|ARVP2^4-m52+q!{Xzz?ynY<r(x^q)TOdGWR|6P^l=dnu0y4a~sRW|xG}Nn??oNP1
z#G?$weurgA5wvlS0KIE6#9f9D`B?EXyHd-{7o<12p&;KdSEFek<jX@90|jUd+;VUX
zWd6AWyFT=+mf9d02tte6oi3J#2c08lt>~KTN>@3bk3P`VpGaxFUc=wLOy|ARLq~lJ
z4e$&LD~6UTI(L1kgAY4TSq!{xkJ&N-D`8VS4EL(EXcV%HkA9LX5IGOCY<>AtpYK#h
zb_aR(UM#eV3aMf|M?@zNZGI>Wup;Xy&yO4DeTZg5Syjbsa%WS9TFK3_Be<}=SUmZ<
zxY7>yj~w92<<$WtLwrd;0C^UuvD#s4?e#icW&EtZ&w&$+ja9=wr8?Zp+ZbS{uR3Xt
zA8D@;bz}%>D@}1@so-bl@{}NQV|8gtc0S6Eb<k$1)%1Q14-R%u3W~P7ZplWtfAVJ2
z`w`7UzJe#-kDl6_;r^>bw?p{2<N0{H)60MC?c~3mxr6JS9UXNJ!dKmn{e2%kcME7G
z%6x-2i=LFU%8%D-Sy=2Dfhx(3SC!<+ql)t66cl;$7L-75$<dn}wa$)yK05yOh%V3z
z__05{hV#$ube@HGWlc=ocKY|Do%`clvUm#Q3;D93!e+SF-F}t(cyxT^{hph*0uJ@E
za?O=c#LW8p(YBwjs`<Q_5;@K-t>z<J2{)=DFI~Uhs&F{`ezQlIz6G9J<1`-Qb-J}F
z6*tj44qffnY$dO!7p)(r*OB%qse9rxA3o#+gQ*ILI;z09)L{!sVSM<>bP{Is2^{@H
zWw5l)7~(6%ihTryw3ouapfzvM*LUkOE}|_>g5QFiAlY)7wrV$h;x=vjo1zSJt8Ugu
z5Z9&K{BeCGea)W~Ac}IBUNTeVO+PJZ$!<B7T&mIPbt^ga(X!30xRHZ~E8eZ;(vXF%
zTgxRCi-@xH1b1V-7+NJ^0R!5yI{1zB-vV*H<ptQfGr%Wgh(zznM0?cmx}@_r^%DS(
z{?LX0@SFF1|IXYAq3XwVV}ZJxcPEs|**4I}cPADDwW0bKg1Lijc^mlWOfHS;If0dt
zn-2d{@{`!Vnyg*479O~)iV)dc01^MR$OS2yOg}@0Pd`J5PwR2|v>uaBKU2_8?=0yR
z06*8}@GKPIz}8kT=IJ8W+%MYcyip=*T?L|A)aqmROx)@c9`uLw?U+thS%wD(ZGJ_B
zrA0g;c4w~RZantJC@MWIs3Z?Lc|7({t~X6geq4+x<fH}CAuxBAQMk1Vkh>dbp}A}5
zf4fiUX9i8%3#|5P$Shz5<odFp3bLiJ2<Qbm-`(&Q5?O#QV8*+F7OIf|y`WU808Qds
z>>~l*)QTMhHk6az2}c~KCGdTKLPalxc75qqm!CML4|cY?`T}>*A9{GAn*Km?%k2C9
zc-cCnZ&hG`9}l;83`{oekM}K1toF7JR7od^CI0J3uZ=IUpvuwpG%d7n6xVe`<;MLj
z-LE|kS1xbdpQ!lSLoqjjjr$WzUwatlj<a!pQtfLG!#WZeqWrs590d+GQL3v0ff#Us
zJ>gF>U_CMSr+0nriIGR7MTGVfbBeyuZg=;gKe?08-u(J|<$aCA722DBx_z|vP)wn{
z`KQ}PYY)Q|+M9p6EwuJ9?k2Q1|8$$}6R*(T{L}5GwI{|9+O{#kl+3Nx0>&zD&t>L-
zR{hmk2YAjP(5k;|>cBSzORH6%L+ijcS9`0qpk1vDw#O{cYSmYX>fmk}23iZ)kLm!o
zOarY2EJ(G0E91Z^#+K-FUN6%u@FZszXf0r8s?AkWcY0D~7-%hEcv*lqOw&LC4tdi+
zYXM8mVz|^Y4piXjF%GmAFzMVI!oIfET6U$b*=pb8BL4bg$;s;WJ&KL5KOAdoXy2od
z`uan$cA^FBkblCV+)ejvEnxEeV+O6~X908PpKyL`yFop9ZfU0rm=?d<@GCnikmn27
z7ypD~$;tBt?2LcH;aKu~0Sn@va442MU%<%tCmhOM<@uj*KlYmwS_@c0|Ah0SeAgUL
z3Uv3B4r_&J&hF(Ukn5HacpjIlM`Q4p`B049I2tO|Qn9xu*4r{`RoBS*l5h<({?7>G
zaG7t9hWMnIo>yjrxFClzCtWZ?N}SIxf=A<X8Er!Q$&cC_n-mDZiB(}Frh+bU68<`j
zE)W-fBiiepP}c6V)9~o*aA|4%W^>uDa&*kK=ym6tgI%n%ZdYLrv1_g0wCqa9XFX4)
zw&7NT;lO6}dT%bnN{R?7^d1!-;urzXPUFb{K>r$y;&Ggbppp2x7HJw}{Yw!ek|Xw<
zM=%Fzgb!pew#PK+zU8OHI_MMygCraX3_`d_repCmuqodD>Q}|X2-tTF;}dUp5lMVX
z_~|Of1iH{1qnhE2^#_A#LeC803&N&{$kt<Ff`RXW346kVg8~38){4R%n$#fy^ZuQ0
zR^^Kc{Qr`7PMfO4GfTSAGtZ?hq3ri&&5rL<;=yN`gZQxAP~0S66{COoMI4QWE5>@^
zN3w5s8BlNg)k%0LBl6>qr~H)O&}z2ChiS$%6ufzU|IWk--@c`v;tY6Y#Q;TK@dJFs
z>mB?vKx}+2o_mAf5Dy>K>pi2XhdQ$LbQE5U`j=_&n|LLMah&$>NgKrk_|5YX0qvih
zbTAa5ivfzJQH1hrFq?<1Co3Ro@D;!s*Xdt23Q+X$%-2S7nuUHWMTo>og8yD1=937Y
zl+H0W07usvMU$1BELU+KJaS&feelH=q6*2)xEU1h9HN<u^CPiP&Wumtqke8|zCKp(
zOhl95r{}V!c-(2k4x=a-fG5y&Of*!3q9>y8Z@RjQ-{pXKqnB|?bf8pEIR!^ukw~uU
zF*Iy|q%G=TK7o2sJud1@ccDh+*|BppS5JpI{t3q<F5bR<0rp1mhiG)W;(6JPac#_?
zNLGz^tE>4Y?{!cnBjywdI;^*1M%ro0s01QffC8kX9WBb2X9qur+Xn~7JG{PN2a$nU
zB<4}ZPjuBo-~1ExB2Zh44$qiO(M-%mnDjq|Dmj%JWtH9q8rm$xXmC(vJPSFj=z{v!
zT*UiQ(HIJ~En9ts#<PopM_(s<D>9UlOqlUxGvxF^glbNTJ=tU_rfQIOi`bQk&;3rP
z(|Y{$X^8hAt{7E?y+eu+s$OSlf?<$_+X({aFigk+j}(;MzaQ=GcMf(}h)99c78~OB
zD<WMG->K=;)w1AG1HG%|2bSmVunO@K558s`%E_dk0Z~NuLs_uweK;r9iev_*a_9Ns
z5x;j!brmzb9F`C#lrjrvUkw5{{C3}RzTg##aY&k9IiJn8s8eV<n?lDNO_k!>%o7Tn
z&NY813mgzg5GpH%Tc3hC1&>5nrY&z_a^s%ZsB6G+%L<^tbeoLNMZX33V?q|L`h%xA
z$aeFTa6aUSH6rp|{$yl+1U@o8(K^GhY9eQ^lOpGQnESS6htH#cONNxEIzm&BFaj0v
ziKDF$mFa_ut0iMZ3HpAr3N+!VL;2YVPK7<g;RD!&)2d@2Z^3^;P7iSrJQQ8LBRCX-
z!K7VI%xtt#%*;qzGApX^oAZg-7rt4s06h#|?)O%d`V7il__ER9SDYgBH)BO(8P49h
z%~x9U;HRGg7Xm8<z%l-E+7g$5xdI)i(AunJ#4ihXsxP8pxXH3qP%Zqb!)}>TxVEGy
zGb4t}IN@t5{sjp-M&^Qomr-(LD-t^5E?9;OVNv0%iTO8Xjeg@g)=&h0NCr_6;Kcjc
z8yVF@rm~tP(M1I3ko6V2k2S<rQA&V)D9O!ng-*Jiy-shZ_c}b>KK;32q~>x!J6zY;
z@>H?A*IC41r4zX$+~nsMTT-!8yMffnWexa%!e!Z|Oc{IjP8EkP8)-wl+5+hXq<tgb
za#AoUKcpt6qUvJW?oga2kj+FyKU`5peOzg<;9%Lowk}~ARh`ABCs1j)u%}Anq7#`{
z5lkkW$fYN6k49_Iov19=+md}g$m`Z-54y)Gg}`%{3YA^;)2p>4O$#Ir;sB)~R%_(v
zJg3-nPfx?w+Zf?-fmuH|JESR>>1HHa7sEJNyMoi+vW%4MBhkfBL@lgDZf|$Lo71-N
zW4OP|d@ewU0~64srN(R>Zk8$4;lZ?z5j)5I7^Br1RxFD5jD{p=lk^7|1rKB2^)V<S
zs$MB4MpV0E3Gr1O8ll)SOX`an@)#|}FRvL8XIN+~9dlZmf!&!c&!ViMvpOM%MM<KW
zU!;8zPx9ot#lyES#!{Dt!AIk{EE5R1U`pTEHEPVasby0?UaPMrhJoHgJUYmE-k%I$
zmMQzqZ5E{%+@3Tfl^oa#&$h;uzIPWRZx*Ntyrb>l`|mjl7%EUk)*(UKXP)!DJlhup
z#gsZwJ}~C@&rL1L45O;+ya=ps9LCiQmzu<sO!G3F&axFZEM7CnL9~LVx<NXPU=Tu=
z^PdImh!~#Zz*6~9VCg@{fC5{WuTYwDzV`W{;JWJ0CkxEsWaP{Glbtro4i9%YiI`Dq
z^Py~^f)Tnl7tZ$I^SFYyPk2{@SJcF8u*YJWFd1W3<^)Tp7a67E!M#}J<(Xb^YfdhP
zH0=|Yitv;1#Fsbi8MkSz1+NS8`w+=Tw*d*tl!Ns$L=^6@Dj5R&hzlqYCYjd@#n#2I
z-yuhS$9jTXL*1L;B^{d-h+U;@G=mh=p$<o=TZ~5BG01LEbg}uYpQLo@g@JNKV>Qsh
zXg-Yiz7Df`h)(HhuBuxk(-cNcqt)Sq*SKnXO(qV4IUA-5+U|F$(-jqsrqdZEU%>eF
zsxuu$Shk|5$=p7}i^6`2nF7T0A>DBDv#BODz$W#cdTR!QQPfY|@iv3Yi1XJ?u{+fm
z`7s%*aKy%Z!c0lB%0W?6q1-hU2oYCU5a}FRvq)6wcBpx32Us>|N?dn}`S3=P#iR^z
znsF`0Sv8j|FJ@(*sog)H>b1hxwbNu6k#wQtK){so7!L~lNwyaJ3Y<Dm1^13IGiizm
zVY91#7VMmy(F}X(z^MlN7o43+42mjJH#h@~m|D!ZQW5m0X+SC<rl5&dC34STA&qD8
zh`369<s5|wfRWJ!^U08V4z|08*G~cT;0oqp09uEn2rTDM5k{ibR%E(V?vH{`adzeH
z5M!kWx6`?z@&GT3BS8@%D1RWq$ye_~h9!H@OXL$qy&jK=Oo)RJ2<QDIiFrOXCNMbF
zp@j@)`QrH5DTS`TiZ8EBvcjZOWy<w99bNN!$6DM3XgnuYwtH^^b_@V9qx58WsNulf
z(PVHdpq3F?EClrTk8b*C&wZxGfa?pk{q@$f0E2o4+qsgqD0vzDv?_};68KbVc@{)B
z(O`}_bcxvnWQ)0`d}U91M&W3Ppn@S3$8t7F;xrOBcn~nhaYx&kY;OEO^`Cxn4QX8U
zjHc*vFwiVnN_nvhP*8M+0LVw<bKtZA-j$2_u(M@SlFn%sJu5&wh(6ANAJ=bM>)v?;
zLHnuwq#3-sX}6ofU(rW9SY0LgU=qeR)3`x@T5oduzhVyow#5Tv;1Jc@{l+tpO6Lq>
zT|<x{oQd(1zvKtO!L<4N-h76eOmGAJ(!lYTQ926#`dD^9n9got@y(L~??*WhkCA#a
zXb!D6kbvv&b9J7;5Hqt*`)^3($4}m4H`oJ7;CJi6{{*ea?_cHs{3trv1OShz6KLOh
zlJDuM=t))No_=gQJ++=dR~s$am0p~W|7ZQFSX>z1|7M*xa5%BS?_7{!0nGMyDK{3y
z2m`)SB3Ss<HcwF6LEPZf3g)(+WxQr`Gbjzlp3`)>!MpC9Me3_!NuYm5$&_{mbNhxL
zEi({-!4yt`gUpmnr&B}X6pAGxEG{Gv*DR>HwXs*gmYv|nE_3FBN=6FIWFWSjAO6&a
z{(^*`rqPlUmfFFr|6|O*H)DR@Zts}WE%SJVeZ9(R?pWXTQCtwmIMtfDXPnb6+0Hz!
zF4A(#ZVOIJRZFl+&Vfb1{e5B6zG;XruvUxgTVj;ur{BGfVHUSe@ndc7ww-S5{N=xY
z*~=HhZ%SXmm}hguS!N6uM<^kkhT<%>W+Z(ePfsD%xQ#Ta;}LA!zomn8A0(m7C($%p
zbIKcT54r#w-s22}GA8!Ie7h)Hp{ACG221E$nX0Q8XOwX&H>*0M6{&s!e{L^xO`%WX
zOdA2@!A<I!tHG%pk!UWnWRQ0(xynv6(9NtA8f&Vx=+?q;GBOBC`|j2B|7Y)CyW6;x
zL}7ToO24A*S#~6wmL=Ko&aq<ehn6UtE4qcG9Oq=bdQoIk;x=z#H*I+)ncx1RE&vK>
zbh9bR*?Z1AUWqL=fC5k`6bgm9j0iR)<$x=$R#~Xo03tz&OPUKbs7=#pZ`kF`!5(;=
zsS8059CEae(y8t{F<Jn{w>}T2i!>s$6}^TG0Xv{MBQUsqDrnG$MS@;pQ%j%44s3ZG
z=68_C`9(I6*T&i^L^)4<>phHt9I!tW+s0TI>W9qVIV-5-CYEi>Uc+yCqQ<H(d!ng$
z)4lWOJ%5BNKk|jfd4s1u^_Nx?=Pi?6xzo(#ZR-?s4QbotwJ1>5HV3?cf6t!bl}3Nm
zI`yZTrBgh!{!<NBsJCe%|J;W}LC+4}7)3XFRFsrn<!O=nS}S{CECTsgJ~PU#zv5%#
zlDEb@Ln?Z4lurX|fs}U@-y%)R%>p=8UMc;odva`{)O+&T;(zQjCq81vF<|tIx}<2E
z*xxB8KW5OS(!~UGWR==AQySg?I7$XfFgcok2x`zpOr&A#w9n6+$Ju;WGN*vs2R+wj
zuJvZoD1vsJPUYZJZZ1#s@<Br4g9-zURvm1v!SVsi6v~*Y0sT+P@&?rky3pyI#8^BC
z7Jl>yy<Bn`h`0f42Fk6>ZL-Lul3)g*DpSroepCH3qMGolO%L;5;dB_awfk+wzg6=#
z{(e6q52eCP7@~px9%!SNx3;!+|9#SfN2-%#I=QbfQCJs9p=PSLKPONdtN#f+rU(n#
zS5hX~u<yaD)aG7yvRMyJYA^C(iH6aSc$yqEk2eGcH&uyF;RSrm$>bq1J^Z+3%2>ik
zCo^^D&juT?#t?xWju`g8w4XL>(ftQ0C!zO2n$wz3{%v2SA{pD9vw<@uT}-DVo2H#r
z0uCF3&4x~pYG(XGvH>`#xAxzuzm8u#-(>Es2v;@C5Yo7N4dkN)jA8a=*w3yuHW_#C
z8~Yt4dL19cJG(y!&kdcCQiB5d21Pt|jK|3Y99XI2{j>AKqx#$Uq;Yy8T|X$}*S|w{
z!oj)+wP?bMo|aBjNzifoy_)d;QRAjl-TnT>ZKkTaUwx+TZm@HPgKshE!8QHPJ&%pC
zhRObxs~pM*sanFiL_l|-9sH8?)h1ADV}C)`qkot6dHG<gieIJdnLAlwhN!9Aqc#jx
zwUH1WK8#8?25dPo#*)^O%CMC)8P)J!Q69U84^f@FQJze%vwsGc5IrZ6@0Qm(z5;fp
zv)ndM<HPfl{rFw;qysbxV-;u+gqG*Pdn*A~bPK=*mP&yGqE_snd3<(6eK<HR?uP2E
z*316s@v-7HA(-yTr*Xd`Hdh_{`tor|e=gqpT3*5(NV~%E;iCLno-@4W4B0hh?}Wee
zmU^K1tJyCgn$1&|*1g(LCS-Zh3Uc`R&h{NpV#r+d@!R^@+7HsW%k&dDU<Yvb5MT7t
z@MzV|0y{Xavm*bX(cXu|(7K$TPL7)=PC2FQ(v==irTS6xt*92tyUs==8xIznsOq{F
z2FR$A98U1Li;j5RftzJr%P4r7>uG~wI_2GzNGCtDzq5wfFMR2ywI?JKe!)V`BFzCV
zzX!m};(P~U3H8BehVwXbL2K-a)p%gn*(`#X>?>38NeSJUmQHuo+J@HD!6~k+hX(wn
zq2I@ay<b29AZ5b&@an;W?gsD!?or(k-plSWc@z=7*@}=U)yZy8?O=-)k`ydTa5e3l
z*3(DPA!v<JwcNQjMku7C7O$GUZV$~?)c%AV=%l{)c4Q<mZ)T*mPPy8zU-4B*FVbPX
z-JxZwV}97jWkiRXA-D5f59G74Rsf%|<nT67kcfdl@(~v~49LApiWEEAMOrnVEz&EL
z8HiP9YSBTHQGC73-6%sm^z2+wF{fW|o}QrQ6M~ZLY^y)v+CQH+_kW5HPET8J8b?Q*
z(|zs5^Kk96{bu~8-in(i2aOMFYtPpmE8$sh$S=gvBmS9n)!@(zj=cL#PTz>Nv@<U_
z+h26&^j=%spNMeM1koKk(sG!hQot!$AP%!MQcc0QZ~pvyG?a^y>tUMJ(4^(y?BFK^
zGnjYB30jMy(ZG1zr2r??jD<mX2vNYmH17iJ%e$8eh8<ZK#(UU+>?BZG7F~5mgNW=R
zqSkc35pA>%j_VX$b$>ch|6GCzkb=+v+q_AVZPM5P1euOHFix8LwJ1R&K()TnwAWkA
zzD6&e|MbR=1>W|4Uknv1=})Kgi$u+6H0|M2P&ZR`-$dkFtY3Bj5SS^VeJJi-Cfp5D
zB5d*+K6$P7KO{3pQ<>jrr9N)q8}Vb<OB>}C@sZ|rw6jUI%ZOFY!sOG=R}Rvu7j{YS
zEeJkT`Py^il%v+~z-GXjqn_0Ku8w;xliVxJ=E*Y@mp_vJK)bpT=wovkA3>h64I|_o
z^CszawK)sEeyFpF$Q)k&E~bkt`r+*xEUKyfgAcnIn3Z-F5rL)ha7@vB!2WT{cDI*`
z-1QcL4akPx7%qsn6_{8KhSMjCM9>gtkrEiNQbrpzW2B5RfuP4vupdSd>RhQ43Tvfy
z=M0Q)U_ao{5fBqIthd;l(FxiZ+0CqG3Ed$eZJf#W*!c80igxraP%Ea;&g%%=OHo;T
z-fkRhsFKZa-ZZ@wOuZ$<hbMGUKj@HTW>m@<hswAcf~`o0C<bJpKi4xOeFdJUq}7md
zUe>AZaB3*fAzV8ADiJL|8JSaVZ@pj`Ch>dz;zQc{<wvO!lWO_<4T~R+hA^Gt(-fGg
zExk6~N~wY)ajsRKu(?-22o&t?>Wf#d>2WZPe%GEhg=EIMQuPhJmH53}xYLLi$Iva4
zZ<T|Z#HG=DKXj+{(7zzE(292kbsSppRm6u8xYGkje^U)V!eg$rM{-9vPew^MO^O?%
ztXvG*c{?L4Zm9zGUH!dhJ{cNO1?Fd4tYu&$4cj7qM7@s=E**9+yKl?ESS+4^z051R
zji}%6)5g%tLAG}4L#%{|80@zGQ*l^21|I%y9(n<X*eZuDzU|N*<PdH4fFUDXkpEFQ
zQ45vKmDmrW415DltS&e(o_qJ*8^_7%apPF>h764J)b#;$7m9tN>dst4+!8y`P_u^*
zqhbaIg5sGH7+N1T<?~^8KB2puh7}PkZRkS~lKvLWqHw^P_tC8EHi0E4U4G8zZxhZ;
zHc-s2^~z_$Ta2Ik|8q=>NVKzIs3HA=2)<u)Hl{IkK>cxj|6L<KYMwMuimF-q+myI8
z{S~c#Zsp-p$Cp1|YaR_RcX*>^Y+PDQ48#f5-x?L}YxK7N8C--WvLJ)!<QPu$uW%N)
z_*M7J9Z}J}s^!?Jt|o7L@>g92FT>?ah3}78uREW2zw$edOBwc^(ojZDjkZ>8QSX^?
zg_d%VUrM!p-VkrOjyB?lV4v3TiDl12MLLM0vqQeNq01PEU>LCuA3xPreD_P-e%Czg
z#PySd_@LR|ueT23<I{siZCzWk>(GJe)o_r-aMdI6j}9?LG1(mA&Q>=zb(xu{%ND`7
zU@;iNOg>>x3@d`BAlgDRh-3+vyGUFwu(RU>ij9dLU|V)(@9oU2gPaYBsU>5KZb^pZ
zDT~4ECL{u0f@rQV#bPibN8JxWe$n05>7vNdHE9y6g$qR?w4aQi0nFuUK3!a1k)5C-
zjEm_ta&-2EV@QKh(#z2D57!WlhR{@|H@MW&vC*dw)A;iMly{(n!devXk%iKB(PD0D
z2Af;UR|qQ5HHg~)StxGKPFtP$O}*Wq_=b&>`kNz2^uhtriaO8?9LwQF598dXQ{W~P
zoehSNFVIaiit#yzL{KC8!k9_yMQL|KU!wt{E`H4Nt$8!bexH$D3tr7PKnU90t0qpH
z4x9lz)(3-Dp`pH73HF_O^9b(R2K;z9L22CB*y7ZkkA^)eL~t}usHA_@#f$zd?tMxZ
zV_C`lxMzY7Kg>LHDH)2`lTAe}M2iEWKe%2Bz|^7m#>|lR;l5XJZ)0yY@(=;>Un~N-
z$1)G0+b7+WL9avZq<9zgo9Mk$bX7z#4R0gFa@WzYD^<5$#kfDk@Ylvez$yF$cqkKA
zNsxB{EG9V+#ac>pnZjdIO?0F<S16ie{)#GZFnDz9b31>S?*(cDV~+gV<bW^hnuFie
z6(93;)n>-ckP{R3f)N^!>OR2+fLoQ6n|^a<^>Hr{j^PoD_z%swUe?Zyn<$+AH|}9*
z3xKed&EkPt%AVqeYKmP25k2Kx&ySrK8^*Y|BR%x#WmzKl-Ya)?NOWKq6FYh9f&vU5
zJ!FKtiyz+9c+jl*5QGII8pXoA$iu_dG{4(X*($uQ@PP;864&cjcAa^MKJ}5I3@?pb
z8E?e8)JAd8Mm0fU)afQ9m`2g7$RSOst)P=6zMM~kud`_PzyWDxxjGJGv^2&@$#HKC
zkyn!6Jz`X!i6EKI#U0+1qn3m@EL7WgNN-9Me)w!3ZKvNhP8zM|e!PEra@c%Zqw|wO
zJj2~{W7*I)0VW1{BbK8u1XYYnheN{Z>))fD=p`yH9c=@RchX16mdCl{X$xHG_d#ky
zOQ?xNBn{Wt5bS||fW<EFlTzuv>iK?unBvb^Q}Rh|P-SfclQf&o6Pz+EW?&f&Q*>-)
zv{efs!d)F<Ph;QqO3Y~tGAmh*sJVj7qUNdPAc<p3kbpsgT#94HfQx7)?JC?Cpqqzl
zP~Mj~?-wK8jah4LyFg4)a;TC=^4F`ewCmg$OJjYo{0BXPG$4N{?Z-h}QYdSqv=llX
zQxM%!ck9{{pk`I|v+h@Pi3-Kop$N!EAuA>Wh3;Db+8ZJ)2sn+l?`A%3O?z@cQifj2
z#_s79rMy4<efMnFJvut=Q#d;I1fa2TS8=whH;B^U!Vm-{R@W@zG(}h|L=p|9FovKG
z!DU7ayh1yX<i{;eFysD%7?&Ud=WY&n1;=ifWDo^pN}of5BTCf*L9C=^x)@EC)mT>{
z$4x>$OkMToEaH2_il+n>>h_~u{OvLS_RRV1IfKz{9;<Vqcw13!7V@G+%Mvj0z%eeA
z+#S0;@i*%4B_8Cw3EVht(GxKpvxHPN9;mZ$I*X^H=e;yY|5VT9Ezx_MXi{%rA~Ab~
zpvYmPuQkj5`qLzxd}q{&>grArStb}eWz_we%u~{MFt^qZSe@&rKLi(axVOVC4juFZ
z@s768F&&=QoQO3D2LPwWYY%;C;LU3WN?RSu2t15uqebckyn&{qj-YWtRWqw}(Ypdi
zP1Ic^nL<f&-6O@umub!E4PMb%%@T2P2bjv7quC5ELEE4)kZTF8@FF$LGJYHv<JgLR
z(epk#q`?f+h>sDd*i)A}j;R#Y&zg}oenmi_J@3o6AY5hSjG!gZV|*WkjJ}_0F%Xi~
z%#fOgbTS;U2gsG?7s#@r)0@x(WoH_7@gi^3U<xH2X)Oe!&=<>0O&#=4syRN-YPVX#
zwPK9c-*Yxihe$}h(KJo;*XCIS?lK7{bMa;=l{@#sx)Zoa0P_($d&Aw@`Ro(w<Il~L
zpIH@e_N4-WXA`0ycBs14_tef@*S?0ur_(8Fd+2<^(H1fq>{!eF)Gaa-ozj9`8}k<_
z<SW`iEXGFI8*7$s2TuozTsm}P#I{jf4{!lDyePP0KGqAwfzYUZtV^UDcy{6iqQOdY
zcEam#I^zx<!~s(A593bz*AxFVX1PQ@8IvX-&e7D7At_x1T+KN{gnTHTBwu2k9U||4
zWI;+JEigenIXxi(>mWXBv>;?bwDUti9{|T1NL9au8-0{ojv*(KtZOZQGC@@@PRZ=*
zU<!<U_6yx{P0UidB$zjVyu*xbfbTEpDx(^jsSH0Fr*8XA9rQaGti*hB!F==`!A-sG
zk20==Z3Xsub^&B(+aHV6UO919i-!<aCsvY0{&oSqsagS<bvi=hY!t}2mgBq4<&IEh
z>bU_A^f37Ah6XKLIAW88F1`oqKP#yJ%&(t^oQIi*7J&0SSLeB3$K|@Ru3Hjn6RI7w
zkDn(TbSq&+cbZ>aDhMpDS$DQ<(B_Nz7Xzue2{DwA8W4c9+ATjM)gEZPs7$g1bjSt5
zvGTpgx#U-<DB`l3Z(d_Ks8jz#-}@l78Ef=Bk(!_Sl!OJRPpUDZdBTPshA81tC`M2a
z;6*TtSJ6gj%Md7t61KA$JvDO$zO!dM1vHG;!F9~rQFHWGJ-qN{)jdCu2*y-FPFpa#
zUSIP8+9peQyK9mo4>QBu#d#Gy)Ff7FYNLAGhk#;^*zSf+)pDf{But|LLNx0Kl<MJT
zoK5>1P^rd_sxS;BEU%)umqTTIv10NEUT=2^>&vlQwg5tTNLO~Og8D^+fvR#qYjz!U
zu|9^lkH0%xOx;Yy661XOyoTE2p9hLXI&=_rfKpKN1WVMZOBGNrtr$jc_H_fC;_y3t
z1w^HadUY%le0vwa>(1%lC(iejzo+^;6d*-Xp^b-O7E=8~Q%4}Ae#at4EJ=^X2X(F5
zii`1-E;<GO$9Ds}5F(tD<x-M9+%-etb1i(TYf7py#qtH8>>~`}i_PYTTM*6k$>0#^
zvR5_;Seww920wSlfwO2Vw26;`S0|(U!8#ePT)5_5SV!b&h!6uCbng+@Ml@2>(qy3+
zPiYGw7rJ$mURpWc|EYa`jI;!U|HA}+nNZ-D_;Yt8u7F3+IwsVM`?alKFW?tU$iCmE
z6m91Awqgg%;GdkDE;y=LHT1k-3){-0iTsg>`Rn1lpqmz~pZcU1j!e3B(A(i8dd@LS
zkYO($z|pg##)&fm`ocr-wREr9<L*fPr)r&_G&?Y?Fg?O<<&<N-m_}Ozvs>R{YZz;5
zsuQ{c=NxHH-oI@%;&*EF(GTvvGID9@?lQG0HTSD<w^g>Hxa1)owB&8mqgK<i{ugH!
z4OV&o0dDti&l)ewYQaO``|>IX=q0(29oP4P)XopiBFYhssyUr6SjRYje+?=lutOs7
z<UnQ-y@WDVzZf6L->dq&-mdC*g^2yQc>?L}ksY|P>S38iyCOsxk{1V%OBZAKL?aqK
z=UN;^nI;Ew<K4zEU`{^V0S0iR7StN?(aW}?Hwzo#-tibDy`tX>wPvswz|;%cX5!S-
zsE?kzvF9+Tw;E33q;AGo?>aD=&}W*~HmElzo!@o9uC#VX&xxzBJ(Txdv$wSkzF=+g
zqo(4XM6b9#U%!^kkDg181BZ{;G_<w&=O<AJ97=vH$&_q_7VLr>6KOe>BI|Jo6f6w!
zD-(gHnVP#mpvoQ3vak3+06_$)HM}`tMFQc{C`<4LhBj5Y)l!BR(k!FTV9jZ<!rFN-
z<g$s(#7_x#>N1C1=xJnehylg>^XW`%E`7bBfL<ZLS<BIv;bS*<VD3tycBW<!u<IO`
zc!cj39^t$05ngefmW<1Pg9{H0++RbQ<X85{TXNiM9Zr!h&Jh62ig`jn$+M}H5BPyG
zk~U$$UD<&)V8NA{R4<;TP?@opvGZcsA1j~kIniRfNQ%f6;De@XKJwIhf-+e%1%(a?
z!^F9cOm2c;=xPMsaszGWEKjCk76hyL39uq#xIIS$?=GJ+5GIr)7{Ij73!|!yx9q#v
zSZ(CtY(zuR=Morc*K$!u6EO>!KZS;Zr<OjnYUZgCcq1f;Tg>&Vp-vwHFdb%_I`3oE
zgf8t#Z`nAoB8H2XDZza3cQt2)qiuAPoJ{qRysq;EP)-$$$c`@fN^CfVXt8D~Hzp8R
ze6%T$K}cHHL2b2BtIOn9VrqIrSqFW~Mg*5GU~3}sv&KwQ3n@JiwAdks-=XCp$LkH&
zwr24N0y>#)8>@JaGN`rP2J)>`3NtkDt*DtrU(kJE1m3CL2u+xyWImtH@o;5<>8fjU
z+PFfKgL;c;FTawdA;9QH*~K{brb@-?RO5>?TX_apxJX4VwZ@Yqi`iZx6^0XP92gu+
zSAlmT3g)RUS`WD%9~Mq@P9S(5C4YNHn}8Hqxkm>EwPjuj0wcGTc4eiYMBrAHA4~^-
zYU{Ot$^~X;Sg;>jHE<7g>hsT7!MsYdRy8b0EO`eH7^padD}T@}Xl;gP4i0=TDOFP#
z0wX&e_Z|M|`F<O+Es#-8smV>zgrKm3B|0sDT1j#ysH6)hy63NQD61X;jCbnpktA4h
zt1o}%2F)1gh@a`uxvVT9ebOE|u#_v2P}5Tg<HeqFf(cYOIX!8xijU5Wr{>W3s}x3S
z)`BdoE2`K@$Lj*sb3A3O$Ze3fxSAV!DAQG*4P}?=GNodYN962*qi47U_DUt<Qks7L
zSJN~ONFwHW0b&CBCGU(<H#Wic^LDd^TBrS@V~txD=$Le~;$mvMWOr7gt>+$XJ@*u@
z@Im#sxkO`N80cR(EUn-w8CHA0^Vg3HI&}snuIeI?M0le;*Bh<UXmZ@=xzBx`yWHow
ztEpafGiTR*4oea1&2*Dn>Obj<s)N)l*ztOOt>n}N$p`BiW7#k#ll5+5k*?c@;<>{6
zI^2z7u-WO()nU~yGT=xB|D@M^w%agYE7)z&8j<C;dD~7yW*B1(itg00oOh}Xdz^cG
zzzBONF7hU;={)&;F`Q!p({3i!(t-RM6ej8ix;Lx)G9=-H)KlcbhfxSG)h46_kljgi
z+-?`7S0zi;UlNMCIUIb2JO9O3RhrVR8P)=%1~S>U;jey>9qUkAmtMb@>Yi&aORD`C
z5?|^dSd_sXI{8~}CIMhD39w6^Wj5)_->9OzytA9{kFUxtJ=i_QHFD$SefSW~-2%?T
z6n218wmp7aiwr%`5A+_5(gYL3V_T$OwN0!jD#%3x#?u?|pE&p?l=w>vo*R!flF<Xz
z*!44w3fq4B<yr1a$j0B4RyX!nn6a%~dw>7CwE0J~1C6sB%G6?*#@5H@vEExj6e39p
zG%njse+%rSb=IonFz(agly}n8GI}yJ6mUMbVaGKVo&e?G+Dp<|N?8sjLuiw?R*kJS
z%lu5A+9V`M;(Jac@{-WpwA91dXLEea6Lo@w7&?o>j+{%(+)BubN@w$FHuYIJcA%&s
zdZd2>n$jQh_A1&Lf9xFA7K(|z5_wt+ZB(^_#e;_W<Ta415yoE`y03akC;AZM1^;^-
zF8?53m70UdzvC-HX1^6BI{kv_b9>$1$m+FbX|m|E#!G9A6*YI-r`n6d(RD3#tjkfF
zT1p;r)g>`g^i2^oQ}I+!o1zo7F)o#?5^H>$C7$6zpcJPUr)Efw9;e)4E2-6xo&sc7
z6upD-GbdN6z9C+G>kaY3Y={?jL%djZL%g_~4e`H3e78jW!Xx4rHzDE|)B%1eAzphA
zqCpZ?UGgn*&Rs!sq22Jb7CO>{bp`P}y#yX@3bgI-pBHG_QQ;Qw$6d(^Zpnc+w#%dL
zPG;i@0&|~F@*s08qZ&w(DEU=`BPR*Lh@MXrHu)h0UZ`lxplpXbM+?`MeqKe*v$NJ|
z=M?rPNI1)P5{Ixd@~QMXl|HA^<5Y^HOZN@bH_oF4uA`otweMtY(RSNi4$Lw);y}sL
z9Z&hJ0?+4^4g-b{6UCtOW!uoaDr<2uw(zC@0GZm4jqgp#9t~fSDUFy(yTcavWPNW!
z^}Fs)VH5n-NJU;;O5Of*{>e)TOI%WPFWyw%9keipTX-VNh*Hp`fD7oU|9aFo2?G_D
z0I)^*tlQA9<K|`DSOL^POAa57o^$O@gupC;BB6aA_O(kam`FRh4Imlp^>7S4!c`{l
zUCSsG6t@_2<~WF}<z9*4yRhURngk63m1^oI>agcxq8{(!&ERbUVPkLW68K|NN!+5e
zv!Y#1zg-yT&O6q>4+s5ZfYf!=e8cu;5UKZ|@#g$(kwYT*I8xZNt52&b5q%jCy_1RM
zBv<ZM#163Jv&okc_WBj`+!j=IKqd&rMSL_I4>N6?@g<=ww%Q9`(ZCb*eJ3wx-N^Ab
zU&RL=?IWZUGt(D3GS{M?hm)TnFMFcHdt&@*INMB+Piz3z0wGuEnz5mrLY@}14fz6w
zk!g~?#Fo);Q~0feO@ia+uid{%@1$z`)gkn?^$|zM5Sd+=%FGPbP1btptBo7mcb=ao
zm*jEZg^=F#uxBd4*0w(R7Zmc(^yw`CMK<gw7mLeF)blOov#CNrjVw@xeF`y%XAG(L
z$blaG&A-l)6ci`AW6$Oy`fiKk%dw#HT{NB1EHUj3B-teB+JT>)_euGy+Mvz?O<*Rf
z+cAU`pOa!#TN|Z$+?c6LZD83!p#8`5+dR1n`M9{pz1V&F4wPIyc}<^nhEt*TzCizF
zYn6&t6zJb=CCIYTV%3nv0a-#etU#wufa%y8V{40>E^QoX1^M|(M0j%f#-^GLxX>Ac
zhtD)QEB{rSTcM4FWTl({O|wibjS$1MQ3kJ)(d>2?4U}=DU}bFqo=e?q`Rl%ah0SZ9
zN`*!g0>f%2E9fBJjYln1yO8ObtqKD3kH@6V1SiO`aLpCBiBjFbs>6M8gW>ASrV?}1
zd7#_;$&nD}-7h+nq#6NiwV=pX<8@NE9juM_T)m$EjX&&}Gpu#EAN}pc4=*_hyV?}9
z1w=_PDmb+<{xg|Rk+rE?jJ9{o=G{p;wjoNols!N(^;B>c?v<T84NYAS)E^-#Y-qCE
z<k5wcLd<ZrEo@x=!pO-|izI~QJE2_rV)jWtRUDiX@^Mr?>^UC|R0o7TYwS1cM-;jB
z-7loE!HBRX)<qSm+y=%dtj(qgn;=LQyvXMs1vFXI(OR6@ARgEFJOIJh^^9T3(QDv8
zjO)yQu>Xn-fTNDm>E#5TCy_=xJ9Bm5zWZg1^2dM`tr9OVC^GbpBXs4X6w+asw=o7a
z?xvs65RoDstId!m>=;1mFgctrb4cTnD)t{RQ-ltv0*VQaG5~hQD9I8NgPCAw+D?~#
zB?C#`0k^&!2e&sGzv(pyun~Jh=1Q1@kqueQH^(f67Eq^>0?K@uD^<%|Sc8_`FD|;P
zhYl=^Tec>TcE>L7zk`&$mwTzqn^RcDUdXnd#V9zhizAUOVI|h?e92vh%_&iYFud$K
zX5uCku+=1n=A$DN#i;pw0_w;o6i~o%Q`d5WMyzvnvV*Sx-AEoje4TpLDBDDczVW7~
z+Y8wx&`HIr600T0S5W4bfp=(RaagZVlcRetm`7fyA}?x}QJbjF_jKAVb-`{c&J0|-
z-8er`*KKldrM^({4qRYEwTvpZ94G3$<aQ#a7~KsOk92IOJNsv>qPL!I`1o&))Qn`0
zmJnzpuR15AdA=tS|Kg_UbdX`6GOoMqcbIKaRgihtmT9ubn-ag<gjqp~+ICuP4t-R+
zZEr~EHcVt#9FPR>-`cCpsUT&$%P!K={Oo~fDcTHYUHc3KbFb(5ixf11*}1v7co`pC
zn}*+pANQP{>2NzAQ+nb<_v#T29z*6%OKrRYwp{2iTCTSF1}0w8*weT41o+{bu+F+h
zBAN~&YkY~(w+`;r!-;TBMbj@OCx9++pmrK0Jm^A1?WfLKguS{DYvY=<eKWzFWvKV9
z#l+}w^ag;H?M*m}bRp|2G}Q}qz2|wVL=fV6t}``c^XVwM81gN-+_;S|lFM!Ww*wd7
z0-e4-E!4a>Jk@+?52Ak4#173@@M0a6gmw=HItr=zITpsA<D3>cMQL<7j%Cw4vbb!;
zRL9!JsD=+)_2UMZaf<XD_9@s#nl$>L;pJpHceO#rJEts~&+9;+GF_UbR0!S3H*c3j
zg9?veE{cLI6?@)z&HG6}mIw}w0(i!#wuOrR@U%!32$iL&<)IS@i)ky+zh=bX5fj|d
z{#dxr7$QjXmUa$9^yGP@HT;&)iZ_oJ+f8RSAR{hLw!I{=K{!tU{#3}5<r(IOiZ{<+
z92aQE%92Q4ZyT7{_UH4)c_Th+oE-3*2d3mf!!0ju5FTV~S}jZ@>LVS#223IFQi`d4
z`lO;ak!0T=9RNo|y=`~I(FwfQoo;l|g{u_EQpgV-KSD3${zf2T{^R_xDJ<6mq@jFv
zhBbS%m1R@N2?x1ugqUE0A&%tLu_V~!X2iaAp-9i-z(GnyI8V%(qiH0{XOi%-gJ*Ts
znP|aZ2{wa7t;zPrhUw~YG~A@r3!Bw(V{?lcJjsBOvqfe)AlMYO%{CJ~uDRbLF9Ad_
zm4cVk;W1K0AYVs5$HL=Rfhqa7-aH4mP^ZCS7Vn@wv1E6L4pbwz<|c~5Cxn@-)cNyU
zbsn6_L)}!3Lh)!Gk1^ISuD)Zc?^LP2YpU;7ss7AVfA+CFPP}SDc`2S>^aEkymHaj<
z!-|gM1BL@fr>AGYGuNK4uTj!Y8{M#vqHg5*nb4+={&2q@HputHXig!!B7~yf^NsfX
zy(ULtwpo7$|H6RvR@3mJU}$@q8_|A$<^;jFE)y@FZ)hl@>asxi4BNhayKTe1oZC*F
z0$&-oQkl#vK;`572FA=ww^?D26Cv%~h>*S&#jICd?dpqti?yz>)Kylx(n8;OotKDm
zkX7M|j@6PIxxW5{SKJhb)Ds0fCHEPw$7>t17D_ka+kJl)kZatmSAK#i?{FxWDY(6*
zV)k|#PG*$Jbc1II=8zk@!sdTFv%!Gh9*9vg$S{k25r{m5awe(A1iz`nT;k77=IflA
zQrsbKih|FcsBg~^M7Lj&F80kyZ;mDh?Bd*;E+!fK%GiPb!$?y9pn?A*$KC(IVws=Z
zZj0bPX5jz=UjO5xvGYPM=3eFuf?u1^4L-_r6)DyRPhf#1v-E%mac5(U$YPS>@?4bB
z7=#oCLrUXvBrn651nD4-^sYHw<u%+Rp{2grd0NV1MTpQ=t}WMA=9vsBAo2G-*Jv`k
zc6=+tH&C7WPwy%l8`c+kYi2wFO#rpEaX(}xWt%dWAEy1wIOQZ9EEG@m)fHMnm4o%<
zmC?qo+umeC-^aQFSkk#NJ&jSLD4)kSkP2`u$of%>XS_ZU#^#=X-LTn(|CDP{1cwHm
zT^oF>0U5~oS-$eCnFYtxkeHp@<hsXx>@phNg+XO8Vfz$aLdmzH;L_xXLA6ItP3>zL
zLnYcIxKxXRY*@|VYC7usR>_&oZs>i+C%MJg`%1Y2_i}d4xlNmUh0vjaIVmRl0XnHY
zLrF9B&d!$Sxy+WPthCdL<i;y{Fu*~BWN6;aFp9_WB$q5f;MrqY7<029C3fkX@ld>G
zu$l-tbEB~x&p5cdF(79qWwe++hY9NqL##@}fx&7H=jfH!)-J(54Fu)sfL55a62hk_
zr*X!mCg;xK1Pz?sD&|3gK*-!lo>^rs+~y2yJ2GQSK>)NVMJRAonQHn+Hl7G1_tlRn
zhMd*q!9-P}xZK?tWTj5}geERGI%qdl@Do1vOGbl`HB8SCggzTpGWWG<R?s$+;oEZ*
zfG>KgF+3xIwpcy_*@)!0ygG5PhKw15Wxs!tpDQVqHLsHIR{5tF{o?YF9#|qh9oX%g
zAyUgfgNX+yvF+G?y%>mmRPtW_#MX7GT0DV3V(=kZ@+)$fnm~I%s&9y+9az;b2f9Ul
zu_jv#D+-r9ogR%WlhP>xw0`NGYigYXYsov98xK)J`PT>+IGz5K2%&u5(og|kDe=J^
z)!Vh`;J6O!K8G!hrcT1y8(3Y^?Ok!(5H@m_0&ZSIcf@PKY`FTkv*aec6m%m!9VX|@
zOO@-S!G+T#kObE`ZFCOY@?^KXSBBKdpKP1H;W%ZOn^V0Heq#Ly)go;EP44a?#QATf
zg*ly;WLQMiO10Zt@x4NyK;kZ;MGI9rED#%AF(W7kvk8IOt}pr3(@N(`b~JfZOQb>=
zizgMr=BM<t5gB28Q5?>wL5MwlPSjlKG;%F9T+4LGe+SalXPF@tGCOtJ=Vy-Ond{2l
zu2f&8)*y6=DjG%b#^qEFO0Gd0mGVKx>1VzJI^Z8gS?)%d8=%`Fe?N@8A#lyY5zD+|
z7YpEaU_=FR7B>o3s8)a!P9EP64;~;`_)5f9f8%JN!1SGA_!j(GkvFE4=QAF^8Ql-b
z2jFaB-g4L}%{J!;WB>Av5e}%~{dTWAQh?f6aDPukx+{T`2T-*oti5dgUWs53OFNlP
zRsjLz69Cix3{xO9P?1fDl6S#KCo{!kv%v-|#FN+1poU@grt;G!rmenTL%){7z=+l^
z+-!Towb}V)n?09|TCcp9X*%;WO}qCqN^c#p@gG=vp0%3q>zzj2IgQ`_vf+VLv;W-9
z60NS_E8b@eFserl8KuuUXVMhJMB&la@^;X##4k4Eb;oABCY#xMyAvO_8VxrKphY1J
z0B9Zz#6Y-l11<R2TW018U)qgMeBN#x017yeH)jA<QUbawaer_<!1s6bveLPntl{pz
zV-QCtF$Hu5R$1+z&X3XJQd(w38~?FRVOc#)P#zSHxK~g|2IVWLVuLIcR<VKQitAX{
z_-ZvPbPIzAAJ@VPWXIh(IV!IP0p*uhB8zXXx4AC1RAx+?t8OYS$LVGdE39)MoRPa-
z*k~E#5Qp146t8{jiq9Qxj9Vj%9>Kpk<x#iaouRy?e#_69cl{oxy9Z_p`N_V(^-FP8
z@eA=U{$19$7F=f2@IHlkiyD#5ftDAAU@M|RV2|2xN2-m4@bF<|FvQmM4ixkzu){8C
z4YizB&iryi_1HHvj@*o+S5Xnqq9*HWxJuq3t=izZ4l5pCf%vE$a+;^{;rYpa{H}S@
ziQhN&VGaU4g3$8E;@(QY+wU6yTwt#hI3RGv4w}bjN7RRd>*8(zYCx60sNQP5?4KSV
zpPopyy0=7lW7mt|T2Aj3jbzW-cdv;2Rj0aMJm|tP7YsS4obE5i<FE1jTC*G0QTJ#4
zPjJI=q}Z}27*wB!D;wDtCpB?u<wfm$l+Jm#m(U28F~1z2yScbiER@f$@!!%qnXa?0
z6<80s87i<?g5*#5)~c&z`D&S{MseQB#xr*nLH4iO>At)M`MZm0keLRo5bs}HqF{G_
zfr%C7;(GBidXQ?Rnf<bL9~Yc^-Xcjk6Tgulht!2VKpOYui^@N&ys+G^d~riZVR6Gf
za|`36wTNe5ec585sK2m|lqb#oxZSBM;pD(%Wsl=-HXRRpF}lxAHXdpa^F(2Y{?0J(
zO&r%dr^gCJt8rBS&^Xu>c^}QF<wD7GXD;xpak}R<v}U6??nSBr01`sw4uH(-`OA~n
zu*9R`<Wt<Aewk2A7S^EnTqk-d3Vlh3y8ufxkYz%>YPtLsE{b2HbYh`$`&b#^Jpz5g
z*PwI-{OOh=u4)52XExLPQ*SU%mwf$u3>&XpOHrVh@ak(=(WBpSFZ<hZZXP4&_!ud6
zkS<Dp(><Vy8{s^8jWMj}_)=lAD|6B0B4&N@oZr&s<}Hn@q`hvYwpr3wMQ*RMgf4Tf
zgo2t}B@ke)b*<k3M<%BhgrmUg979J2Yf>BIAovr96tK<?lqiRs)uQg_?r?;TJGK{L
zl3nv7IZzA@Xv`N*$Z$2Ia6RThsw}XI_J!ba<CO()rNG4a6tuJF7B0~t%yZWr4>G=$
zvLU#|jQE;wq6G6~4(p+I7<mD6E4N_JrQz%jX*gR#!~TQ1z)V(3!<JC<kG?BlJ%7oR
zjWcO{A2yx#s=JG%8x${67FZ<RDzHdKCCaA*VFt@9tdwaGh?Rb8p{+Vg62tJV_B^@3
zjOE=gFpT;^{jAeyDH#cMW3I2%y+S=%^W>m$7I!|hK5RM)N3Fr9s2S;OI2ldV1rz>K
z5`j8O;it{Lb=SuS&Q}~h!WMJk82YW|$y*BAqWargcinl&I%Ga4F%O<$$-frD6)3(%
zxO=duMbzbkK1q0MZa)AHZ%A_3i%EXqr5@nJ$q+=8-$8zICQ@<K(EhI(G~3jmBO(lV
zj!(dIimM+WF_HisI%E4VP*0JYkP-<y4J{b%tuGzcx-+cMm5E3L9thPC3pWMby~1Wz
znmf;v?tE<6fh<8rBCLAc7LyD48N?NOB&LT`7FbLf=45w@?5&BR!gDdWMr_x7aR6M!
z>7wKtB5fKE2asP-KLIw8uxOj5JZw7qpUT3%IRgrA090Vw%cB_*JFTIPAZ4`cI+8@G
z<hJ|g^z3Z4{j;4Xf^5};Ec@nEP)RPy+=J|2;y}tu4y4X%2U4euw`X_B+wmw;h-TYA
zhu-;fkl|-8!Dio-;TMr?CBF49NwI$^-!ki{`PP~<Y>#a*A?PquoR^uLbBB|N&2S=0
z_QFoOV4>9InzJc{6q(D)=E4WGt%w{By)C*&4pXLdh#ZxH6;!W_=}y&UP~ihEtPqlu
z^0TVVG3+n8qp1B$#F~vM0|CrK%FSLE4s{N#STK?=SHs?wx@tm#3=T%6M+N^%@8j-e
zcQ_HbUWb_;3Cds?<Ldf%eIX6*s9SED8*+I+A_H7%rjvyHRu?n0M_m>e1Z|m7?&(c3
z^D0laE}ma(-dT1pP`kvQ*t2^kOQlF$$@Is)B75(Ujj->zTpE=`xH#q7S=XTcwcfoN
zGpLu0{`kY7D&Re!_OPv<zc*`dqdpri!w)|ic=)?ETSm)a7yGXyf;|U&s9t8x_K=?~
z%B|Vhi#z~Zo2cQl$UVmlR$9{HR8lk?v-OSXp)@;me6XE~lC_^81@pn!8^TQKry!bw
zJ{{H&JZEMo)f~o9ea#z|wpskszK_B3z1F(wpdY!vRq|GPuOgS|Mc9Z9MU0zBh@PpI
z+~LOgqHr^ZcRw6p1&m=+0n0xF=_405k@z<3f%*vC@8_93^8z~HkS&#b&kOP{IL`EJ
zq?uGPd|%1z#&XfQNJCbJ{=F%uKxbrYv0X?X6h;v7{do#`!AD7yXF~Jq{;cdWRE%}W
zn-sNx+7z{ZlBIIAAUq?kbL(q6+SEU?s7hl8n_ce;8a5u|ZUBDnmi<^GB6<)|Z_nAy
z)VckN^nY?<Y@%<YVm#a3n4`<?{CZ1P<g+(KmUIy}glXw=9-^Ch()%nQs7+wcB~7eO
z9*Np;??SXjPokW*K?eTP0z&J95>?y#@%c&peZ6^PA7-k~<8#t8q5CS<NAtp!rl1ug
zE6w1))~nRj;`4?>7!R#;d&@nu3Lt8D?#}mX9bhKnz%8VR3uHIt0$H95I8xbCF5vI>
zEWg_wZeFn41Hwyaw+FXYR<yMomVB?k4A(ppS7@?IT}{EOwh0hV$0tXJ@daE;E#nLM
z$OZiC1>++Lt2iFP!|HNd!88s@+zM}jj=u%;QM2xx95K2xcxNCIJ6|GC7UK(blT&xK
zHwPRK)84)y)?t#SI$cL%qGE!J+JbAEz`^Q=;b3Tk^y>#h6VX>6h6Dw9XfFO+@PH*7
z@(Rc7K!elAsW>*P9XLwdH=)y*)pq+(nbeC`ccggG;hTe#^W(VHc)Pj6Nu@b_g=5M$
zAkQOCyk2UiZb_!Jx;e(ooyq1k%{MF+$aKpm!IgDhQH{E`A9wqo<5BnPbdhc3^*)kB
z+4C$P`1QIUDIncRPthDf!Z3Xk?IB5>MMKKz!1kCjT3?}#2M($F!Tb2A{_E*^$9J~@
zYJghiJhN5f#tG0v4bvJpGY6FzvX^ewoprOTQp2%TtT9RrG0>@He6hi1<OjnPQIcIp
zdK~bOpC)RD^&!wE@AxgNGa1hmW&N&)FHF+U=E-Mpo9fNG=~a@FAv$T)NTHN*cu&P^
z3EmuWr&cN+r&51Me3zQ$(bk=3mGM?;6;+5--^$0e@F_L!aZyA=WgPvv{%`+Ee_*6f
znY*glD6X<~b=Q4tt3NMZJXinjK6|mf&HwJ;clGDli)Y*aw)1>v=h^e!zwLal>g_!H
z+wSv!i?;82AfZ1CSf42Rx2wf?I4P;Oto(oIAGKrKX9pji9H~=pk|s}@eYJVvyq>>|
z-n0*%JbSV~0tM~5VwL;T+1L5-@+#ZtZAQD>yW3CHUpvveVS6|lDpnC4L8MKH-3a>{
zd|D>p)Dkm8gj_O>{rFvMTu<^Psu8CVyKjhc>*~J$S#4;wo1maH7~W#^Nrpp7tA*ke
zHp3W_fyHb1xlonq#p`tAO~YH4VrC3%o4*V>Zo>*;9B&+QQ77;;9`*A?>i7IOi&;3#
zB3~uP(jyIouxvQtbj}<k0cZN~A!eNee+wn4!>8Z2KhlSA97tTR4X0u)Vj1<(CVZFC
zg}58iNV?d?IIakXzdwEq+WN7$i0ansHyMTK8;`v683av_CMYvgpi^UDXRn-5pHiE#
zy&VAPbHt2lfhR+8Ps25Hp>n8p_@WrpcCHfVw&J#OuFd*7Wj2C%yt+|T*{VThb&QgN
z_^-FzbfnF8+&Gr0@`(VQkg<h|d?&SPF_+7<^@zKEu3H6N4Rj1<4E~ene{<`WyykmN
zn~&(B24YY$pU03m#(j9gt7Z)y*iCJyr7sxl!7c%CkSTkWFu`cx(zlpsOP>m%`w<!k
zk%O)`cNUw`k3W(tzIM_z{XUFn{6%jebCU&tjJ)Z-v!*}e*ofKKn(j*gR<WtaBE>#(
zry$ViUv>Tq`A^CBcP{$jpC$6&i)YVwK>mBa{kQF%zdcjmcXnUA_}l-=e}BcFTgZPq
zKddDGwc7#Fk3VYZ?nl19p>X%w`#u;=zra`5a~T!C3QYU_400qz8{l4RG{UOjuvLGn
zQ*e7lC#NT-6nuS`)PMw9<u$-fc}bO1NK}}wqbs~9ZT@2EC|@ic<%{K`d{H#Yqi1ou
zwI83J9Q_(BJZN`{3ZIv?d~RB9ddmyN&69(;^X3Ti9It)9vkOcUl9Zy~gAxF)y6IIk
znod70W>JPxmm<GXD3D}9QSkF0^3{H7{7M}?-_93;3%)v?kLzdgar>t=O1c*q@w<Ba
zU0gqUdm4968)rw&&i`EtK(n>T$#iX}w9c=`$Bj;_xsNcT-LkqEFcyXfGJsH^rb=X4
zfM;iKa2frVIFN0L+WI4~?f-KxFfTN8X~%EQ4-XqHj8^;NIjlw-lGt@q6wQvi*Xs0p
znrVYLPywp-@W%lb{n3As<4e0OQ@p(FjxMM3VRkjHMX={F@NZg+qEE@!8UqC>PKYa5
zt&3_J01l~Cbj&@-ECK`)1JpejERu`K0E-z@ah|}s9FG>Qodyu9@85DX@^LQ$fbRgH
zsvt)dz_<M^O)@7jD3lB*CYD>AU5tJ!q}z|OC1T^Z;`RB6Gya*>Z_q_AN!gPKM@#PT
z5XA~BqSrV)O2U%N7b7(Cq99jLn}u{p;M+X={31d|Vv=SlMAjIBlGDNA2<hRZxt~+g
zQkqQF2d)KqaAGpVdGBdIRnjEqLZqy+>Q)vZ;wX3UPm9ScnOy##-EDfR5b$*-O?Z3|
zvGeRyF&}8!Q?fXFvBahtlRO_<!_o9|H=jzImI}&DSmNl~q^wilSu(wjUcW}KCX<JQ
zgJ-EKWbR^Wz-^U<Lsf{PA#XeCM>Vvas=mCOwL-Y3w~kTj56%2Ko2Ek`usuI=G6=#p
zu%QfVXhiG{7;v<+Su;?y+<g!Kef(H|$Cx&D{tV5udJLa~mlGV%TnWhi#Vnqw9SxDL
zzD)h;Fu<MjBM{_azSkHIo1x|$WcKhOSU8F*Y$8Wk;Jv-jAaz}<8hlqn&AlG!pH$c3
z9-y$)GtBgH!(J3Fy0@7Jwntr$V&sqTH|WZ?u{;XO;KVH)hT=u@uS-X9gFytxVEwcK
zL@FX{bmy08=<P_18(q6K(~VJP2(%F90FSU{04+X7Xg(>X=_`XR+rVUpm(X-0K)&eT
zm7DNl0tZ%E{oG{f?78?#<T(gU81)fR@e%e2f8=V8@NhNou>jq|nH#H<F^F6n{v8h3
zN2;0wB1yC9JV8){;Ydxa@QDZ5wtt((i^X4gk^Ue0$KL<5@i)5uFTMZoZa;(j|Fhla
zyDy&aZo~cm`QN_(-~0bx@#iml|LGj(umAK-T=UbcuNXl7>JL#Ye-C^f$MmL;Y5~b(
z&~k$kzs(_`X>Z(*q$HHi5+(7W^nMO*0mm1!)U`&Lr=R=3egBc9LPx>fyD?zka~YX>
zncuOWXO6`>eA@Z#Irp8w1&ViQJb}O{cx6$YY8;-N9yG{l2{a(JP(f!u_!;jD!4h@R
zs1<ZSN<Jr}T>nRn_l=|A0H`EC0{R{t0u`AtIOre8=~Wlv;?CyN0f^RWB%ONm=;yd`
z(rNv=5w5ivO(-OeT`8yBE($FHxRWQ79$QMeFM9$wrWlPF2CWy3<z1tGKtu8R84c5{
zRxp*#{9IwwMKgr5{Jbho#OdG>m@kA%Jybt(f6t)>=|dw0{|V#7kdlLp2?zM`#-KF?
zGFbm8=?<`diUIdwyFp}o@dO7o5I5ewR*g&Bg`0SbSkRVgMFv|>z1WrkQt-(TzU`Iu
zjr~rHdET-v%?i(_(}LBfaUfeuORJFSU|@u*EmEO7v~C|l%XRh(P)g7W+p+RUH#N$K
z4)~5?WN7s-My}1KR&P;1JHwa5-c@&U$%(&@5ehaYNqeC<x4MbqYhd&XJSh&d?^5)c
ztWi>NosZX6hTgif*@z7p-~B>fWzb)GHC>GQsB=(5f7(w*N#=B2*e#j{Y261!BNPC8
z+CT3~oyOgH@9L}C3S)Khs7g&W2!w;4a0Vq{VyR}arNK{UGZ(zA%AH&!7R;2~4Y#Di
zgnBgU5w!?<4PX!k|J_lKri#nG6`ez*nz53t)E4;!YM(h_1nYoT9zM~kF9>eme4oRz
zf&2j95lGMCLJ0mQ<_hB?f*)auY8@d}tT7y`p{BTV4Dg11RoYF{;pGG)dov0KQwVdX
z@pO@>Ur_gzzJx~b=eO;e3-!s)$Cqkkb9G6XO(#sO>36A~hi>RJiXKPX>YLNBv%kH(
z)lR<EPQKOF)>aXKzvTh^ZF#pp_^lYfw%Ix<c6~k05BiN6n75(~mRjK7jSz2tgtvXG
z0>bL-`-{dJ^gGxuKut7Ya1Q`uC9bRfXlvR^lrzn|DRb2)ML=@~t=nFJI39m2Z{mT=
zX}*Dbc@H!(w_w#`I!nt`NNz|&4wc@WU-})xrXf>AOjRG$NCX;8XC?LJFll0rCd#dx
zyQ72j|Gzi%fASxD|L14d-re_6djEf+ZvNl@4d4HFcDA>l?ZEy2*|XjMegFSU{(RH-
ze|cAj0Q=+o75-w8#<SkgEg(|Ne@B~~(8o`oLFr4z0Y#RgUcqPz4RW6g3{DlNn}=#A
zK_LC!Md0grh6bz7qiVa+df(h{#LbhA`l)`jwzfk`F<_I6H209L>;HV--2ch8+VNhO
z(dVmq5TCto9>6>Bq59+XeAqmKAn176e}A~<zfa3zxYV!tkJDV?un{-jwi@kr{C+2X
zgPF{?H;ZaQc+utwRj*RFA*=2bR&AXk24&^l^2!e2XN7gC+S=Mi$=EQOyZZA-X-9=!
z@UX*um^qbqVybO|fF89lAk91(b>Ts~m0YR|8(dI*T6%kQ`lfyqtEObtkfVY9(^f+k
zdlb+-K9i-MLBiqrN!)68U~mf03bb4NzOmmqZEXu65C;2=--oQWe|+$B+-S8_t>@<@
z&=lF9HruBss^0en_3B4Q@o~HPfx*2v_iY_;M8DLV9aRmsWMT3CNoQ?Wl>_1r8~YIk
zSDw!M7*P{iKqf3~<=7QC;NJbBmU2Hn2F=&WDL{#~i)*~8D<%*{JH<6xZItJCrSdNM
zoW&GrMJw(!E*kF}3iE2IYQcizHy^?U3U%Rvv(8z#0F8>YMh`CyK@Yw`(o;j7bxD_M
zenqPYFs)P*_%Gw|*gk7C4#3hO-r0UzGoKAE_UmVLG>6$h%x*@1m^ZwVy7lwUX~n9z
z9GlUfwe|3@cEA5;4y#h#R=Z^U&;K>i`u#t3Shq*3;wdXmV3ir%cv!pt++j)HV0jn4
zr_-~8@yrt+3tz$6Uqn1rKf(s^JZ{4+SyP5_wt#2r3L(l=%>WEcPCxrR?8jQ;mlTgp
zWF7cS0f7li0Bt%6K&Q(!#VZH(S7|u<J(-ax-=4!CgfHrT$B@l(+>6KE9{e~jG#qfp
zlgzPp^hmc0Olh8sr=OEbz;mV})!>s6fjUFNbM+gb4GYo&96J)r<?Z@YC%9e69>Z@!
z8Cvk65)ZmU0~FMW(W*hcAgsY9Vi2T{ARMFua(sprwu&A?BxH~3X0!m5lMVBaI#w>m
z_$72`o5ip{lkbmCPloUiOmzRj_U?z5j~?-V_#6C%!4hrzC$Hh}7*i`kVAbNn=VgW8
zf7}d*pq&lkKKVVz!};&qMc(E`4&KMj_CCuu;M$F1SuNTw?u>oh@2;;Mr>}sh$6e2-
zijvV888{|-XP0m#GLuZnBb(RUP~jtpI`FwWDh|u2vqOO8pUE6Sn{YzW?<j4AMtyJG
zS2GFZj?iAz8iX49#W34&ZyvQsfQ0<J!wIHG)#FqHGR{=ujvy`^Iz+=gJ!KB{X`oVq
zPr#qa0Zhx(olhtbr~=4AK>JCS^fFMxqQe<~C0={qOUFPDf{F?B7bEt6hg<;AVuKh)
zrH=a3$#+>{ch>weEb><;pv%$pqC2_;4MqQYWF#-ZH=!hIzdA87E{o{tEf)V3Bt<Jz
z)Zt%1T66{?Inn1O;u2904yhvf*eB=Dm|k-mRC$!OR~9Pz`8`hOxYY9d)faRQgpxVt
zR<_`<V(5ZR@p_#-z>dO$1RPS~l@X_$MuYiu48ITO;++lC86}tWVxAjyE&z==CG-;D
zH5&=C-D&GEG;)H=L7=Jy{B^jsi-zL%t$I5?I}DCM?F>eSYOYsMdy+?g$9L=KrOq^H
z{DISSF`mJ*`AZ1+a`83lPQK#nelKC7gh;mI?r?N5z1C=@NVnGdKgy<;#vx%6eMzD(
z5QGF>iaE3i1Ebg_n7$hfXYhp@0B|i>nkmJdal71#+Cw#@8p6g`WfKI6eUHiI;X?$d
z<!&ep?r@ygR`aBn3{^vnVynh6#ZhBW-1%ZgeiKME@1Fh={R7_Db$)CfkBnop?C6Ug
z<~N1nSfF}_qXtu5i|E-wK?1j?VfE2N*p|R&FuDA6p(9r-kPeqA9AciQ7K}15w!j%x
zeR%t5LIT+2-lCoFfB1n{DxEIoy`*^5P<82W3r-QycF#;ItX2z;yq6pKI2~SxN1kUV
z58b{%yhP0?CVtfcsl5IF(C&7qe{$HM{Gno+`Hud`Gt=V9Hd?L9lO@96c!fKw^<lH(
znzcR<n={KMStL!xVVVzLMgP47$ex+Lcb*ha^!Uw(z(fmhxVK&m2zl<_x`Lro!`owW
zZS9fexO{SjGj!Pe#cI<aWzyjcCa2a9$9|IzIUDw~Nhp^i;ez`S4zExU$lZo*PvWDZ
zsorRAtVWiOMhPjFzze1<W?B~Q3omHIwD`oU>EY~&NViLeq^O~+o6zwrIx0qNcQjgp
zT-Q-7KzVm3irn~U%8SZp^XWwr^%of5-d>N)d3k?Rd$-;6pjpzVbEtXU77%t0N%8^4
zc!MoP&>v-$1CuMQ4=;VPwz)P{9zHx1q4s0NcJx@J{*;}I1+=ZCz&;w|_Tp?ZDk5t6
zS+Qk`{KDa9tTDLGsyMWHNz`eB>Od3+=^CWEid0v2rENew0FB9eAik}-X+jSh58-c~
z_vzU_7`wNARcGZsX8Bf=vza=CFhigweZ(1q*r||>glsWs%wnWYJ`$ULM8=XaNhfoG
znxXeC2(tIv_D4Mgsx3xgH;3ppn)Z4NNG522Z(l#Sh9Pi!a~-XOy8WX@z2%@z2ZJ&>
zGS=i^c``QAs+tV(Y70UEZ3&^P9Qg+O>ubfx&yh(k8O)kqfj@&ZZ77SWd(NS!(3;+l
zQsxD74?YNNVoT4gyJ~jzWtZ#F^;c|q=Z0+sknMtNx#PFcP5n<OQ{gu!Xk}n8`l?-e
z)>soGGpn6bK;Vtxp^=^ToOADnCmv7cM)&45J?$IZ+KV}{_`Md%$tuLse4}lFSxEJA
z1-Dpran7y+7jG7}^<`KK-44c!1pOc*;frwJ4&r6*bbbj8CA!aAEJm^@(U`NJI3JUQ
zRMVtZGxaTJ@=h4arRWr?u}$Y%yC#CVFQ2(O@XKc&5Gs5fpQGDbsdtbxZSSz_^;|Em
z<8gY)bM>{0fnhEtpC*t!8T<Te7m4qLjfuwy6bft{2*Sd}SD|?bJ;~sF18I0bmw=CS
z__*tOB9}etVs*&(#qYU_b-SiWNA;7qc@Uo-9@4d;akjSeVmnaj&99JF2tv}V{ot}>
zF(jA{yaIwh;-h);dj;mLJrEHJ#XQG1GrqGflbb?Ki;B8<76{p@`niuNV1qZsBKHs9
z%4~jqFL1pj#79pH@x14?`wAJ*qYd5gL1Dwq=qXFlfz=5>Wo7FQ#Hk2^H;p+RR4({`
z(F$)GQ3plG-=Dk|eQPAR*tfO7lm8V2c>cR$@-Hz4i4OuENygpTZ~lxv`mhbXtR}(c
z<kyt_cMv*w0+CErGt2qPB-VS-XAWVu7)ewWvW}8h1GdWtW+>mtxw`};;})QzNBFZB
z2$ngGlHUeq^UVe@)}v;-6CbL3SAGB8hHVNFrU$$f<Q)m|C~ZVZTazmRY7EhHU{$~3
zRUeG!*ysc0*R^8ahO;-Q-KGGmINDa@`1F0l87vNNPsdAyIEkW|3OM@|r&|gw3)q+3
zcwLYb@UaCICKHhM)nsq6Tp?chPg>4g&`(>R?>GNB?v6&&-o|~)F4XMr*L22NG0jb0
zO}AeY%r|hUJT&(j>ILUdI~0+4KYx=fBs(=;XMy(Ix@Piv?gpvNlXj!kA?INqnE_G^
z9O2pur~-ZcwPdsA6SF-e>6*m(2)=MC3e23NSvWo>Tk#Hz^wBVcPL{?={moIs&&w4u
zP`k2ras?fseH!xbJE3!z8xhCymft0cJ>CZTbg96$=*I3`**!*7bXpjykw@=J=6nIk
zZz-YV8JH^9Z=oJZ@Y5)|_~KrqL4v$X0<G%W*qYCiOZ8)FqO`&NZMvXAQj$-%j391r
zMeS*gvfI*wWT<^jAJzzHTMOL4D!vfgzyQu*;)j9tr2nqKu6(kbPAE6y!-w|Z4@4!C
zC_t$JWj`E^LBW><quhDL98}IspK%9?E-*aVR@9u(!)&jc(t9r1L6G&NgK*>soS!to
zgcft~09T~{h3ZY`JpCxS1_ydV8a~@HIQ_ni)nVgop}(>gf`$`YLT}azqd+DZIITO&
zPw(8wqZX5FIPxdX3X#4*_D%T8L9>mF#eaaUuqV-|b#2Y3a!`Qo*~sh&^Oa7;NHk$p
zZUIrj?Zg!V_C%280trwyr#s~;jG>yf@G_2YSL!%%!K$7VJIv=oOSd#*brr;Avx?@?
zs9S_CsTn+)nV(4hw;5<>0r`A>ZCi?~F@!z$Z^v1%Y8I-x?3DL!%3?`?mN)EV?%Djo
zxU<mJu6c6OXc=$zXi4qUb9F1;3`uV16BE~x<u!aOweav3Wq%ifoJ|>L_9Wm}jKH`J
zs)1DNd^YUgsPpP-0?_IUG#-f5*|g+=B$|OWm-lKRDeEWOq9q`1i2XcyJ<Z}lnhCP?
zUm|v1AVz80wowX}hE*B~Mc<OqAvyiUqce?$lN<D;8db-`ib{t7skT-9Xnu`UI-5_k
zX-~;v*e?V=0S!0kA$-My`-a8_e>bF8y52~gRu-h!FpqNdK$%^wO8Cnx&a2eFrG^Jl
zo!t=Cl~0z^19{nzA_IE{&y;`uLG2x%_LwFHub1|=M>U9Z2v+S&9VuB6UAd=~3^HqY
zY}UP`(4n8z-#LVSCYcc`smd!Vu$O75N%rC-jzTp}y3JcDq){pc<1beo9n#>2XXtEP
zgK{uUCsnMKrBxICO4vA#JN36akWKIn)2osZRD~z6RhPq=5@|1Y)a5z)d$be16y_L}
zVegj0-n|*@_Pf(x3I`5#cUUnoAEHU_&3gzAAL{NF^+0yn!}<6NM3}-W*6?yN#c)-_
z)QbTIW`}3{O@*xY&35w?p9kJG&$fTCuS(0us%}vG_0~a^l~i}Op1Qr?4C|twWvd$Q
zN9Wm`M7_lv!UIO1lX(hwcz>7+vQAgvGc3TEoD;b5ADkWhM7fzTOef!cCkY!%Xf`IJ
z|09kMY1?YefZoH}^6~5t!VByx^qZ%Pfq47Swe<_oA-cAnDY13`7+TQ&w+}PA{)1e7
zc%Ru6eekP@+a<h-XqIvpXC!Aa#e)(!XTkAUel%L`I=g+Y$jDb?<00MVI2re5Us+{~
z&2hQ602)#${mpvnf?7qUUp%So=99|qbW&NRNoAo)nKL(;s8cScZK;-DwOi(5#SWdJ
zo3EZ4(GmQ(npko-`k`ylNS;qtw;8OnOLb^^#gzoxvH)dT`r_`FfyPR#nX1yeP-2C9
z4USb*4IG1o^>!=N)7M+QJ)Bvu`<lCusE1_s(1KiYlX{RwI9)|?5m29b!1e9lIQ{b9
zqx<yJeRba4XYFLpKGDBhg_&7ksMRH0t@_I5ArsPC<QOzq<&*h7NLcp9Ey>W5iD)<o
zJs<mh7YV*43Z<JFQS5hGN6Tc^;MfXm4*1q+es&56P-JkT7M-yLGKM%;>E&m@&wjTy
zB#=t_@Ts|ylD9n5LY3zodEX1{JV}Das?QD3#ZPp>09Cx2vWk_ED%%aiEY%uF<k`(z
zwlQxsBMuZEm=i~{sywM>Q?gbig_BxJ4QwbT-!^V`G=B@?sDMfu&8={$_<I>9ktbGS
z?bWuPNzYWK&jHMtgrna=PviAGzaCR8ZTuHB3KIw>OjfE<HlD?l*mO;hK>q!9nZ}1Y
zc?Imw88!%!Tc&H>8}M#9j7=T_>g{!%hpujzDa88hsXH*=dL`?0FTd>ZGMi7wN|sqn
z7byihLpM?MdKcprwfKeK+G#>6WVYRg(dga~j+PD}fhs_M@|p=D6?15P0HeI4)B1s&
zPV{#&uXi1ZJ=1}}M&`#R4viv=258*NRcR&e0BX}HaVWf7s_vJyHIL^~e(OKQ^Gv}q
zw>z!onY+pbOMsFah6=}3xXB`5XSfESV#qCmvj(|)j=u)(5>!}$@&&-Ya`>-|ei!@N
zdSuC<stceiUSe0h#tH>wR;pt4CCw`K!{1uP+F4P>niZ*7QPS)u1O4=WxdRd>D#CQ$
zF!&g%xf`mvTU`-X-`{VXbx7amE8)7mUNWPuZ=m91$mb_zuositK}Y>z@wj(yIqpK(
zIPRN3N5W~Iv<o$?!%3RVvs)<3We-8!s_o&1Dsx5j7y%aJyS5ugs)v7)x>`*!Zog|D
zb|_$9V6w39(yQSh!|-G7eE(OA{7=;)XH~Vx6<=75hNV(iLsxZ(YC}UhPVmD@*QBCT
zFOwQhPlFj6LM6?m1-d0!wABfU3LZNVx=m3@9y06#DKwQu-L11xE|$`@;FXE@OS`gu
za$uf%V23UnTwns;*kDEYYM&n$pC$%QaOAsX<;>SZH9WRyF&Q50E+bNu=6R9sCw#fi
zLW;z!s?Kx9+7fhL`7E4P@RwH)7E#S^G!x~snu@c+$h<8Z^ml>C55n59Qp`5A;Qkl%
zcL^Deo8>GqK6S0hjZaG<Xt{;OHA^CgBHb7Oss+uj*=lz@F9kAsr6ka{1rPrgel;uf
zUg~*MkwX4O=;7YCAc&pi1fkhxAu2hP?M<<{L@`*fopDM!f<(!a9rB}luky(us@ri_
zaS_=LT;5%dX+4VAFdoEM<e@kr&-!c4zk>%>z(^>}H>J)L)^eB>XH~{d%H<U+s7#VC
zab;n}w3?3kF(0V6kWJW|2QjK4!ip6yhF%C$yLk1hnel5thJAW!vLX!(ud`}Sry{s<
z-e+REFEsHM{t~s<`daC3u+cy&O-rw;ALJuMymnIB%frmbSM6D_C0Zo$QoY(xm+!M2
z{%<qVb>V!GN4e`Xv0Y@^fL>>)h$|673j8A+0~8<>@?h4-$yUH{WUtI5!fX|-s#l*#
zADK+N2N_!cF4NTYlh^sz^*!ysWUQ?VZ4cbe!c}t?2*El*69j4hP&^1>e^K0hwULI+
zFxHE@FR+BLb(fezxD`umA#BB<F+}NNu4Ex$I`VGiavxQ)UvL0bxscy5*T5>CiKWM*
z-7K|8@g9A&2`@f<_LLk|R=8VPdNGVo1j(L!?v7Ob=`0~N*uAKp8r>6ug6kR`K~Z#n
zm?B%$&mqhwDM2Yh(xOP&6zFy*FLm2|r3;_(6nvrhq>o;5pHZ2rVlQAGZZ$Nx?qQim
z54MtB0FhUeUGv-EbRL=WLO%Xhu@7+10g@{wtBz#OBO!AmJ06NLBV`IbB#f?!9Wxey
z83Eiqd%Gi%s({Eucup~!5{dJ!kRR|m<t_^Gk7Jc%0`_GmivdE5#CT1f1$(`0e=<$u
z&oA>>^cdQDXn<;53I!#!vcw=!nl}XHXU4kfBy8z`^3rrPy6E;kF{|)j4uQ>qzBEKl
z?)ZcIv1|q`kd<-Dl_tQ-U%JAE=1~2JspjTddbZq^Ne0SmIH-gPGp1zU&RIo-<D5`?
za-+W%zKqB94?5USXfx^qg|!8M!-Z<^>GZ<j1V3~g8}+NmAcD=|z1t8y)2wPbOZ7Y%
z%#)O&$3vTZK67q2ocIsKn9=#EmV@y({U%}&ReYT^cm)4d)eWEO)o!dh!0yJqsx7r1
z9w<Dt&O*jx*Y1K^M(?|thgBdv22*xLFX#dZP_OwZ$f=wYFm6jVKB(`_`bIi|qY-4F
zQRn(;>l(q}^Vdb9Bhyoag|p)Wek7AY6@vKDKE~nag?7>Ng5f)S_`!XUGKLf4Fc5n(
z(IFR0Z-rWwPn3ojzcYo|UlSywbCsxlIi0I*I^?$i69$9w+gli{;0pB-eZdeD7%hXM
z>QVd+P%|*lZc0EDL`EBy=w<eaIPA~Az3k;sf>xcfz~xwSFLymL>kH<W-*Ry~@Z>#M
zOnSIGdTPiDgFQu&lynnt1w$Ar_Whr<gWv&_!T|ENsoC%y!--b}F$Bj+cLEVZx|yYx
zt1fK3gsXFAhjh_{MuWv@L;-`pB<6*h;}7A03>24jXH$fdOwt8b>}F-P=gGJ`RO3=p
z$IT4m0V;%!iCzbQTFN;i7=g*8gEvnnkq-Wy4JVg@96BN%#}c`*{Iaq{ehkTs-u*$+
zHd<w~{;5QkMp8yYU=)zlD$fQ1QZBu=kSG`Mye;s!x5@l$&O;|?Livy}+yYSIiX)ah
zkLiD&;M74_Q){HyK4&lSC>=fxrVzJBQGf|Z^F$v(4)vwcxcgPzmj{p^g%j9JQ$>53
zx7&Dcak3S?2|QS8dl(`gPIQD@KVBCR^`svt2Y3+-bAGp!UPUa(QEU~}tWiOfuWm>S
zTfvCZs=v#|plu?B@l0?u!ABV15K_b!3!Uh+MVEzTgUZ#<hmdPt6-5^20M*8<dj)pd
z`l4_TXr{oN`ROA=&{DcUK1hk1){M<83D!Y7?kzDEYjwMV$+Mp}X+>M-s!s@FrpBHb
zX-B{11l2Bu^ioZ+TI3R1Rd?bKo5mX$XBq1+w-hOI@GO(D3I>=J4sfZQrHKkRGLE+B
zvVPlJxs2cj)f7<pTQtnq&Dd!o)1C`e1U>D<V0UC@-6GtbWZ<GHJR7Vl-bjR%{3Ge1
zu@Fc}fBX>@R6wI7RVA12W1Y0bVR+MdQ~<{WymkdQ-`??F)YR6S>QsudFH_Ud8Z*B1
zJE1N%9xOI%rh36RppuTKU5cCXItD##fm)x<l$eWj%bOzNLlt=+`=t~(BSe1`dZPrc
z<I)ib)lKN|Q_cf`+&yKn9;WY=x=eX(6*YKnGgQ5f7@yrxI_+P&f1~gZmpZl2RW$^H
zt`-O;C|F5ZNXjyLO|*s@-&OpDV$(TOCm%797fp*FX0d{Tj={F<oW+5Xu9sXc&8py%
zKm(x9qBU{4uF4CkgE&h=iJNPY>#&th<8hkC;~~hZYvHo)bv}#C06SpgpsMZ^HnI?b
zUd<(<(>{&gHq_lhNvr#(Cx^{tP7$F&y3x&e9Bf2sPP@S{8TB`~P#b}(-jCbu__%oz
z9|yj*ja_dfv1*K-#kVLFV2X-2|B6wm^~{Z`d%bK_Qphbb$S&~lS&To&>8#r;PH9Fd
zwxLR_6KzWi=|>oQ8TbVi8&ggEp0~@x{(7pkcLSgD043!B=3^JF7V@lqbac93?=-}1
z#bC=gBj`ypfb-+`aa#eYAMJxLgr2<)VQ<#dqA|Cm&vrL#>B{lU@R&I}K2Z0)W+y&6
zeY??UwJ7d^LJ%z<b25CB)Byc}X7ERh{=S|kI-h}|XPIEiW~kIyodPapV4^?wQ&gJL
zY3Ji|B`qrP%4m3*Oi96r8t=hmy>lAZ59(*?xaa&L%Pw_h6Xd3~?bEFzvfBZ}dV-k#
zr8|MvSb)3ep|`EpjrVA&83z=2gZVMk!KP0xztmeN%@f78@7Hnpe5$EM00E5=E))1y
z5KM3a-r~dHpq}DprV?!Bd-uGGit4-xykvX4KsS2?bdid0jQvuwSxo-9gyTQ@<q#8)
zk(Sbsgiyn%`GSQNQcPe`wu`o%lYi3;AO^MaUyVV1%0S<oz8QW5lFC!W>sL7hN!DV(
zl*Do>KPSy-6o>ql(>6R7J2I9@ff*D1<afuDCwtloZ#_^9Dc?g_n9UP)<)d6v-G1K<
zFaaM)3vn?b3w1h)!FW?0dsfa-;x7ajXD{4G0LbEQOu_=!(b8^D-8rI1x?6<|_-9Y%
zKp$RSaVDD$lLK~BH~8(@NAQ2!eJ)Z=hN|siwVfABs_kI4A7rh3rR|S$e52`?lHq-C
z0EQqv|7gT;EqyRfpS&K7x|dqiG_uQ^W@nq6Agy>nsI~Xd93)yXiV{=^jx@(N0I(y+
zQvhJxLmGmxMCJ1VDZ{p6G{slLXS*SJN|Oe(%(og%cV2`9YrS9(qwVW~`V*F&)gfr<
z9;GR~$&^dcm>q1Mq%(VV>dgRO)%CES*dm+0(Ai+q8B~j=Gm}f$fDLIIpfF0Vlinh8
zB*20R)aajA=76`rU2~CBA@ogW=4sxF(FX^XL7CZ+hTxAsBInDFHTBoli873|Q<q${
z4-Vq<{rL2Kqjh+6`b$tl4A0Y$>Js^enE0X>Pd_K~fm-MLjw1L;<K$Ec@s&D1zG3I%
zDxI(A7O`+H6UxV?#4{M8T{Sc6(5l(Vg%*zdy^7Xug_YWonCV|!>dbs-@gGFaFirDV
zX`FNluu=l*TOj7>r}MLKhL+KE`e`w{6SS0ox*1yZ8Dx6UNfntDm9Z19qk96jB_uCn
zb{62UG!2LMg}5sYzlt=%l89T`=o%i;rCPIN_$^la*CZZyc(lCwshLnlLL<}TPeU!N
zX-Jlygs$QAtgS@B_C7e{6IlQ*H-;#LM?-aYGtHkwJL=2h$C7%A6&t?|KWd-2D5T>!
zIIy01l$lty*aDd%`Xg{AQq%`^Upzdjzl~2CA3D~{YG`gNYdQd_h6mSp&=(Nm*EsIz
z^2OTJexX&SSunkIp1hu=pDVNk=yqkG&V;wU3A1i*wORjJtoI=bHI!NY$WX!ra=M?b
z@@IxM!M;>~A%%^eJEY-`UcUx`mc%Ezh?D&5wp3K5TT+djCbLMyg85OCnkP01p9Gg{
z2N?`Fj8)(+Q7)>{5)PAZaK~H*l;`=B@Jravc`4f|-V%js(gT^rL~aCnYQ5bySYZ=X
zAWs@mh&Y!}Cs^ee+FY}E*F(Dri5iaVh{`U9Dmn#%C%`;WS9qT(+Lf_PTAn4uuN}t!
zkX;mV-2cCe*uPF*<sTpga0<Zu`7QY9n#){RDR{SJRmSyJV|(A6wAM=xi=yjA;FX}%
zECoJD<`gum!axLfDb?j)KnwCgSCrpw^lC)6Ci&_qNLtYIYGi!t3_|^6bla7!un}%}
z_J7-hpYO4SNB^Q1)@Ew0jcX{B%t--hRFQY4<}IM?{JZEfvqGQjQFRK?Ri)poov&gE
zt@!Y`gPFZQ%B_%GDy*jH-_QKg2@>w^k*ANM-c{231Q%RGVZ$^ccO-2cau3iqOk?~S
zcT>{p3WRPLd`j}gVnwIpZf0w#Y1E>Ec}SaP193069qNkFEhfWWH_hyzRp~waY2!h<
z>H5`b^cA~Gsa+1%C=YROZ=3B6Y-#gfEWq5LD7u_y#vsT*=wlmbIRE~zc@Q6qQ#n-L
zu5na(ezM<k2`eWTh~iDdeseDlgkt^clh>%kg$(bh<hqRSBf9>8<+xsF)rGb@*IQ0|
zy@2hus)8+t8BjFTqUc5FYK;j})$dzTE14x|9Hq$!Yf(!#!L02|gpdh%#Dw%5$l-Cm
z#OK$o?`WYMZw~^H^;ktDLK79d+bM>W544iI8ifb6d_>&$TxU5BKdAw9A+QE)%iV2!
zz8|R`IiD=f0u2eH+;i5Zj_&KKSgl5Dbw(rEi^~PSB(yWHhU6a8U(7~Bc*i!}aPDM}
zbrpb`Opys)byITUVInfKy<ZElr0u<smQFDMHztfjvdrv!@aqoKD>7)a55a@sM4dW%
zrt$a&2dX$vs~%Yep!jXjT!j5=6j-`*cd2)s;@8E8vWmLV0Fu=j@9Q;&&XNe+LG0=>
zb4ifBn6@8n=y5&+Q^lR-$w$whW9Rt0-T9}PvN`=qLj;X`hBvCkQG>%DQ*AO&1d_r>
za^D0>fm32^1t$!GW{m9XXHAbjHTgL4$qZ4kTY&nK)5%C8%KLOL5zXj$ieo5WOn@Oo
z<~erQzpfP&%@k1=`}!Gq?yS{(UstQ3gt~XXY=mvnH&+n9DrZ}i!UT*>i2&J`>HL%0
z&zI_mf`tOBS;ZXTJUiZZPCj%DCATQG{n<SmW3F-;h3%auThTApH?R-l#2A1p$pkRX
zZi}-8fiUN)A`|FX?YA!UtiOYN0x{G~$EH&}2%|SdRbRSa(VtO)nI}*~-Av%^Up0jp
zK@~+?)|qmmh?P!jY4XpsY3Y)Tn~B3Y*r+My+UqV-^4waax)TY_kT`4=r*{VHf<#E*
zde&7l?NO)cEa?pgz$DO_Y&rlGi8e_p4XK$+j2EK}*>s7JjL~RHxG!vWuSu0K^*I3-
zRWmFWsG8GRx`i85+?<@QTqRb%;i9bJ3cl-q!A-$qmEv%Ad|-5MQh)wu;j!s!LGJnr
zT6&ed0YCa5dB@{d;lJ{lmopIFs%}$r^UIDD*h6YHEwdNh44yuciwfQ#`kGU4cOi*J
z$eiMVJ2S6<#Uehxn&oy!E==ii2|%9bcX(z)rWtkgT$58U`0E4tllY@9>FWF&C7+WK
z3<x%JG9Q42ETCn{R*l?*Ir_5_G5gmazm2d^{Y=U6Y6v7;#^hP=pKnyg;QuwbyJtgE
zk---@Q)ma{rSyx?R%Y)vr|W{ArhH*qk@^rpF>1}1#;=(&^=}jmVG}Q0-QJd-wdHFi
zbT!rMde<~FbqU4>?rYgVv5TG*;_x)V_*&LC%utQ-3#%Z0g&tH^ke~j--DATfgB&ck
z&P#XGxKZC!d#!lqh4#FeXCRW3(2Y*aU&1Hgk|z&4I;$FmF(P!mYA*vJ_+WhQ5cCio
znvHwY*;m6ojk#uJ0<XdgrTP7Oeq1lHoXv`>@?S<78pM7(BJn(vMMUi>oTwQ24epgA
z^zuyl0rJUjA#KF_Cm}-+Q4kZMt>SZx+oPeFR~+Vi=smXK&b4r|t7q}@98JOD9ztLR
zFByRZ3u;+zqK0!1r-Gy?S6^baHtNiorCQIXeq5@{Gmle7WQu#;S=Sy$!r2OSer`QX
zQi2153(7!;HGO}`T5Fur$@#Gk3h92`%c~H*VT2WkIUx`Ah(aLy&tyLJRe>mnf%`)?
zoRGF`nFMEB5guSy{XJ4xh4Viz!C`gsrsBg6YKAWKhOo7PM-aZh#fsqvYvQpO3i0vH
zm7fn%XD5=#|MEfK$bC8)G|!l?l;{J=J6axcLwk<=S$6x+`4pkK$>+ha@47}87>hwg
z-lx403Wxtr#=K5Or{)PI+Q3(sXy^az+DF_k(|I4Y-cBMs`a*mWx==J;2#=OY!--zu
zn4+iAGsri$#=!LF2mBd56h;^ll#FtA*lI?@`N)<>uy{Eij{n}+IX?m)8HT>;&}9L<
zKZ@ab&|Hm`m>J>XNf|Cyo%ik?&pQuqwRsoXMBcGh%CSrMt<(nEKUD5Sp;d0guwPxl
zRYf)Xmue;D1J3^onk{WsUHNs~e;hBgt@p1CPdPrLS@ixCAMa5ERx=qi$OHgnfMG`3
zFGiPZsA$n9zi(>8Skqu<)dss28pt>>|MFHQxs#91IBXTxY<7!H5pKNto;I|7w!fK|
z7kGDB{bz*nJV&GZVq^a08@=R~UH#qRt~q=un=U>Io~@$!{C|jxi~HgDf0_7Awz06H
z0oG^2?b^p4;^VB{#q6_J-AR9xe3wRGqsBaai`w3TZxR4to;PQl#5qe?XBFOQ9#=4!
z)@VfGok1W~!-e~%qKc__*dM8(5Mt<%({DRfUz8m8#=OZ{;DAl+8&m!%slY=0uik>U
zW3SQzp?CEu#w9N_Z!dlTU=RwNu4&%8CKvIzfD5l;fP6QGR>jI0`#vXs`G>w}+F3-e
zrB|d@yp)H|M6I)An-&~KY~xfb%tN>M9GF8a>X*^>e;Xa6ZB`2oqLAIn0|$*^T&oVW
z53`4luR^lj2GmDl?S<N?^z0Jn)}3fj!U`1HS7oc<A6`a_B9E`2k;(chMs~<K5U2l8
z2pdL^!7=t99$x=p+@zKo;5jJ&$48CHWvE<V6DTW3YYwl~DVuW<qKnSlBz@Y#Se({m
z53sJW?V&q>Z=0!5pPdykf01Ngz$n%1c4`gQW&(%iJo7cNQ6)XBq{OgF)-L`wExfOj
zt-knneS&)18&X3xa=24^Fl2zH!`;z5>Gr?c+C~aNvvgyW&?VEhRVhavh1>4CL&!e#
zhOgkcL$Jyjc;`>#eA1!Y?SdZwNrwubV7lHX`;+IDn?E#!MChIvLJSLw6!^9$5F}9|
zF1zdQtMbyvdO1UWPjk$r^JkfZ6MLFbdk5STRUcv)tQXi?g93AJy^1A@**EUvL3IO1
z$FabhBgMy3C30y&AFS4KQ=Bk)R5-Ly<zQcKSb3*24ZULX3Fs_@kCBfgK6_swP}oXO
zl-s2blm!ZjzwV8)WZwrK8SloiprT~A9(Wc+EUc}xTimz28<5>MkS&e(i~BfdPrR4#
zyEVsJm#=ay`zqJUzsfmJa!cbf17nWIzhj!I((v>cluMV)uXUS9{Fn<=FH<UTr9BT)
zW}9crAZ0$JJ3RnhSJM!bv%|{AXx#5z0G2Qf$|LbhxMn76W~QcA{V9aSnT`ky!5p)m
zzcDcjoLCE+qvH5yNK^6t_~2&@KOl0yNrb<W^*dbuVE>J&9WAYWdUEvZX6OP7r8%Wi
z&83_NpviGRnCL9#v#jD?QcurLPCM=Mvok)#B>G(oR6&<&8}rZZ0?8FAXq<VC?V2I$
zC|(DJQeFnFj~9JEd94oGtd~Zw(W5WxVO;D`m^G@0m;TpG5%>#7xi?t05Bm9DYO<5E
zD=M<<;5c=RmFID1zm25A?5?cx4^VkCIIZa<fUZ`%9ntD*e=9xv{wCxfet;Pt9-xFj
zzmEFDd4m2b<#V^=uE}97!$W9dY7Bw~^yl!p;ZCNZL(Zpby)TmA7hTE|dJTng=$SwC
zz!*x$?H}5#`2G-|x7C@Y7~H80uacW3jsc>a<R)rL+{>bg!9c|i`X3|A&grd>xYYSb
zm`*V5R2EpxH848~kFWgtRyHxchd7v*=CI+~2CuZ3svb9ZOj17T`Kai1aIHdw0m1I6
z5$@x0cQ#8PAFAExnk1;!id2xlx%!g81$b1=hm*?~yyD`|3hUGGBbiZtQk~dX=Oh!Y
zwY3pE5hA>|M3|0}pI!_I`Z(+_4Q1k#W%Cga5YlE2Cnh2aTD@&lsO!Yax1*()eKg+b
zOe%V_-)Hza?kY6lYsI!xtcv9CmtJ5M2&<^DqSZeTK?R~|wwfnzL9%$?*zcUSv@IT#
z9yE@;(!C1dS*A1RE&2B+uhkf0vraO^4uw1rOGtSdem;wvC!M%?5Fb&v16L>Il()mZ
z#8)fz^KMB$@30>_SS<~i(}a)&Dg0U=FemsZk|l2y8b9nA&y9R(=L4p<K#+n)o%q9?
z<-#QalV`3&-5>iOoIDq*o%0}B1`;QKU~^~Cuj-sKyQL~57>k-?^WcLsJpLpHcsVkQ
z>4Exf`(r3}g;&cV1#~fG{lSj=B6^cpKI$f<Z~!L=+?HyQq-TiB?^!R>KD&S1o#7Sf
ze4?1?eT%%B<XiJ4L7hsHFI3=_CcK?ymqiM)67Oa`T*_eE9ewG3P02@XnD)pQYrdFe
zltFSx?zq}x*R<XF?-QMf6<xm}h!7mBpOX<;`2ax57tE<B9XMN2=Nh%$t!rHiU8m94
z7nJd8sV_k6yy|j3RWmNiT8X3Bf*A&~zxGB+cdk8=!D-rLo`h3SXTHSTOyEv@CGsP(
zgR$1n^Vndd7BSR0xN4gO&2aljr|Lg7bX5z&LUk9Zb@o^28TLUGar>!3I@v3k^LH^x
zt^tv%slt%yv!;>V1=Ck!A(Zr3{{Tn$I3=|pcq5t>=BT$l2?_)w_>Pk^MjZe~Rhj^D
zK#jj|F^=3k(Q1=J=B~3dU~=mCP%`v;bw9&2(KHPBTXzpL8G*~FMH)J!r^)<tLW)`4
zU97f!$~zk*_2cFV@b(%`OP6g1l!Q3|Lgdu1F>SSvFT1m7G#n4rK%UOw6-NJ}L_<Y3
zU-j>bP%fu)MTBE&>!$2NBL_2?-n2VXj0Ur;A{M_(ZK*XwFdUUR1&sER-u{O*|44Ci
z$;u<E1?2~g!}|GA$G*Q;1KYVJ*trYVG;O&}HNJm7+5oI(0<D|+K7!kUZ9_(1*|q~-
zWwtRXGNOD0`DKSoF!+1Hn0}UHT6Zik!lEcZK~h5j$2=){LV!YHGz{qQ0x5zxObpyN
z78B?*>U@ZxTfChigVPt3=speNr9N*caNLkbq)(Bc_W5q+)w<2RT6aCK<wqn*sOpaL
zt#V!#>a}y}Vo~3!K!7yLiV;Nm!Ty_|x(aQBFk}~)?ntc_+_}6nVe5XmB1-dW-b(SH
zXTn`FuRh$5+nsvnyp6_RXLWTc4~+^!6_F<&C5r9iAp?Ws<b5!<;bbsfHX=cgaD{Yo
zCwp&bMX$5A$CoQ*L?vzWXgK*4EBPbo7hW$ZfrzO`nT8$1M?8YtaDW?WK^t1>#p*7y
z>61xvIaR_2NkbP4WNdTFm922ME{~2x_6RQx=+hi+Z`PtOS3`C1Q`UJO?3NbZkZyWi
zwTHoII=z}MM(9}s7~wqhGVF=$Oej>3nkPTS?XyPXAg-Tx)S3M@diao3u-c)LCm6#>
z)Ifqsll&g;mGzKItxXGsozOzT!pQZIj3~z-mNEwdua&8lImBJPakH+yM8E5@ksM<5
zdkGA(^wn9WC-i9_P)f=h7qQDS34iM(!c~w{^cZB-_cXKI+s`uQZ7xd_RBrw5j+;NC
zl<!r}LX|U7*_-7&O=+h3hdoZMbqNlN6PEyxfe$W0QO*Fh_*?(5!Go&lQEd7QiY;sL
zW@VU_7sARvX(+DZq(A(O7ZG(!Bd-6nKTPpokj^RClDc>(X;<IO)Kv|07Ar&y7003I
zObd*C7igcm)^#&`smq3A2#N)^zxqN*_dJ|Q$F|W~>uj(Pbtf5_@J~2hq1`pNCjrfj
zz)94bvMJDFrX-qA{#5xI2A%?Bc`OI_)YRIFrtoz8WeAMfLpxm4^f7?nyQw-L)G)WA
zH;atZKV#Q=u4*pBv6^BpnPo#0LsP=hckCcC0%0&whoic{Z0mDNvy|vJKwZnytZVzJ
z*7Z|`Ffn>ZQ(}a>AaQT+tp}JoRAsJ$QcR+G@rg-)dk!M&UVvvBZl7nG7=!?Zpr&Eo
zGHp_@N-t?HLRs|WuAGy~?Mz#>B9+5K6JLL<-54N>9wCrsXWibXg!R_yE~F3h<-=9L
z#c&<=$VsqM$UveSsTQY)hexON18n)O-hPKmqS=<^u=XKRurgdK_`MG~^B_3=D;;&v
z!4<3uRJ-b?S8QibboWpLtAaoe;5b{@Ox5l|kS(M$!#x&Ud;$>g#utl0-2Xa(T>uP8
zk==L}&y!0C*fh6YEFmdxgw_ZLO#Ca5<WnssS`PlUb&AVR2Zn#-nKgYFTGGz`S$w40
z{~f&-qL*fE<hG%d*$O;vZR%#pFokyVI-a3=Hd9PWPq5PdZ5()EI2iuRf^!g9#RllP
zHY>2RZS7rCHWIkcHtR>t|LY8;)c2s<1F9>3u7XT><5`-2Y9d6#qz3abhR>~-p?Q^n
z`Gj74c0Ftzb0m%ORN+PAavrZZx1X&OQr7FKoBG3vtZxmNAV2p}<Kz~(we_f%twv}i
zR&nGofTr`II?KBwn4q?`o(;CfGo2)c_*7V)m&Aj%rL$#Gc03#9Y~e)BDtu26!-5B6
z9Gp}QEg()PWsv3xRvLqry&?h-91AiDh(ZHFXmZ!HbzP$Nx9Xq>F%rvqbgFup459%?
z$DQ+9M6hvS&@O-^4@a`c3T!|gJf+d|i2Bq)bkqBiQBVxPidpX=1u=R|Bn!+Qk|e%s
z)DKoySb6=bd4eHNdB7(_im3Q_upp6NNup^sMMDDi47x}L5S7PKVcoCEsp6fVp7X2<
z>CJij*F75&s>G1mL5aR0*^f27r%~~%7-9Xm0sKbZnU1^H!?C(ve(sJIsInI@m2_r|
zS4?Ak%Nb@Ugs0s>GNP#T6ps_Ib6+p}eSC*ikmtjKnDl~s0g5+t%S}6o+}>Pnm0W$<
z6cIgGh-gsxm8lt?Q}A%Pnq4w)BTdsb$7>G=XD)O==wo8!Tx()RrRJ%V3QdFPmDNXi
zO_XRv9-r@il{%@N?c?~}0r=yBgd-sR5maGO^}SVlSONTsuvZ=aO~${{1XiEHD&XG=
zlCrhSX=^Z?U;H(+b=Z8Pq#9?uD@|=R*xM@r-(D5^?)TN9tGX*ff4;)lpRYXj?^l5S
z{mRf4#jb+*)iJ*c{9S~<@|F<WpumpAi#vf)DU5$bx3?GEB6@qM3aVDpA9h{qspG~$
zvraFJ`=@7Tjg~jZSH@DY<V--|{+_iqSB2mT*gyd|F_EGNkfn=r*!<w!DZSNkgh_Zy
zOJSTragu-VLxz}^(IfbKnT*LTZuZdW8Bto-HDhAo*cMrP2r{Pr4la#Go&FujRv?e4
zE3DcI(}~c~Dj|#{vv%{z2LWfEq|?Q`XKaRyZbUwFS@%+7Jdbt(Y=i$hWrkLZ=g-2m
z7J=ng2&Jp;T&N#RvprcO6E$3vxL{_VvJon8@?s^L#_YHD)r5PaMV}2}xb+YfQtHyh
zqAoR8m*+R?=s!Qi>%G&L@vV)Vw4}njSJYKf;HxM!&L_bOhOIf8PoZk;j7m-FsCDWN
z36wLWq0%SmMnFx~JbV8<-v6n6ejNQlhA9QQtYvl150=+y?{}70Iz8_w-dt&1RJBUa
zKQ$Vvl3MAq!PPqoTuBX#+S2Z{nrF)@9X5~3L1~5W5~Qm|-82iD6)$L~I{G?Q*1l6=
z?K>6LzEfrGMWthPWo*Xn#@qIi5p~+9B{klEfJNw>94)E$w$-Rot8vnJU!~$Pu!X~V
z8*aUghOUUrJ-eoakKGv_H;|Z2A9sbuD;{;Dvt*bO#7UT=1k-+Lf6bEvwMjZ3S|3DL
z$kB<~bQhqm+pnM1<JS2}r+Ey9OYzU=jq`?DxXyWQZ{(_Xoa%<WO-~PBMgN^^tfusf
zf^gKpt-N$DXPq-K37-{)A7Nl{?N0sp%$`K5A%-Lx4aZR~&buih9l;iOP<O8-Pe$7=
z2=P?Y<->_QNpj`g5$H3xM*XPy)~)lW9a;9TH8QM|CYOFcYQw;Jc?M2MKXpuJsKnEi
zNxHp`C(}usrPKHVBYwKmb#8<qiJBFvOi7fgV1CW-Xg+$VfRQr?y?T<w*_9G@uB=X)
z^jED9xS8Y5yH=z9t|m+?n=+)xWEyopcZVa4rPsP<T`j&L%!e~DPOgEFF&(3=Gc>1H
zMtW{$lkfhVG<g?a?Gu!d)ui1xL7)e2Ynll&0TA?5wS&kuZ&XTrCX9MG%8GE5NgOF^
zo2LaB>cGRNz)zr0vz?Nxs|6SRdI<)T5LypDo6+H0<)`GUBjv!E`BURpSISXceIX|W
z04BONQWP`;+qlzK$Bx932(SzkR4*3u)D^4r3^DsBJnksD4?^TR1F(p^D@bBYYOfd>
zw*U~b(zYXD28MJyKw?B_+Zvjh;Ra>HsM30gVcFnI%+@x`FK!q|;gM~joni2uEsInE
zYJ0!+4Gu5tI`|$@z8zEO-71}^4kp=PLkwMy7Mx{9i!Jg0ec|Ji^U31Ir1khERyT@v
z^Hkkoe(f}#X|F6{ik_>|-n=37-R01CZw`HDIrN>IL*HHweOp17b`C!}_L;^plUDTc
zD|W+xphReV1zSMfsK5J<?eEMrnip7s+8_em3|JhB{6xijgrg~<0tGD(VMCT}m6h!<
zi}%E)OVGk>fJa59kUH!6ruSMaE8(d12tBi9wv!dWB2OK3aQe$h@uQ**SWnOT0Eh=w
z#!?JDd6l4f^a$SI;io%B=Tfzxs`6!+^{!ZVW{pkp_y&7rgBntjLB#i+?c<jvg{7r$
z%UYHc?tWiV_`Iy;_hp5k@Ga?-O08~D5Dl6;>1C6cLziy{m+%yKF;BYizRpM6O`zt-
zcYgBI3DT;CuiXmng&<c3d~$ly0OIf(K=`}l+L<7I+RIfnJIfzO^mli&scYZM(Dw5I
z8g;IK$lnT|{IL=nu9Y75z;?cLhZz{fC{cR`VPJE)Bye#1?;86*fs<0BrPy?&=qCd9
zto|Ki5Jsm3YS(Nlye3Aw)M7V{HlVfoNj0UU)6=Xw0w8zE0*n};*ce2ho@9>h&l_D8
zp5a?dBL~x~<??WCJc&=(phG5$19+jvPuR3S{W94yXIWr2Y~>)r8|&V-mXn5Gxr~Or
zs>}9Au71gB!j?AEg?@_fPkqzW@YyR)v0&t>yxETuRU(UB0Fv{9Hc9&|;}FqY{GAZ}
z@kf3e`(7#MXPW{XTR!xYQTJ;+PB)4+5XDUXa;3(OQzHs}@&pfe9lu*+SqAYo2c~p)
zcTZ!pyA1$<s#f5oJ=z5cQ!6wP3briZF<=YDeC99kRmr<Kb(BzeKf_0W7_X1_O`1;5
z%F{RY>QS1g%T&KR{~FEaQ}8)L-vYAU7oKeBL7u2P&}5j7(O*`T4hLVgAGR9MSOD?!
zH7DIs%td&?-q_S0MrW<leVFTUz4dFzXem5CcWh)CgS5Sv`TlI=&1Ouu*IC^{4iB8q
zRkIT|f!7JFkv$DDEqBU3bdZcqyO?u_+6EkK>%M5zQj%^p<O|jCD|np4B@i>6Ne3_O
zlAxAk(PLNm@vN(;f?w1)nQHfIGWTD}TzlAi!XUQYsVmeT2y`OfpddSed82FKcUdtO
zW#I99(6=FR;MBe^*%F&CX+DL<!9DVh5}9vrXE5cOT=Ik}nqB&H6L#>#QUGJ{TnKw{
z*3GW8t@O?8sKR^$I{sJV9OynYjrxo6_^Sx?kYghVr+BMYV<QsCKaG{35OND<!eKJ%
zXHASXd;t+BdWuQFe!~v<*yKPH&|R&>|FhDThjaP1`;+N>It!9{$>ueYgz~1yh1=#X
zHn+jtjkY(ioZIi;S$Cc$G3<-jz4<%V?DCtaOJ@4|QdX`&EH!cuhNgVTcGAYfeS>;}
zZ%j$rvhNUG%Nt5SJ!x!)RZtKE5W=uRXsj9Q`j<dEt~XCMbG|D}5c>NfQIel#G{s2G
z-N}AFZ?t~Jo6P=6XKig~J5=00f;ar*_Wo((<X~;b#awP>mO6GID+PBWB}zs%(x!F?
zt?cwcgTs6#<l`^1#N-@4a^sYa9--?*VKAlTK_YNDtYpNji#MZ4(5n8-i=sfRi|hr8
zbjYO?a>PLRK74heVf=1sY3T(bu$;~Xf*0lSV;#rPArHB)3$`(!iZZzbh!j-7YN%*I
z^!p568mn02-T98jxSXngZH+EN`y3uMKG5sw&u4g1Jw82X_!)r`QZ(3TJ=2R!ZE&@;
zgZWgQ)5G}~9}qE54Vl}ks?=Jz(V9pYIsyU*HP9}uoX!V4VBa66Tc&q{JmIW6P)kiy
zarmq5=LC%P$KA<S=+N{voKV~GG|e!CLb`<#z)|xJ{9|8?dCvG`d{|rO&_D2SN;6|8
zy}=MXb0J<9Iswr6qGw9Jo76Qy&=IiIT;#0Lg*R1#deokB+z9Y7P|Kkt9P)|AK?mRh
z9KcMkH=XxU7@9(Zp(;>^l<){95NR)&bmzlqsu2wf1D+a#QF0A##u&^cO)!L3x8EO9
zJPW`hk0DXjhe@gfPo-Um+|*wr!bu2*L1RR+S2v*^C$gAN73%!4st*}BY}*O(Bca+o
ziy_`QI~7oXGNJ2r4IyZ_V<l(dYu&IPT`I1CcPb@JM%&lVww?7;OCi?QzH7sFSxza@
zk4CTLi66_`V$>WRc~<+?xPvt+m*vn(1GP#^#mENOs<spCV-`Shwm)%DlkHXWi31`J
z4F3h;pD1>gZ~BRezqHM#&U~WH8ESL`2ra+dda$vW)Dd=`9vo8GzTVw|)qn9^#Fh%<
zCO_GH2rY@Pcg?fyA9x*>#wj70MI8v*()BMs4ZLy~#wr5L4aF5D=e63c{a`}7YT+9T
z<qeV&5S3EaC=0`wlaeGJ98cIhDX=T-C_z={YyqyYCd4J|i|FyXk#d3+lj}@N0v;v;
zqJrzUx$Z}Ufm59>;sfcZo9|Rt*o4HzxHw=tcn$~!?LELjiKc9ZYG~@D0m&z({b)=I
z2?5t;7%)&2IIhLW)@?TB0QN-V@DTYOItMmq9Hd%l)VLMr)5WB}m~D6^HQO1O$6$}{
z%=({mGZUYd%uF_3Ix`2XJF|oLdRA^FIV(|8I4c<}^3}TIIstYH;Ym!?_EyV}_VXO-
zlu4kr?r}!7)gd}0ijlS4r*`2r**=hyfZZEhx~}Vk%jl8%%e^7H3EuO5_=8Kz@*{a1
zyluUBE;8-K*?1OT4KJ_uY<>jTrC{NOmJw=47PZ@R^Yewh?%h#r%Cy7$-gU{5cifnh
za7wAh7*U_S7|K@b*)DHX=u365Db6iii2cL2amQU7@d;xuQ+JB{ph@S=J6&`7R3{~6
z9+iQaL&ZcNIEdNR*O(K&tT2EbXV#(<a7jehh~p*Y77fz5=|*E%v*6h)>dYb_Uu1hG
zN06BONN(A43t1w#p9K0Ah1ffjqDaArL?|gfcRsj7*u|LnxvjO@Je~!~2!a{n61@wO
zktilIaz_2ft7s!XD#ehW?I2&?F@&e>2=znmO~-9Vrg=C$1s^Z3A}B%dpu4~!TBpK+
z5W=7-B>edScfF)U=+FcacNHMoFN|JDf8b#|di^@u_yGctZEi*nl{7vWtimjJG_$0R
z6kF=X69}t6?k=Op?T?nFko|V|VmN~Mv^U*Z5@Q_m@J;im+4(iRvThZ-vWxL&MPl9F
zjhTz-;r#f0+<9}PdaCc+g)Jy<Yk~5fI|{Rka$JrC0&oZh-4Fq-{xP}QTy`C#N~ASD
zbb_Q>T#4BizLOk6&$%PKNMog+uN>{jx>n*078%6xg!iaR4g{WD&$^S8!gm|pin_F`
z@6!n+zE(HfT`&(yv!vTcNK?3_bWs%o`d^CvHTt?mR{g3uB1=CLQ;KP{z*pB?b@idw
zABtkPfb^lm4C2Z;vr}RqT&~sSx3j+$9pG~lj1M9z>zgpe0K|SAb%UCxNtAN7-;7(0
z_f0fCg=7ipdi#IkdX3SSn#g_nik{Qv*eu^Prmh;1YNaIA%PTQk`Eup2m7zwDxOUEg
zSLcN@B}b~G%aGp1v^(zuD|s2wEfL=zNzgQzB8d!6_K#wr1_Fz!!Kj;Ft*aUSe^*~#
zMzblZD)2eUxvEnQ?8J(0Tn9)-H2}2^JnQ$@VWuI~uo>yn#~>7dp}X?LCckNsn@$x<
z_wFa}E0l{-j-3t$DPEVI%+uofAI$#abt!_e6THZT0IbIIhlb}bQ#YupLgVnZ(IJ7Z
z-l|*9p%o8)k_#G}5Qa|=58DdDasE?V-gSm*@$I>JfD#ngX}38XdUT{@H>=ymsGFp7
ze6IE+lqHisDX`h|#tnB~Fgot(IRB}gyNUTDi=O7b^Q~}=LU@^Va)W&-o=qh}!4*{A
z2-S~A3{})QAb0AGsP#BoOX6S2%i<MY4)GdT@hO&q=3?$ya_k!SMXcyYHc*JRb~e?l
zowIk$lace<qhcdKivD5@=)yoMK&b%c?J^*5mycvAjP0dB$OyX(2*nmD1@e69NS-er
z$@fcve7_tB8-FiZo#j|r4rbQ_Bdox4+WsQNv*ULV>#Gf#63vp{aG;~e7OA1b&XUp?
z_(X{buG=LmPJM4X=~vf0IUt#o9MW|4B`$b+FxfbsivW)tXAs;>>m6MWGnqi<px;N*
zNmM6_AY0sG^;0Dbt)z?65Yu?uoVwe53EK8g#9ZZ^(x`A@09>f3cvV6=zwLa@&G15%
zwAQsYgKHPM8EiY1HVfCXpi@o{!s#bV!^Br3e{EHj$C{F6Od``@jn`pn2RaR>h_G&2
z;Eo!NrqfT0S(KrRuShzNiTmtXe_u(%Jqm1XpUo(_UvOMPOeh}T-YP7{d)umx+$AzB
zJsrV2mtu+gZD24g$_5f%1x3;@1WHn5q|=pzOAlgRywsvA21x!R5I2>M0VV!G<mUK9
z-C;?ry4^VR04fP*VYHM!G?jBk4L@fqQ@GvmU8}%a2K?(uMe~i`Mqy26y<yBInUDDA
z>W`-(cc48HJ&6Fv!@hV>&{uHxCZ(aMUIb7Gv;Uioa>QX8f%18%ksBQY5=rkjrPGHQ
zfvU-E6nE@ziIJ`A(4e}aKwcB2wuZVU9M=t(E3B%7rm9sjt{PMYZEd@;zr4k+Zm}t^
zM;F74a^M(Rso7TSeUIVX-_T<+YPR31t)cK_mI5>(Hdv>o3eeNAMqq<c2eHe!jlSP_
zN)m_}%Fha+axX%85s1ROk+o=r(ZPz!Nl3$1`}pi$n-m*AWj+Ikf^Pgu(4`(C7yVeI
z36eIu<uWDhI(vk>iRFYq7RW2-G`t+ei^(u^+U%d!kJR<D0a?t>AqC~`d0RIEsYiAK
z@@e~*c)xxWpS2t32dDA7cpqcbP<;%RBO9p7?RU+?PFz<<<3Y2%UspF~FpJYIFz^L%
zuheO$q~CUY&^kRs<IFZT+0ktv#1~u6iwI$4J_12dIv=1t1<U4_Zr@^$4fY`BT+U)o
zcS9%sV7fJ&eSQ(Ay=-Qp(OAu#h}{ou7Jb#xrxf0WB^K22&;*>pZUX#4Tp!aH3{Z#7
z8!HMJ##t|>d{S;^0O=kgj;BI#ArP!Ow<ippi@iarK46b7z$*L0H2|+pt@WcLDWp~+
z)Ey+$B07B+rqdvqzAGWq6{&Pr%jktf`hW67T1KNGqf+M%vXnyE?7kv>zVqm_lspM^
zrJPds6}T|^Je=>gnx9$B_{!TFuKFk!F;n|_7blwI$eKmQ*!G3{{xS4QL8>8_7>3)d
zNr#rC&mJtiH{JAZ(#Vf1pcePfpn5~h1Vf&(szNs^ZSbbP|I^t~{iN|Sd<MD`dDHEE
znyKxOgy#~RN<fbi=;wU$X#y6tW7{9(1iq*4Q(^^WC&uDZy3;R-EiZKc(&XcxX$=Su
z4C;SZK=sVi>~jTL>%nV8Mb$30%qe)w4fXsSX?7=KrnAB2mb)Uw*B1`o;aGII?FDNR
z?@dt0GXp9~gELOXz1i0d(;Gj4^H9xi`FC`yAn9!hyBBDtf8DdDTO5mxD@bD<QE9%c
z5@c#bCJeP_FpV9*<m!tenjSy0Z+qk*b?DHAV>VGUp8vurz6z;;jQ(Xlom`Sm-buzS
zPVYd6g>;06R8K5urqN&=BdGMXu<gZX3viVa<v*&cM1I`A)LSP?8W0i*%%QUn@1mfG
z;n!w(Q$*ijE&_pNN6g6fvuUJ1J?Nc1lU3?KNjEu{M0L?IFR4|MljeYvA?ZMWLSZcu
zc8RvgHr4yep`)xP=m?zz%tNhbVJ&x+IIkR=?59zn1L?YN?tzL@aa1$(_DAz!HuFq-
zSDsu_M~k;N^>!m}@4sVlf$D$hP9Q!snn2KyfnJP7M1`Co6w|r_M-TJZuuEGNfmkMi
z2zp|@T=t&EH)Pg|*qgPV(8ANvR2!TdXd>4~)xk+?Z*N$6%lez4O?2_H`UzEZp5FvJ
z@~C7uD~!Zms|HC=d-Z##;|kZQ!^S>F1DTIG<897~cIlo_+mh_(vni5xc@`(MLm&3V
z7dX6T>dU%TTstM7p)TgxR0r~GkQ0}n4vgSidO3i30Niub&2UKuE@w3PtXoiwO1qri
zn31q4Ykmf4j`1bGvskiY?9F*>F_;1{CER0dt$EGBPBPz+By_j);&FZ+_DglqAuo^c
z#!&r7Ab#Wp#;R1el>gc{1RL0%Q)@>iYTx@qZJT8;sA$G<h6QMvH3936gR_I5gtZnX
z68e(Z%s~*V$((QSgUEG?j#KO?sH1+I9cnWv|Aiy(n<5@H1m<(Q4^}`MX`ml*^8oX+
z53PI7Z4xoF%Rkvl^wqw(`cj^ho8>osk*2sx#VPe9=+*ahSyH?lWY<}`Iy>OReDsok
zaPIH~M|8o>WI7c_J*pAtPu|p`d-pi@)Zf*9eu=3LJ%g0xLHB&KqQY*afwFH(#Fojq
z+Nz7q+~vM7!rwO@O2x6f{pKTiTMZ}QejwYGM#45a-*P0Xiz*{|{_Sz{yc$lv|MnyK
zzS>B%$<a67JJl%VFBr?NKbCTh-Ei``J5tgJX$;u*!Dt-9h75T&4E&$0yissYCSq9N
zT0%qHe^)<w+dx4|zbxKf$^my99Pd-+^{gg?L+A#Q4>>nN^3Ps(6qdFfy&yY~q977I
zGC%%xZpcbhf)S`%>Zd(vcU<GB6BMm|ea-&Hx(Mn0%FnzskIV$c2f;~w<8<{(%<2W@
zDNpw!gee#mjNV{Ib<0EkZTJzRj%Yg}qlbtdMsJ#(jiFZ2Lj^JTA0y8T6(ubhMC!PK
z88oPO-<8#CZ1wa-4N!R}vG?Rvl&e=oytA}LiDhp?TxzX4AM`5eWSsbXrUdDo-5=CH
zS&|En>bSJh^ViznimIF)Ky)Fnm~Q{H1`D$D{ib(4qzTcestS~bKn3cGjO9a@z<i%K
z6*bA>`4HYAPxm<!c6G`Y6cQ%xEr&evEy&XCb>YhFnfs-V7&jP@dsyz`XuwfE7j|F@
zFXb{z^y;kFvI(Nl8?szb|Bza_?7m51bhr1cRZy|*n!jG<Oa@S<pg(@RXNIbNEzb`K
zIly?OdFhk>#*Ge!Vg}BAL^j}6^%+;<y@VBFWyIj=&dU8h)@;t<ab`8CRymrS&AJMP
z3=;U3el3`>=QLiG0$fOstL|E!uG3okOuc2#bL+)58}!Us+1WQfZWw8aLqqC4Q{dDD
z&jmP~@P4?V_>rTs+is~92yCP1UCbWy4<AN3GSpjA9IJX;7NTAUlD#4BC)1_qM^XHL
z+!BO2pF%sUh40<{8ZmxBxl9NirktZOo_@M9VUr$PvPkvWOGtdxovWJ^G#L-oMMV6b
z^~|qn)~`iZL&%c^@j|Eg!``=(*#pC?MVP2d{W6}V0md(g!o0dVRFaQu!N({KNkEU>
zSSRXBY2=pjXHc~SE{-*B0NC;QQT*mth)E@Se@s$|7iMM8rlj@3IgJT8xXOT0YW?7#
z*=e4h)Q_M)0{l42fnHy8)*Z~22wUFByfv`YAy9@-uk{ZbrIaP2xfEd5p6BIagk>RG
z0z)cSY`~n%f{KN~hKc-X2c~C%A&(i(6Ah<;2G#^GNdd@~5L_+jy(+X~BxMI)nv4cp
z9N9vQ^+|piiyDunUtGD{0}N~N#4Mm(@uzmu2hI12Rvp{p94>?jSJ^ZGMrER1HZ7MV
z|E#nr$*!3A*;1_XslYqp$5+t_sApP@cB2K!Gs*1~rep!?pB_bkB3<>Y(b{jEbfTw>
zL*xMJnBwnVPX!>K8usQ)LGL=lq)T}W8B3eSmgw`%o%LN~)-T5MBr2sBmndwPD=ok6
zHNV)aT|pfpQiuewAjT3Y*@LaLvW_w{)V0NdPUfDW6P=H9P?Q1W;GvF>%WS5C%<+GS
z_N@45RwMKeVrHy)t(u~x!n=^e=5KaZ->Di-3U}J*l)il#F*Uj0m}tbuoYIWqVHe!H
zNrIeCvf+dbiv1z%Nb$8?IQ=iHyfdQ(qpQC=+wx@qk$X-{o|9Ps3DJ=iYGFl-<|@+i
zH-yAok2F~4q<Z9Yyv^t(_39EQ1uM<1fZIbrM3S34FQMb+HDb4xw8M-5P30$3SQZq9
zhNDqD7-og{r+<Au0CzL*Hdx9A#@$pWV!9)a;Po!0M*o`XER}ZH8u0~r)J-!Er_viG
zAQeFL9`()9<NL;&<mMT@Cf4%gN!80H;6c@ZZMng?*&J@leJmLP)~<93g_?SsLy&Wr
z3Elsvc=7M-2d?;4_n!Rfvaq!<Tl5#_$rG~;jigp#Gob??PCd8SuP8-j$SVF0w(1HS
z^<R6N<~Jnlz`(BkHhZ*agZ@9YJEJAL(rn6>O|s-_<<#cHn9{56P;b+%wrvC3^QOD=
zFWQ>Z$>=LTYZ;|L@y@KeG4<o#{^{{q<D?DmK=A0*XsvBuKil8l4pn$pKT<Ns877!s
z``*-m#7FTjNAcVG*_vv-^Mh*r?G<KAv|Og%Rd+OC`I+TrcwF15%tF9<&(*vYDC35%
zGUvwJ!@U?=fchtSFRpZ5&x0tqt%vUEY`}RuoM2$O&)v}i<7s%Cb_g#&9D@(+<2MA_
zHg&Eg6A$nH!Fwfn?rwb#kk8uc=bi6=dUJm(I-q!bK=Q_jGX==p9fHwa4$OS~*n6UL
zZR#mL@#4ss&yVx_fV7hZ)UQUN>1xl1tuG1UYmt`0YoxVtWldP|hs}PJ6AdZ+?()6h
zU-TZBgKRfu{`$sv3n~=7xwvhgNG8Y3y-Xdty%$iFsI3%nK*hOZPV^EIl=T)P*iUdw
zT6%XZIkeGDXFshNNzn|^smL&OpRirQNCI2Xm|sTQa!lz0vZ4(ZqgpgcE>(-q$xD3E
z4~Afz-=V3LPFoA!SiZ4%Er2JH6B6yew^s7uy6Ks<^w9DJ(gH&(EqXqARq?10Gpit8
zNXv6+4&{Xt&`Aj)#HYzhW1dR;(X8A1lw`gom?BD)<{%U+YMBMAcJk>JiZrf3>}Sur
z-Kdri$yZwHw3rpfbf`M(4*@FpH;Al3m@p_wDf^0k{zvaZ5`=5)w}=^zKyN+i!<7&2
zVzwlLK$ZqPrWTsc`?QlOd@O>eRHu}|F`1)p(FB6krqe-&u`qiWH`5>v+X&_YeVd3_
z>pBI@7dTT#Amm*rywAUK-l2ZdQ^#$Z=;V<(R%NmjX`c(Ih{IMaq&rSVUuy!k5+}&o
z6dq!o_j>+7(u1)zth9J|2$rp$eLN{pQ<W2>+kC~w{w@rdKZ!TMJFp9MSd{a;cnkBq
zfWJ?5E4$VQ%$Vw!+L=_A0RzAMpk4bubyU=G;vPK$3s}uIwfJ7JL{)Cm!l<2#7J0~U
zeWN^2Vv&}9WaMX~#|l`XxM#wrY=0ZDi9o=PdQ-?Kd1FLZT-jp>H1~Db?`xxMz}mi0
zU5d*Fbw{S%`D6c9c7~d;zKnE;s@rTd$7oj5xRM)@!cFkrXg9ng)fkZ2^7}D&L0uB*
zudr(!>~C0${vr2p!44^ebJK8tK0p)i&usp(-LDbk#j{>VO%r5PBsCe7&WE#1%_wD+
z8iWOmE{3R9+p$^chE{WP!#IQ5TE%Vu@KyBR)c~lbi1~jI=Km3y?SsxCrzZ`>xhm24
z7M6~E2q0hrXM0W5we}y@;JuJ}^{?@Q$413Hh2!7;VcvcV*q6Q-y?)IPUTYyH76SPP
za>YDbgj=6Oahhf1z|aM)cwkVz(zu|(4TklnaiecT;PG8ab=?fp20$KE->JSRgk<4P
zTZtoDsVeO7VjkMq?|lh#>`ljG2zh&Dyzq-uk2htI`=`fo=UwYy35OJ?)1#CRsfYfV
zwwL3oYW!@VvP8uBZOM52aQ|#25k1OGB4ThEzh0TU7W8)u_Ub~c%wH|4HXr`~HFu?j
zT*_CmCQu=g9<md(o1x|;5fY=(n6+#*%xf}5$IMlOGGPHUW?gxVE@i0_6mr$#aS>Ck
zI4r?XR~l6bM@?_YQVX`%a-K?@4|1#|>D6@9zoi2qGt#>eG7CB5N__Fl=$i%aV8k04
zuRMT<7*9TY2bC0xBe?af#bua8bAUqpr;sk)_65?19Y^s_@xiP-ire0tn5LJ>2t_n)
zi20)2T`}+D;LtMv=F-+U87r#Vc*unqa|*7T)4>LR+GKG><G^#tMNH_b0u#$(oswP*
zw8j8N__+Ey_lmJjgCitNtu{nCG|&Gwtsc5){!OsN0_WYKDzELjEwa2JmLsg9A$4HD
zmZAFtc1K(qP*h-7t6-y`Ot10kBG#P`85~Jwk(c4`c&xdzvf?;%4yXPhSwsZONFX<~
zJPO6gD#Sg4s9!;Ys5>)qf`A2&;ICIE&SM302*E*RaNcw<qo8Gx3HhtwDJc#DM{+;}
z8}I(8dGb?ycz$%mF>+i!8;m{#3u7U2xFNrbD%*CSP9PJm0b&*5S(Fco7TC992pEvh
zpVYzWFDJPK3LKj#Ti`6%C}gwH2N~v`s5{OaLYmUaOCbbJ$TaoscL<R;vk{lzH`P-=
z$z6FdN-4(vYM<}#H`;A*16W(zE~-^OYBlNyzf!H8qFTpqTbOR-^nIgscy#*9+S+bW
zRY?8=(Ugvw`<=D5XNHCpf_P^7dBe<W`SGA?M#**3TVy6>Je&t*_^WXc#a9m&TmLbU
zfk;iaV$DskeH*FC;@FM-9K`U;a1DW7n*+)cQ$dL3V!Q{#saQO9`+X#JgAa+Uad*<a
zgoiz}Z<u~g<^v@q+UU#9$QU1`gOe*=5a*?IK%bJY$Vo@TURH4!Wl?1+q5%?I0^KTx
z0*ede;c#rd=v9W}Mvayf9@y+^RPp$74rzS~lw5#~G>bg8tsBM3B%6OV4{GK4c=lu(
z6Q0tZ$akWK`?)*XyW#x{g6k+cAQC?~5HD*SPuX0vfVuu|MD3+BTm2@ojCGXKf`-l^
zGBKcO6}gfT3Kz{>N-Q&V$YTsQwI6Ky<TXNj6v&2!&8T?OKT=AM32IYwC^wiSZJx~3
zO+HA11yqKgfLj<hDxj7}_$eM{$(XDN|0^eHgn+4EmqcuYpo?m?KnnxF!RU{8))=Z0
z+v=v#MWWc&ON6q0y}k3p_WtfR{Aol_o<v7S2WQdozD|YCFZrr(aCXtt*~2eSUW2aB
z2vI=Oz;2K0?VsZJM|Fz3iS-oTmB^)okcSn6yd{`5!Z0><bCXs3YWQq72SAa`RW_ZB
zHtb|J^G!$7ofo0Lp=k<D)%<O<VT@wh#W3SQ;MZWx<}DnVxCIy$h@vH&$`d&Z;^3Tu
z2XC+^T-$k3g(%F5{8j`=KPS3F4;u&Y9p6%|xa6CUh@{|#5bYj%B)*r|uX_Uu#_^OK
zANiM^@9<-ldr>j_G8}8Ai%?0f$=Q559;Q7`>YKZbIK}Fo0ROO?Wip8u7$IRz|2pp3
zqKjS)xyENsiDh#1-9s4Gaz(5lL*EXb8_q~J^-+L>0ATo8SaDL=)Yj>7v%L?>uJe7{
zVjO7kN509iXmU}l$s1_GwLT9hKCs3>Sbs~$u9+RgKVPoH4J=9^00>ord)BuMsEi4m
z83PcYeTh;wH>|vBRwGX0QI~PN<PCQvv}uT33A7$D@ey=M=K~f-f4HApA2{IhU8qCb
z5dEB{8DTto*t$1~#$Aap>|Ts#as!U>_d>ED+QGlogzT<`M)r2EWl3Ixl4JZ9ahLzG
zP{Qvdp|HwU#bUC*rzo>2Fu0Snm7b;&T1OKf*``3uGq#7!U<9@dqH1>fHJYw?#xCBf
zq)EaJ7*1c!mA|!`XSpw1XxaTp?k*1yJ0Uo4Hia~Ifa;<1Q*Va^Hb*eAKr!v5XwSMj
z^=(D<0pMFzyFwXL)yle`)ZcJX)(vWGXga(cPLvq0Nd3!jG$OlSCA3md)2*mI#fo!`
zj@XT6(=;7&VutA;Lh%R0^<jUJq+3xl<E--t2mSG2BHyJh^8mACIIh(Nc9MX>d{;ra
z=uY}yhW+d+TBJ%)rU@<PU`Gp-<^&?=wbj(L)9%FY?RL>i&v7pCHxz96yJIa-vZo|5
z*nbFyUQU;<mhGep5|X7RLfz-V%LfaWs_v7G!hK0yCTGE22u+Jg)qQ=F{pT&5%j521
zGav+@Z^MegTpMW6B|+AMm<^(RM~UJP3g7`-EBYVKbqm-fq&UZDy|6=w+tZSr9a>^X
zD6%&uXF{<i=-X1^YD8Fm%=-kWQRa-FNbo*SBf#eZX9heLF|fsSk;WwCXex6u+CmOl
zAT>O{yQ2|i&r=;>5?M+~tG-fFy&gFK{vA*D=%q=7RdV<UAT%U=HuBmKy_<vQ>I;+g
zi|2~0IaOfFbe+uS-U*XITB_k>H0^zg;jayRqkx~h)e5c@Ia26M2oA?^ATK6)*j`R=
zyO=CeiUr6WQK%|fc1)pzkq;&MqV^Db9MrTw0v;}qFftkpN9;^BN+_=cynK=m3S<Nv
z6N8V~Ib*KQgW+fRW;`VIM$wqhFCz$8Tk~re&6Zprg+0^gp?U65g7N9$;n8XRfOI2=
z%_Aj%<Ziq)r5Lkb(j?&BQ^*D$KVK2~YBS+McwamiLL(3p!Ec1|C~)X6mtC(l)om5A
zM(-wSgxA3NoMJy0jb5GY*>vs>pU<G^KC^``iW`9u+nNlJ86ctreh5M>l%DiCwqzeH
zy@UA7h)4eaA~$-fj?;lUuD-zjatBIi9>dW!PsUx^g83@s7kEpq7NEa7Vr`o0ZpzyL
zLthHnn)a@$nSJ2%HQoaMLi{P0MW>uS6(NxM6SJrLk>E`l7k9&(+!OE4*^=Qk75Eb2
z;)aarZupYkBC!9eNJ-y<y9oXPiy`0$wB-Es?u0{VGFZwGgdDr%;FTCHV-2e>PnC1y
z8?TSU-}5}MB6t6*SJ^r*-oY|!26m_GtVhm#W}|2sb88%0FJE@Ra6nZ=2X7<Vc5;RM
zbD;{8l?m2XVX=f(eI`^<aNR;OC|PqowyJAhC4mAMf?>YOWlt5_{0wX7ZOj>rexOKa
z-{OVhZKD&n56{&7{qR(9P1T$KIN^@RdznaQPhL~TPJR%^4(j`z=KDtc^LeB7>x$0@
z;KU;Go(nzOm+pMR%Q&2m(a%1YNf^?Ps##&iPttU$OOaX8;tZ`6D$<d6T*?8!3K0m{
zeRW)(`Bm$r(&-p-#^NcZgg`REn+~Gm`aVY&080$awyY;O?tTSj>UJ#}($$xgqm%D4
z_>2xgQ!)iaXwq5#Ud|YURtuJsl1urlSyQAmG|X9N1mNtMNe(gh?9A9kLU?S1GE8X>
z(KzX<qidLbr=+V%1m>%(p~Loi-ZizdxUP#?p93hQ{PvN`IR-nU<+GDnMxL^+KW_4?
zSt~+;*KrV5++AeTNdgaa)QW$PId!nx2r+M4Y&cEG!Ao&@*O;{Vp>aUteCd|d&pW3l
zjkkMFwB$0x95fE==SLlbnIfexzku;;Ehe`&7OOg{9Vf!{6J^>b?+r%rt8m^&NM2rA
zWBV8>xPpbPnFQ6XmiO~6l75Emj0L|ogAZa-W6;Sy?^yx^cIbzP4|7JrP^gEN3yQJS
z=9uT0w=eeCoCA$aqOZEMWFFJ*wXjNI<mN?f_JY>bdLfr&`=SA;%k7044MHe5pYu->
z`svVnY&<)>kvTaO>WvqYzr~3bI?tZ|4u=}Aho)uJZjQcMh95La&oO!S{n4W-vMf>M
zz7vom<B$oDmSL8h-$mx~T1+iHjdPTuP<DW5x<bt_++Og|*ND)g+H!YEo`;+$?pP3K
zNUe!rkLvi!9UOR^;p09&)9c_nYEjH%y?@GYMW^r*`eg_r0JNU;hZuE_V*qu@zgNFq
z8KS@teT=`<jYUL4f$jrZD@@e%qmwIRz%Wy9j3#6s>@nv+Fj%x-B?ppq1IH?@d(mp#
zd*wScu#RatBME@BS|5EQ2|4NH`AY!Qp01b^1Z-`u$ZsM}Z@-By+H-~zs4u^V!-hrd
z%Q0AtM$8S-AVlv2$3`P}v=tyySkD!nrbPy|-FceCz3B{=Yj*XO-XYVC;JxJ$iTxoK
znsebed-rP$jO0`e=s;&<t+#(tL)^aJ9jtq7+w>e?^tYvnmp!@l@)g-)1wc>)lx^*!
zAE2dxgs2nBZibIA!%|HKS3d4pSs2;*b2e=-DtqHXv$T^3$7KO{EEjqJyL}~!XTubj
zYSDy59XpU&T&1a74UbUs4qu2rUBh&i-<KB3!*Yu8KnUF3Q?h6X3erB9?-`7}!N8ye
z_y2P0FH;1RyD$7^26R?$)sJb}4s@UlV=giD3?)J_FhW2$l(l2iQZ)jG1J6*J(GuM-
z4#l5K6&Yot(A`&xS`b1=?r|xv3Q%k8nBuLX5GduBG&CTIs=_V9SV_9Qjlg<K0Wv@3
zB1tkY_^m2V++3QF!bENXt4b09rtenNx0qFgfg6Y?0q$;Ui_eAp+>XR4Ddwlea!)mq
z&e5{-Fv349dmQ0vw|XFnUWxdVv`@CiNq^XN1>fVwL9-sCugm`F*;%8t=@MVjPNkcq
zx$IQy;jsCps006=i}066OJVVFnK3nGob(SWcJSr)D@V8-O{cRsnM7^^PI3#|b{S7V
zRtxri(^S;pz1e(AjyI0UKD#^UjGHt#@F6mf5+HN&OlsDFip}b45xKD~tKM3z`dR$|
zvuCeTzqLaBo$r76fjii)TD?`ddj0GyK02#fTM1%~6{;WZw^u@q8a6aB^`#adU{mo^
zqj47RxAwK|3}^uq@ETsSjdiD@)8Q;q)esU|h*;CK0f-K%qYnUp*ccT1(01nP^X=PR
zkwHk<0z{A2yoN2sL%Y*zT3mBXuoatDL%dofaOTFK`<>SL$v&n8SYg?2(OUI=esa)g
z#mCK)xY25fmYne&!j5$N@t~K+mQCgS6}f0-U)`|%EV{Rm*@1A7krHL4r%2$4B2+^a
znNU<;#WhMayXjLTDvao|)$Y_g=WY2OxuWxPUQ~wxY9p&~>?I@O1;SbI6G-ml$zjWR
z7j>g#&{dXx<J+Z}Y<zweAB$zZch5m-C`*kLlgbwu)&pu#N?Q0q%HlqikURqTq^kGG
z(g0)<QH>FuFM!K9^_6?EJ(7!nX78Yfe30I|Pmw8-=<m_}#q56cGP)0$Ib;9??RF&|
zqgZdOzE};EKnkx*chZlO&&ed1TZ^O`R*~DS;G5upSSY>?drA76u%aL*MiH-4*F~zE
zBwz3ccVhs4jcQ&F9idt24P;z-;nL9Lg-d_ilnhVpHj4!SqxOrbXxWq;Dq{@#$<>#d
z{cU(<3fU&A`OWF4k>U^cI1nX`DC??u%@dkln()LzTEsM&1BzosA^lM@-#{0iyentu
zIv_TvQ@p9&O1{xmVcp9Mk)V-^;#2CF2Xo3zf0cs-sx55%1J~}LeMm7dLZv>vp0Gp#
zHULWg;2!U9Y8$JhJBqub?tF}kicAMG5H<H3>d5J+pXx`oD1`KyMn_oDh5qnY-FY8g
zCT?fd6!xkccV}_-`%Ew+!`uVs<)N|Y0q1_z?qzjzBAm)%{8?R;yS-%P4$-?uHIK0Q
z3jLZ0S2yZW$u3@Bms7A+oX-v5f~i{X`x|uY1k71|0FKM&jRwFFUWVh{RmA}sJL`aF
zlk^7T00^tkpOW|8bndG44cC0ozujyhDiS|6Pv@(TfiLJ;N)N^q;J1AmAGg~ecl%%J
zA66S8htyQyZ#=Zi`P7;b-l%s4p<?gW6b#rn6b!qg;eS&88uXXLoG({smKbR!3!H5R
z1@nY5NTpZ98M(*uD=vM7v@~D96H%QHizLN2V9Y}`U(CP}vWJm<;l(;h`k<{&r}TOZ
zW@)MxgaGO;QZ+ZoKZBlB;Fa4QdHvKNN7WSspV9Bni%D`lQ}7efVNC&>z+D#oboE8n
zCr_Ag3`v7x8sE*f2fO%YbDm{&V$je2vh*cOQskYOJ0O;6(_k6Ff~LZi>uy3#95w1K
zuug&NgcoR{y49r;>)@YzuJK05(5J)$n70(#B&Wmc7>TNqO3~;8F%Fl_Km~bBlP}g1
zLfgfVG#QP-gxBm7qG8aRrrM7ehQVg)9ke0DI^+t>k<WmTTlKas8BPp9lP3y-EKxG1
zu1G#b0cgNn6E@3nyZPi=15sxcIHj{y2ydr}+Md(-C+%YoMOb{|d}j;KXgW(K-0Ta_
zj3+&vc&x(&e?Y|~;(4BQfwVqbuKT{R-#Kk<$EQm613hD_@iwO<!O&Sw?fTJ?;>^tt
zT0z39iN8lX>ZWE@abM;`C2}t7PwQ7)J3?4?8`(pxH0ZE7v|VhBhTtjV#xGkojA7`R
z2&4H03=H4eAcZs~)V%Z69joo&gYaH4i0uk6wwD0e{eC$RRi_-t^9mz*zHB7lR{-+;
zG9WwKm5{O&D^<YkS}-D3qIa?4Kox8%^<WVlU(8ZaxB0Xp#Co#BF=-~>0{{+a;lIqm
zGdvMBr+tGrpa`FMh=b5E31BW4>Z+>FPkRCnrXwYPp*z`hH0*tS3Dx!y1pY{W>LW-6
zczG3)D%dCt-mBR^+OaJMMKyI!e|ppLY?NTaN2e|f(hM)PrfPXRZwpH`A<SYP+bt+K
zL_~<8H)(h}O2c%JWA!P?L%ktn!qiva?pL0eg%osbP+YW!J{_U4vV5W~?=7h8YL4g}
zLI%Krl5RvA%mpXnQ$2i_GR=@AWYhIJ<MMjl3a0VIgyqQR+}i)N_s^A#nDY;jR*7YG
z2}_^#732yJpC}T7cmPLd8${P)Zx9k<>CnvW%o>4!O^NoEToKbpsw2LK^k(cQ)p~D{
z;I0H{^5FoF40L(`iCV{?Q8GdaiR6f3ZO!Iy2|w)XlrG^?>*Bif@FeMVc^DU<#X(O$
z*~h)^j2#uKD|;M@A)4CagSg^a^E0|u=|k)$V@zNN7nzV;CTyO(XC1=b6_Ogy!Fx_M
zd7|1(6?a6=I8T0GsCz9fOmC{>t+~T8NgOjWpr*2|XrIh;A+06`K$?N~*obnC=136k
z&-$(w9ES+vQanqm?+&WtW`nAXVoqY(u$O4<wq+Ce+0|svdP7s4e`ZGuu!sk9`28lU
zbHBAI1`v<A31Y~fPOHA(*x={d=xvhOo4{}yU4Y!cflo<FR})C0H}%$T)I24f9U)$^
zwBa<y`mZ9MCD7*>l)2NzyqEm8`*90EaaV`tRGf~-KpS}BwkK~eWezSBR=n9A7ap0g
zdC}$8?PO2bn$eXMZe^%!j`5bSjYC57Sw52+&tci<<+!u!c(zEds6%^@*xMm^Xs2Xo
z&+>@93r;={=hF!W%LR_DP%!aBGg&dICU(4%HGuW26M-Ta6@m4`i%Dq1NpG|OeLMu0
zBC&4{o?KH@(o--g&?BOdStHjsU{(~?*H^bBHVdy@3ax0UwiJF~COxH!3!=#6okjxk
zpj5G;6nN!uJcOIBf^exmf;A*Z!rJmj%)$XTz(>Q>dHE=L$)!Q-zOZS|>ar?bh1C>d
zAo7Kb9=257i*D~ztS7l)_ym^I(}}i!WyZ{kF!Qd$r2&a(`S#KMqL!;@$-+Yo=;E_k
zXcJ3NWT^>gVjj_;i@((;>X<IrDTkQ|A;stjW&<5?WH|qQTd*JC+z!e6bYlm@6;|dx
zg9L8>4vZos%9-bK4E;VMs$C6zzS7gYp506(zij7HA7AXoZCZBjsPlC!laZp6=pjV1
zyYf*#P<1&r49|JhAya}NfDI3HcpFwQi^dLRa;wf$e3UjKZFhc|3bRHplFii@+RI3k
zZY-NB>`{dLxY9Z|L-6UchbK+ks_Q)E6khOF;0Bh1qcb|+VOcsKD!J48Fx)r8ynpdE
zA_*>Roo<GoHybvKP<$gGYS72^7->F#Tzh(Uucw#mYxvH;xnw1^UfaX9*49f(<p`8C
zI!#vPYJIVBbVa+{H9TF>Zts_txp5Q`!QCu>)Nx))86<vNOv;a#vcm-z+#<gCNO-v}
zkH(kcwL#9*e(fhpNS}U{;%i>weCdnQC+9~;#pY_laA&gOCFZ7AjKApe6EqSjyt+7B
zhtV&XLd8vCxurw<a%UC2cRJ7W`Sphrqi9@(d#>~Wtz>gK@)^9xWs?!iHZ<aY!5z0u
zymV)<(tZo>t)hn%H3IO`hyY(epues1I^Cu87wm(uVeRj2755>IoJB8&nS4GGwUxl|
z-;TW`soXIbMgCdE(d{3D7T&<uKK91p&QxR7y_<F^3^9IpP!;IAgX(ar4t15Wt}xiu
zM*FrR(EMP<<A`kUB;*o`LqQrhpg?p|`KJ<K7*WNqdleS7D#-21F!|YUIZXTZw-n~{
zs^ffKeVpG{h53DTnEH*d3PM-FXl1Co0jPJeN34+u26`!d*%q;8{4KKlaVGEVF8u^^
z?+AOLZ6|%-s%z{$^i({K<P7(OM_lDsp%uF&9_04AE~645oQFR8Hba^z0cB(R`oZ;P
zlw9{H(uRET@h@y&Be-3Hy$R|DA?Y896do=#K|N_SPu|y$N}h0r6U@2lGGe%@Scp~G
zZd4R4MWe~(!{IYI`h#=LRH>{EI<ttu-c_Bw%6+fad8OW0=>F{zSZ}LOWErUK%COWi
zQ4UL0s0!=(vT;4HKCbVV!TP>BEI198u48qKErqs=&|IEh7$(i^MDqGB-ik1|N*fHQ
z*3fyiZ2?Wh1H4n~UH$0LCM9Msgiu8%wpu}kChg`wbr^6#s?Rky{-wjRz&$y7r2e{1
zjEw3bVss>pe`@>;n;_ty6F|d8*S%SI92tH_wO5O0e)WtyF?><(WK_o@+978UT8m!F
z6ZChX*LeRWe`vBtNPk(`s}2Y8yB`Ok<mL&P()fyBewAEWu_C+`0GcbDi0fzr4r!E|
z@KhqYkS;T!CxkSSw-jC;D5YTgGv03+P5_$6sB2y^oB(IS^CAbVU`$Oh0O}`Ivi1cB
z>-d4Xfdd>{TNtVEMh2v+UMT>;j&VYU*bLyXqQ=fs%lRL}_nSB$yHc#)t>8{(y<|gg
z29*-@Q6!3r++SPDRXhU%F|EN7)r&O}jB2gP5~l3%hrRWx*$!-UznmoxIjx3b&uM$L
zj*ThrHO7R$XoseA{uu*s(tQws=^)TD15ZF}HwjsBx|*$0Gx<#98l5><5Tmz|=GKj&
zow0%dD<=p+tc{%VL%LXGz{2OLwla16RT4)k-{7ltw7sdYa5d~*ag^Yosg!4g*NwoE
z7nu1NEbuN9gTD(1JPvBxKG<WVS<(eVKDOtg*S+%N!m|?&9Xn1oF)|L-lNk)J^`-Bg
z<ITJsV!FWyeU^#WB-1YDx>fhvEq7W~)4hLJjo8Uz0|ZFovL{EsD#7L1c6@mDwvO`k
zDq&Y~AP`P;n8w+72I7cEw*L;Eun-r}-~0t4DPwvC7JxjG?6{HqDZ&7*lONb#KDFi;
zgA8=KO6;EyXA3jjo6QYj-F9k)N(!de?rb*tT28DXmv3Mpia_CS)_A#&=$@bupl<cQ
z^r~0C7DX`2H%2#m_3xI5&<(vxKY>)nniXOjhY;M1{tgHW#p#Z`@ZG4&-ZSjUbb8N&
zZy>|ULPaeFhBQFA;o<^9t9)cid0h>*^Z8ha384r=L>NkyF{Stbg~r7!FOpw9K8RJ%
zn1Q26Cay4;H%LRMF{vZ@fC}2V6zv%fQcqT(+F8>vHd-Z5UUV|el9!SDE=)aOGL{SQ
z#u!1@l%7a;1f3r2zsXtMxiD6?7Ss{=$Jo&-ArAS~dVbx9sB!VA`*pg=0>(Smgdn9y
zZMoJfjTOzK2vWs?GKEAG=)`Pz2tgA4ouq%YE7{0g3fMAc8ju46T5Y^63o7}4i4mh4
z=4>x#UX){|#inU4Qwy2rI2By$oZPg{{U|U@ZC3)Ud7g|CC9lQfi^U+-n~P=3cbpp-
z)aEmktni6l(Q{2ZGotK18iCaS=TE)reol=4v1?sRhFe-3R5+kG-SlqXw+eSK;7_Mi
zieNyRb38flnI<>}#u>W&s8PZUJ|zixWy89#zXy9&Lozfly4K#^W~N#I6)1K)(x_T;
z<pSO{zqUpSRT4^-o4CN?QfTI4tSktp(Ifebu%Q>9_X=3Hk@L=4&G!($OLh3}myNI~
z&!$w;u_Xiywt3QNfx~J1e;ch+2z=IVbY#`fNpE>g)F0r8$%$M7_&t|~m}wU#!*SKS
zN_GOpSSGDx=^ld0EXZ;C8O_m6DPDG%g2CsPyz!#+3KI!~TYQvt(@%V|%(}xlQtVHS
z)=A@t&DB#IeO_P3Frm@RvDRhpe|h04kK!}G{+;6eX#Mg%VGKQsbr&1btR|G|%Q43B
zY;Xj!nE?Z$fRKrYBa4W7^8`ZVGx7%HQJHkrEm3&<Q#2g#R5r>(lOx6$DG&PEP}#BX
z5yOyEFb{4xiaMCF!rF3wXfvDZLKVhP5~J0t+s%Dl<Gu~Eo}Y8@iE-ds)50(wEF#k;
zav_JH?wK3Ilg7#EapTyWF9^|&9yt~tFwWGV-j{d^@d{IS)p5XqE!O(b`Czx$T4=wz
zRsPgk_unbO_x2ucyy(XeZD5hsxr?LlVmRrC!b;R&<v5KQ>Dkwa`LvoRZ|Qc``cOlt
z&UFduBBBs5fzw#h)pE<PswUSMc*!Aw-!aF!s<l}P*6NGMJr;CLoVq-jpl7Ng<uuwz
zwl25iSF_zW*|(AM_Q9#cgreh1UQ8!QPH-5FAoH1N>S~8zRevN-``B{*$p!AEOLuyk
z@D76WQmr08-ZL33rH6pW0R*?m;o+rdZ4f({Cq9r60n4^9)B*;y<W%Jxalw;y$u;#h
z;p6_&L%HOLtA0rMjNjQ5{TakXOC|xPakI@{X}7QIv|XW%=~1rc2gs9=0nispd056I
z%9D;%aJJPX#_4y<#5R{C(^R)9jMN4T=G?9Svh<>O`JRr*#VZM2u3SnhFpfs-#&I{B
zj)!Xfrrmx#q2!(@ByZv08Qv4(xZXKEZmJWdaa0EbK<6NTbKd^7Lhe!cnNeUyj;nv7
z0Jl5!R!32R8yy(k1_94<avPgb{j3Q-FN)VHv4pPc<YRc>sd=AW|GJkt8Ug#xMdY@@
z>xb~r{k+@n53R!@Hl%nlq}Lv$QwK;gn9fOE0Ed99aM=V=5*;TYY%xcn04V&H3h^S$
z5WwT^(j*JY-<54DC$TwAS63lV94&z8S}{mDfmnbJ_sxeAKp3)Kj490JD>I*;*_Apx
ztS6m*Vb+e>_|!rXO5v3y>im3$06_Bv5h6gs2N4`fJJ&3egKuYxf7#R#HXve;j%dL_
ze;Bcs!%4CgolX+@#4QJ4a!rd)*v%XS0ew?l*0g1s>O@d<%G0fM+yw;Cm4WPPm%)SI
z)pZnuD8aZ45*2vD^3P}XqgGRCLejB9x?=@pI8J10Wi!hyV-tY&K%)UZO)RA732jA(
zQ*y~w>_v5@V=579YxpumdulQ1kvBiZc2I&tdS&MYfm!eY7TujQxg0j-Bw@&qg!b~L
zO+V{@qA1?bf51JLXd3VF*T1K$5N;62yab3_%j~1&><qQb%ae}N$)n_1b@NcbKo#B{
z_4H_r;&*<XUB?>lPU%=pGWlHxf>qT_Y}?QwXuZ7iUZ=1#l?Xe())FnVI76)bnIkHg
zl-ov@aHLVk<(K(I9hIsBB{rv5Nk0%$#{|JbMG$3EOVmyLX*Tap(lO_0oppPk@F8~6
zH`E6sCn6%E5}_aTQj^Z-i{lw&m@s(h^mOTR=`0tB7wRC(W>qjo`rX!UGq(sB>#U~9
z4tO7xBOq+>5whrkZf&p_-MjDm1qMj?r9sSe=I<ka+qhavJW-}I)}1-$%ggZLWn`6Q
zQUKY9oVP0OoFx|wJ<z*~qALum?#mADTXu*yKqDv6JA#rmwh+s_u!^XOhUcKrN=P5S
z71fE2BL`Re@NzW0=#IdOxp{m>b!r?-g`!9(kwQQGW3J)}s>7fof^+@UY-2iDKsgNj
zwR8QnWi~ivKqm2~M?v*;)CG=FnPfWN-d5D6;{qXpNW&U6RzLS;%m!+S{6E#fV6@?Y
zuFp>_wj(}WOqeXGP^%`X=0#O=g(}sSmp?z`qL=!Q9pP~8fq?f*=c2vtdgFdT?&cK5
z)(}#^sF6RM8Z!h^aV0`Iv#|QR;^Q?hsb;gOd;=n#+v*S2(ogk&oSOZvE_6CCPc@zU
z4^>s}Lh*1jbpwkDxH7a$VP~V_ob|Lh742W5$NbhB5OLTo(RU(aFba-<GQ$+PN{y8?
ze@1_@rd5DO2S{5B6P8j49<{i$u38^b=bPwBPoYEocJ9U&Dbe3m(GM1CM(n}+S1Cq{
zH60#A6j+kJcEMUA$)BE`p<-f*C=RpyGQQZLr`PC!aB5dXNe3w;2JXY_r#VrLfNF&J
z=}gM-0P1W`tJ#}(mC&5hV~mbMjRAu|>QE=UBI+%(y8UF-{TgEeKr(b4cg1_fQf<vG
zltca@WrS=sH7jE~Cs?sJx{y+>^sWzcM-tU}AoAx3qjCk=^Uu(=4CgGD+sgDkOdqjP
zCcle`<dSt%mvzI|UdYWy(=_>~MYJ5|Gx})^F|DK3-NvRiuR3d;?!&9}ab0J#*4rQ-
z4Z*kV)E0f-TITQHULHTgm}K~ra-ujoZHvv%;?u=+ZbLCFYYz0Z9+cL41p*s)HJ*N^
zikMU(qbs$D|3IIwDdoc8l3<WC!D*`#zp1wy@%y9tNqo?3*WVm9WO6qf6eJgPLa})4
zl}(03IV>oi0G17W=_)8dFH#v%5Y9p*TLDrf3&;lxqYSuTi*j!_CD%MRq^6FZgRFT5
z5%{$8YoU+CqdC_!561La16b7=IG5Ga@rIE#Ln%Q0#GtCa8KBVrn$g*Bv>znEhkg&i
zq|0aZb44MLav8Uu>`jOLl)dRRQP!xoyvubrDYi)V-2V00?>rB#bilA+q4Aobtu}uI
z7nrJ`wq&vxbIdNf7v@QCP?+NrDJcgb>QSUqZFEM4nE55g@1bSaQ5*8c%{D+o*nHf?
z=`P<oXj^J_N%YX{3>4JKE5BkmSl^nT19x8tB{#%SnsrB$M1=3w3V`5T&|LdvLE)SF
z{!eF$`!&p5bIv%2`w^`}7rZS*tZH(w7%ZER_KG9_1G$>~CI@PdBnAKWfiW#4o$_>%
z?d7AUS05pwZ!!5a0R@{y*T#dz=9Vy1@u(s&Op4I3&)(<G=!}huCcTFbBg-2LAsu4u
z9J>|g%bT=5&}Nj)D)iKGn=PB%x|-HYbDFrDuhK@>O}vf1^m=o1YrJyb4FTosup*R#
z1P;81f4O3(D2MhDn~L7;_TYC}(75O@_gZHc^da4fnprN8H^>f1$LIy2_6fW(q*oC9
zHDI_I)UNNyrv-j5MrgV1%CBq_kebtoFT83d{M@xPj&#5si82Vxd-&L8(M5?-7-gVl
zkV?!zCUUX@jP8NgO+Grc&@>is6xT%{bRglCDR67R*kiqHK0=K{0X5emuRuX1FA@IX
zUyj_D9klB?R$a8gwZ4$gS=r1xVVUm%Cug*%twqqa9@4T#H<XUg&6dCrOfL+lRSiyS
z8604mFP$^01e!iRWT+lfon#7p*mxDqoDX}VnsxdKZ-waZZn{+c`6ZjfmR*o3B9Mr(
ziK#OR;{t(-)oj53T1J?z4;^jvqU~&@UF&VM9n`yvycp4-muE<<fAQR6MS3Yx4+?X~
zatVz&q`J1|c^$O}p@{4xa*YQ`S9NdRlWbGh;89FEw3I<S%<!=Woj<=5{!!n7!Ykyx
z1~xCOdt<QomZK=_ma9&bav{*gnK&EN1v(r|!5~WHU~!L#N;tYTia1NKi=iNbmbx0+
zV<i25=@{`$H4U4(8eU$-U%H?;Q^&UX3`o#l$)w*DL8yTES}ne;52_zT8d|x;gD?Hi
z%AQLmAW4yTKPEuw4F^LYItojC-wqJ21GUJEjDFRlf#2|ffSct9gf+Ca5j_1Vy7_MV
zJHB585K;@E!>g=&ua#oLAx1ASmwBWOvvgD*dq+yi%Pn*3z*!YqjwUCwqWch@Xb%>a
z6MJ(NunH$cLD5h}Z-o#2fNXCtoXZ@JSwmk{8$tXFJnDna4`+w_@-7?gqgeqiHyAGB
z9JVx#1iB-iy5LyKd5TuzDrqgwdeQ4>2QHY-xruHts*rDjfzc}lhn1dm_M^0?CNUpQ
z)0!Q5?kL+@#_7smMFjn+X|kOYvNz4fR#D~`8LlWUG@TE#uN7JAI=j1g<uk)#XLrwI
zJ??nV+|fXeW^CgU9qhje(p?9FOoWsA^m`Xxl8$AoMo|m&z8mzmTqf-l<r%e8ESa@a
z@IRhm7a*usfSy1j!@ToF)tPvHu}UPH^Oc0)O1;V3i2F{t8k;Ww`cGx`ikSyDo5K%7
ztX?(T5?KxIlFwJ?sF1{a=CRe;UGi1nO_V8oFs&@8>ISNmfBKgbRZ-)i$2-4{$G?+m
zL;ssIsbG5_%-qYBn5Pdbng*EoikrF<8x-;QXV5Mv#*b0+K;qJvQ>XofI?q$S<Aby1
z2<;NGo>k%oD(@6V3_PxXh?Qv50$iO^m_P>v9Hk1#Z^MtQlh;LCwq!34+aE&!vJy)!
zzN8_*m-sIP>{E66U*>b{Bj1UYenfmjrvoy|S3k_Je^>AzR3Y0(;j=Tk=3x#O%q0ek
zR|FvQ0I*FFfYH^U5b_302ZNOC_LhxB;f4&ZL*uD377L(cJiX~+Lhli`HItYp`0A~8
zz@6Cy%L_?K@-~+pFU{MQ3#75sgtJm_z5(Y7y)MtJR650iq)KHyu9$QvZ?t-&d_&%d
ze4G0gVz562XBf_B=Vb)e)(l&|5x%8Ic+g!RrjTQU78BqVJsZo^?SQyT{L2sAZ!I!L
z$>(I`X{VdVXK}01ZgeQ6vx&_4_UQCY{fLSngE%4JQU-4~O@m?Jb5K_Az^PK$2io(6
zdQb&%tKEsoNXG{*O5-;LkdImhaN&FGFZ!uUDrIRmA-)AM`70ra%9s@trjnmqU4;=?
zOy+o=oAkZZCIW6WVd_WG8xk5(aLS}MOE8Md?f9R4VIiP6Q^JR}bwc%wlMxg4E@W0A
zu`hMgcL_*TQy3fapzWTAw)eE1l@gR`1wnt{p+8*93e~dek2Hf|bi#M)x)h0Ns`Um@
zng@2DgDQm=d!?!J1K+>iRC!>_rYgxYZ~~*fm_7`U_E*SzyeyNpF-D6X*&knt$(ygX
zAzayDH)fx;D#KL5RuF4a-?M(HH#>3re1E^uZo5AD)@)%(>rV5yaeCg79vmpkT*BRQ
zoNPSIK3hvxyC!t(q**e1Zo`Da-3>9wZZx!70Or+$QGe^f){Buj;j+(L8MskHhz|Tw
zZOEQ`Z-b%jIrd#k=F)2XeBNkx99QuA+j<kdTtr*4E>(Z;IiHC^u-O2doUbDPOmrK7
z@?i|1@b2;Axw?Chy*(ZsIHdiPPV@*xNx$T{9X*cn2nYM<O}85q5r{ztfIN!SZDT(^
zQ#X!d^@BGhkW>Th)Ue!&8l8D;?uEPs1EZ@6lGh37YLR1(=`Tv?>1HwMF}{@$8hj1~
zSr@Af`{g0xz0GK#Vu0z$i|s5*WklzdVo4vq#k0NBYQBBjX!+^CbRcMq^9<T4J68sR
z0C15|x^MzRtI9ma&ja)xVHEi07DbVuL#f2k!oL{R%dlGkH`~{Thle7p_L@Phx^Ka~
z^EyfTH<*JpwZ)8UY|vd2Q?f)rpr2Ra?UF@1;;_X@h=&>>%8{^wVyR8@P|!fgk(<Fo
z^I!@FdW@I|u;lnbX6R3OBhJhhBQ5Al9F_?A0g9836L#R>TuP^lF)dnopv$iWMe=TV
zHOw$mDgFj;3%qA}R`VgHpe%-61G)*};Vrq_-aRVZn~T@$+2O5weEKL#)lu4CfW5<I
z7vd-A$ciI;<v`;L+N0#mqp|7@uSnwNrQkl;35FE_q4Zte6wk|UOb$!%Xx<q!Wn(9P
zZdw!w&LLY)(aNfVr5s+&%e1f&J;Iu|z9I3?IbofhEn6&8UnLQ|(Wog!`Z-YIFY1n`
zlgpH}IofnYVk}cF?J^tYP>XmLB(~+oV=79awivG5U&}zty49dd;w*=4YgUA;Z~aRF
z>xwc;`_fyNv(i82bOKgl4$y$nKp6-{v8{U3c^{cPr9i#aJ<6P`bF!qMk>HQTocn!a
zzjNB!j!!#E9B!Ow=ABbtFd(lLlG;IhcG_&8p2Tko4%Q?~dcZsIpgM?V(_uQDu)UHe
z=vC;1eV_`@i@=O(8YP?J9k1f__Ky#KjvK93rP)DcQd6!rJ=@9cXBRX^z%Uie`0tp=
zq$<6dF4NZpT6+xlE@LKrc1UfS2TrI1VGzju8#_sgQ8P>CgXw(S#Q=}9feyhz(TsAj
zjQdjxX@th#-QnnBdTrt?gONE1*im=#)r9X*ZFEkNT6B@1ij0~=tq_PnOSH;|2u%21
z&CPN2&Wl8Z`8-A=X^v@pdnq_jaSV!`fQK&<nW>J6ru6|F_a+&+rsrj$yoj1(Vp_1c
zDet)v?Ndf5&Xc30%8fh=K>@OP(t({^Aoy6@=kix5^dL{mwf^qAu&G`#VN*D>m=DHD
zrBwait@aaKg$~rA<)$)w@>+BO+0^v*BjiB?R`B2O1}%f=+=<pO<RuN*)8DE_7p)xq
zWd+Y=3cOq0$y~ZiV-3!}0Ar#d#i}YP<XsPYlTjca+Q4)Ez02?h9_TxWR=~@<wG_9G
zSxs4Oiu@qo7wJt>xJL(K738847)A*Jhty05iq(M!55!CK{A!n1H{PGxMxD6(VtkRz
zQ%EBP&s0W7tj>zru=nYSTKXrwt0}l$tM#8l=s&2Zu#UP{is?6>jw5t4kJ4GUmuyAv
z5=C$|a@EukuILVuP6rtsK&X#YFv&-XBlO#7PuN4kkpZ#eY9XDfgh4VY^lEPPw=^E0
zC})2K`w3k$UitSkhloQp<#o$Rk7v#v(g>~0?3S_$cf*^YgrdfZY|!L)1DjEZ{R#pp
z>!p$Kx+8iBxtfkBrXZt!3zoKKC9@FgM3)tc$Pqy>A8?wu;9M6NCbQS2Edl_PEQKN7
zK$>C$fbWzD25B=Wvzmg{?IHQ+#=+tl=xAU_>Wmmc(lp#8-9FSH=`8vM)0{!>8P!V~
z9yElOhr1xVV#@YUa|cH*;^5Ec&HbNj+`)B<f3WOeA#KyGf<~?uHPWs;cS>}kI>ZD8
z5U>gbV)d^My$%B9XNcB9a_~9_YDdvMokA8soxqO6Vgdrk&X5zF4j9+$8GLG04$8`4
zl*A_i4oIt3^<aOYgn`RLTry&8kV}05P^~!HrH*vD<qjo$5NWh6b=lD~0nYhNOrc7`
z(k+XnR|d#u?IBnu6%W<+0FvdTI&{*W#)5CnBw=t>4~RxzJ}}D-Vc<I47zChZ&>zlq
zgx4Dbnq{+_H+CW}6(>k42XZ-|GBR!mV372xwOvVK%%#C_V{cmlFqhWC=~chW<U_c^
z@B=|y{S<~3gw^#`!d!_Ev0|VvR|;2Tw^~8FurRhHrVlA{w6ujM-6PD4y)24Vn4N86
z+r2wb+=t#J;r0?XDj_N<dCSC?g|WIhxx7?_nzaWl>z$MoeR-Ma6h=B=Hr$^O{8peP
zh$WcP3j^klrfC+8$UtX4w$HA-JWG7A@-0Cp->Mj(RlgpEMR~1!Y45*l9Go9D;)BLv
zqt(*eu1r&90h`8bNYOaZVog|kg{P>t?|Y}!Y}P)M;`1w{!V%t0Kczw^YiemJX`_PZ
z%xW$9!Vr9kx+*q)vnFA&E9=`AgrE!c$<%o|0#{{>CahN71Q%u>>B5IX@q$z^I0{9%
z;%c3s8Y!?uW)JM+Tjo%w>KUe}Ae~Mwr#8$mZvuVo-J+WUYhrrciH?$t@1o#J1Vro@
zL~hw+KorKGQbucGQO7EwtYqSLt;3#h6lW|~f4T_o3uQ*2aOR-3#pKM>1rAu<Skftn
zI>)H}kSjui)^Ol{*Hw4*#c0IOe;J9CG(3pGjJg(`&y21lwWv25stb~U;tua(3(pk;
zqX&uuFd^bMWAlWZ2|T7iMNe=I1>ni_iw)0z8{+n9JO8j&W;I8QR=**;w({Cu<;rHi
zv@gzKa99Mt%+tjMe1Paz+zI`NEFY@@_crn>0)qJc+PciGi!orJ{%dI@2C)zu?RI>O
zW`*A7eb8sVtoSxtkwgeEdT>8FYc&@yp0BSN&n<P91WgEXhRHQNb-1k9ynqE7;52MV
zCSFeVOj1>|NfkjUxd*rCqe=3G?_S!zA>{zzSJTOK&Pn8MKs6yF*<z~Ei|p7g1!%#F
zA&W^myqsW;7U4O@X^OkEZmfia4HIFRSiZK8lWikaPrhu~n(mtx_<A)D;@$7xHeMEd
zk6Q=Fb$Dd}`Q%l!8-8Hn20Po^Z?OURezzO@L7=*h1-eu4utBBUvQ*qKagGJfc7!q|
zlOx)EmplDEdgRtaqAWn~YN%9{sbup}b~VQgZf+#G5O&>xfD4yS_Ux9#*~RF$9WLDq
zHpH0~wS%9vLZwM&06bBOE2Rddql&-@qc98S1hV*@?Y9x8!9;C<*Y8g0fVYbWyi+#d
zZ9U-CXl^xZKEEM0pH~>1L+mS!>iZjx>ihht#Evqix#TKaMP&ofF-DbwdNCXgv#+J`
z09M*+9?QCW|JIvC>CZEONCxHaZ<+6V9@o_@+PzZgukw)bSh{5@e6rX!1)k#6Vq^RI
z!S!Z7#^uFV>?%4tK43#Wr-uSEfR5c&g6_d_24WJxXnr(P6v{I@Yez8>V#6*8M7e3Z
zS~)ws^?YA0r8+^>5(>@2I?}RGTaU0x-T<0HgX2Iey?Y04(EG;+8`fkTbszCzV;>{H
zZle1{ZrQLMWoH9ooen6ZAYzR#5)jy7XFGa(F>`YMy6?cqRDLuR-aczI4&syZW5p`@
zP4SV|&TI>6&@rg0zsP&jl1i4G6@ZUZ#|Xf4W(_^dmpNUk)z_i+BGmy#YhaZ<B@vNn
z*w<ygkenZ=!3<gBCq3<BzOi#2{b+o@$qN7`UO!jdqXA}QdleZeUg9U+Q6XibrP3q4
zO>)$k4rZvy)3lk+_JoB~HlCRswrBHp*bT8VB{!K4A$%o7eT7#7n6(J$P%|G00~p{E
zF125V80DJcThcYOA1Sn%IF-8omfzK4Rx@i_*dR#$CPqch4nk^EOE?Bnp8b89^_GsE
zW|gDc*E_5Zd1N`MjatatCEl-}fzZ<aX#=oFY7ns(b@rO-`|+*1(zOrI;^xWWsoad|
z%-@YJ4S9PpojrN2?m6?X7`#`XzV-c1^F6%aHCn$09MH@5EM4MEe2!q`ljAcmWs}i(
zU{@<#$-P^!Z>_Gngh2oi<+(vIC(zNQHSJC3keE=(QbRiK>4Y^ZnIS0d6p^QpD{(?v
z5msn+GuaGPnAsIbA*12NygUDD(p#l)y`1z&`$HxTbZu2|A*Q&cdf}C!7OSf+{h#p(
z!n>5b`^8e*$>|{p$C5*olO;AOa4(RcA>w~)HPG0k0_awIHMp&Ik(JzSri~|qXzVfB
zDr~<v>`Mife`7h=HF?XOKxjmyJ1w*sgc?_0%8x4yO?#(u)Gfpi{VcY+Afoq`8)<hb
ztr)XXMAtAG^*0>(p_Z2$5Y92F!NP@Y(F#7E9v<d5%+f9Pmkh07H<$0zzhq<{KUg*_
zJcylv8CTAdVHp`vdxaI>yh+GjN#M<$W}w#uF&B@e!XvHdsZ(!R=g#EZ%z`_;@LpfY
zw3cKoQC-Jc8)degiBgUO%I`quE(2)QP{2UZQz;d$y9KiQ{o9u%J#3eh?rs+kAfUDq
zlptCZsWvTc^1)j)9mZf!t*8@?tnz#q^$`=!i)5|=!%#RV2%0n<5YIF5rtrZ42<-K1
zRp}whw6O2k%H9rjg5upy^mi0Eqn9N?7+~mWrK3<!<KIbe0x67ksX~3UdxuHf3Jz2@
zMhQkqqeuJM013BXR~S-|1OFH%fBTJ;M6!u{Bub}~yjG5)fg0rsC~1TU{-eyVXm5C=
z0X{oE&{2iZt3!+6U{4QGZGhtt?@P8Ww}2MF=li+2fZZ#iOI*ibm?jphS%c-OuZ9yd
zEFG&7-<XUno?cBCqdw*(f#Hf_D)vWoEY(Od7^3sI`{gRZu;P^7)?85aT~nAjK-U)6
z=C-QFT?@8Gvp~*Ln~SzBI6yHI_GB}T;%J&aj0$lpV+9$M!L9Vc^-}ay51J?>L+Dk5
zb#7tHET03{E(p(O)Gn_gju3e3_-ocktAgW;$5Fg^`}KqRS*OurYp*3NV$ES`5rrSr
z^DErlOK_W8acxqnr2^hn1<Ehl$>malK^-XqfRn<2WB|)=iot?Vl-fwJlqWjZn}-tN
zrAWk?YUL~J8w|d=vV3J@UrlG~cZf4NMF;le8dL)}iNHabxVZgIZ%JA?)cDYBcN}}T
zo2y=toJ`C+(6aEHBbqafnN+bBg<JnI39DgsR52wW^JG>1d-r585rKDukAgQ~jrIhr
z3o$rN`4yJJPtxVWX3PVF7xP?z5pIN7LbmO!aRYx?luuq1ltakSqsB?}AM0xyZpoX2
zZ7g{lDAQ0O1#k2y@*5(^%@XqYEeP)8UV&2iqQ6b|V);eBilIlOLW}&?o6f%SH$$5?
zs%tQQsy`qRiF64~|2F&>BJ0Lk>y)pC5Vt}b@&oM_b{grt#te6BFzQ}{2O*p{z1bqp
zrfOR8&I?)-Xa$jF<CDgRj<$D~cq&x08mywW0WJty;UH=}c}*l31^PEuADdK%wl1v%
zYqO4<CmTqvL8{x#btamZbf;@=mg#&2tMO61<mpE84(1uOlE{4nJY%gyVT;D67<>&K
zsL|R@Z7oW?H5erLn1HqnAhJ=eaB>yY1YC|v-lov~I2re5O6FFbsk^a*SNf(QdJAQD
zir5!B)%FFUkwLwF1-uD~*Ca$Nn1-Tq-7G&NLmYBSkQ>~z(0e04FFUcva%S=-3rV{-
zEz79Fs>{p^*!EA<0Lg?|JO#@R2Fm`1cSP^}fM{|Uc-TZUmS>46RX<;5SK?;=h=T@F
zF>?nIx4=-4NpqafvuKRa{9Kg<kLosoLV>8FM3b^ji?7(uu6?QQJo*co5KSf+X9Bjb
zcj-7~Liuu~1S~<=KO$Wd!JD(hH!KL8?JzQ40ztiW9w@r;_JR5Ck-KAi$aiLM&<@ql
zWdz~k3y2tVX$*Kx;`wsfJbI*l(RA*~8izk@?>-09BeloZ*0!&=pB2{l8Q8!N&!7DO
z)p|>-y@-E!@$3cE?U&Zw{XtjU*~wMJqWJwz{EP?p7prnYECc=uh(oxe^bfAotym>!
zHy-NJTC`o$YBc?AlaC3kNQarNgo{TvnZb06xBiCV1)C3@epMCX7hv+`_2P=~d1i`Q
zA?&}@^-XJFHQcR0HeZ*xK$Xd4_~bP|6q`W&r)Xo3>;3$1XftZ6GUn|m6=(owQuu8!
zM81_r^6bTmBT=Nv;#1|(&@Oq&T*RO=xz327ehh2{HWpZ64mY0!KbBYS@Wsj<zVJG%
zf;r|HRaf%Gsw?>-ypn}+w@rrQDY=dCSRO2D>e`vjyRrFTFSE|psYSV^FHyS5qr<wQ
zxy}KeBiEx0^Zow&aG)j;?H`@)Lw0d>wx5EtU90{}1i><_*}>&#c+mqbY5EkMwa_S8
zb7yJ}@<IsG`oCj@h~<@4#fcKMP0bUCSgW`&My@?*zK?dcx3{g<9L51ji7+$Ko=&>!
z&f0dSxER#Kdq}3v1@appBiJ5$5$u_wg<Cd(U!Ud%gb3H(a1!a#ks^$EBjB2tz+zC3
zqGKJbSN$732J-_kuBU!1--1zySiy)IA=SF!ql<k><nw>fM<o30KkLp@C2LIMt0CA&
zEhfDUux-g8eWN;_KP6w`CSX6Pp)3^5le;ACkna34brT5yEPYNlPboOoI|yyWX|mT~
z=Ym^`!p^~l>SI$2scO=_@oa;8x&Jxo-4~%aiom|dFv-R?$ODpoPO1QDzi*TQ8G;v9
zB{<FFv!gOl5M^sRsRC;M^jK{<e!t=5(^y$a+>}2G{Inv9!vkJlvjw>GLw+nJT&31*
z4%*x+S`Zk*Bm1!UXwxn$NE^dRR-|^9gki;BNlfuXjb+0j49Cd=KX_4Qy_FSj>PQcJ
zg_YF`%F3|rC6#fRocgrH#Z72AWD{P>paH=B$#jCy!ZGh~-(jYt?ktVR-SpG#HXge9
za#+RS_M%v4iWal!Vl>j!2u9zvXy*m6kVl5a`9xsCHJ03bXh!3UYfMrWkA~x6b_cwq
z@|3(8ZA%Z&@3*(dDVnj4XTv$_t+6(ompY{KbYNoQ!LlwU9F_(AERDl5IYD#VRA<10
zXUWm@3%)OQCusNQ_EXcK*+N!;N6%@vXG=R*m>B!-9l!Yi-pUx)KR#+6Q;_(F4*_uW
z<E!XgQRWWHJa!+Ws<y%sS_#CEBh)Usw3>xM`0h$m-2CDZ@7?VFXZ0c!2q<21v<UO)
ziVdnnl*BFJ>{Yh55QzGOs8dw_c{EH-)=HWfzBJ*#v>4=TVee*8o7%C8mVnW!1YtaR
z4S(BYC#c{d5H47fCnQXEPo&B<bD6HU-a<|_gCCu^=wX4FprkapCYyUJ_SIRfuk1E`
zfv#Y`e%40QuTW>s+TxR#_<iN>U;{YBAL`QGKB~{$elk(%xJwAn#{C(2$=MdACp>m-
z<HF(~`q2Z-yO?g>UrGoi$GbxZ9G>gRYj4NOUzuRDZ!`D+Wt9v*3l84n9+@+Ev$X|3
zxF^HKg-5!5P43j!FP=yDb&k&xI*oEvh(q)Fkn_79T%I}KE91_~aJ=ww947I#5Dn9)
zL#IXVTVA$g2CG%05C)Cz@8ZKNkRP{n(n*SdfPX|lCR0-5suT>z{1H{j1K(7e&Z2^9
z)0wWN?ptXRtc4{|jRW5-ri+wAYeo5ZQKHmu!_f+h8gVhS>W)U3uv!VRneIw93zX-Y
z1$qmWL%VUdfalvNj3q9GiWtKeHes%!DY4bar$1DUBCV;4*Li@V<7)?~{S7yLT2z-x
zMGHBOe2c(X;)}1~M_L3QOG6{#b|s^-ZJ`v@VPR}KrBHqFCH|~#gG$y6A<Hd=`X*)`
zzRLUc-BPHZmDbO4^$mo1GD^B;<A~w=HJn}wTlqEIxj6eh)R)=!;)~q;;Wkqb1x4Lt
zxo)zh-DG|@p=gE$BNH|9E%o*;ZYehS{Q7r#^LB{Ml7lU!S(Vk!yxOYMiv>grMSD`y
z#FCm@%4jQTk}JgxU~=4t_KQ>MR!>W-^WN9FGu#qgJzR>6lcScwUwKTak0!2}Q+u9_
zr=JtAHhl~?NJ9$&c89F8a9Y9lF*n5fNUoI#(uOsl6&muh7AoHtP?xA-j#dbaLZ1T-
zL}{)8I;R#kfKsHbG>xyi>6JGyN%C$Drx6GYIqGs6=^EH9$-3nTfM%kWX+*Y&%Nk)V
zLz_zI32!en-V`;U1xA0Qu#Iv4O!Z1lgKReJ2g%<lHPxqs0fuDD9hQEnX)*g;)`2dC
z>J+NyGV=a7fqX7gT~j`u=WB{muK_(Q6*Ztz-NfW;4~|Bc8nV?U+VKn?hiK^};Reca
zsdI+^vZs8hXj6bIF4Yy&(u$1zY#bmr%WlV#)D-ij*#GMIo#b}4SBeebUFfU2SDB+M
z*MVEZX=F~Z!baj0GvCmrV@?+jbrz3jxmLLv`S#h;_E}N;ZvP((bv|K`t?;NtjX=+~
zUB0EM;k2Vv6|$k<&eo`{|G5{wg7G;6Y}VYu?5}hOb3$smeK|!W=i5{Z-ne8Dov<Q5
zj9b+yg1Uk9uexrah}f`B*`6aLTSOIYNaHncZl-{*F!KU5I7JS!tuB@lp(7J7G9d?x
zFjc&TQi45@9pS-#-m?w*$tcu7%MZae0BsTOWKq~jpaFN{v<bW;(EVi?b{^BA!k3u+
zaka2c86O{D2nxV&Y(vm!#r1=OR(yC2FGK&g@o~?0`AX(A85{ync!ki_XU7L|^Q6g{
zKs&Aaeq&?Pyy)VgjgywK(2dMh7zf|Z)96AT`uY)B%?SBAkF0y8!>_KL(Rk*MD;x=%
zsu{H;2Zv`ZDOyErY=RC7@D0HT!FKDo-uhKo9jZCb7D}-4`^$x`DGNS)egar-){oR8
z9%$v$FpWQhuZea$(4kX(O4(zayRRW~N%%dfonWK~5T6w#U2_O^G}(%}JxDl&={PCa
z!#G=DBi-P07lYeJ2WJOAMFV)O)lWZH<V>_R#+9@IUKNDsG0hR|T~6OOTJIY5gM5H$
z^obdk1;<9_GN(N1A`ytB9mCZP4N8tgphdS>I2(j01lQJ3{?X~%jYg{lK7r_J1Ngz*
zQM18IH$;a!TJ)}ByYKpFH0{BXj}<dff-_iF1M>xRAJ_LI*qDmoI2VA&1~l7A`IY5A
z$6WxofkCpLsM7n!s{sFK3%n2?*yJqGx-Krx`964yBO^IEKjvI%fQ;gS@KexoOm+3l
zAN=Qabn!JyQVbrV3WeV!MneMsFb5Y})m&{#Mbi<HPr<bKxN+<(l|U#jmu8fa^_B2>
z>83Glwx<X_WkE&QwP55BcT)<zCYo+&;F}_ik@__6PWsa^M+5g@i>S;9hg=7!E*}TA
zsNg&x!l*nA+m%(QTYkaEB8CW-dDglUwI9f?gV*#vJ`+O@PFl-av`8@~F-}via`eC~
zGtY(GR@U6H#$dd^QF$JQa2^&>@Ne56>8vVa$_`6jzvEEeXN{8sFNcyg?rS9`aV;km
zVwsFG*l9^a=0Xf6p%tc-V2E>kMqa-dvYA9obSL5zAJmo2q%oOh!@*Z(t604tJ60fS
zznj)07rft|jO*SW)RFQP0p<Afx?rs@i9+yg(Jq0^^1kjK8!v749fIuxW>Mf}P&xr-
z=LsaUPZ{a#!o}c}G9S(qSF?G~{AyV_6fWkwLbyUnH%t6xVRDR#ZzZuVkuyuA%Nq-0
zq2<j<V&S9_KZ;ZkN2hI_GQxQhbLHGJ-qC6tD|yFFCE>0DfFiN2H-t%EByu4zo+m{-
zprD}h&x)@=$zrldlRkT5l!p<OcA(N#1Bx$`NitWAjC$q<Qjl=ZT)Ft0vYK=G$r)=p
zlcbweZkDT$nE~lRM;<|M7Cy-8KGji0|IpyZ-Pvy+Ng428L|yw$crtD(dW0X}D_(ut
z0$cER=k;G2P5Y<}-`+Mhqd#jmY6>BiZ`BxM_ud%7_uIFH;0HIp`D8R84PonZqJ)Jx
zy)JIo)K@SVPa&b+B*DzyLJJYzIPfbG-?-1J9<|~bKM{KbfO^k4D5ATUI!PtYp!GgJ
zfuK6ab<86Z{oxcfPdcsmsJ+h*-xmopMR#YD9tK}Pykh!FDiwsQSYoU3w%LYktPu2f
zqE26^U2~?RNIX<K?$qBLHAEY4lA&fl9iJYkRX7u^?mvo#mlyG3I90R#JQz-&C^+|n
zeb!s`<G9^vDa=>^>m2<mV3rfzfAu-({gHl7{vgBEKgbvrMaLp@n97YDOBB`W$DJoH
zzW@H&_pfs`bCw`bn~VfiWuB_K(AcTA&kqlqA1KM_XnG095%RoRM1P;0b`+^sZK?B7
z=zmS?fBWA*|5|@w*`Bhkfx2PLzC|C~>d%W8&(*)X&t7bA^S?Xz9sfMr{<odyJI{8X
z@4k4xtIBtt?d*R4Z_)O*7>xgC0ovav`nRjacsMDkx2*hs=pWE`#k;$3e1Ixr^fG$1
z2kiQvJ+A-#^Vj^r{jc>eAY^_XZ1wKAkJA0W`)ud?ZQTFQca*&KYzOxL^X={b-T!~d
zA0>6R&kjC3Ia0TjNt!%q_CW?643qiG=uP|J$+IW>qprG=twYqd>Fn!#czKm=^fsg2
z?VTT<>~8PwMDK>};b^FCBGD0;j6$F_5MbB;eK_fj7JYU191SOn>!&0TUZz`DuSFTi
zeVDG+{mj&;+T^Pbr}=NeiXhy<SNr+CAoZ=Q`+k9vU(&#5c<Kp#PJ*?;Rx9wi-@6EW
z9navS<Ea1sF#f60IE(8?5b;}Q>s{NWvl8wJi&VOgavPoG*ECq$@mu&!C=Jywbrca*
z2PNhECmkHY`nrPF;^a<{HLS0GyM%ZZ^W31ET-5QKW@l~9?IPYkZ8c=E7qP%3pQF-U
zw^RwxajV@?6Mh@N0nqCvi{s}(oO}j5j0I^3c|PwO`<>I)cHB_6wGOnc6%;A?xv1zA
z^w7>DaX5D*55v!C6^Malf?-6Fb@js9py#ye1`Se}@RrB&B#)qMQ3%Cm>;wa!LJy<8
z^+0>?IlFLTel!iE*A{B|JoNnAcS#4)&HC_6;K~$*rYEVSLRhGj%^-U%B?JUy;Y~h^
z)QvT|P#bUDh1~%!1ZsbHib^#M40F6dPXWl{8`S7%EmEIzMPWp`>CE;0QtZfm-kzIa
zR>XR{eO~bm4d<b1W1?cHpEqkTYV@hBpB(rBOqaihVMrR7H;00upqJ(W%Y&T{A_cv{
zv{0pweths$i-^Gxqm<-4!60D*7+i=I(_{BuuJZ6z^xqr#N>1!RMh%(TtcsgIVWl6f
zbAEZXl8QC;5uUIPdlHSN(@%?8)D;0tbs_@5l=upkn*i?rQ{P@vTvJo1zC%%q1`cKV
zjcH0Q$d~G-J(18v_|!l@bVlc?F))W}B*__=WK0|g`JlR{2;Xm-N6pT!(eob!#gbBg
z&xT=|P33Px9c?koMk`Y`!M1T>@K;{LcBkGsZ{HPpdmuyl_<P)c^iWg=w8Tfvc4u?b
zX|=wl=BuU`K;K@asVgj+d8?l{HTOdDHL$4bZ?eVnefUV>uv2QHPo99^tQsc7R3qdZ
z#9&APs-@=tZJZv;yfLNo9`<d7pT1S&0}i6cdSp1HxOuRdi#0`2S#CIantfSUChQ3!
zfFdLIDPPUup%+Qc7UGt&L9j5O8}5>7C<&870a7ro;$MXp+nGcRN9QkeXa~U#jZQJG
z=PeFP)iRq;HCrLRBNz+}_*DsCHyGA)YO3?4-Ta{U6X3ck+44}#I`QwD7J&kP&<RGt
zY=7&O@_P~?>^@K=HbcjBWUukS_2Fy*#Elcs+(R2apiNykr3)*&$P1s+<=9)hJ@N(y
zc{qR)?5&PGk1KkWg5>X6cvi?3k(Y*HCny06vO{Po;!8I*X|gZAMvK`@iCmmF90EEI
zx;;ugTGddqD73cPO5kETPA}1_!nnU;9Ep?We!bn18AenI<obAjR6haJC)G{O80)|T
zb$=eC-4(U*#&gs-VUrFWfnr-6c+xoKhPFp!W)`qzlCc`uRIJ~R7CnRWjRzo%_@Tjd
zr)+cg=Q2A7dsF)VUy>kO1a@@}QHH;SKowZ~|8dF)xs#P9kF9c%_CsEFemV7U8*SwA
zt!^&6o2vzm4BOp!u_WaXr=z~MRy1iB4H5iSFxZcKpdAB))!l%p>J126XKhroRNLnw
zQFpS-MR(p+8wOVU3d15h5uqY*B<@=aL>)#7;pn}{7dbWOXw>}*i9!a#RQbzv{z;oF
zYc#BA;JGC81V<;9yQ=D56U`rr1<6<ZSc~-FJ<iVNyg}G^%1e$<51NO+)}pR=t`txY
z#qlrZAV3VTiVzqZtq0#9%49G7WTwWeZt%3YSmW$4`jpJU285K<1b`ZBMZaKVu~fAM
z>JnK`x{lc?(6j1_WF&&182J6+j8obwgl%nY-N%?mkWciY3+gN$#@V5hk{m`wApD`3
zX-pGJr3*HWU$A2;KzZ}`MUrL&V4mm^gEFiuqJnEPTrr6nW;!J%N6nu!&J?c)sG<u_
z@y?N)wy@??A=+W?%d<x7m<7CBF?A+HO{FB+c^1X*)WWEPQsFhp9G;G=@_At7MPU)_
zgay5e5jy9NpZmugJZX4@FU_%&KX-Ii)Q|yl&OUi1%k0WIW{MBIYAR{%M^Hf^`j&#t
z@%d4wlpP(Dw7Z&I!_qD``sc_shmKq`?v+zmK(MJU^Hz8r_@A-PHxgn0m6n>V|Gv#?
zgB;6YbufZN@P0!%dM5EjFP@Ei*qi>epiidC7=O<vOjIkVddsHqY;c2wsexRld5ALG
zsgV_LAsuJ~JA{*>XWKl9z@9#xjv*mcSK&4xfj~qidMe`valW+)pY#flI}Q|M)xrJ}
z%XYSKyyd`p-3jMS*7Aw<kr;hNIB<+Y@;FEIP`JaiLq>LiFpqAP3H(ddG@SQVV3G1g
z`4G`p#6)-mFmf4Kg(&ASUtEHmm6}0v9VJ-t(r7?IAxW>|R1H8ifu9Fcke6VnEQh_+
z5F%Gr17iqCDEL}!rszlY|FHi$%FwT3I=PRHcDJHBy3b_p;+SN51#3~0l&8DrA;avI
z$d;&I5Ud(0N|zv)O&8ha6x}K3-N9hkQwv2CR9BIHTGNme-kql8k_oaM7w`wPd?w#3
z7C}`fhE6a^;QK?f6;gHOiDp+{Q;g*aaT;h5pKV1a(=2%zy-DchpP$A|mT*)T&%0{Z
zsv*4jYMnnvYN`})Lw5>cNm0?<$NBak<Kg5xOehHK3J7u_NK??D+J*p610t{(mox*K
zOO(uu3B#iV9_%RAsk2;2^r&qyXq?SP9GNs#;x>$<2N;wd1R`iiR6lD*+A~?PXAK5u
z38xwwc7Oxn9#K^AU8d<kLy}8}8GR6J*1dG+lhAyuBW=ZGX>dNiKcu8{!Y2z80jopy
zx9yM7EBBOz>?h4OB@~u5cc7*@7NWmLJJCy2x0)KeTw_sK;~Cc&7uI<Gkv)UuF$Gr-
z93$Ca%Mn@_x6DNhF3;Sj%}2aKwmfmlh9lmUMxDL0+#zA_e2bZo5CHS1+qeC@6jxSS
z;lL*TzVnrCbDigFMa*%4lTy^7ETT^(7hmdYY!53xukXJK(ph(^r%(~|Iy%f<qCOBh
z@t;Yx|G)OWy{nC5%lG^XpQ6JoJIKKp>>SSwgv`hwY+dt^C1E?0o9QK_270WQ)e^?%
zB<Hi={i<hIw_4aaXU<(=tvJy2uG&?#Yd?P501Q(-)<}IV|B6$+I)Uf7p075|RY?4w
zb)NNgvjRPTwV76^HPXe9e<Dp{ZiYj%<sUKzyQ2JzF+QYabGzcfyk5Or{%i@()g`Ls
zk=2ip1&MEgt(t_DUrHaqSs1WW-nTSIBlM87?KrVgiZR0wEEG~k7tuBZ0?jzcEr#lx
zv<ECgM1R9C`xx!epzR~3(p;%5#4y2+Ost|<sVeM9R_YsRnfns78AbzZYDpSeF?z5e
zKgG7J(cZcxiMTk+=RoR_s<-v5LEZXyMI~l}G{3_&Vf4E;!QbnONacaiHxcaldKkm^
z<Sw#Hy*z<3#*A;ZlHK>%seBo;ng`Z;+9RYK9R7WGKUBs1<5ah)Rvj|(>X|9uIPFb0
zU>|K<jN!w^ez};aPv-=zr5$-pFEWW>{8cW~X6KHn2U*m8(~2G}gex@b2#*nrrG%Zs
zUk3{Jn#Z%Hhqx8xiC_hmlJN<aZ&24V=QeR9D<+VwQmye35{;8N>b+pwUZ>+k4KJd2
zqrKs$-sg<1N0B!sef4ZHo%540&8Q~zMABt<|8}O{{AA!eqX0?xSQ|2`4OU2#qs%Uy
zdbXqP9laLYcPf_-cS>(oAhAn0z_S~CjPko!`bG6{FZ5H|gPA~xJ`!w@@h7~@^s^Rd
zZ3+qNtYaDSJMku+>PNr494}$UP$4OO!=9Rn;l?o@2i3zcHuRb$Q4-{uph$q`MFbcy
zJ?UTpPjI)LEtD|aM7>N0=va)CyD3GY#2M0UZmG%cA<mk5Cf-u$D7<}Oy3ouE!vvF>
zR<AHFg}bg>q=3TjG&mDv2dW`|44EVMWk&AJ;`xjRU)=7zjRoDFyMh0z=5ZuLyf4k9
z0jZ&J|Lhh<Mo(O6E`|dmlM_XSf`zKKXjm!@H?JR@Iah%dfL3V}@zHnPL-`PT+svNK
z5S&5%@o~``vyCtP4TN%yPyk0jxWBhIBQEQ#6wQ|zOn=fF!kd%CCNzuRW+v5W*5ojo
z+sMS%9PK^b^3QTxk}L)TZ(2O>kbcxSu3wyVEu@!9)pozI+L>FeF4}gBs`-9%vWc@g
zx2Cm*D~}XM+o8Xhp%xRRX$TTYa+V#EyU>&q4t=_020s?`>5bhdZ4y_?0bxBvY?gw6
zCd<2>VH%^<wu39SfqQ!#si?DyF}50Y-$&T+=7T|v54jDcf85}1?5Qi}faDOV^hxOv
zUE6<c4fnOi*8Y;QwZHb*mPV-c{c-;84=b-d>`3&8{ym_;D|W5;8F@53-ZaD)ur(j~
za8>_5pu+~?f=CD`pKVrmd`T#WZolOtT~S`<c_{PT%Iu8-k(y}?>KFAUx}Hs93YBef
z*?98yui%2{sS4HEU4OqRo!U~pa9{`VdK3?OVhi-W>~bi^PC~$isWi}AdP}z`uo(Pq
ze<H8SCyZHz*ACp8a8xU{f>bbBBBEQqW=DAN1k2}mlHS~KBovI2%}NwE!%PZ|q-)9u
z(4A!o=m@20xG=QjBk}_xawdI^sZIAl;X)9Tk%=Y3VhY>vgFjT^AyAo2N2}AhCpy<Q
zD+xZO$Qygpjywi*jVhw=y$p_R=;n6xVnI`pCET<cD+0fbV2J%>I!_U*m{kB)J&HjL
zPKIJ+9NvE(V-rY4z(s4C<@mq>>I$iG{rKOwxb3?qFkx2jjo@M1!fp%__s;%$zy+%m
z_v!Hb?6~>z0?%3LBkyr?qXS+Um-C?x0ejLsdmVRL2rqNoB&4|fU@{Dt2}~_3yRe2Q
zgT-_RFD+}QBm*73oPZ8h^i~Es#DPJ5`x=ju$hqC=s7u=DzHmkc=`88bEft2aj60fX
z)S(e;>MS#3I(>tHFHkvIck_sxb53y8Gqi$Ng`mXw@$t!d{fJ7ws&`(gRl%bP_A3GN
zSYW7Y`s^~tC>-{D_-<S0nN4MbJbb<cpjHK(8xe1+zyvzCu<dI~Rk>$6`Ic&1D-~|Z
ztu#=h=XY8FVQba!L~*X>aDCZ6rv>A)+`nz~Dm)A=Liey0pFsJXaNSnMP<t^{PlU?N
zEa|4Wf8(q7j)CLjIf_XuVXCRU<-w}0OZ|HVR}}7I4un?Wq}dUf!79LzOP~2NQ$P%b
z!Z+=SjQq>JtZ2FyEGl8)nI$lRS{+#lwo+o3St86ObGZ2;+I+BZO;_;iikh_5{Id&%
zxhva7>qv`a7aSAz@j+AwRUEKf?iyQ@Ct5x1sovp8wuBgZOTr?p=N_5c(V=-BeM(T%
zKhQBf32YcGlRWbls>U^-fUH-rwXz$hJ?}v)RxGwXgMy%9(-^uDi0_CPmUqe*0gecl
z+%*8<i(fHD*qjP7nl1SD4`|Ja69Wcehz1WBdKCE?hc9X!!^;|KvxAG4K(Erjcu5AZ
zS3_57o}veA5u+>8x2Xg}Ki79Bb4hf6-XW8f0Z#*m1XQQg{V6hESG1Hjy<0IfnohDT
z74PB+2WDkVToKtoWh$bpwo5>eXo5S#RP{B}OX#lOwu-dO#`CxoDdz3Z60&8Gbwb?l
zbOi5`AuxaNaFf1>^@1~qYbZIF;IJ&(QAMI&bh$vwWTJ>Rhlk~oTQ0$SoTg@H(e{K?
z7dW~XN13)};d--3Lqaq6DcwT8KFyTb1y+Ladc$Ot@sf}M$rns6Tk7FdC~2W?xHH+R
zvg|a^V)!J2LJFRMoK-qk{1%!&r}Mc26X!LeH6s(X-rQa)s>IBF`>t@2AW7DRv)kLp
zI}xQ*=vn-Ym86FSw<DynV}W&2{z&pSig0xmLnB4px4XM8#o9>3K-g~*7;F#+t7j6L
zMApRHd*`jQ^KR#&)!H|P)g^uy4l89{yx29D8#55xWmeU>2S9Z@>@q=y4s}-wsuATA
zIfTz6{P*_+=QU!5k0PbD1+%WQ!3aoMvHLBuUs^=*t%^A9S}C%iUyh&CPV@15s~$Lq
zCyQBMD-ra8VpFtHzbcM-n*@dY0J!^zLhM~+XY3KUqGMFi!9=31z13q>VR5pRI=52Y
zsc@^9ewYu5+h*>p{ysi#*AZv3aYi!o!}eh$07onlm(uB&1IJwnN5aLMXYq@p_{GIB
zSsgoV*<k@F^V?$&`rgeB`|uzNb@g!p-=lI4fw4y*YNul`E_feEuT*a2s3m9?I)bCM
zZ{TgwY`y(HK78G|IE{W~DRm&z#ZhZ%9(<%M%hNgRF3)s+fiRtw`o&qR^saMQ??T>^
z9Aw;%*r}~$nU0$$<yEOi^OD(uC9CPRofofGxBA?4t1N7{!lHF6EPl7j!djWgwE&(+
zFFQ+m)a{&?<aqlY7omH0vLxTjcB4wJ##!TSm5isj?~m)9E*v3^hRR4M_WX{lSz+Di
z4!QYM)41tc(1E~OA|9gK&m&#JR0&gpC78)kf-b+bz2@0b17`Mp`@PlFfWtobBGZI`
z_SWO}#Th~J0@1#?Xk0Y#U3-z+8@cRVC%YzZ-4X&Q<O;)(-a!o~4MLK0jxaPU#n{ey
z|4^O8ti$&B5+x1xnMnGTqXywYb9y?q5A$4lZ<t=|9QBjtOE=GNrf2j2T|J{bS#s^S
z10;=CRtv$QUw3t5^x9XM*}Ls79#6*cJe$Oq1H4Jy;VQrE*_{aa{1J14j2FYS&ypmb
z-vH}yW8?y)7bE~`*g<jkRlCu7wPk58`OPFAA@J_)-2(GU25W|wHZc}51aa!aBNQJ8
z*6V;ui$%p?HknT4>8oBrn)9*EGPnkQ7#Yncjs&Y<iQO*EpBB|25IRkgH%IfLIhxyZ
z1Ozn83TCK_5?gD20&VIYf{{Ii7f|w9)I`oNhxA$Zj)bfqlFts~fEU&4#!oIgLvh4N
z7>JcwO>4#ki{TsKyxk3v2%b5__Hh(lyFoQVEJ_kY;HD50(dmGh$gfqC)h8f-%{dlS
zMCVt>;n@OR`m&0w9+A>GG&H@z%eqmebodRVg9YN#42^YS^zaZA%0kg7N$Y0Gb$`gd
zi0n>GP&aVK8%d}_p*%c2dJ}irC<1!9r3w~xLo|VLI{Ua&7`CvWLGo7MR<W)4MZMEt
zVQRQ7!Dae-P3<~O1+hK#bR$ej;dI*%M{Cj_(IVaUhLwzI!`PzyY}QrwM}v<fP>&gm
z(JXL=LEx_a&(OH2H;$8epDo2`6q$C0N@r1jGDAzW$#}q0ylX+Hup5hXyt&?>jBvX3
zE>5u$6ufA5H=SGzsM?KR)S`#(a73VB22$Llh0GcXx~1iiIF>zyqG#1?3W-pZFf!Bm
zrg{kyDC|~b2}#jc5=v7^ElXuvYDbu=b_5I!C@dgR#R_0qO6K!8Ft)&c)!DXinWJC*
z&xmPjwdSto!{~1%OQW=Snt%m4z(nhUda~{7;pDP6jQivHci)j+ink6gDP2Ni4U#!o
z=xwo~p^D8#u!S38kOCc-Ymgu)$-s@zRkb<sXDe#d7zP!A_-aM)WTBMUD2c!$fz>!9
zCf!j=hs^`r2@&w^ywxHW#%RGye%{~n-YMG_mDkXzYrlMKr!U?I#>P$UXklP6O7Z?W
zl-gT&Nd+p@2Ok<Z;t5os)3Q%@Exn3wdgH+`nUT&hdPFAD_5tdvx`Nz1B-N<o{_kVX
z6h5r2`@uQ1Wj5p_J`$e}Bd=4=i~fa5Q8%ef8)5ZevTbWhY(^qpnszPWZSKmV+v%ZR
zsC_15+84oU3t0^^E;rS{bbU(kcG<Kt5!v=pE?=~*_SXGv?rv{|+E`o((66op*N-X3
zQt~?W2rss0eUh!*7#A;y&2><PVe+-Hut-5LP5SATve+q$=$wDa+3&%#^E2;FDB5-Z
z-C(~EnrBCG_r-}~tyT6Vj|pwcj6M(_hxW@<S&Bk$8bvdp!{;s^`<4@4Tw@+Q!hdtT
zlBzL_cQk5(xLtkR@evVnnF$a9JuDO^LgAESb)lr<`Nrc0NCUySr;B*^`6gH4=d6X7
zpro|QRV!STg2H0yi<yd?n)q0#PNGUxkRLzX5z()|vW_d5<Hs;XB3)aGFLQsB{vQjH
zjU&9W1=*TIj#&T$Xh31&-$olza@S|os8Rb-o~>ZVjHgve2VDiW*n?FtvxO(-?DGoq
zTZsO_h;r~EZU01aw@#~Z*uirEUZ)OLjB#M`jr~h%V5b9Z`mdW0yUzcd{$hF0do^lc
zDCI!9CPlW%=ImFdR-{uPS0GxTR*ubZdPFvEjMU4@!7u8E;|Un_dADEy!qehe^4M&P
zz7Yx!I@LnJ8L@EJsVl`kN!hZF!=ewfK8j(BA!)P)qvzyA%$H77?s~1`xOLHag(3F{
zRak^VjU)2dGluSdzO(bL$!n`Ole?+9B>XZLXRpuB-<|FIu8Ywl3d^odk6yhax4>h?
z?%@32USUXdX9~1aO+h;~`(cLB5_<47gM$H>g6m}SVW37}hM@cKFHF`J$?13s^pmZA
z_~xS7Zfxbg6tV#*#9y**IfTo@SB=Bh?vPM0e||whQ~r!0QA&8<ht@YVr25%%tA(YH
z(}5foA_sy;${4sKwE(4!@8<~WA5I+kr+08+%i84Q-+q@j>YWDF?$|jNnG3#bbj9+R
zQ1;1ePz(VJFtaoqy_x<W6(aO(F3(%|%I9M1{DeZ<w1C-yMbMA&oCQ~K<T+A}zM<&Z
z%eIaIN!Oix{Ma?yBD3e@E}cicOGM*>>v_rsOa4|RG#j*0n~XI`4oc1wWzmBmI*aj#
z@#NDu+8iZ4c#Tc37~`@3p+?Sju|B-E%sIw5Jg<_O;s?+wsFy|GIt9LEQ=@eLEu=^@
z-*U6c0^%#26crDO0`t3yi$|f)%a3mB1~;+9S^R+pk1{I}wj@^Y94dmx%OS;`Sm&%-
zIaa{0QE$lM&dDFZ(gdpDtrR&$87Z+j9ak|(`okVFY@v{^Xo#mH#-f2(M4BXeS0eV7
za_|VYXn^vK?#Fw~b0k_{d#P$5$__Gcc!XOx{N-$0K@{fw@QE$I>>B{#8I(i69@kP<
z6{vc;ORJtz7}1Rmn@-Gac<a8Dz(K0zC>>bNB%wG0I!^RMRYsk!u%hk8+h(T;kJRRo
z!M%=x>7FHjQ5A(DLay8(1JEsd5IIC^{88>Hz9p(iGNtf=wG66@lJrC5_wZG-we#<B
z-E6w$kAIOv6u1hPdkQ-RuZI|-d+wAuJg=WLI)@GPOT9p;-_whZDuj<%yAc#5bl$<~
zaT2#Wjf<o6_*HyJwg{Y`G^Zrmb&9oKcRR3k&s%ikbqHZ<SCv7_t2r4%#g^d~&eFe;
zV!Znv%ai?<<&lC1)pk0)eI951`Ba-v7=G3ARLSFBaT^zBdEhH+v8|W~MkrSJI^#8R
zOdE3~sL9GAMXC_xh>=@i6>@ZaqN<Zd{p7?J3{;|uU80I2qIeZ1iWO<%sT3(DiGR<N
z#0nIF&pRm*qK6PQEPbx?!;IlK;O<-^1TkLs2PLtL@Q6*vgs~o}5}S~nG;XcqZQnZH
z5-!-%78F&mxTk7kcBzUDx}(xq0)8KIzyeDrmR>@5MWOYE4Iaq;KxHT$d@*KIfwQ@f
zI}e)ud3d<Uwv(nGmA}e(u-<JL=AH7hW6wj?z7?R2Kh$#Pgo6Z*k0;TV5hI0M%u7*5
zD*J6>$JnR^yTOd9S}emrk*5Tj>JwW`sE!7h95`DNj#$_r0!k?*k##aK=Cfp&vXhPL
z2NMx?uR(cTQ{J$oe8J;oGFbElLUamitm4a|gNmS!Oojv9UvX1Lo?j0Ixq0${U(5s+
z^)eCMb>j21M+ifH5LGERn207+{1%+F8-)MRBQ;Q`Sw9)~X6Yo`ljPl6bezscWJxqg
z2Mji;gWSQg!mZ8m57LpEyr(rQQDwjU99^l3pf{L(vY1PWXIz5j!kz`0<}4i~W=6<U
zTMELD<%mkyG1_}+lw?`&n#`MsBS)tTHN0q-d?lVLzlae6zYfz6h$KTU5IrfS&8Qe*
z1#$f+eIiBRnczdu<Y4WnnOT)j5MvPKwU;q$e<t;1dPRZwu5Z+Iz+5q^s`k5)K_H{<
z9%Jw7?K4zj)9$lw)@x)`-!_lb_CRzTo^lKg@fliV)P#-VDaN&SCRR##^Gnlkm7@_d
zh>){$O>KXD|G6j0QM03BO4(ZMQZ5z;7(5ELq?>t|%`o%>--zy6+rPTrR*sjt@Bg9S
zl5X!gAXc=uWM~ymd<8gCc$InqfV*#69g)8upCd=G_B?+F{9KgzK9K2n4ZOh$T)7P$
z`!wz5<S%M=Ij3m*$l)@>#Yw&c>X6@a7d6KZs&FRurE6VEKkxja?<FN{tJz^t^4GU1
z`!rlOEV0&%k*E3$F8d&v&Tm#&_oGG&o~nA~zhAQQZuWbxJyo;X;=3*1Z~19*0z|O<
zabPbhB36kd^Q!cKMQ8b<%gCY70#URS{oXXJ;x*<Eki&4%nB`imtuRH;^kE%ln%y-{
zy2!rAFKXJGTG?ljhq@NdSR5WHa#$jUCQxoYzNw!_y)>!)WgIEz63ZApxMIB<S#uwf
zEveD7DgOTE6Vw$WsNcf~ZFo`|>KeB}##AN%7k@12KWoX#-Y>y@CD@JcN!A=6)w^{a
zhr+JL)E+%Dzu$BB!L>pF0N(Lyao#I1-bH?s*X%7v6J@rW16(4Ty<o>#L-y<o?8&HE
zZxnY;4<eJ#`Y!o2A>~Psr4V$TUm?h63jYc(>DK8d?`!R(y)8*eXqBR!Sn=(KfdtB;
zpEz`-GKYe0-IG!<d<oW3L?^1rqKIH6l;R%FDxk=Uce5X2Xlais&ANj&P$-RXL8Yh{
z$sp}13{sxQ#!<7*SY>RrQ-TJg1;aWlg%0KI;tb`*<5lEl{@%>Bvge@*<>g}q+Ers9
z_cFNW!`-*eOSk(ujlWdP_&px9VOa|n8@x&jc^;vxdS<t()lVVam<6NgCn^qFc{}bI
zu%soIeOxB~Dds2fs)zHE$0+j9CD!&f*qdgkd|<aKM)=Msqzm(j9N*LtJU{|)T45GR
zg44x>UR8EKuc8BIggH7qIew6bS$<!j551sd&?(iU0q+W?7>*?X8HeFgU=2{0nFh2N
zM-8};(>JO$w-1%Ciq(|y)p&?2a+k2wrGcOqrn6dhTR2ogd<`X{l09ty!<c8(cq!<(
zl~0IYbEgJ2&CAXZXiLnht0^B>qFpC?6<oX+CXIF=-(xN{i`jt@Rw@9T-sikFn<R)v
z;7Q;u29RdUf_h<z6+!b%C&M8M4gY6y$q`Vsh^t4zj*KJ8U@}eub@WiNZdKB|?xo{x
zV=ZB)X&@83ifa<z6ArU8oJ)>kl_kn2hfWftOn*8^95)t|3nraVO$x!qFaB-j<j#v8
zwco-wVH*Y*VGP5I_3)M)E$Rv6!h<P=Fye#3Rwla!rx;L&f&t{79@vDx?_@xN*Xj6&
zlPvIm2lh_b4}i!~vW;?QpB`-f`tYIeLg3+Oz=5ez>-Z$YS%R~UHV~Xn0^Jt83GG`m
zhum6r6;eS|iQ{IPj05r)4h)Fzzs^gFpZw=)kS2J5z!@ClfPXHi>lfPu49ISduc(_j
zYFQ0qOpGa(tXVY!WBLI%#Q`cR{sZQB58?7*?No~tmq~J2;tid?`wQCWsL{&<QvP-X
zBD%ygEJ2;r`RT8mNUVy&$$YY4Csd$QX>qG)2^>s0F0)gGGOD4#1xVuW5kTdup^nkT
zwgGpGjxm-FBDt=8^sy~9+UVfHLL_X82!hrit6(C9Hzn;qJ;xKmaa;<GR0tUu9HuiW
z;YPFoQ8zuS3L=<{?V*%~yhQ7J=e4g$IltWBXeSIG&BBw(S$6`*&{1_p2P(Lb9R_Vx
zt*`#dnhj?=Mtbv8R)y*)-&TTle303Z{q#Edawa{X4gQTHc!;CdDiPFR$!<Pj0F87C
z50Kk=@A@k&+t-_T@APBrocQoqRC{LHqx_t&5OoAL#{-OY2($3J&p7Q6ZHiKM(Bh1a
zdfA7s2(=l6OjkTcR0x~C7-#7<KJ&3l^U*ZMZkaV_0rpouo!ui#Cam~)HoiL>*g5PH
zyJ*u4hK}g<H8m2H$l61!@$h&+I+H==wYGkITJO9Lz}5vo>x@(2WTt~~k%m_Gx{d*_
zX1*dau+^QKsB_KT;+@GVU={U9A{H$zpreabfabG-nsYKYn1Z*snzYlVWLhC_A@v|A
znr*`5`YMxc+Ww;XrVa(C+doe$O?jx$3e#RGCbhV-VjMME;kg|SFTnff**ffp&#d6<
zykCKf^VvrE^!$7LbeYcWztchHpDvzy4BAw0d_JxGZtdq)Xt<O|&C^XN`}jv_qUI^l
z)c2p$U)Vkl7YgbE0wp8CwUiKWtZevE+%T{{&qnL{_Yu1x2)ZKLv=e+H<lQ1S1~hUv
zKp7c_Um+_QNEBAhvT@PO8dm)XCxV*8cRHTSGdLTOuK$wECgN@lWiH8#^KU6pGj<c*
z^lG{&xoX2d7y<?kK(aQ4%CHn3zFY~G`tJiS{okgN8vG$kx5l%*&wtBIaN|Gz$PvoS
z00i0Lx7<dk&ItQ4QgVzvvi5I}Bc^#3>K6|I=YD@c6<Rj6P;7>fxvCY<Hir8ATgCmx
z0p_djH`-^ez&pHQX*vp@aVi)iTkOCbepxuiQieeZj{UGCHbaqz1l>od1AY(Q@6;6t
zd|ocT^+Ra*#RqE+6W`@KfNW$InQmw(9F7h<{$OCel;8`$mS!u2CG|oH{7!LmY=m0k
z#vch!t_!aI_V$EQb6z-@V<NX%@;^y`4rF?bVds?}ccn6LfUQz09cRgG9#3!K`5kim
z4)zEQj>C=Gj^Aj{m~TbFM9ceAJe-)NsZXcF&n}y4vo-k>&gTA!(=T9k1ZQ!rknb#`
zVk9H+XA5x9p^z&Ts23G!y<vJAh6a<^t&m*sNOYctl+k?|RuqiYPnvHVq>XXk-D_1|
zfnl}Uha{Qu$X3FNF<w>o#*6tPNa$6qAP`y8nm)${VuklIoRHW?7U8rZo%32EItG*1
zCLE5n4f|wd*;UdT!Yub@BcgqgTAEIwqe-LvwhkRATo=(t85gu7@RS)UnEsho(+Ow6
zPC&LA1x>Trnp*TOH1TMJeV6nXb9%b!xDN(*27P3E0~0SRYM!>F9<s#-W&*!xuK;02
zS-Yh|6mV}Q(?l#4D7TnSi(c#5&M4DiKnY(*ki>OR0Se9m%_Y75jnt@2_*GSc6y$W%
zAJ0UGzLTz!%K(ghcL%#b*<U1AczshND*ULUcqLO*RPd2SxsJ2ZvzioiHjbwOTOpgk
zub1$L;H6XLjxtL~FU=TrD3%%seMoJhpbDQAnesODuCl}4xStHIRUoY-FCg?-+Sn-H
zVjb93&BMU{^0rCU%|#j~rKT%mU>sC}cH_-Oqa(_7GJS0~PV3FHPJDRQU3<2^Oz~?;
zx!xWZOSz2NysC|X@p~>(scU?rvLTd!3FI`IVHm&lwSwcTd^IN1N{jKerq?C2J`w0<
z0YOE|Pq^yD>;xw!&y9%RB|mux4X>Id3})A$Pu`*IfaTaS3yJFM-nhC*7+5BUDnl@e
z?L#9CvaW0gQbvmJF0m}(;{euBO+b#fE3<!NOPtN3$sv#{LAY8|L5-!esED~rli^@9
zgc<etM~2>;sZjD9SfVB@nnILBuhX-O)A)2N_o<@>uG&@R&&@N1xQe(sfhqYv7{}<r
zBEmvCVg<)pPR5hP^^L^H+8m|hJ;S0%J6pkKT-mYb=V)d|lgLt|ObWK99HhSNd2UDK
ziWvNvw=Dc!#2yM8Z@ar{8Kvfzwd}FXHqTU89@S-C@E~EC+`;GSDG>negf>K}n}m)<
zE|Ooa(6hxY>X_%}?T6OO&Cl}g$YTs@SfvXlrptZ8t4DTd^?aPO%Hh?m(CTbMbl>pm
znnAU~tEc6$)g1!iK!y1T%d1lcg-a%P)JO+NUWG7}nmLzc&&K>I+HCeVv#4q51Dt^~
zZ`sr*&E`dSUbV;ctNPgys<Mv}r_Mf~N#jb6FDFglb`DP(^>)|@GWfFg54+o|AX}o?
z%;n%G%V0?U9uI6yQO6f&hjF)EKWuE;rs8_<r4w?$Bx7g_aEA8KFpwmAQExwun&(kA
z?Fo1<AudeFq8S>N(Zcbaj5J&G^V46pu_^_+t(;2xlhFwGE8BTnhn*M47g-Bh1<H88
zy@D(O6))N(ZX-rEmh0{Ee%`x>%lfu&4F3sB0$&EyU;xgBWxxhx+3IJW@61`T2b%V5
zcc@)9QH70(57})UtIXNzK1S|N&0LyTBijYS*?-xCYG=tc918GW(3C{!%#14qhu)bU
zI`WqF?ptB{Rhx8{79XOaZtj=E<?8XV#YJ#X<lLmB{UMlRT+J2SEL?AyRY{Reyq!9V
zX2dj>XExA9mhn*n8=|NZ8tp4}2+>KL!C}lAN4S0PmR1v=DNL+wpSs0RTncb692IuS
zgM^idsx2y7_9W4xu-!9qlTqZpK}@0R%<SQbtl&aKG3(jSCmf8ta$j>7^r|GplQ_Rb
z+wE*#L_N#8;l43$82&m$L2gBII+CBa1whrCU1w@b<yMCE0fi(|I#>}Ti~N`@(N`O>
z&4t-H_S8AAchX{P_R_k$clJu4(#;_xX{DzS=Uj}-&*9<|SnHw8NnCt-?ycKb%$_BX
zu*Yh?!i#=Bn|!wUfc(|H=kp}U-xceI93PYMKR2^i!s6*&p=Ophl!fhC^ghfz1<ZCS
z&QtZdKrK_KCh3<oNhRd}znI$ZLBm0M4eQ<~BrE+gkxRf+)^#CKv`Zr5BLbv#G&>t^
zZ#GP*W74X?+D;hzW;o<`^)?B3MX;*kaZhK-RO9PxM|F-*jCvHj?>UMJ+P-Nu3Ztqj
zHXI(>;|c3IE-AkG+=(qdzk4#f6QRI1^?G!<xIzU}_wGqsrI6RuCBNr;eN;&q(@YTt
z7;P27an4mu_|QkG9KkjXDIPYvLRp5LERD#>Q7N7Ag<<6vy_0E3f;%Is)G$%Nt}BHq
z&r6=QA=r(wLYL-a97ZMw!O}LI2tEakSfJ_JJ_JpFjI%6qJlc}b;@Mc+gn5zs(ZMcU
z3n`aXvw<&Zs)6!kQ4OcIzGhjrgkge0qE7ct0DcW!TlMa*tf2TRR?d~L7x!w>$Dr7c
zJ+l9>-s#roePi$-ClR(n$cZS|{;x*+9Br98jjomRHt8?VC^4VWWO6+eI6NF@dB^p2
zdx9c21d^crf_sdB)+8Le+9rD3J;XkX32!Ugw2yuX9hC2P`#lFH<$kY)=D^MJo7d!E
zikj189B7Vg3qP{y<IX<KMf3x)`zU)fVWK%n*>t-1>LrG22uKdMa1I=i)|$brr}%l~
zSJr-SCw^3ZKdfqm+4zB1{X0WC<I6a?8c;A;dqnEed(4rrX)f6yl6REE&l!^i)U*d{
z#1WsgsOJebr{uftGZ~sw_qKaon`#$RwdVM|aLYpiy;&%5r&mLvF`Ip(er*%Bl{qyZ
zuvxT<%0VITBkH(_o)aFbVmI(io!!mvVs$^OGXh8XX>>{LS+SS&dcjSeC9o9-z1e4T
z`>FUp@o0(`0Iape`c<`1Rcpp;-JkWcn?xLtm1v$G^~fQ>EevG8t=CRNy%Unr6@_$_
z4N=Ppp299;_w?HEFD@Dr-$8;;>@r^JW-7iMWG>2A3gc=vUtY8+GJuNk0o7#v-W&?(
zpl%jRnNyS7>?SXT??1cL>VB!Bj}GVI#6)&n_8|Jb#Micij#AzWVG_X0CL;PXqI&!M
z5bxR3diy79VS#4zFAN_QIqZdfQ0Rs2x<(U$*pk?C5;!^USbJ4Cpi6QMWFlKyoT#VF
zlp$bymVc?ZtXjW-Tho?5A&YR;VgD8Fw?*NUu`KUxI~|8Xhql?bpL$RW8A0x^mn@=h
zZG_~?5RwlT(G}!|gJ>W@j~twaY6hcMpA?)FU4$k30By2*K=q~sUbt+OOPGW62$Cp-
z)$h4uOqf#*l7&Mzy>g#`Ovc$58W_*7Hm%O9-l9+EaItOuw_yh6+f(Sm9Fp`MuuW}3
ziGT4^xA81KRap2s&QvZ-r*_ZUpDwTc>HTZpU0(a{{cGP@Ui%KzZpkKrU$YowW7xqf
z`W<?#L~tR)PLAvlV&DGXoo_X>EDH=(Z8Cw@0)`UGs;|OTVS_`IZ4@&{af}%jW75DQ
zRnn$MYaDq4|E^nQIq-@%3bMc)C!gpSvIb8^cuzl6-$=PEHr(nPt(po3=>c+>fRO4%
z*J(8x6m=`!-8tPWNi0o$Syr+n@#&vS62C7i`RB4k=xte}oJu6=BbqP*q|D^DgJj}O
zCB515Q7u=jG~YWDl*x&ZN%pd#imTSk0CekKevQN8L$mDrIkmVh2LkgSt_1I*743y&
zdR~3K#e6cx_|ojY^37&oYcYI_9+&Ot#CTIQy5pv@1y$#WwSBmcWZJ9mO}%{zpJ@|*
z2$lGHlIsR@QN&%WW_>2;WsU`!eB*byn|B__JGb(dnXQHOfC2cl@|b%{Sv<QNz)Zl|
z+xt9O%=0=fOEZ#jQ}!getrSVv$UcFqxTo9AePn2Vcj?#Hk=^}HGBoxaHb$v=(OLi{
z42MFNZ|E41p}ZZR5soXuWfIZl+si~uV^Tler2QL_NF$Dxh`X~J3SULiw>f&cv;EGr
zm(I|<E_&T)pEXVdNsA5d*yK(?=e0XU&Q8ykcUKb;YHz!5EK`zcteS8oaqBL+N={Sc
zDTu7emc8!D>PX_zL}5n))2in0YCtBs<RfAk=dmc{w9|Z#8UdQ}oXir%Ut%fZ=%1{f
z)WSR;I`IwRRgcT-OUIlhw1f=hqkXrT4V7cV@S^!)2azs}LcFKC0k1DzhTRi4BGW*q
zVxtsz+&DWwZJcWLIh-I=uNecGZdzCI-&gLteouj}a~Uj==NkO=0%@+1;o6WDYQCs;
zv0s<TQaN+909lhex{@7w_(<;RkgHaqW)&f?c_q$BDDJb&)`7OOXfxTq-nPH$BY+=H
zk0Oq<h=O5}8mdSdm*^)oX9e64o&9xD6YOqfQMQ(0D-rf@d7CZoRIpBv&|K_Qltvd&
z^j;-lcoolmc2Wu5xxS_CSHimdhbXHGuD|=}m|Owl@1)SFb^y?>FWROa4Qr*2*6P@R
z;AN+Vb8Likqsx_}ip*TRv>;Qbq?}BaS*FVPeqlM~jK%i<y|gnGjHbU1sxVx1FD^Pi
zRnT!PQT)`~T^1(0Qfc*UazweV{bOY{MFr?2&qd4aOp&I<x9PL<;i2dnpUA~RadVB~
zF0oVWp)#LM*w<7Z!;>pueY<a3RKX@@fcpj6VdPgawJXLTq@PrlAvJMDMq!T@q>ht0
zhJK}*lJRvqPPU`-aiaM-uLE>{;7w*V!Zs`%1xl<vmKAO5qRN+<uRnG&9`$enn7?Kb
z)3W-=I_Be)jbfl*dJ>^}p5-?!^Kpd!XqQq0J`>nXC+m&GRtJq6+4Q-mN4c#{g(x4q
zb1Bf8+}>(H+Z4OY1PGJqm8l(V5%MtAr0t6)<KbuM8{DVajTsnp3!(eP&v|aIhd}=-
zpB+OJ%IAP;8B7NsqAL~JH}AG1?!siBa`!P?g>r+H%t|V8bH(@wub}v?OO)~D8o#`%
zvELi^U2S5K-q_Xt5@xSa|5`dC=Tflz5^^^3xH*Bn)0SF5Y2@~<=~X^!)iWOBJU2R=
zfZ^0^3tnr+jXJjqW8i}mm*O64#jN8^u14$#Z364MXKQag;__+9_sQ}U($$ag$~s|>
zxkUNeI&ee0z-U@M85cP$J3jMpZ^rFTH%2DpMYG$9{x1v#!~3w)EV-%f#4k_IU(`?9
z4Ma!5(5x?N(XW^@%H=#fZ#SysYo4~MWW#IS&R1KvRcO7Tjn2(i`w-swL#-7?pJ*&D
z&&%G>*tGS~+Vj>ptdaXPO@w~6Vg84HDo&FPKd6wQtRQ-&?N~D&YRF%ZU{jh5IKC{<
z0TF<*g!KU;zQ`aoL1;Nk3(gZvzgw4oz2BeA2=`s?5rU-d!wrXVH4mF`K^~v9Nd!R=
z5BV8FweVHhI@WhUg5s`E2^y<%TBrTEdHyy^?&dI{WMBt-Nyq)+g4%t1EGO7HN9Ro8
zwpI9eJ@mLjgr#UW8DGQblRLOT=_;YzYKf08PEMF$q^RjCqx0h!#3Ys^Mmn8QM06e)
z#<j2$`m*Ms!F0T}D`iZSVTwK966aU1Oa|HK3E#1nVQarPo24)tlf~SNcF8l4ME`^A
zL3%x&5KrcJMM1t8(qd`yAno(5++zb?TVNo}5gT<%Ei}C-M-+jjSbnf^G0Pck(P7C}
zHPde~;da2ELxNSYhmvX6=h-Naw;~q85|KdNQ#w?j<NSt9I2w2J3qJE5w=Cjk5Ct<1
zsbBF6{s48Hfb+A45ZA+p(zRgPx|Z$P)%?Ikf_P-F((9YZ+L+OUfeqdwS_S(RAc3jP
zNg~r6eCm<fS9$x;k@oqk!2Zc7#E>L<WPUw}0+uGGAo8|&X3lTb1)wugDGY(D=;~d)
zi4k574;!5hPo5Hn)ycq{0WKKrhK9B!=MkBo<6gVz-6qEDdtFEH_0f`;X(w1=Cb$uX
zrQrA%SQl~?T-q{XpI#~ZdD!>N9$zMNvOJ%VeE^(#vtC3-c&;q1bR(S|3OT8WHaU7y
z+2Ob{d(O7G!VTA^A;L#vYDlq>)pqwg80sBzvZLud%hm6#8}CV(XEKdpZws#+{8d^=
zJT#nK#HjJDybIHR+G!ldtwuYB|HGdb>QDUcm1OKwK^P4XnMGrQ-J>4kE>KdSGg}t@
zE9WaE+IOt0a_EEF6I@d)%|47ROZueWXdMf6Dzf$Bsn=iDn`ee;sj!1EsP*|p*LEWy
zCiNNxDWhcb;ruq#*S6dg$@F{U!OnLcbli?vL!0{G!EmtsVEg${hZ&vUZqILF3Q^`x
zzrtbNcL#%ATWKt^QnkR0tlNvsaw_<De|-tf`K-5FfB+J(s!at!Tod3d=547{hi6^n
zM%FkKfSY#OiN1^Sla5BYHMc2?(u39HsXajK!Opo^OX>gq<nI!`zc|6mNj#OrCiiRk
zUR6F|ebrG390uh#z=$jw-U&o+C__0909_UM0Tn@jEio0dy}`aJxUX$whW#*bh}AS1
z)$M<sTmH27A&D|X0YoYbhMQusM#zqvtGG;vM+}u6B*<i;O}-sBOFb{-wpOOM`5<XX
zA35V6R=*n0KMIDnE?NX9Nn)byn>Ji4bjuL;x0U<}3nWdRN$}V7Qt+z&3Qh-=XhoYS
zEX&Q#8@6_xEqpA4X%|$#$TvZ6R`l>g7x-j`az4~T!fGhKJW^<l<=L&r5#u-!1KB4;
zGy+jVW<cM&z_3lz{)fl#?t9$7nV=~)Jb-2>{l$DR=X9U3R2NY!7}A{JWVWMM$+(Z+
z!H`pneB~iHxtcRWLT5YFiD@Dpw%seKg+ye-)Nn;7$|??y>tXlCBAfXycE4bm;s3^y
za{2BpkQI9XEi0V1VOgu~Z}G(<<`rek`T~$fwfKc>e^A3r8XNe(GGds)d3B3IcV<hK
z$%A^FeM<DRN8z^vA&;CcGfW!FwD+CUUyI$*V_r@UE2^yNEWzk1zlZ=P+m>oaCWboG
zPtx0j%hQ-<y>T{zw<PS_56L`pFQS5jOHEsmV%Z{m=6@A<2kx%^O>cZ%2#`sR7nlvw
z{czjIr(HjUyO2209EJOZTH>NOoA}-)D>``ZKoQ&{DwyV2#f(&jZ3;8p3MC9z(mIF3
zpqa+l!6>uZNT+hg!`ZgIy}hB_+PB4iMz_gLu*%VCUW+xYrs(7}vOn!!E&#+1@}6h{
z30{xGA9E=!o3I0N!gDIU;*gmpny7ZYHZ778>_eh8r*_|xt1FZ+-b!yq6rFpX3_ow1
zNrswQr$>5-H)M90LpsK4*=1j<zUkq%#(1AZB^t}mg!OdhZVO*<lGPiNYEm8W=4M-D
zN}l2m%mS^J{f#+wK^MA-#I|PgZFqqYTHwk7r<s(a900hc^_m}}T^kLM!ATZl@D;1X
zCfArV9B}J}D-k0|TJW7xd-n6rFBG;w>acVePOGRWwp*=G6`SB2e1K4oIQLdmP#xRB
z@R>y=VFQhNbMAtiC%MS=>Oj#9GyW`Zz(_2P_*`>{C`ZEc$=-&DYBn&on~*e}AO&=-
z%{HaywI!B30ei78kGE1}`d)aXFOQ(^BAA9zC02oZUB<tK>e47qoI5u>HGu+rQwCUN
z948BFF|lv%S5Kut^Y`tXW5lz1O}d`z*+j-zv5plP#u8H~^M=Zq&ic)+DWIUMiO5E&
zLcH;aNyA{**@CcRt`<WHt77DY6(4=8SYoY?U{>VUu>yFRGbI7&GLycyl4G&iQU&G0
zFRP%5LQs#qZfyx$!&VeLp2D|1qC9-ym1w8=chMXwwHF@J>Gcf;CZEpI$qaSKe9?2s
z-e@wu&KR&pYb@!g<)`T!BP(2{^G(ORU@MX?@xf*~;+Y}rv%hAvv{s`Dtx&beT)F<1
zEyAqOgp+@TQLNC!s`YEV)v~&E#(m3MHkZq2V2i}RC3@Ugsc5}2);$+!MDG)eSPLzA
z6C-LUh&2<ku?=$z!ALVJ+J2}G=T)*Oy9+C8`H&B*aZPl_QI_<*H=Yp~h{eQwmR?^c
z%F#&~3X&2GE8Py1L=7xya*2@}0;jeu;<9mq_XEl);W%ZxZDsi2dSl50LS$n%0#RO3
zgp~o0HCUkMMo50OF1%{z@KxjJ;-nEDHI5tYwz@6Lg#M;tU075xjU(YX19|}e-g$-N
z7RYiQF}<B=PVqkKWgoH)Td<kK+uN)loD#*Iz57<Sv5?!-sw1~CgP3Gz6X&Fdg=g40
zSa-p*qvQ?iRiGw437+`{-TQ5+nkKMf*!Kc`jqC#ry~~5pPZE0lr-*@z0;<U;CUO+@
zPKIbz#t-zAgC*&AFBb3h=L@*!J{#Kx>)o4S6rpiHF%RD_S~P#n@`q`eW|<ETL$zYw
z#!qwGZ<bHp{lbbU3ICX7i%a|f{Z-ZTuXK1(Hav&)n}jMtTU@1gb@P%RJLdmU#qmMa
zDWcspI-U5Gt@vDWd@xYaL(wLU&9$k*=)p$RYBv|pzvs=n0ViTmIlks!H(PXeZWZgy
ze=B-lk{dFbDOP!176diRZ-2f=w!ex`QUN~em#T5K!I>7DI8LWU@T7Sr|8kMVZ0@fL
zS)yng6{H+4kwi}YG`d`5K~U?kC(zeJ!gu?%6a?Q>POm)SO6+~nJQu-shQW32P@wV&
zm~(9<h2af6SsiMnxb*E+IzdWut4PPjb&V5T`zgJ)9|p5q>?8qH9X8|FNA0(9^W}>e
zd!_BC%Cke(_+{g)(QY2f3M=l_Aje~`JmO&QuA)g7Q9qX3kgLTe(j~C<zvUkG0Tj<l
zi|=E2E+YbGbCg1bFQ+*j_GEdRIT0EV491=2<3h!%olG;;HT%;6c4b?+9I$wqejF4r
zowg;JS;U}!JjgM;RdmM5G%CzEnW}sQ=vI)A(lFy_zQ98#DymS@F{_BY7L!FL1mkAS
zr~9Q;c>BU)k^##BjgWVLA5OwxbAb%Ga=`{eIj|(dPhTgwMTm8Z$;N~n%EoFw$at5p
zP%>gK?wm@^U-7s%f^(-JFQ-~1?0)1+1o{$RenubGqWUQ{)FUZZ(koLIQ&Es+4c=J+
zoralR;59e1n})fyvNpp|cJ{E{6wEs>%sbEJ)ujbB*_|Li)u}yL!cTSkuD5!q4ZYc|
zFKWk!^H03thN_?Es-KruKliH-smTj^WaY@0RC}_xq_rn!cON;j<+V@cb_$QCDCgYE
z35{JYW~ghM3=+<6NXSi*X)4H`OQ8c*1ey4c+Yk7l#hgw~23xep#^{T|%>H&4rqNco
zs51C{B*h3N#GF)|qASHzEMa-S1#bf@on|u2;6Bc7tRnWJx~Wb9y#1WHbPA|cDw525
z!7k|{Rt{Z&BTkkTpd57m5RS++%M%Xfw^K2<qhsL$!I*%VmEDS>p382fVSauFU+1r5
zc_3eBnhRiKgk%s;5g3)bZ*@GBF64}6#T5Q!%%`FuXFFwU{kQ!v|6?(M77JuPFazXB
z8hv7N68ToOA_wFM+)8Ag!ZOtLGdqcxJK%F-at9Kbh}1jQUkK-s%UO*|HIUUL3iB{4
zoD?U~nSNV>%Um!KWs#W-KARwUn@$|F%}q;Q!oDdoNQU7e>P!lj!ul3P4J`^A3Ko%u
zoKl6b5%l={2V)j5kH<oXNG^bzK8Xu$>rC(T)8b+N!C`0A7pXG9cUdF)y6-&ZMpM6M
zVRiUahljg2HgiEJyBs`osfP684ClF7KWY9K`8m^akkf>*c~#P4e}R>`BAgEy8V27|
zxF~x~a<AMaVa+(oCws737PjtM>66iNp0{_g1hmOLbzNlT6~hePUX_Lky}jDk0w0Yi
zHiE5(vF<16*Eu2cCd+n3j3>P<qpe`X#^*01MjR9U`C~}ma4cvPY--SMsV0sqDzB3E
zTpY&G6Ee#=yEql+2Aq-N-iXWB^64^2W`99x5jvuB5ZP!$=~AK%jyW?++zC;xMb$=C
zGNKYpG+Z)kV)e59W6T!26OMVyfpybye=?gTeRl87`pFoPBMBDou7{d{t&qJR$|!An
zQ!+J00|ky3#HOZV)wqD`&@$8W4I!bk+F*}L7j`|^69i5-I48cjA*>~k#r0?9JWdsa
z46<y~K-c_|>^!|O^!yQ!c5tdX$~N=1fhU=2jzj$?qfLJ95lmw`-(tV&Pidx+P*h?s
znnCrGQNXCt@3p0eEU*@=Y<9@Hbh(<j1Ipge%ecQDH0`V0lHQ9Ciw*@g)LU}FIM>V9
z*2T6OXGfm%hmuyd6IGYio6RiqUd8Pg&1tOii^G}-L@mopgsnVnF_j>rE3T3VqN8lh
zxhZ4P%@)9NWwC#@<BalK$R|&{{9ZR2tr%wREg>p4+HdP8I;L76L;+8Z?XBaQ8d-;)
ziF+6dI<RitYI{pV46M8N_MUNJ$i*C3w>Y1@AUh@=!Z!ak{V->-Ksb2-%REb`2qdT-
zr~GX5@>(QW1y&1YC~l?#svwR}CgUH(TbFRu_hCQv2BxsLF==d(I<#L|+#k=2{2aeL
zvd9m)a3CJ)5XWAr98;v-I6Z&MC_e?}zF3ud5BF1?r%MN_pENyuhp@7AcI#mDYv}%R
z1*;vw-69dndJW9L45pmhR>~@iyK^}vn}TX~Ht)5U0}=Fw%FoB#SXb}2RHU_RxxG;<
zR1m3FflcE7sSb{M)1QA~`N&_j*6*nCwh6?IzrKa*;k+F;kK$Js^>>ZtmVu>)Z-}lB
ztYa<uZR`H!+efGMxOIGJRkVEzycZl4405>zUooNthFVOK)q%^w5=DfG2>(=zFdB#i
z2*y1Z^-FFVNQ^Z@`C9K<`Hs?H+Hd1C1eZUplf`WGtCK`Xy(gVR(JWmia?bd)&Vm^d
ztL8HBcb2bE-Eh*h8!ww3xU$GVV2sWfNRGExTi(cE%|k`vZvDkc!!4K_a;WU<)AJ)(
zo|ap51K7yx%XpDaVECw#ehigu1lz8+>!)$2i_o7=9qa7;k4s-~!>YgMbMzHVV6<^?
zoAiIpZj)cL6q)p2k@JKnz=l_-d!Ir`Ylrn#2NtmN8cO}J`}p~v|NQLFKjw0xBRc{v
z#3#*Dh7^F@3hWiK!+8JnPyU0e@kCilZ1;bcHg@3W`Sb7L|4*Mi-`SD>@6z|3oj*T)
z_Wk#N+Wmg_`<-Whe)jZV|MgEhyHB4#d-|tn=XdFi_p`wFM-=_(W-&^~CHa=6|C9c}
zG1_Szy?=ZHm(Ms$9ybSgs9vSXY%hAzIePr;@!=5h0M_B9b_kE1S$cgl-|W|-r#rj<
z_W0?})7|J*+DV5gTrbf{I!Y;6ES|{g|H61>z+CWC6pyy;n;)(3^m3cvH}i3W-yBq8
z`)0#WKm|kKGiv1mpNA99?Q@Wfbxc+@&h6eGeWax55&lbeFp5ye^99O|;M3zD$H^Uq
z1zHd~9jEqlsidKhbV2|<h&Hj7$CUd!$&D;<JYI}y(F5;`%>+9MPy^NX7*Toxn27Lz
z8N~hUBljS_f%j3#2no<X!c1R2R%R`+_>Y*)G6%={qaP2b@WY4v=MVVj!WyQX>DOP~
zOfb$TkJcrMM69G?@nF=8M+r_zXPWeZX!}Y&NLffkp)ACd@EU0|I_2~pX8+4%3{PW*
z&`S}G7tw0dYc%$t*lpsWI=%UvrTyMewUDZPGQbKip~(nM45<45#QE8S(quNQKmuvj
zc_|h%+E4$9{N<hwh$S^6hCq_dx#ItX^}HUBpshXVV{gvVK=?#e%1mGv=M&m=KArn>
z6?8T!p%2Am8;2B*!=`a5b^qk8Ma}EXtn1^ZaiSR>J;#YkYV>II7xPvmPwKyr;RZQU
zpEgea3k_(`>Zc9yqJ{=lv^dVFBVO^JHF1)nE@(^Bt^9MVHyCU_40Ja9;KFAW_0;M+
zJ=JHoNqjk3Aa0}6p{=NMe)t-JJ&)r0*-z^2V2`SK{<e<3Ro&*xEi<Wh&elsDb^P>H
z36`-71~p9M2Z?MJHWuwtMA9G%JD{%YtM7QAz_-y~@D<0tx8|V1SrDBUW=JQuJ)MD8
z>VN>OVHMdwqc-}B(p(HK83|}ZE$V|z%daI=i{48j;@gXywV@_?@&a8dM61vmNDl6J
zKY}*^@u6`r<|9^LaU`3Y#k5{C(^-@8Vv+EW*KATF(NV>k_XBjW;}e1GxG(|i_$$x3
z^I{nZBY_sTSjT;49<Lbcq`qYIz4s{e8dq&;u}k>S!<PBF<K0L+{^2RUYdVK04}5uc
z+BoY5<H=~<3si<jbj0?{9>$zfh%60Nz{L4QbA-|*JvSN&#vyt&;G8JJTPM=F20KBT
zV`P$0aFvszx!uA*ZEKr4x3+<%Ko5tVH?`<L*i!<EZ3Ax-?OA`$KDv5p9-38|>4qjm
z62-9)&QgbZ<Y&!6abz(ggw*F0J35hOQVGYGjBNw{zX5~VIBdTu4n<~20J}I#7Np?y
zXh8KIgGyw5i6uuE$HJoF=f^*ie4Ou}{&ay%*f5EApKofyK0c|xjL*(V8UZhK_j~h9
z&55pg&93;@r8U26lk%S(46Tw6110|!D4LrNvT{Tpak!F~O^Qh6wY%PA+DGd)S|0vA
zFmDnbQ~U{QJi8`BX7EtKG4kNJ+R%)1iplvER^}@#P3YjkVIiwNqc>EcVGjO{-Ux|{
z<PG(|L2(PIgVC+wr3E~{w7{zs3LG_B-Bt3xYSfQb$lk3tD|f%W>Ui6$j<>zyc-yOu
zx9yL&kT6L1o2QJx{iB(CybupU{EF6r_(yr}?9|t-8Gt(Bi|KCN7+(x0pORS&50T4s
zo^3+=H4B%uQkAd#Di_n~{i`%<Y1Qa4GC%%k=~_<TFb{%ZSUb_L>z-W+Av3%qjQsY|
zPb+l9Ba(`xyuD%RX)Ba(fBi*jfBi*jf9WEv(9k^=A-7>2H%52QiiUW}S?=#{n-SCJ
zM{%av$1o2`C6t(HNjx|2BtZ`Fz+njYtw0wj__6<%$0>4%TF^wop~9dO{vN<lS_YgY
zB@F#42I-q3nHv1L#ey@GR&n(Q%Hz@HF+a`F=M^T5vTZ)txvQ~wYxBWkD|)ba{9sW7
zwvh}(D1qq`T5u$ATkaR?i*dLNtD6ss)Xl3P>xv8_sCV|vJj8=u%ssSb@6|i>Y^@*F
zTir$*jR`FWKOI2yT%J!fFcdJ*96b(<I{J=3+Tv5^14@tbr4AHrNt;4WB?0>t1nR_H
z5?ID1*p-OU6?q;o{J-pkZAawl$#+@OogqkWKZV6+-g8q&9~52`duNRAGVLXsvA2Ad
z+$OW$Ffvb{jDu*Pm=uwJQL=cIqG1QV_tC5niwO&Ch0%b0vCuB_x)azr=@~1MX&TO3
z1c}t`#K1bdXm%Aon3o6>TAX-VKP*mxSNusX_02`2{gYIx5Bz)v?ovsH!;?n69iO(2
z<95A+oO@}$irJvUR3!%Dt(19rUd+{Kw;{*z`POgtDVieLQKZO}L^@F#{Xj><QS)@u
zTCy6XeD_^VP8EAC(_fHO6^R+=Y&K|K9$G`)F+hBCJR4(|c4_O<6WxfB9SIknS~_<+
znqnPT1)YF!ISkYB;?DZ`n|{oF6#F7&*Rb|i{bFjoZyc(48F1gCv4NEeueAC__th4h
zPOV1!G?$8@Hd?K7#QDNJ=PmezU%ZU4HWv-@2FG0Q@fW|U#`|teM!zUY>a@M&3rKI6
z^zMt3*Io`(va1XfiP=kUH#!$5x`}rE>}A8tAt4X8B*cK1`l?BY*}4n(S8$Zglat2F
zIt}#fee>MQLtSgqWWA^#`NM3VzlslEH4b0L$G`%ap}<-qfmNerf6-ln&XGj=%eF;J
zNa2PM4ULD2dGuxh_@nJpm+rHIT|iKp#-V3A{2UU&Ddx0HJVYwF#YlcZrQ2VvqgV+;
z)Q}V#wV2H?77*+5;9vQ!!r88`IpPku*6|9RE>PBhRsFp4%eE1F&_d_{xv(1Y`w!SL
z_1AabDF}q<WinUDD~LQfxiUB{#2QB!8-dL|sWGnLm&m;)DajfLDTCIm4-`Y0*4!Cx
zz7}F2aIW2HvCZX%>4yZ?=$nH3SLULoL^ZL26V1;Zt8jOJK_@`CKs_;9Y0(|45S!oO
zI4}gKF`%@T+N0h4*{dntBUDp_u&s*-beVBwG52R*Oo;U|S<HFH*VhIUq7!?s8cqxu
zM{8H^=s4o{22&3Jl<>{EaWol!J7<$*q;Q%99UB3N)~a{I0V`2)bcMgwqP)zCQHOTW
zL2Q&|t<LNiUw*s9K^xc%jw-OoHg`1;5KJ`37Ds(I?9oj%`#<PyF~5uDqkbIf-o11C
zCHXci!)O(s##Pv}fOm|{JpE7U<SCjN|4NDoC_p-ILTrN`;UAH&MhD_!qO-ChB}?X6
za+MCzZN`%9Gu}V`d8sf~lqZ9!12!gCLBPrsRDjmmaLJ<nL#sp9^3#~P&|_J5#PQ<*
zc5W=anF_*evNzA+7n2>|hxjr^ca_Byb)}nwMWPW&YSCoIW%W-u@|$UZbW%@vNuF$P
zZ*QJW#*hCinN4cgEC;t^T?YozQ{^xNcWg3E1b)U~W*L0Z;b&Q{vk4s9k8$u%XiyXx
zmuytjxK;f+H%0H$VT04LOBS}-hQu3AX~r=Z7n0BPf^)tk^FG-@IQK1<tDtEMUabK+
zhMmu~j<K#mt<$2wo#wow>vpNn#*$NOJ$Kp^1_@DDoeuPXkp<~FY;6Oce-1<}_(@h+
zPgm6Acp73Zjq_9(WWwu%4QRu&qb^#KyhXl&mLsvcXH%|*R$j;L1mk#eAZukuBU@g1
z9g)Q9ih@I@3`}N4+*Gj?@No8Hj~HG?9>~mA6h8IW*W^gH*(V;XMQ5JejM<=qIuU$q
z?U7s9=BO}vv!HCvuula!N?EDGG8_v}@q~IcqIWb~gh(k<sDtNJQsop4!;Thn<xo5#
zB7PqCx6EZLVvkXN1z9`-lR=<71y{mWSaw2)gtoVue(rP{XYkKYXNQ|Xc8?W)wVFnd
z_I9Mjn@Ly=1wxM;qA&(tnZUyXCzTI8d`GaTPlV$5o=_$YRri~>vwiOavgvxnCo^`Y
z-<xJ+C$*^$Ncxnr(l#dmAf+$QAR2H}5N9la!?#<&Dv8e_*A>WM-u_ncWA$o9WA*d1
z_ywZV4KymwHJk?<5kFF`Qmt+abJ{-})A@A6`I0LI<l4IEys}Gfh`0GhajDj;pD=o~
zQ)+tiIfgfDNvZCe7PQw!NzqY*3vXa7miZk4rVkP<oGS%vdaHiq3~l4)Q#|brtfA#f
zb-HzTR8R_*+#Xe+)Ws3>@Z#*OaS|VPE>3CY7X#?wVmwZUaN8_Kfte?%nl~G>UbbX5
z+V79x@$oi3ssD6-(dF5g-3{QmavKAOj2vue4p03>hB+L?CK@xg$fAjgk_knMB9YMV
z98IF>FWdNkJX!T7F#NrpO_8^eI&3V)AI6hU<BhP2cht*1SbZ-LH_#~UBtoFk_*TfF
zK7xPjxaz0%_j)U?J^z0F%U*<}R;IB}X4hN%+c^0ozu_Q~L2ka~t;p_sI-?Gg#S?@X
zN6Dy<p+QUo4`DQLhT*JYKo7A6QR$?mP=DlJ<<Gx28C5=v$8w+t5dC+gvqTT0d>?f=
z9+_KIRp{338h@xhKpNSkssTEqdT6H69w3&fh3M5@Qjb)>*|fX+5JT9<7bhp1DGNW=
z$aH$V2*oO(HBl7!c`r%_k5T)Dl>GQXwykWf(yb_PIi$5>O(-K}RHN;R#J%QRM!A)L
z_H@&pVb}KXTHup0ajWdEscB<0g}6-jsUC;r7$;KZz<s3^*t?1;FYN?fT{Rbt6uwDd
z$Bg0_vTRE*4kEJK08W8$n$XPM2<wmq<|-IRZ4kk!8o{aB8~5Q4K3X}_vjmb-MF*24
z8-F|J!V3E#SlEq)WJPy}UUP9XVP3%KvU%{YgqndYuDlq+2C#5NM0kF99qBMmv8gMP
zXZ;Z6obcSxv2_A7U=MFYoZFX<PO}>KATf(gsYp_aL%By|hvzMf&0D!GpRc(`lU$N2
zsobovIQM8xGe^}L3X<h&E#{b=6;Fs9W45#p>ne(~(+_AIRu*eJd@T%K#W_$s-hBpd
z_``|>Rb_yIO`^wRE+lnj@TGLQNQb~-PE)$X$mrC)SX7dddpjLaiPChv)x_?`$0v>V
zak~TEesQ8Y;P{9e#sID;RY|e=4qt%k$*XTdcpaBtr#X>W;3l0V*>t}^aEAXF`IsJk
z&<yw?zfC<o_wl><ZKEx#j7>#e^p8M~$mDlhFt)JF;~%X>2(6kDmo*KzI7tvj#+xjJ
zHcrw;3J$=1-?ijrp(uIq(AOBUAzp*~s+I{W6N!ci_Dswb_08Nef}TR`k^7ys2`M8Y
zVWbd@^TE;%Z0p;M0vjutMezMVw)K!#>j-jOn3coxh;V3-Y}kst5VT9kOa;P>I)sxe
z61xw1Q86!wEv+CtjIgYtB-_l9n9@w4)N~d>>xd1m8bv7q;^2#jXiTDRk<25jLl{&r
z59we5OchzoWcI{*M%nZf@&?M|vSSzH@*x$P5r-skHXMg-!nki`pH<0j^{0DhD`}PX
z$nJsBAE^qpw2mzdoceeKC}hq2t>inYXz8D}9=5hs5ri6K6TeGp&UkiI!E;~Mg?6<r
zw3l^3W2mt&OdzBgBq$Id*L_IGATb7=Mc_H+#U!EG2`v}a9yV>E2N0Z0sQc;l=i;=2
zI{U)#7=!9zn~QL0zA3^{bf5BAIM_F=V8?ynG_S(LP~nvjHw-mQ(TJ2uS_C|p<lZO@
z+s3+fju~kp2=VhHI-bFU_0web0gegAvO)!z9pgg*ghX)F>(iJYI$Xsd=?{At?kNN-
zLUD=|DhUO3QgNE;7~vZ5*a$Xh-2<NxuuXK2YRu9;DWR*6nN2ku6eY$?d3X^0E!2(u
zaBvp5d8fnAv05y9t%_aL3`I)R9YqA>X^z>kKga;efN0O~%OmLTr`KO&0H*H!4=)}Q
ztwaefq#w?Sf?s4m7wtQ_CAnyMXjH?fso5cW?cmHP?<c|l^0~EKJ<P9tT*9synFtjV
z#`RxFfsLZT!6q&>GiqliKgGMxpY6oQt(Wy0Gf`x`fPpHnwY*?@^I5&{;T@cgrfN%S
zB*MX#-WjNMLwy@*S&|VfB?d7wRVaR?99C(6N&I;l=D)>AShp#1WG<t+YH<3hQGUcO
z3cl)wBlJ_#SE3pY85qmTYuu-Ys*GGucxJR4Z<`$y5;c$Flg622FzTgSx0pVE1635>
za939Blpf(p*@Lhn`{>80cl&DVZ|R2=J~)W{e!Ob7cK$uCb6;$7onFBjU*(0&tz%m~
zw(LM4sWBS#Pp=5FcRrfNKw@I66BzrWM~@Ui+T@If^mOn6QpHHet<T^9S9n{~ge{Yu
zI52N)1615wx1+G{R6l=P{}(hOxmxK-cHC^AzN@!^Av!;8)uCs{FD*1iI9UA0S?~a|
zpJ&<ulFl!4Mypxka?%AhOnuupLj!J_n#P%#mf~_}hn*%Gw4S%!ayylYB`-8|8qo8C
zBC?})6JD%#*M6h9f#p`mY3>EjDUQQH*&8$TwEEr5_T;_lo{rT_P)f7e@2-$iUwLxu
z?1$5hm4RJlY3W%}>CxpKvLDlJ@$krfpTofy`i}87)%U!!mb~%GRqC^X=_=8^n}@0d
zK{N(ps5^3u#I`i!se=U1I8-Fnz<D`{=oE@Dvq*k?krfsdtG-O|Z6j_+2>oO%9dc%m
zCH_E#m&;kc>ja6cVzg-cO9f4>tS`;0N@jn5X{bua>T0JTLZv6|sU}1V1fL6Cq>A-a
z(jblzBKK>-o6#QK`kIj=xq_wrb+<wC5Q#Rrw#|zw3#<BIxY)M-+t3;`El#~kli^@f
zil`Hh#By|1zxb)!cov_U8!VimQ@dBqPnXsF^u9IkE~|O>zBTVGt9b`%t~m;AiWy*u
z40o(e-cCL)QnpUBY?dVE5lNk{k{$w0A=-I5Lu*!g&h_B{%;vyIGe?aNRYbBuc@08y
zU!u-wg5I?{I~pWoHv7ad4@N`+R}ZB*3M46Lu)LE@JXO7C3SKdxfbsq&fy?x)dG^xY
zC|pU3V^+hZ2ZRNSucOR3k2Vd`A=BAPW>=Hhh-Z!v<Fo06&KqL}3x{0~%~}PD-kAf{
z5q?{{!5jI37nqBZ_bxvS=iYP#c70w}BuRTKoOK1L!pj6nz<bPRlg}k6GE1NY0-OLl
zMH?O<Eb|gvmx9aDsUrt9vaHt@1eB9AAZuHmO}S6IU2u`BzY=pM4$JPz!K$ZaJ5O=z
zUraK3Kh-5bIU?!}1}eg5#sLy~$^(dH=aCBZWOkZ)?&EI0geME{&jhW+$Kt6o{LCO+
zj^U;f%&Ra3cB3e`S3#d=x5>ab#$w6jF6l4k!ooy{s+s<0){*q#PqGUBG@&pOy;(ZR
z_M#qIk>1QEW5f&e8&{HW9h<^4Le(edrD<N72V5?)&l0nOoU4iTu?s8fW6gUhn`Pu?
ztx_C5<I0&PeHdv!kx{m3r1k7``mPQKFG}t6JMBxE`(owC*XN6W`=`g~{XKthAsGMn
zYLL#hZ+?$9%JF}9pFZFHR}cU9*$#aA1ONB$@bkOk|6Yv;$yLNc;p3ww0=a0*QTM9{
z3XI{%2o~6p8x7(Q$>+F#bshcH2x{?DmM9+^{F08xs833#x6fnXTnBM7&ZQ0tQsJ~N
zDa)y$vh2&an8Nkg>(A5M#Qr|QXpSh_(rM_>Y;4(&kI+)+Wdn!he25Wz!~OC!_XVR(
z<twZocHv=R*T`Sse}|1$H*VDtkaR1TeAGT~=|l$AcUHigefTnBe|zn9JnG%iIt`QY
z_58-3hZ#bIKqr6B4d9o3#Pi2=QgnY-4tNf-L?4}V3rg$aHyFAdW5_{itC9jblK+RQ
zq`^b2Y{~Tg{d=ICL5fI_880+PCL)7%Lh@iOhJ0Z2N!&Eevoo)Jt~gxX1r_9+{-h}6
z8&AfM{l=cSG|;_hoe)v+7>+t!!O-BpJMBZ~@3$xQvlu2IKJIk$A3F_`6BQY#1J@r;
zp2qFYTm5IV1>9-J{<GCS@18p?H(OhF$E-h3o;j6aW|Yr5*_{t3-#Z1m7iaO?v!?U+
z@yYqSxOoKMcs<Nq@ZV-G_-{4r-Q1U_`inIS{6WtG|EXs||EXrdv`ND@U9$evvtTmI
zpiOq?L+7yD!Vba*G~uSj=Pj&`T)mbEWCeMmrzYvF8K1*c!T(MgXVEjA0KH~ZB=`zH
z-{VF*p`DFH*lgWCSJ=1PNPm8@*NvZG+M{P!424bTtsXslimGoauA_YQvIy^jC<At|
ze}fy-t?un}uJGM?`-lTKxOF01jz_ZTRj@+;IHMy;HkEa(WiyKH`Lk&4V0P6c{9;`P
zgKWMe7ae<8SvvjMnn@=aYY8Vao(_~o0fzkzi}>FtR`0xby&L-Y)c(jJ$^=kVUyIXt
zKFQn<@UoasoRReBQ>@OeO>WFUFU6V1YRD=O>;xy-&6=-JTYNiCe|9PLmta1QW;)mp
zU0?{%gn>8zYIO;|r2~6mXA>AbovOy%F8PQiTstfa@3HwGJZ~}Ywpf1+k~^e7wrcY7
z(MK;MdkS)PU5*{kg2g2*hq)w?$p<TRmNV>@^pbDSOm{5%qArdvSw3Qu7$V@xU2T1p
zFYbz9R?^Y{w|;Gt47-QYHpXB+llamuMn%%`bTP*(-=;z-5g-wy9mPQak(@L;s2c3H
zf7;BY*Qf#FU0N<m0lmQ`*S4Ms-b6QO+_Sd}ObZt5+_2b!8-%lxWE$+9k8M#;Gp~+W
za)t50_MYuh<L%@sK~Y7LZ<67X2GZD}ZpP$bp#F58QB`Le`9MXv9QEcXOHg4Tu{+x;
z;*vU_iQ{Nv_&~y-g@gBKZEfdnw<yEg<Ct?iEy{6tet`k{Fwgh?9!_V>z+pIR-?+s+
z($Sk`zcdG0wps*32PPxPxyOo0$e$_DAL2c8eX%>LezDI}rc4gat3Q(Ml=Fd3CtRF*
zs|6jNq4U*ZoWg!$i&EpDt`|r5p0_8Pn7lnEdyL*~FTEU+qJVZV8*35Sg_g;!4<rAs
za?bp5D6ViQ(nkeF;F>DYvBT9$<ZQBL#8}z#P$6#TDjnkf9;VuFdcn^0L5htNrdo8Q
zf8!i-c8;1dKF;kVMfmg^6Ss6`mSxrY0vV}fVOQ)7MLkh@q)Bo+)Lqf1whFMaWO8t#
z5$8WRFOnGOh+3rR5&p}qb9sb*^rsd3uoYO1+J3GO4o=2pm2##fUr2S-X-IW`U!n6v
zb!#37vIVX$Igd%DN#xyQ(wZeh3gLm1yS*NyDNG8Uf_ltMD)?IwF%cm=dUVsvZZIUB
zJHhxh;xvU;<{$3(tmpqZN3~ua=pH?i=>tzIIXPOtL!}H8kNt5?9}Q~)bq5qR`(%U@
ziSuhZryk`EHEp#HEQc;av!IFCQxSQEsEfH$0o78K#(?L(p7lnB<*X>;!4rU{N(@g2
z$<S_wCH%eN&~C6&2gwN-r#z@zG`Hwr%S0S{L^q;4J@gtV3Kh#1m|pIZ(6XFg_Yoei
zq$yird}3sW7rG+^#Vz%Z76<?F^T*F0KY#rE@$<*eA3uNm{PFY0&mTX3{QU9r|LM>F
M1MeQ^;{X5;03GMPod5s;

literal 0
HcmV?d00001

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 974219f9bf..e6ba15f77c 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -3,9 +3,154 @@
  */
 
 #include <rte_kvargs.h>
+#include <rte_bus_pci.h>
+#include <ethdev_pci.h>
+#include <rte_pci.h>
 
-#include "hns3_logs.h"
 #include "hns3_common.h"
+#include "hns3_logs.h"
+#include "hns3_regs.h"
+#include "hns3_rxtx.h"
+
+int
+hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+		    size_t fw_size)
+{
+	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint32_t version = hw->fw_version;
+	int ret;
+
+	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
+				      HNS3_FW_VERSION_BYTE3_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
+				      HNS3_FW_VERSION_BYTE2_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
+				      HNS3_FW_VERSION_BYTE1_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
+				      HNS3_FW_VERSION_BYTE0_S));
+	if (ret < 0)
+		return -EINVAL;
+
+	ret += 1; /* add the size of '\0' */
+	if (fw_size < (size_t)ret)
+		return ret;
+	else
+		return 0;
+}
+
+int
+hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
+{
+	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint16_t queue_num = hw->tqps_num;
+
+	/*
+	 * In interrupt mode, 'max_rx_queues' is set based on the number of
+	 * MSI-X interrupt resources of the hardware.
+	 */
+	if (hw->data->dev_conf.intr_conf.rxq == 1)
+		queue_num = hw->intr_tqps_num;
+
+	info->max_rx_queues = queue_num;
+	info->max_tx_queues = hw->tqps_num;
+	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
+	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
+	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
+	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
+	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_SCATTER |
+				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
+				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
+				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
+				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
+	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
+				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
+				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
+				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
+				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
+				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
+				 RTE_ETH_TX_OFFLOAD_VLAN_INSERT);
+
+	if (!hw->port_base_vlan_cfg.state)
+		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
+
+	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
+		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
+
+	if (hns3_dev_get_support(hw, INDEP_TXRX))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
+
+	if (hns3_dev_get_support(hw, PTP))
+		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
+
+	info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = HNS3_MAX_RING_DESC,
+		.nb_min = HNS3_MIN_RING_DESC,
+		.nb_align = HNS3_ALIGN_RING_DESC,
+	};
+
+	info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = HNS3_MAX_RING_DESC,
+		.nb_min = HNS3_MIN_RING_DESC,
+		.nb_align = HNS3_ALIGN_RING_DESC,
+		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
+		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
+	};
+
+	info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
+		/*
+		 * If there are no available Rx buffer descriptors, incoming
+		 * packets are always dropped by hardware based on hns3 network
+		 * engine.
+		 */
+		.rx_drop_en = 1,
+		.offloads = 0,
+	};
+	info->default_txconf = (struct rte_eth_txconf) {
+		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
+		.offloads = 0,
+	};
+
+	info->reta_size = hw->rss_ind_tbl_size;
+	info->hash_key_size = HNS3_RSS_KEY_SIZE;
+	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
+
+	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
+	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
+	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
+	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
+	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
+	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
+
+	/*
+	 * Next is the PF/VF difference section.
+	 */
+	if (!hns->is_vf) {
+		info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
+		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
+		info->speed_capa = hns3_get_speed_capa(hw);
+	} else {
+		info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
+	}
+
+	return 0;
+}
 
 static int
 hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
@@ -68,6 +213,12 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 	RTE_SET_USED(key);
 
 	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
+
+	/*
+	 * 500ms is empirical value in process of mailbox communication. If
+	 * the delay value is set to one lower thanthe empirical value, mailbox
+	 * communication may fail.
+	 */
 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
 		*(uint16_t *)extra_args = val;
 
@@ -116,6 +267,11 @@ hns3_parse_devargs(struct rte_eth_dev *dev)
 		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
 			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
 	hns->dev_caps_mask = dev_caps_mask;
+
+	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
+		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
+				mbx_time_limit_ms);
+	hns->mbx_time_limit_ms = mbx_time_limit_ms;
 }
 
 void
@@ -425,3 +581,183 @@ hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
 	}
 }
 
+int
+hns3_init_ring_with_vector(struct hns3_hw *hw)
+{
+	uint16_t vec;
+	int ret;
+	int i;
+
+	/*
+	 * In hns3 network engine, vector 0 is always the misc interrupt of this
+	 * function, vector 1~N can be used respectively for the queues of the
+	 * function. Tx and Rx queues with the same number share the interrupt
+	 * vector. In the initialization clearing the all hardware mapping
+	 * relationship configurations between queues and interrupt vectors is
+	 * needed, so some error caused by the residual configurations, such as
+	 * the unexpected Tx interrupt, can be avoid.
+	 */
+	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
+	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
+		vec = vec - 1; /* the last interrupt is reserved */
+	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
+	for (i = 0; i < hw->intr_tqps_num; i++) {
+		/*
+		 * Set gap limiter/rate limiter/quanity limiter algorithm
+		 * configuration for interrupt coalesce of queue's interrupt.
+		 */
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
+		/*
+		 * QL(quantity limiter) is not used currently, just set 0 to
+		 * close it.
+		 */
+		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
+
+		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
+						    HNS3_RING_TYPE_TX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "fail to unbind TX ring(%d) with "
+					  "vector: %u, ret=%d", i, vec, ret);
+			return ret;
+		}
+
+		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
+						    HNS3_RING_TYPE_RX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "fail to unbind RX ring(%d) with "
+					  "vector: %u, ret=%d", i, vec, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int
+hns3_map_rx_interrupt(struct rte_eth_dev *dev)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
+	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
+	uint32_t intr_vector;
+	uint16_t q_id;
+	int ret;
+
+	/*
+	 * hns3 needs a separate interrupt to be used as event interrupt which
+	 * could not be shared with task queue pair, so KERNEL drivers need
+	 * support multiple interrupt vectors.
+	 */
+	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
+	    !rte_intr_cap_multiple(intr_handle))
+		return 0;
+
+	rte_intr_disable(intr_handle);
+	intr_vector = hw->used_rx_queues;
+	/* creates event fd for each intr vector when MSIX is used */
+	if (rte_intr_efd_enable(intr_handle, intr_vector))
+		return -EINVAL;
+
+	/* Allocate vector list */
+	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
+				    hw->used_rx_queues)) {
+		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
+			 hw->used_rx_queues);
+		ret = -ENOMEM;
+		goto alloc_intr_vec_error;
+	}
+
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+
+	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+		ret = hw->ops.bind_ring_with_vector(hw, vec, true,
+						    HNS3_RING_TYPE_RX, q_id);
+		if (ret)
+			goto bind_vector_error;
+
+		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
+			goto bind_vector_error;
+		/*
+		 * If there are not enough efds (e.g. not enough interrupt),
+		 * remaining queues will be bond to the last interrupt.
+		 */
+		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
+			vec++;
+	}
+	rte_intr_enable(intr_handle);
+	return 0;
+
+bind_vector_error:
+	rte_intr_vec_list_free(intr_handle);
+alloc_intr_vec_error:
+	rte_intr_efd_disable(intr_handle);
+	return ret;
+}
+
+void
+hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
+	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
+	uint16_t q_id;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return;
+
+	/* unmap the ring with vector */
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			(void)hw->ops.bind_ring_with_vector(hw, vec, false,
+							HNS3_RING_TYPE_RX,
+							q_id);
+			if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
+				vec++;
+		}
+	}
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	rte_intr_vec_list_free(intr_handle);
+}
+
+int
+hns3_restore_rx_interrupt(struct hns3_hw *hw)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	uint16_t q_id;
+	int ret;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hw->ops.bind_ring_with_vector(hw,
+				rte_intr_vec_list_index_get(intr_handle,
+								   q_id),
+				true, HNS3_RING_TYPE_RX, q_id);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
\ No newline at end of file
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 68f9b1b96a..0dbb1c0413 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -30,6 +30,11 @@ enum {
 #define MSEC_PER_SEC              1000L
 #define USEC_PER_MSEC             1000L
 
+int hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+			size_t fw_size);
+int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
+		       struct rte_eth_dev_info *info);
+
 void hns3_clock_gettime(struct timeval *tv);
 uint64_t hns3_clock_calctime_ms(struct timeval *tv);
 uint64_t hns3_clock_gettime_ms(void);
@@ -48,4 +53,9 @@ int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
 void hns3_ether_format_addr(char *buf, uint16_t size,
 			    const struct rte_ether_addr *ether_addr);
 
+int hns3_init_ring_with_vector(struct hns3_hw *hw);
+int hns3_map_rx_interrupt(struct rte_eth_dev *dev);
+void hns3_unmap_rx_interrupt(struct rte_eth_dev *dev);
+int hns3_restore_rx_interrupt(struct hns3_hw *hw);
+
 #endif /* _HNS3_COMMON_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 181694bf8c..847e660f44 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -1929,62 +1929,6 @@ hns3_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id, bool en,
 	return 0;
 }
 
-static int
-hns3_init_ring_with_vector(struct hns3_hw *hw)
-{
-	uint16_t vec;
-	int ret;
-	int i;
-
-	/*
-	 * In hns3 network engine, vector 0 is always the misc interrupt of this
-	 * function, vector 1~N can be used respectively for the queues of the
-	 * function. Tx and Rx queues with the same number share the interrupt
-	 * vector. In the initialization clearing the all hardware mapping
-	 * relationship configurations between queues and interrupt vectors is
-	 * needed, so some error caused by the residual configurations, such as
-	 * the unexpected Tx interrupt, can be avoid.
-	 */
-	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
-	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
-		vec = vec - 1; /* the last interrupt is reserved */
-	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
-	for (i = 0; i < hw->intr_tqps_num; i++) {
-		/*
-		 * Set gap limiter/rate limiter/quanity limiter algorithm
-		 * configuration for interrupt coalesce of queue's interrupt.
-		 */
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
-		/*
-		 * QL(quantity limiter) is not used currently, just set 0 to
-		 * close it.
-		 */
-		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
-
-		ret = hns3_bind_ring_with_vector(hw, vec, false,
-						 HNS3_RING_TYPE_TX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "PF fail to unbind TX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-
-		ret = hns3_bind_ring_with_vector(hw, vec, false,
-						 HNS3_RING_TYPE_RX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "PF fail to unbind RX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3_setup_dcb(struct rte_eth_dev *dev)
 {
@@ -2255,7 +2199,7 @@ hns3_get_firber_port_speed_capa(uint32_t supported_speed)
 	return speed_capa;
 }
 
-static uint32_t
+uint32_t
 hns3_get_speed_capa(struct hns3_hw *hw)
 {
 	struct hns3_mac *mac = &hw->mac;
@@ -2274,135 +2218,6 @@ hns3_get_speed_capa(struct hns3_hw *hw)
 	return speed_capa;
 }
 
-int
-hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint16_t queue_num = hw->tqps_num;
-
-	/*
-	 * In interrupt mode, 'max_rx_queues' is set based on the number of
-	 * MSI-X interrupt resources of the hardware.
-	 */
-	if (hw->data->dev_conf.intr_conf.rxq == 1)
-		queue_num = hw->intr_tqps_num;
-
-	info->max_rx_queues = queue_num;
-	info->max_tx_queues = hw->tqps_num;
-	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
-	info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
-	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
-	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
-	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_KEEP_CRC |
-				 RTE_ETH_RX_OFFLOAD_SCATTER |
-				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
-				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
-				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
-				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
-	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
-				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
-				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
-				 hns3_txvlan_cap_get(hw));
-
-	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
-		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
-
-	if (hns3_dev_get_support(hw, INDEP_TXRX))
-		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
-				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
-	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
-
-	if (hns3_dev_get_support(hw, PTP))
-		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
-
-	info->rx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-	};
-
-	info->tx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
-		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
-	};
-
-	info->speed_capa = hns3_get_speed_capa(hw);
-	info->default_rxconf = (struct rte_eth_rxconf) {
-		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
-		/*
-		 * If there are no available Rx buffer descriptors, incoming
-		 * packets are always dropped by hardware based on hns3 network
-		 * engine.
-		 */
-		.rx_drop_en = 1,
-		.offloads = 0,
-	};
-	info->default_txconf = (struct rte_eth_txconf) {
-		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
-		.offloads = 0,
-	};
-
-	info->reta_size = hw->rss_ind_tbl_size;
-	info->hash_key_size = HNS3_RSS_KEY_SIZE;
-	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
-
-	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-
-	return 0;
-}
-
-static int
-hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
-		    size_t fw_size)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint32_t version = hw->fw_version;
-	int ret;
-
-	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
-				      HNS3_FW_VERSION_BYTE3_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
-				      HNS3_FW_VERSION_BYTE2_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
-				      HNS3_FW_VERSION_BYTE1_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
-				      HNS3_FW_VERSION_BYTE0_S));
-	if (ret < 0)
-		return -EINVAL;
-
-	ret += 1; /* add the size of '\0' */
-	if (fw_size < (size_t)ret)
-		return ret;
-	else
-		return 0;
-}
-
 static int
 hns3_update_port_link_info(struct rte_eth_dev *eth_dev)
 {
@@ -5281,98 +5096,6 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue)
 	return ret;
 }
 
-static int
-hns3_map_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint32_t intr_vector;
-	uint16_t q_id;
-	int ret;
-
-	/*
-	 * hns3 needs a separate interrupt to be used as event interrupt which
-	 * could not be shared with task queue pair, so KERNEL drivers need
-	 * support multiple interrupt vectors.
-	 */
-	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
-	    !rte_intr_cap_multiple(intr_handle))
-		return 0;
-
-	rte_intr_disable(intr_handle);
-	intr_vector = hw->used_rx_queues;
-	/* creates event fd for each intr vector when MSIX is used */
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -EINVAL;
-
-	/* Allocate vector list */
-	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
-				    hw->used_rx_queues)) {
-		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
-			 hw->used_rx_queues);
-		ret = -ENOMEM;
-		goto alloc_intr_vec_error;
-	}
-
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-
-	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-		ret = hns3_bind_ring_with_vector(hw, vec, true,
-						 HNS3_RING_TYPE_RX, q_id);
-		if (ret)
-			goto bind_vector_error;
-
-		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
-			goto bind_vector_error;
-		/*
-		 * If there are not enough efds (e.g. not enough interrupt),
-		 * remaining queues will be bond to the last interrupt.
-		 */
-		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
-			vec++;
-	}
-	rte_intr_enable(intr_handle);
-	return 0;
-
-bind_vector_error:
-	rte_intr_vec_list_free(intr_handle);
-alloc_intr_vec_error:
-	rte_intr_efd_disable(intr_handle);
-	return ret;
-}
-
-static int
-hns3_restore_rx_interrupt(struct hns3_hw *hw)
-{
-	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint16_t q_id;
-	int ret;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return 0;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			ret = hns3_bind_ring_with_vector(hw,
-				rte_intr_vec_list_index_get(intr_handle,
-								   q_id),
-				true, HNS3_RING_TYPE_RX, q_id);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
 static void
 hns3_restore_filter(struct rte_eth_dev *dev)
 {
@@ -5503,40 +5226,6 @@ hns3_do_stop(struct hns3_adapter *hns)
 	return 0;
 }
 
-static void
-hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_adapter *hns = dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t q_id;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return;
-
-	/* unmap the ring with vector */
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			(void)hns3_bind_ring_with_vector(hw, vec, false,
-							 HNS3_RING_TYPE_RX,
-							 q_id);
-			if (vec < base + rte_intr_nb_efd_get(intr_handle)
-									- 1)
-				vec++;
-		}
-	}
-	/* Clean datapath event and queue/vec mapping */
-	rte_intr_efd_disable(intr_handle);
-	rte_intr_vec_list_free(intr_handle);
-}
-
 static int
 hns3_dev_stop(struct rte_eth_dev *dev)
 {
@@ -6927,6 +6616,7 @@ hns3_init_hw_ops(struct hns3_hw *hw)
 	hw->ops.del_mc_mac_addr = hns3_remove_mc_mac_addr;
 	hw->ops.add_uc_mac_addr = hns3_add_uc_mac_addr;
 	hw->ops.del_uc_mac_addr = hns3_remove_uc_mac_addr;
+	hw->ops.bind_ring_with_vector = hns3_bind_ring_with_vector;
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index a28c7c262b..55518a913d 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -437,6 +437,9 @@ struct hns3_hw_ops {
 				struct rte_ether_addr *mac_addr);
 	int (*del_uc_mac_addr)(struct hns3_hw *hw,
 				struct rte_ether_addr *mac_addr);
+	int (*bind_ring_with_vector)(struct hns3_hw *hw, uint16_t vector_id,
+				bool en, enum hns3_ring_type queue_type,
+				uint16_t queue_id);
 };
 
 #define HNS3_INTR_MAPPING_VEC_RSV_ONE		0
@@ -1038,8 +1041,6 @@ int hns3_buffer_alloc(struct hns3_hw *hw);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
-int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
-		       struct rte_eth_dev_info *info);
 void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
 void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
@@ -1071,13 +1072,4 @@ is_reset_pending(struct hns3_adapter *hns)
 	return ret;
 }
 
-static inline uint64_t
-hns3_txvlan_cap_get(struct hns3_hw *hw)
-{
-	if (hw->port_base_vlan_cfg.state)
-		return RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
-	else
-		return RTE_ETH_TX_OFFLOAD_VLAN_INSERT | RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
-}
-
 #endif /* _HNS3_ETHDEV_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 8632c8f19b..d8a99693e0 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -422,7 +422,7 @@ hns3vf_restore_promisc(struct hns3_adapter *hns)
 }
 
 static int
-hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
+hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id,
 			     bool mmap, enum hns3_ring_type queue_type,
 			     uint16_t queue_id)
 {
@@ -434,7 +434,7 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
 	memset(&bind_msg, 0, sizeof(bind_msg));
 	code = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :
 		HNS3_MBX_UNMAP_RING_TO_VECTOR;
-	bind_msg.vector_id = vector_id;
+	bind_msg.vector_id = (uint8_t)vector_id;
 
 	if (queue_type == HNS3_RING_TYPE_RX)
 		bind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;
@@ -454,62 +454,6 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
 	return ret;
 }
 
-static int
-hns3vf_init_ring_with_vector(struct hns3_hw *hw)
-{
-	uint16_t vec;
-	int ret;
-	int i;
-
-	/*
-	 * In hns3 network engine, vector 0 is always the misc interrupt of this
-	 * function, vector 1~N can be used respectively for the queues of the
-	 * function. Tx and Rx queues with the same number share the interrupt
-	 * vector. In the initialization clearing the all hardware mapping
-	 * relationship configurations between queues and interrupt vectors is
-	 * needed, so some error caused by the residual configurations, such as
-	 * the unexpected Tx interrupt, can be avoid.
-	 */
-	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
-	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
-		vec = vec - 1; /* the last interrupt is reserved */
-	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
-	for (i = 0; i < hw->intr_tqps_num; i++) {
-		/*
-		 * Set gap limiter/rate limiter/quanity limiter algorithm
-		 * configuration for interrupt coalesce of queue's interrupt.
-		 */
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
-		/*
-		 * QL(quantity limiter) is not used currently, just set 0 to
-		 * close it.
-		 */
-		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
-
-		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
-						   HNS3_RING_TYPE_TX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "VF fail to unbind TX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-
-		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
-						   HNS3_RING_TYPE_RX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "VF fail to unbind RX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3vf_dev_configure(struct rte_eth_dev *dev)
 {
@@ -649,103 +593,6 @@ hns3vf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	return 0;
 }
 
-static int
-hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint16_t q_num = hw->tqps_num;
-
-	/*
-	 * In interrupt mode, 'max_rx_queues' is set based on the number of
-	 * MSI-X interrupt resources of the hardware.
-	 */
-	if (hw->data->dev_conf.intr_conf.rxq == 1)
-		q_num = hw->intr_tqps_num;
-
-	info->max_rx_queues = q_num;
-	info->max_tx_queues = hw->tqps_num;
-	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
-	info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
-	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
-	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
-
-	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCATTER |
-				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
-				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
-				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
-				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
-	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
-				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
-				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
-				 hns3_txvlan_cap_get(hw));
-
-	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
-		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
-
-	if (hns3_dev_get_support(hw, INDEP_TXRX))
-		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
-				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
-	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
-
-	info->rx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-	};
-
-	info->tx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
-		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
-	};
-
-	info->default_rxconf = (struct rte_eth_rxconf) {
-		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
-		/*
-		 * If there are no available Rx buffer descriptors, incoming
-		 * packets are always dropped by hardware based on hns3 network
-		 * engine.
-		 */
-		.rx_drop_en = 1,
-		.offloads = 0,
-	};
-	info->default_txconf = (struct rte_eth_txconf) {
-		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
-		.offloads = 0,
-	};
-
-	info->reta_size = hw->rss_ind_tbl_size;
-	info->hash_key_size = HNS3_RSS_KEY_SIZE;
-	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
-
-	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-
-	return 0;
-}
-
 static void
 hns3vf_clear_event_cause(struct hns3_hw *hw, uint32_t regclr)
 {
@@ -1634,7 +1481,7 @@ hns3vf_init_hardware(struct hns3_adapter *hns)
 	 * some error caused by the residual configurations, such as the
 	 * unexpected interrupt, can be avoid.
 	 */
-	ret = hns3vf_init_ring_with_vector(hw);
+	ret = hns3_init_ring_with_vector(hw);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to init ring intr vector: %d", ret);
 		goto err_init_hardware;
@@ -1821,41 +1668,6 @@ hns3vf_do_stop(struct hns3_adapter *hns)
 	return 0;
 }
 
-static void
-hns3vf_unmap_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t q_id;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return;
-
-	/* unmap the ring with vector */
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			(void)hns3vf_bind_ring_with_vector(hw, vec, false,
-							   HNS3_RING_TYPE_RX,
-							   q_id);
-			if (vec < base + rte_intr_nb_efd_get(intr_handle)
-			    - 1)
-				vec++;
-		}
-	}
-	/* Clean datapath event and queue/vec mapping */
-	rte_intr_efd_disable(intr_handle);
-
-	/* Cleanup vector list */
-	rte_intr_vec_list_free(intr_handle);
-}
-
 static int
 hns3vf_dev_stop(struct rte_eth_dev *dev)
 {
@@ -1877,7 +1689,7 @@ hns3vf_dev_stop(struct rte_eth_dev *dev)
 	if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0) {
 		hns3_stop_tqps(hw);
 		hns3vf_do_stop(hns);
-		hns3vf_unmap_rx_interrupt(dev);
+		hns3_unmap_rx_interrupt(dev);
 		hw->adapter_state = HNS3_NIC_CONFIGURED;
 	}
 	hns3_rx_scattered_reset(dev);
@@ -1918,34 +1730,6 @@ hns3vf_dev_close(struct rte_eth_dev *eth_dev)
 	return ret;
 }
 
-static int
-hns3vf_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
-		      size_t fw_size)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint32_t version = hw->fw_version;
-	int ret;
-
-	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
-				      HNS3_FW_VERSION_BYTE3_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
-				      HNS3_FW_VERSION_BYTE2_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
-				      HNS3_FW_VERSION_BYTE1_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
-				      HNS3_FW_VERSION_BYTE0_S));
-	if (ret < 0)
-		return -EINVAL;
-
-	ret += 1; /* add the size of '\0' */
-	if (fw_size < (size_t)ret)
-		return ret;
-	else
-		return 0;
-}
-
 static int
 hns3vf_dev_link_update(struct rte_eth_dev *eth_dev,
 		       __rte_unused int wait_to_complete)
@@ -2007,99 +1791,6 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 	return ret;
 }
 
-static int
-hns3vf_map_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint32_t intr_vector;
-	uint16_t q_id;
-	int ret;
-
-	/*
-	 * hns3 needs a separate interrupt to be used as event interrupt which
-	 * could not be shared with task queue pair, so KERNEL drivers need
-	 * support multiple interrupt vectors.
-	 */
-	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
-	    !rte_intr_cap_multiple(intr_handle))
-		return 0;
-
-	rte_intr_disable(intr_handle);
-	intr_vector = hw->used_rx_queues;
-	/* It creates event fd for each intr vector when MSIX is used */
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -EINVAL;
-
-	/* Allocate vector list */
-	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
-				    hw->used_rx_queues)) {
-		hns3_err(hw, "Failed to allocate %u rx_queues"
-			 " intr_vec", hw->used_rx_queues);
-		ret = -ENOMEM;
-		goto vf_alloc_intr_vec_error;
-	}
-
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-
-	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-		ret = hns3vf_bind_ring_with_vector(hw, vec, true,
-						   HNS3_RING_TYPE_RX, q_id);
-		if (ret)
-			goto vf_bind_vector_error;
-
-		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
-			goto vf_bind_vector_error;
-
-		/*
-		 * If there are not enough efds (e.g. not enough interrupt),
-		 * remaining queues will be bond to the last interrupt.
-		 */
-		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
-			vec++;
-	}
-	rte_intr_enable(intr_handle);
-	return 0;
-
-vf_bind_vector_error:
-	rte_intr_vec_list_free(intr_handle);
-vf_alloc_intr_vec_error:
-	rte_intr_efd_disable(intr_handle);
-	return ret;
-}
-
-static int
-hns3vf_restore_rx_interrupt(struct hns3_hw *hw)
-{
-	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint16_t q_id;
-	int ret;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return 0;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			ret = hns3vf_bind_ring_with_vector(hw,
-				rte_intr_vec_list_index_get(intr_handle,
-								   q_id),
-				true, HNS3_RING_TYPE_RX, q_id);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
 static void
 hns3vf_restore_filter(struct rte_eth_dev *dev)
 {
@@ -2125,7 +1816,7 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
-	ret = hns3vf_map_rx_interrupt(dev);
+	ret = hns3_map_rx_interrupt(dev);
 	if (ret)
 		goto map_rx_inter_err;
 
@@ -2442,7 +2133,7 @@ hns3vf_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_vlan_table;
 
-	ret = hns3vf_restore_rx_interrupt(hw);
+	ret = hns3_restore_rx_interrupt(hw);
 	if (ret)
 		goto err_vlan_table;
 
@@ -2616,8 +2307,8 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.xstats_reset       = hns3_dev_xstats_reset,
 	.xstats_get_by_id   = hns3_dev_xstats_get_by_id,
 	.xstats_get_names_by_id = hns3_dev_xstats_get_names_by_id,
-	.dev_infos_get      = hns3vf_dev_infos_get,
-	.fw_version_get     = hns3vf_fw_version_get,
+	.dev_infos_get      = hns3_dev_infos_get,
+	.fw_version_get     = hns3_fw_version_get,
 	.rx_queue_setup     = hns3_rx_queue_setup,
 	.tx_queue_setup     = hns3_tx_queue_setup,
 	.rx_queue_release   = hns3_dev_rx_queue_release,
@@ -2666,6 +2357,7 @@ hns3vf_init_hw_ops(struct hns3_hw *hw)
 	hw->ops.del_mc_mac_addr = hns3vf_remove_mc_mac_addr;
 	hw->ops.add_uc_mac_addr = hns3vf_add_uc_mac_addr;
 	hw->ops.del_uc_mac_addr = hns3vf_remove_uc_mac_addr;
+	hw->ops.bind_ring_with_vector = hns3vf_bind_ring_with_vector;
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_tm.c b/drivers/net/hns3/hns3_tm.c
index 44b607af7a..e1089b6bd0 100644
--- a/drivers/net/hns3/hns3_tm.c
+++ b/drivers/net/hns3/hns3_tm.c
@@ -4,7 +4,7 @@
 
 #include <rte_malloc.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_dcb.h"
 #include "hns3_logs.h"
 #include "hns3_tm.h"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code
  2021-11-04 14:55   ` Ferruh Yigit
@ 2021-11-05  2:49     ` Min Hu (Connor)
  0 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-05  2:49 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: thomas

Hi,

在 2021/11/4 22:55, Ferruh Yigit 写道:
> On 11/2/2021 3:17 AM, Min Hu (Connor) wrote:
>> From: Chengwen Feng <fengchengwen@huawei.com>
>>
>> This patch remove PF/VF duplicate code of:
>> 1. get firmware version.
>> 2. get device info.
>> 3. rx interrupt related functions.
>>
>> Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
>> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
> 
> <...>
> 
>> +int
>> +hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct 
>> rte_eth_dev_info *info)
>> +{
>> +    struct hns3_adapter *hns = eth_dev->data->dev_private;
>> +    struct hns3_hw *hw = &hns->hw;
>> +    uint16_t queue_num = hw->tqps_num;
>> +
>> +    /*
>> +     * In interrupt mode, 'max_rx_queues' is set based on the number of
>> +     * MSI-X interrupt resources of the hardware.
>> +     */
>> +    if (hw->data->dev_conf.intr_conf.rxq == 1)
>> +        queue_num = hw->intr_tqps_num;
>> +
>> +    info->max_rx_queues = queue_num;
>> +    info->max_tx_queues = hw->tqps_num;
>> +    info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
>> +    info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
>> +    info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
>> +    info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
>> +    info->rx_offload_capa = (DEV_RX_OFFLOAD_IPV4_CKSUM |
>> +                 DEV_RX_OFFLOAD_TCP_CKSUM |
>> +                 DEV_RX_OFFLOAD_UDP_CKSUM |
>> +                 DEV_RX_OFFLOAD_SCTP_CKSUM |
>> +                 DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
>> +                 DEV_RX_OFFLOAD_OUTER_UDP_CKSUM |
>> +                 DEV_RX_OFFLOAD_SCATTER |
>> +                 DEV_RX_OFFLOAD_VLAN_STRIP |
>> +                 DEV_RX_OFFLOAD_VLAN_FILTER |
>> +                 DEV_RX_OFFLOAD_RSS_HASH |
>> +                 DEV_RX_OFFLOAD_TCP_LRO);
>> +    info->tx_offload_capa = (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
>> +                 DEV_TX_OFFLOAD_IPV4_CKSUM |
>> +                 DEV_TX_OFFLOAD_TCP_CKSUM |
>> +                 DEV_TX_OFFLOAD_UDP_CKSUM |
>> +                 DEV_TX_OFFLOAD_SCTP_CKSUM |
>> +                 DEV_TX_OFFLOAD_MULTI_SEGS |
>> +                 DEV_TX_OFFLOAD_TCP_TSO |
>> +                 DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
>> +                 DEV_TX_OFFLOAD_GRE_TNL_TSO |
>> +                 DEV_TX_OFFLOAD_GENEVE_TNL_TSO |
>> +                 DEV_TX_OFFLOAD_MBUF_FAST_FREE |
>> +                 DEV_TX_OFFLOAD_VLAN_INSERT);
> 
> The function changed while moving, please be aware renamed macros in 
> upsteram.
> Can you please rebase your patch on top of latest next-net?
fixed in v2, thanks.
> 
> .

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH v2 9/9] net/hns3: remove PF/VF duplicate code
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
@ 2021-11-05 17:02     ` Ferruh Yigit
  0 siblings, 0 replies; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-05 17:02 UTC (permalink / raw)
  To: Min Hu (Connor); +Cc: andrew.rybchenko, dev

On 11/5/2021 2:46 AM, Min Hu (Connor) wrote:
> From: Chengwen Feng<fengchengwen@huawei.com>
> 
> This patch remove PF/VF duplicate code of:
> 1. get firmware version.
> 2. get device info.
> 3. rx interrupt related functions.
> 
> Signed-off-by: Chengwen Feng<fengchengwen@huawei.com>
> Signed-off-by: Min Hu (Connor)<humin29@huawei.com>
> ---
>   drivers/net/hns3.tar.gz           | Bin 0 -> 203522 bytes

I expect this to be blocked by mail list, but somehow it seems passed.
Can you please send a new version without it?

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
@ 2021-11-05 17:03     ` Ferruh Yigit
  2021-11-05 17:05     ` Ferruh Yigit
  1 sibling, 0 replies; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-05 17:03 UTC (permalink / raw)
  To: Min Hu (Connor); +Cc: andrew.rybchenko, dev

On 11/5/2021 2:46 AM, Min Hu (Connor) wrote:
> From: Huisong Li<lihuisong@huawei.com>
> 
> The patch obtains the upper 32 bits of the Rx/Tx queue DMA address in one
> step instead of two steps.
> 
> Fixes: bba636698316 ("net/hns3: support Rx/Tx and related operations")
> 
> Signed-off-by: Huisong Li<lihuisong@huawei.com>

Hi Connor,

This patch requires PMD maintainer's review/ack.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH v2 8/9] net/hns3: fix the return value of the function
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
@ 2021-11-05 17:04     ` Ferruh Yigit
  0 siblings, 0 replies; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-05 17:04 UTC (permalink / raw)
  To: Min Hu (Connor); +Cc: andrew.rybchenko, dev

On 11/5/2021 2:46 AM, Min Hu (Connor) wrote:
> From: Huisong Li<lihuisong@huawei.com>
> 
> Fixing the return value of the function to clear static warning.
> 

Missing fixes tag. (And stable based on what is fixed)

> Signed-off-by: Huisong Li<lihuisong@huawei.com>
> Signed-off-by: Min Hu (Connor)<humin29@huawei.com>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
  2021-11-05 17:03     ` Ferruh Yigit
@ 2021-11-05 17:05     ` Ferruh Yigit
  1 sibling, 0 replies; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-05 17:05 UTC (permalink / raw)
  To: Min Hu (Connor); +Cc: andrew.rybchenko, dev

On 11/5/2021 2:46 AM, Min Hu (Connor) wrote:
> From: Huisong Li<lihuisong@huawei.com>
> 
> The patch obtains the upper 32 bits of the Rx/Tx queue DMA address in one
> step instead of two steps.
> 
> Fixes: bba636698316 ("net/hns3: support Rx/Tx and related operations")
> 

Missing 'stable' tag.

> Signed-off-by: Huisong Li<lihuisong@huawei.com>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/9] net/hns3: extract a common file
  2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: extract a common file Min Hu (Connor)
@ 2021-11-05 17:11     ` Ferruh Yigit
  0 siblings, 0 replies; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-05 17:11 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: andrew.rybchenko

On 11/5/2021 2:46 AM, Min Hu (Connor) wrote:
> @@ -1047,28 +1031,20 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
>   	return __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED) & mask;
>   }
>   
> +uint32_t hns3_get_speed_capa(struct hns3_hw *hw);
> +

This looks git rebase error, above function is unrelated with the moved
functions, also it cause a build error in the middle of the set because
that function is static in this patch.

Above change is required in last patch, 9/9, where this function made
non-static.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD
  2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
                   ` (9 preceding siblings ...)
  2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
@ 2021-11-06  1:42 ` Min Hu (Connor)
  2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
                     ` (9 more replies)
  10 siblings, 10 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:42 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

This patch set contains refactor patches and code check patches.

Chengwen Feng (1):
  net/hns3: remove PF/VF duplicate code

Huisong Li (7):
  net/hns3: fix the shift of DMA address in Rx/Tx queue
  net/hns3: remove a redundant function declaration
  net/hns3: modifying code alignment
  net/hns3: use unsigned integer for bitwise operations
  net/hns3: extract a common file
  net/hns3: remove magic numbers
  net/hns3: fix the return value of the function

Min Hu (Connor) (1):
  net/hns3: add hns3 flow header file
---
v3:
* fixed build error and some other adjustment.

v2:
* rebase patch on top of latest next-net.

 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_common.c    | 763 ++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_common.h    |  61 +++
 drivers/net/hns3/hns3_ethdev.c    | 749 +----------------------------
 drivers/net/hns3/hns3_ethdev.h    |  47 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 328 +------------
 drivers/net/hns3/hns3_fdir.h      |  31 --
 drivers/net/hns3/hns3_flow.c      |   1 +
 drivers/net/hns3/hns3_flow.h      |  44 ++
 drivers/net/hns3/hns3_intr.c      |   2 +-
 drivers/net/hns3/hns3_mbx.c       |   2 +-
 drivers/net/hns3/hns3_rxtx.c      |   8 +-
 drivers/net/hns3/hns3_rxtx.h      |   1 -
 drivers/net/hns3/hns3_tm.c        |   2 +-
 drivers/net/hns3/meson.build      |   1 +
 15 files changed, 902 insertions(+), 1140 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_common.c
 create mode 100644 drivers/net/hns3/hns3_common.h
 create mode 100644 drivers/net/hns3/hns3_flow.h

-- 
2.33.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
@ 2021-11-06  1:42   ` Min Hu (Connor)
  2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:42 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

The patch obtains the upper 32 bits of the Rx/Tx queue DMA address in one
step instead of two steps.

Fixes: bba636698316 ("net/hns3: support Rx/Tx and related operations")
Cc: stable@dpdk.org

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index ceb98025f8..00af73c850 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -322,7 +322,7 @@ hns3_init_rx_queue_hw(struct hns3_rx_queue *rxq)
 
 	hns3_write_dev(rxq, HNS3_RING_RX_BASEADDR_L_REG, (uint32_t)dma_addr);
 	hns3_write_dev(rxq, HNS3_RING_RX_BASEADDR_H_REG,
-		       (uint32_t)((dma_addr >> 31) >> 1));
+		       (uint32_t)(dma_addr >> 32));
 
 	hns3_write_dev(rxq, HNS3_RING_RX_BD_LEN_REG,
 		       hns3_buf_size2type(rx_buf_len));
@@ -337,7 +337,7 @@ hns3_init_tx_queue_hw(struct hns3_tx_queue *txq)
 
 	hns3_write_dev(txq, HNS3_RING_TX_BASEADDR_L_REG, (uint32_t)dma_addr);
 	hns3_write_dev(txq, HNS3_RING_TX_BASEADDR_H_REG,
-		       (uint32_t)((dma_addr >> 31) >> 1));
+		       (uint32_t)(dma_addr >> 32));
 
 	hns3_write_dev(txq, HNS3_RING_TX_BD_NUM_REG,
 		       HNS3_CFG_DESC_NUM(txq->nb_tx_desc));
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 2/9] net/hns3: remove a redundant function declaration
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
@ 2021-11-06  1:42   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 3/9] net/hns3: modifying code alignment Min Hu (Connor)
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:42 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

This patch removes a redundant function declaration for
hns3_rx_check_vec_support().

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index 33ee8c61a0..63bafc68b6 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -711,7 +711,6 @@ uint16_t hns3_recv_pkts_vec_sve(void *rx_queue, struct rte_mbuf **rx_pkts,
 int hns3_rx_burst_mode_get(struct rte_eth_dev *dev,
 			   __rte_unused uint16_t queue_id,
 			   struct rte_eth_burst_mode *mode);
-int hns3_rx_check_vec_support(struct rte_eth_dev *dev);
 uint16_t hns3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
 			uint16_t nb_pkts);
 uint16_t hns3_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 3/9] net/hns3: modifying code alignment
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
  2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
  2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

This patch modifies some code alignment issues to make the code style more
consistent.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 00af73c850..7e55b24cb8 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -1907,7 +1907,7 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	 */
 	if (hns->is_vf || hw->vlan_mode == HNS3_SW_SHIFT_AND_DISCARD_MODE)
 		rxq->pvid_sw_discard_en = hw->port_base_vlan_cfg.state ==
-				       HNS3_PORT_BASE_VLAN_ENABLE;
+						HNS3_PORT_BASE_VLAN_ENABLE;
 	else
 		rxq->pvid_sw_discard_en = false;
 	rxq->ptype_en = hns3_dev_get_support(hw, RXD_ADV_LAYOUT) ? true : false;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 4/9] net/hns3: use unsigned integer for bitwise operations
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (2 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 3/9] net/hns3: modifying code alignment Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 5/9] net/hns3: extract a common file Min Hu (Connor)
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

Bitwise operations should be used only with unsigned integer. This patch
modifies some code that does not meet this rule.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_ethdev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index c5543c48ef..ddf85a1705 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -2104,7 +2104,7 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 	int max_tc = 0;
 	int i;
 
-	if ((rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
+	if (((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) ||
 	    (tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
 	     tx_mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY)) {
 		hns3_err(hw, "VMDQ is not supported, rx_mq_mode = %d, tx_mq_mode = %d.",
@@ -2114,7 +2114,7 @@ hns3_check_mq_mode(struct rte_eth_dev *dev)
 
 	dcb_rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf;
 	dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf;
-	if (rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
+	if ((uint32_t)rx_mq_mode & RTE_ETH_MQ_RX_DCB_FLAG) {
 		if (dcb_rx_conf->nb_tcs > pf->tc_max) {
 			hns3_err(hw, "nb_tcs(%u) > max_tc(%u) driver supported.",
 				 dcb_rx_conf->nb_tcs, pf->tc_max);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 5/9] net/hns3: extract a common file
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (3 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

This patch extracts a common file to store the common code for PF and VF
driver.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_cmd.c       |   2 +-
 drivers/net/hns3/hns3_common.c    | 426 +++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_common.h    |  48 ++++
 drivers/net/hns3/hns3_ethdev.c    | 430 +-----------------------------
 drivers/net/hns3/hns3_ethdev.h    |  28 +-
 drivers/net/hns3/hns3_ethdev_vf.c |   1 +
 drivers/net/hns3/hns3_intr.c      |   2 +-
 drivers/net/hns3/hns3_mbx.c       |   2 +-
 drivers/net/hns3/hns3_rxtx.c      |   2 +-
 drivers/net/hns3/meson.build      |   1 +
 10 files changed, 482 insertions(+), 460 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_common.c
 create mode 100644 drivers/net/hns3/hns3_common.h

diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c
index 50769c6226..2ce59d8de6 100644
--- a/drivers/net/hns3/hns3_cmd.c
+++ b/drivers/net/hns3/hns3_cmd.c
@@ -5,7 +5,7 @@
 #include <ethdev_pci.h>
 #include <rte_io.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_regs.h"
 #include "hns3_intr.h"
 #include "hns3_logs.h"
diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
new file mode 100644
index 0000000000..85316d3425
--- /dev/null
+++ b/drivers/net/hns3/hns3_common.c
@@ -0,0 +1,426 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#include <rte_kvargs.h>
+
+#include "hns3_logs.h"
+#include "hns3_common.h"
+
+static int
+hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
+{
+	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
+
+	RTE_SET_USED(key);
+
+	if (strcmp(value, "vec") == 0)
+		hint = HNS3_IO_FUNC_HINT_VEC;
+	else if (strcmp(value, "sve") == 0)
+		hint = HNS3_IO_FUNC_HINT_SVE;
+	else if (strcmp(value, "simple") == 0)
+		hint = HNS3_IO_FUNC_HINT_SIMPLE;
+	else if (strcmp(value, "common") == 0)
+		hint = HNS3_IO_FUNC_HINT_COMMON;
+
+	/* If the hint is valid then update output parameters */
+	if (hint != HNS3_IO_FUNC_HINT_NONE)
+		*(uint32_t *)extra_args = hint;
+
+	return 0;
+}
+
+static const char *
+hns3_get_io_hint_func_name(uint32_t hint)
+{
+	switch (hint) {
+	case HNS3_IO_FUNC_HINT_VEC:
+		return "vec";
+	case HNS3_IO_FUNC_HINT_SVE:
+		return "sve";
+	case HNS3_IO_FUNC_HINT_SIMPLE:
+		return "simple";
+	case HNS3_IO_FUNC_HINT_COMMON:
+		return "common";
+	default:
+		return "none";
+	}
+}
+
+static int
+hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
+{
+	uint64_t val;
+
+	RTE_SET_USED(key);
+
+	val = strtoull(value, NULL, 16);
+	*(uint64_t *)extra_args = val;
+
+	return 0;
+}
+
+static int
+hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
+{
+	uint32_t val;
+
+	RTE_SET_USED(key);
+
+	val = strtoul(value, NULL, 10);
+	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
+		*(uint16_t *)extra_args = val;
+
+	return 0;
+}
+
+void
+hns3_parse_devargs(struct rte_eth_dev *dev)
+{
+	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
+	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
+	struct hns3_hw *hw = &hns->hw;
+	uint64_t dev_caps_mask = 0;
+	struct rte_kvargs *kvlist;
+
+	if (dev->device->devargs == NULL)
+		return;
+
+	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
+	if (!kvlist)
+		return;
+
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
+			   &hns3_parse_io_hint_func, &rx_func_hint);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
+			   &hns3_parse_io_hint_func, &tx_func_hint);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
+			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
+	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
+			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
+
+	rte_kvargs_free(kvlist);
+
+	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
+		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
+			  hns3_get_io_hint_func_name(rx_func_hint));
+	hns->rx_func_hint = rx_func_hint;
+	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
+		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
+			  hns3_get_io_hint_func_name(tx_func_hint));
+	hns->tx_func_hint = tx_func_hint;
+
+	if (dev_caps_mask != 0)
+		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
+			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
+	hns->dev_caps_mask = dev_caps_mask;
+}
+
+void
+hns3_clock_gettime(struct timeval *tv)
+{
+#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
+#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
+#else
+#define CLOCK_TYPE CLOCK_MONOTONIC
+#endif
+#define NSEC_TO_USEC_DIV 1000
+
+	struct timespec spec;
+	(void)clock_gettime(CLOCK_TYPE, &spec);
+
+	tv->tv_sec = spec.tv_sec;
+	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
+}
+
+uint64_t
+hns3_clock_calctime_ms(struct timeval *tv)
+{
+	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
+		tv->tv_usec / USEC_PER_MSEC;
+}
+
+uint64_t
+hns3_clock_gettime_ms(void)
+{
+	struct timeval tv;
+
+	hns3_clock_gettime(&tv);
+	return hns3_clock_calctime_ms(&tv);
+}
+
+void hns3_ether_format_addr(char *buf, uint16_t size,
+			    const struct rte_ether_addr *ether_addr)
+{
+	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
+		ether_addr->addr_bytes[0],
+		ether_addr->addr_bytes[4],
+		ether_addr->addr_bytes[5]);
+}
+
+static int
+hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
+			   struct rte_ether_addr *mc_addr_set,
+			   uint32_t nb_mc_addr)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	uint16_t mac_addrs_capa;
+	uint32_t i;
+	uint32_t j;
+
+	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
+		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
+			 "invalid. valid range: 0~%d",
+			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
+		return -EINVAL;
+	}
+
+	/* Check if input mac addresses are valid */
+	for (i = 0; i < nb_mc_addr; i++) {
+		addr = &mc_addr_set[i];
+		if (!rte_is_multicast_ether_addr(addr)) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_err(hw,
+				 "failed to set mc mac addr, addr(%s) invalid.",
+				 mac_str);
+			return -EINVAL;
+		}
+
+		/* Check if there are duplicate addresses */
+		for (j = i + 1; j < nb_mc_addr; j++) {
+			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
+				hns3_ether_format_addr(mac_str,
+						      RTE_ETHER_ADDR_FMT_SIZE,
+						      addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. two same addrs(%s).",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * Check if there are duplicate addresses between mac_addrs
+		 * and mc_addr_set
+		 */
+		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
+					      HNS3_UC_MACADDR_NUM;
+		for (j = 0; j < mac_addrs_capa; j++) {
+			if (rte_is_same_ether_addr(addr,
+						   &hw->data->mac_addrs[j])) {
+				hns3_ether_format_addr(mac_str,
+						       RTE_ETHER_ADDR_FMT_SIZE,
+						       addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. addrs(%s) has already "
+					 "configured in mac_addr add API",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int
+hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			  struct rte_ether_addr *mc_addr_set,
+			  uint32_t nb_mc_addr)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_ether_addr *addr;
+	int cur_addr_num;
+	int set_addr_num;
+	int num;
+	int ret;
+	int i;
+
+	/* Check if input parameters are valid */
+	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
+	if (ret)
+		return ret;
+
+	rte_spinlock_lock(&hw->lock);
+	cur_addr_num = hw->mc_addrs_num;
+	for (i = 0; i < cur_addr_num; i++) {
+		num = cur_addr_num - i - 1;
+		addr = &hw->mc_addrs[num];
+		ret = hw->ops.del_mc_mac_addr(hw, addr);
+		if (ret) {
+			rte_spinlock_unlock(&hw->lock);
+			return ret;
+		}
+
+		hw->mc_addrs_num--;
+	}
+
+	set_addr_num = (int)nb_mc_addr;
+	for (i = 0; i < set_addr_num; i++) {
+		addr = &mc_addr_set[i];
+		ret = hw->ops.add_mc_mac_addr(hw, addr);
+		if (ret) {
+			rte_spinlock_unlock(&hw->lock);
+			return ret;
+		}
+
+		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
+		hw->mc_addrs_num++;
+	}
+	rte_spinlock_unlock(&hw->lock);
+
+	return 0;
+}
+
+int
+hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct hns3_hw *hw = &hns->hw;
+	struct rte_ether_addr *addr;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		if (!rte_is_multicast_ether_addr(addr))
+			continue;
+		if (del)
+			ret = hw->ops.del_mc_mac_addr(hw, addr);
+		else
+			ret = hw->ops.add_mc_mac_addr(hw, addr);
+		if (ret) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
+				 del ? "Remove" : "Restore", mac_str, ret);
+		}
+	}
+	return ret;
+}
+
+int
+hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_hw_ops *ops = &hw->ops;
+	struct rte_ether_addr *addr;
+	uint16_t mac_addrs_capa;
+	int ret = 0;
+	int i;
+
+	mac_addrs_capa =
+		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
+	for (i = 0; i < mac_addrs_capa; i++) {
+		addr = &hw->data->mac_addrs[i];
+		if (rte_is_zero_ether_addr(addr))
+			continue;
+		if (rte_is_multicast_ether_addr(addr))
+			ret = del ? ops->del_mc_mac_addr(hw, addr) :
+			      ops->add_mc_mac_addr(hw, addr);
+		else
+			ret = del ? ops->del_uc_mac_addr(hw, addr) :
+			      ops->add_uc_mac_addr(hw, addr);
+
+		if (ret) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					       addr);
+			hns3_err(hw, "failed to %s mac addr(%s) index:%d ret = %d.",
+				 del ? "remove" : "restore", mac_str, i, ret);
+		}
+	}
+
+	return ret;
+}
+
+static bool
+hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		/* Check if there are duplicate addresses in mc_addrs[] */
+		if (rte_is_same_ether_addr(addr, mc_addr)) {
+			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					       addr);
+			hns3_err(hw, "failed to add mc mac addr, same addrs"
+				 "(%s) is added by the set_mc_mac_addr_list "
+				 "API", mac_str);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int
+hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	rte_spinlock_lock(&hw->lock);
+
+	/*
+	 * In hns3 network engine adding UC and MC mac address with different
+	 * commands with firmware. We need to determine whether the input
+	 * address is a UC or a MC address to call different commands.
+	 * By the way, it is recommended calling the API function named
+	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
+	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
+	 * may affect the specifications of UC mac addresses.
+	 */
+	if (rte_is_multicast_ether_addr(mac_addr)) {
+		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
+			rte_spinlock_unlock(&hw->lock);
+			return -EINVAL;
+		}
+		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
+	} else {
+		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
+	}
+	rte_spinlock_unlock(&hw->lock);
+	if (ret) {
+		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
+			 ret);
+	}
+
+	return ret;
+}
+
+void
+hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	/* index will be checked by upper level rte interface */
+	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	rte_spinlock_lock(&hw->lock);
+
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
+	else
+		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
+	rte_spinlock_unlock(&hw->lock);
+	if (ret) {
+		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
+			 ret);
+	}
+}
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
new file mode 100644
index 0000000000..094a0bc5ff
--- /dev/null
+++ b/drivers/net/hns3/hns3_common.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#ifndef _HNS3_COMMON_H_
+#define _HNS3_COMMON_H_
+
+#include <sys/time.h>
+
+#include "hns3_ethdev.h"
+
+enum {
+	HNS3_IO_FUNC_HINT_NONE = 0,
+	HNS3_IO_FUNC_HINT_VEC,
+	HNS3_IO_FUNC_HINT_SVE,
+	HNS3_IO_FUNC_HINT_SIMPLE,
+	HNS3_IO_FUNC_HINT_COMMON
+};
+
+#define HNS3_DEVARG_RX_FUNC_HINT	"rx_func_hint"
+#define HNS3_DEVARG_TX_FUNC_HINT	"tx_func_hint"
+
+#define HNS3_DEVARG_DEV_CAPS_MASK	"dev_caps_mask"
+
+#define HNS3_DEVARG_MBX_TIME_LIMIT_MS	"mbx_time_limit_ms"
+
+#define MSEC_PER_SEC              1000L
+#define USEC_PER_MSEC             1000L
+
+void hns3_clock_gettime(struct timeval *tv);
+uint64_t hns3_clock_calctime_ms(struct timeval *tv);
+uint64_t hns3_clock_gettime_ms(void);
+
+void hns3_parse_devargs(struct rte_eth_dev *dev);
+
+int hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del);
+int hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del);
+int hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		      __rte_unused uint32_t idx, __rte_unused uint32_t pool);
+
+void hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx);
+int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			      struct rte_ether_addr *mc_addr_set,
+			      uint32_t nb_mc_addr);
+void hns3_ether_format_addr(char *buf, uint16_t size,
+			    const struct rte_ether_addr *ether_addr);
+
+#endif /* _HNS3_COMMON_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index ddf85a1705..2ddd29515a 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -6,9 +6,9 @@
 #include <rte_bus_pci.h>
 #include <ethdev_pci.h>
 #include <rte_pci.h>
-#include <rte_kvargs.h>
 
 #include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_rxtx.h"
 #include "hns3_intr.h"
@@ -105,14 +105,6 @@ static int hns3_do_stop(struct hns3_adapter *hns);
 static int hns3_check_port_speed(struct hns3_hw *hw, uint32_t link_speeds);
 static int hns3_cfg_mac_mode(struct hns3_hw *hw, bool enable);
 
-void hns3_ether_format_addr(char *buf, uint16_t size,
-			    const struct rte_ether_addr *ether_addr)
-{
-	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
-		ether_addr->addr_bytes[0],
-		ether_addr->addr_bytes[4],
-		ether_addr->addr_bytes[5]);
-}
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -1609,68 +1601,6 @@ hns3_add_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static bool
-hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct rte_ether_addr *addr;
-	int i;
-
-	for (i = 0; i < hw->mc_addrs_num; i++) {
-		addr = &hw->mc_addrs[i];
-		/* Check if there are duplicate addresses in mc_addrs[] */
-		if (rte_is_same_ether_addr(addr, mc_addr)) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					       addr);
-			hns3_err(hw, "failed to add mc mac addr, same addrs"
-				 "(%s) is added by the set_mc_mac_addr_list "
-				 "API", mac_str);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-int
-hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
-		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret;
-
-	rte_spinlock_lock(&hw->lock);
-
-	/*
-	 * In hns3 network engine adding UC and MC mac address with different
-	 * commands with firmware. We need to determine whether the input
-	 * address is a UC or a MC address to call different commands.
-	 * By the way, it is recommended calling the API function named
-	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
-	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
-	 * may affect the specifications of UC mac addresses.
-	 */
-	if (rte_is_multicast_ether_addr(mac_addr)) {
-		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
-			rte_spinlock_unlock(&hw->lock);
-			return -EINVAL;
-		}
-		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
-	} else {
-		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
-	}
-	rte_spinlock_unlock(&hw->lock);
-	if (ret) {
-		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-				      mac_addr);
-		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
-			 ret);
-	}
-
-	return ret;
-}
-
 static int
 hns3_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 {
@@ -1699,30 +1629,6 @@ hns3_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-void
-hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	/* index will be checked by upper level rte interface */
-	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret;
-
-	rte_spinlock_lock(&hw->lock);
-
-	if (rte_is_multicast_ether_addr(mac_addr))
-		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
-	else
-		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
-	rte_spinlock_unlock(&hw->lock);
-	if (ret) {
-		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-				      mac_addr);
-		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
-			 ret);
-	}
-}
-
 static int
 hns3_set_default_mac_addr(struct rte_eth_dev *dev,
 			  struct rte_ether_addr *mac_addr)
@@ -1787,41 +1693,6 @@ hns3_set_default_mac_addr(struct rte_eth_dev *dev,
 	return ret;
 }
 
-int
-hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
-	struct hns3_hw_ops *ops = &hw->ops;
-	struct rte_ether_addr *addr;
-	uint16_t mac_addrs_capa;
-	int ret = 0;
-	int i;
-
-	mac_addrs_capa =
-		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
-	for (i = 0; i < mac_addrs_capa; i++) {
-		addr = &hw->data->mac_addrs[i];
-		if (rte_is_zero_ether_addr(addr))
-			continue;
-		if (rte_is_multicast_ether_addr(addr))
-			ret = del ? ops->del_mc_mac_addr(hw, addr) :
-			      ops->add_mc_mac_addr(hw, addr);
-		else
-			ret = del ? ops->del_uc_mac_addr(hw, addr) :
-			      ops->add_uc_mac_addr(hw, addr);
-
-		if (ret) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					       addr);
-			hns3_err(hw, "failed to %s mac addr(%s) index:%d ret = %d.",
-				 del ? "remove" : "restore", mac_str, i, ret);
-		}
-	}
-
-	return ret;
-}
-
 static void
 hns3_update_desc_vfid(struct hns3_cmd_desc *desc, uint8_t vfid, bool clr)
 {
@@ -1947,150 +1818,6 @@ hns3_remove_mc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
-static int
-hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
-			   struct rte_ether_addr *mc_addr_set,
-			   uint32_t nb_mc_addr)
-{
-	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct rte_ether_addr *addr;
-	uint16_t mac_addrs_capa;
-	uint32_t i;
-	uint32_t j;
-
-	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
-		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
-			 "invalid. valid range: 0~%d",
-			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
-		return -EINVAL;
-	}
-
-	/* Check if input mac addresses are valid */
-	for (i = 0; i < nb_mc_addr; i++) {
-		addr = &mc_addr_set[i];
-		if (!rte_is_multicast_ether_addr(addr)) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					      addr);
-			hns3_err(hw,
-				 "failed to set mc mac addr, addr(%s) invalid.",
-				 mac_str);
-			return -EINVAL;
-		}
-
-		/* Check if there are duplicate addresses */
-		for (j = i + 1; j < nb_mc_addr; j++) {
-			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
-				hns3_ether_format_addr(mac_str,
-						      RTE_ETHER_ADDR_FMT_SIZE,
-						      addr);
-				hns3_err(hw, "failed to set mc mac addr, "
-					 "addrs invalid. two same addrs(%s).",
-					 mac_str);
-				return -EINVAL;
-			}
-		}
-
-		/*
-		 * Check if there are duplicate addresses between mac_addrs
-		 * and mc_addr_set
-		 */
-		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
-					      HNS3_UC_MACADDR_NUM;
-		for (j = 0; j < mac_addrs_capa; j++) {
-			if (rte_is_same_ether_addr(addr,
-						   &hw->data->mac_addrs[j])) {
-				hns3_ether_format_addr(mac_str,
-						       RTE_ETHER_ADDR_FMT_SIZE,
-						       addr);
-				hns3_err(hw, "failed to set mc mac addr, "
-					 "addrs invalid. addrs(%s) has already "
-					 "configured in mac_addr add API",
-					 mac_str);
-				return -EINVAL;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int
-hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			  struct rte_ether_addr *mc_addr_set,
-			  uint32_t nb_mc_addr)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_ether_addr *addr;
-	int cur_addr_num;
-	int set_addr_num;
-	int num;
-	int ret;
-	int i;
-
-	/* Check if input parameters are valid */
-	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
-	if (ret)
-		return ret;
-
-	rte_spinlock_lock(&hw->lock);
-	cur_addr_num = hw->mc_addrs_num;
-	for (i = 0; i < cur_addr_num; i++) {
-		num = cur_addr_num - i - 1;
-		addr = &hw->mc_addrs[num];
-		ret = hw->ops.del_mc_mac_addr(hw, addr);
-		if (ret) {
-			rte_spinlock_unlock(&hw->lock);
-			return ret;
-		}
-
-		hw->mc_addrs_num--;
-	}
-
-	set_addr_num = (int)nb_mc_addr;
-	for (i = 0; i < set_addr_num; i++) {
-		addr = &mc_addr_set[i];
-		ret = hw->ops.add_mc_mac_addr(hw, addr);
-		if (ret) {
-			rte_spinlock_unlock(&hw->lock);
-			return ret;
-		}
-
-		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
-		hw->mc_addrs_num++;
-	}
-	rte_spinlock_unlock(&hw->lock);
-
-	return 0;
-}
-
-int
-hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
-{
-	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
-	struct rte_ether_addr *addr;
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < hw->mc_addrs_num; i++) {
-		addr = &hw->mc_addrs[i];
-		if (!rte_is_multicast_ether_addr(addr))
-			continue;
-		if (del)
-			ret = hw->ops.del_mc_mac_addr(hw, addr);
-		else
-			ret = hw->ops.add_mc_mac_addr(hw, addr);
-		if (ret) {
-			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
-					      addr);
-			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
-				 del ? "Remove" : "Restore", mac_str, ret);
-		}
-	}
-	return ret;
-}
-
 static int
 hns3_check_mq_mode(struct rte_eth_dev *dev)
 {
@@ -7111,161 +6838,6 @@ hns3_get_module_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
-void
-hns3_clock_gettime(struct timeval *tv)
-{
-#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
-#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
-#else
-#define CLOCK_TYPE CLOCK_MONOTONIC
-#endif
-#define NSEC_TO_USEC_DIV 1000
-
-	struct timespec spec;
-	(void)clock_gettime(CLOCK_TYPE, &spec);
-
-	tv->tv_sec = spec.tv_sec;
-	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
-}
-
-uint64_t
-hns3_clock_calctime_ms(struct timeval *tv)
-{
-	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
-		tv->tv_usec / USEC_PER_MSEC;
-}
-
-uint64_t
-hns3_clock_gettime_ms(void)
-{
-	struct timeval tv;
-
-	hns3_clock_gettime(&tv);
-	return hns3_clock_calctime_ms(&tv);
-}
-
-static int
-hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
-{
-	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
-
-	RTE_SET_USED(key);
-
-	if (strcmp(value, "vec") == 0)
-		hint = HNS3_IO_FUNC_HINT_VEC;
-	else if (strcmp(value, "sve") == 0)
-		hint = HNS3_IO_FUNC_HINT_SVE;
-	else if (strcmp(value, "simple") == 0)
-		hint = HNS3_IO_FUNC_HINT_SIMPLE;
-	else if (strcmp(value, "common") == 0)
-		hint = HNS3_IO_FUNC_HINT_COMMON;
-
-	/* If the hint is valid then update output parameters */
-	if (hint != HNS3_IO_FUNC_HINT_NONE)
-		*(uint32_t *)extra_args = hint;
-
-	return 0;
-}
-
-static const char *
-hns3_get_io_hint_func_name(uint32_t hint)
-{
-	switch (hint) {
-	case HNS3_IO_FUNC_HINT_VEC:
-		return "vec";
-	case HNS3_IO_FUNC_HINT_SVE:
-		return "sve";
-	case HNS3_IO_FUNC_HINT_SIMPLE:
-		return "simple";
-	case HNS3_IO_FUNC_HINT_COMMON:
-		return "common";
-	default:
-		return "none";
-	}
-}
-
-static int
-hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
-{
-	uint64_t val;
-
-	RTE_SET_USED(key);
-
-	val = strtoull(value, NULL, 16);
-	*(uint64_t *)extra_args = val;
-
-	return 0;
-}
-
-static int
-hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
-{
-	uint32_t val;
-
-	RTE_SET_USED(key);
-
-	val = strtoul(value, NULL, 10);
-
-	/*
-	 * 500ms is empirical value in process of mailbox communication. If
-	 * the delay value is set to one lower thanthe empirical value, mailbox
-	 * communication may fail.
-	 */
-	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
-		*(uint16_t *)extra_args = val;
-
-	return 0;
-}
-
-void
-hns3_parse_devargs(struct rte_eth_dev *dev)
-{
-	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
-	struct hns3_adapter *hns = dev->data->dev_private;
-	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
-	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
-	struct hns3_hw *hw = &hns->hw;
-	uint64_t dev_caps_mask = 0;
-	struct rte_kvargs *kvlist;
-
-	if (dev->device->devargs == NULL)
-		return;
-
-	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
-	if (!kvlist)
-		return;
-
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
-			   &hns3_parse_io_hint_func, &rx_func_hint);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
-			   &hns3_parse_io_hint_func, &tx_func_hint);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
-			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
-	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
-			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
-
-	rte_kvargs_free(kvlist);
-
-	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
-		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
-			  hns3_get_io_hint_func_name(rx_func_hint));
-	hns->rx_func_hint = rx_func_hint;
-	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
-		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
-			  hns3_get_io_hint_func_name(tx_func_hint));
-	hns->tx_func_hint = tx_func_hint;
-
-	if (dev_caps_mask != 0)
-		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
-			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
-	hns->dev_caps_mask = dev_caps_mask;
-
-	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
-		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
-				mbx_time_limit_ms);
-	hns->mbx_time_limit_ms = mbx_time_limit_ms;
-}
-
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index f3cc88f43e..7438a8a2a8 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -6,7 +6,6 @@
 #define _HNS3_ETHDEV_H_
 
 #include <pthread.h>
-#include <sys/time.h>
 #include <ethdev_driver.h>
 #include <rte_byteorder.h>
 #include <rte_io.h>
@@ -869,14 +868,6 @@ struct hns3_adapter {
 	struct hns3_ptype_table ptype_tbl __rte_cache_aligned;
 };
 
-enum {
-	HNS3_IO_FUNC_HINT_NONE = 0,
-	HNS3_IO_FUNC_HINT_VEC,
-	HNS3_IO_FUNC_HINT_SVE,
-	HNS3_IO_FUNC_HINT_SIMPLE,
-	HNS3_IO_FUNC_HINT_COMMON
-};
-
 #define HNS3_DEVARG_RX_FUNC_HINT	"rx_func_hint"
 #define HNS3_DEVARG_TX_FUNC_HINT	"tx_func_hint"
 
@@ -1011,13 +1002,6 @@ static inline uint32_t hns3_read_reg(void *base, uint32_t reg)
 		}							\
 	} while (0)
 
-#define MSEC_PER_SEC              1000L
-#define USEC_PER_MSEC             1000L
-
-void hns3_clock_gettime(struct timeval *tv);
-uint64_t hns3_clock_calctime_ms(struct timeval *tv);
-uint64_t hns3_clock_gettime_ms(void);
-
 static inline uint64_t
 hns3_atomic_test_bit(unsigned int nr, volatile uint64_t *addr)
 {
@@ -1053,22 +1037,12 @@ int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
-void hns3_ether_format_addr(char *buf, uint16_t size,
-			const struct rte_ether_addr *ether_addr);
 int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
 		       struct rte_eth_dev_info *info);
 void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
-void hns3_parse_devargs(struct rte_eth_dev *dev);
 void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
-int hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del);
-int hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del);
-int hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
-		__rte_unused uint32_t idx, __rte_unused uint32_t pool);
-void hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx);
-int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			struct rte_ether_addr *mc_addr_set,
-							uint32_t nb_mc_addr);
+
 int hns3_restore_ptp(struct hns3_adapter *hns);
 int hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
 				    struct rte_eth_conf *conf);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 242ccf7f9f..1df8966cea 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -10,6 +10,7 @@
 #include <rte_vfio.h>
 
 #include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_rxtx.h"
 #include "hns3_regs.h"
diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c
index 3484c76d23..66dc509086 100644
--- a/drivers/net/hns3/hns3_intr.c
+++ b/drivers/net/hns3/hns3_intr.c
@@ -8,7 +8,7 @@
 #include <rte_io.h>
 #include <rte_malloc.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_logs.h"
 #include "hns3_intr.h"
 #include "hns3_regs.h"
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c
index 245652e2ed..b3563d4694 100644
--- a/drivers/net/hns3/hns3_mbx.c
+++ b/drivers/net/hns3/hns3_mbx.c
@@ -5,7 +5,7 @@
 #include <ethdev_driver.h>
 #include <rte_io.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_regs.h"
 #include "hns3_logs.h"
 #include "hns3_intr.h"
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 7e55b24cb8..d26e262335 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -16,7 +16,7 @@
 #include <rte_vect.h>
 #endif
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_rxtx.h"
 #include "hns3_regs.h"
 #include "hns3_logs.h"
diff --git a/drivers/net/hns3/meson.build b/drivers/net/hns3/meson.build
index a99e0dbb74..8a4c7cc100 100644
--- a/drivers/net/hns3/meson.build
+++ b/drivers/net/hns3/meson.build
@@ -29,6 +29,7 @@ sources = files(
         'hns3_mp.c',
         'hns3_tm.c',
         'hns3_ptp.c',
+        'hns3_common.c',
 )
 
 deps += ['hash']
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 6/9] net/hns3: add hns3 flow header file
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (4 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 5/9] net/hns3: extract a common file Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 7/9] net/hns3: remove magic numbers Min Hu (Connor)
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

This patch adds a hns3_flow.h to make the code easier to maintain.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_ethdev.c    |  1 +
 drivers/net/hns3/hns3_ethdev.h    |  3 +--
 drivers/net/hns3/hns3_ethdev_vf.c |  1 +
 drivers/net/hns3/hns3_fdir.h      | 31 ----------------------
 drivers/net/hns3/hns3_flow.c      |  1 +
 drivers/net/hns3/hns3_flow.h      | 44 +++++++++++++++++++++++++++++++
 6 files changed, 48 insertions(+), 33 deletions(-)
 create mode 100644 drivers/net/hns3/hns3_flow.h

diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 2ddd29515a..181694bf8c 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -15,6 +15,7 @@
 #include "hns3_regs.h"
 #include "hns3_dcb.h"
 #include "hns3_mp.h"
+#include "hns3_flow.h"
 
 #define HNS3_SERVICE_INTERVAL		1000000 /* us */
 #define HNS3_SERVICE_QUICK_INTERVAL	10
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 7438a8a2a8..67e506f6df 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -17,6 +17,7 @@
 #include "hns3_fdir.h"
 #include "hns3_stats.h"
 #include "hns3_tm.h"
+#include "hns3_flow.h"
 
 /* Vendor ID */
 #define PCI_VENDOR_ID_HUAWEI			0x19e5
@@ -1032,8 +1033,6 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 }
 
 int hns3_buffer_alloc(struct hns3_hw *hw);
-int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
-			  const struct rte_flow_ops **ops);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 1df8966cea..8632c8f19b 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -17,6 +17,7 @@
 #include "hns3_intr.h"
 #include "hns3_dcb.h"
 #include "hns3_mp.h"
+#include "hns3_flow.h"
 
 #define HNS3VF_KEEP_ALIVE_INTERVAL	2000000 /* us */
 #define HNS3VF_SERVICE_INTERVAL		1000000 /* us */
diff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h
index 3f610f7b11..f9efff3b52 100644
--- a/drivers/net/hns3/hns3_fdir.h
+++ b/drivers/net/hns3/hns3_fdir.h
@@ -5,8 +5,6 @@
 #ifndef _HNS3_FDIR_H_
 #define _HNS3_FDIR_H_
 
-#include <rte_flow.h>
-
 struct hns3_fd_key_cfg {
 	uint8_t key_sel;
 	uint8_t inner_sipv6_word_en;
@@ -124,14 +122,6 @@ struct hns3_fd_ad_data {
 	uint16_t rule_id;
 };
 
-struct hns3_flow_counter {
-	LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
-	uint32_t shared:1;   /* Share counter ID with other flow rules. */
-	uint32_t ref_cnt:31; /* Reference counter. */
-	uint16_t id;   /* Counter ID. */
-	uint64_t hits; /* Number of packets matched by the rule. */
-};
-
 #define HNS3_RULE_FLAG_FDID		0x1
 #define HNS3_RULE_FLAG_VF_ID		0x2
 #define HNS3_RULE_FLAG_COUNTER		0x4
@@ -173,21 +163,7 @@ struct hns3_fdir_rule_ele {
 	struct hns3_fdir_rule fdir_conf;
 };
 
-/* rss filter list structure */
-struct hns3_rss_conf_ele {
-	TAILQ_ENTRY(hns3_rss_conf_ele) entries;
-	struct hns3_rss_conf filter_info;
-};
-
-/* hns3_flow memory list structure */
-struct hns3_flow_mem {
-	TAILQ_ENTRY(hns3_flow_mem) entries;
-	struct rte_flow *flow;
-};
-
 TAILQ_HEAD(hns3_fdir_rule_list, hns3_fdir_rule_ele);
-TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);
-TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
 
 /*
  *  A structure used to define fields of a FDIR related info.
@@ -199,11 +175,6 @@ struct hns3_fdir_info {
 	struct hns3_fd_cfg fd_cfg;
 };
 
-struct rte_flow {
-	enum rte_filter_type filter_type;
-	void *rule;
-	uint32_t counter_id;
-};
 struct hns3_adapter;
 
 int hns3_init_fd_config(struct hns3_adapter *hns);
@@ -213,8 +184,6 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns,
 			     struct hns3_fdir_rule *rule, bool del);
 int hns3_clear_all_fdir_filter(struct hns3_adapter *hns);
 int hns3_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value);
-void hns3_flow_init(struct rte_eth_dev *dev);
-void hns3_flow_uninit(struct rte_eth_dev *dev);
 int hns3_restore_all_fdir_filter(struct hns3_adapter *hns);
 
 #endif /* _HNS3_FDIR_H_ */
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index da6918fddd..9f2f9cb6cd 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -8,6 +8,7 @@
 
 #include "hns3_ethdev.h"
 #include "hns3_logs.h"
+#include "hns3_flow.h"
 
 /* Default default keys */
 static uint8_t hns3_hash_key[] = {
diff --git a/drivers/net/hns3/hns3_flow.h b/drivers/net/hns3/hns3_flow.h
new file mode 100644
index 0000000000..2eb451b720
--- /dev/null
+++ b/drivers/net/hns3/hns3_flow.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 HiSilicon Limited
+ */
+
+#ifndef _HNS3_FLOW_H_
+#define _HNS3_FLOW_H_
+
+#include <rte_flow.h>
+
+struct hns3_flow_counter {
+	LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
+	uint32_t shared:1;   /* Share counter ID with other flow rules. */
+	uint32_t ref_cnt:31; /* Reference counter. */
+	uint16_t id;   /* Counter ID. */
+	uint64_t hits; /* Number of packets matched by the rule. */
+};
+
+struct rte_flow {
+	enum rte_filter_type filter_type;
+	void *rule;
+	uint32_t counter_id;
+};
+
+/* rss filter list structure */
+struct hns3_rss_conf_ele {
+	TAILQ_ENTRY(hns3_rss_conf_ele) entries;
+	struct hns3_rss_conf filter_info;
+};
+
+/* hns3_flow memory list structure */
+struct hns3_flow_mem {
+	TAILQ_ENTRY(hns3_flow_mem) entries;
+	struct rte_flow *flow;
+};
+
+TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);
+TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
+
+int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
+			  const struct rte_flow_ops **ops);
+void hns3_flow_init(struct rte_eth_dev *dev);
+void hns3_flow_uninit(struct rte_eth_dev *dev);
+
+#endif /* _HNS3_FLOW_H_ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 7/9] net/hns3: remove magic numbers
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (5 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

Removing magic numbers with macros.

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c | 4 ++--
 drivers/net/hns3/hns3_common.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 85316d3425..c306e0b0ed 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -54,7 +54,7 @@ hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
 
 	RTE_SET_USED(key);
 
-	val = strtoull(value, NULL, 16);
+	val = strtoull(value, NULL, HNS3_CONVERT_TO_HEXADECIMAL);
 	*(uint64_t *)extra_args = val;
 
 	return 0;
@@ -67,7 +67,7 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 
 	RTE_SET_USED(key);
 
-	val = strtoul(value, NULL, 10);
+	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
 		*(uint16_t *)extra_args = val;
 
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 094a0bc5ff..68f9b1b96a 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -9,6 +9,9 @@
 
 #include "hns3_ethdev.h"
 
+#define HNS3_CONVERT_TO_DECIMAL 10
+#define HNS3_CONVERT_TO_HEXADECIMAL 16
+
 enum {
 	HNS3_IO_FUNC_HINT_NONE = 0,
 	HNS3_IO_FUNC_HINT_VEC,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 8/9] net/hns3: fix the return value of the function
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (6 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 7/9] net/hns3: remove magic numbers Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
  2021-11-08 15:13   ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Ferruh Yigit
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Huisong Li <lihuisong@huawei.com>

Fixing the return value of the function to clear static warning.

Fixes: 1181500b2fc5 ("net/hns3: adjust MAC address logging")
Cc: stable@dpdk.org

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index c306e0b0ed..9a47fbfbde 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -154,10 +154,10 @@ hns3_clock_gettime_ms(void)
 void hns3_ether_format_addr(char *buf, uint16_t size,
 			    const struct rte_ether_addr *ether_addr)
 {
-	snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
-		ether_addr->addr_bytes[0],
-		ether_addr->addr_bytes[4],
-		ether_addr->addr_bytes[5]);
+	(void)snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
+			ether_addr->addr_bytes[0],
+			ether_addr->addr_bytes[4],
+			ether_addr->addr_bytes[5]);
 }
 
 static int
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [dpdk-dev] [PATCH v3 9/9] net/hns3: remove PF/VF duplicate code
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (7 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
@ 2021-11-06  1:43   ` Min Hu (Connor)
  2021-11-08 15:13   ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Ferruh Yigit
  9 siblings, 0 replies; 38+ messages in thread
From: Min Hu (Connor) @ 2021-11-06  1:43 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, andrew.rybchenko

From: Chengwen Feng <fengchengwen@huawei.com>

This patch remove PF/VF duplicate code of:
1. get firmware version.
2. get device info.
3. rx interrupt related functions.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
---
 drivers/net/hns3/hns3_common.c    | 339 +++++++++++++++++++++++++++++-
 drivers/net/hns3/hns3_common.h    |  10 +
 drivers/net/hns3/hns3_ethdev.c    | 314 +--------------------------
 drivers/net/hns3/hns3_ethdev.h    |  16 +-
 drivers/net/hns3/hns3_ethdev_vf.c | 326 +---------------------------
 drivers/net/hns3/hns3_tm.c        |   2 +-
 6 files changed, 365 insertions(+), 642 deletions(-)

diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 9a47fbfbde..e6ba15f77c 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -3,9 +3,154 @@
  */
 
 #include <rte_kvargs.h>
+#include <rte_bus_pci.h>
+#include <ethdev_pci.h>
+#include <rte_pci.h>
 
-#include "hns3_logs.h"
 #include "hns3_common.h"
+#include "hns3_logs.h"
+#include "hns3_regs.h"
+#include "hns3_rxtx.h"
+
+int
+hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+		    size_t fw_size)
+{
+	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint32_t version = hw->fw_version;
+	int ret;
+
+	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
+				      HNS3_FW_VERSION_BYTE3_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
+				      HNS3_FW_VERSION_BYTE2_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
+				      HNS3_FW_VERSION_BYTE1_S),
+		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
+				      HNS3_FW_VERSION_BYTE0_S));
+	if (ret < 0)
+		return -EINVAL;
+
+	ret += 1; /* add the size of '\0' */
+	if (fw_size < (size_t)ret)
+		return ret;
+	else
+		return 0;
+}
+
+int
+hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
+{
+	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint16_t queue_num = hw->tqps_num;
+
+	/*
+	 * In interrupt mode, 'max_rx_queues' is set based on the number of
+	 * MSI-X interrupt resources of the hardware.
+	 */
+	if (hw->data->dev_conf.intr_conf.rxq == 1)
+		queue_num = hw->intr_tqps_num;
+
+	info->max_rx_queues = queue_num;
+	info->max_tx_queues = hw->tqps_num;
+	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
+	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
+	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
+	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
+	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
+				 RTE_ETH_RX_OFFLOAD_SCATTER |
+				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
+				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
+				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
+				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
+	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
+				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
+				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
+				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
+				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
+				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
+				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
+				 RTE_ETH_TX_OFFLOAD_VLAN_INSERT);
+
+	if (!hw->port_base_vlan_cfg.state)
+		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
+
+	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
+		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
+
+	if (hns3_dev_get_support(hw, INDEP_TXRX))
+		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
+				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
+
+	if (hns3_dev_get_support(hw, PTP))
+		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
+
+	info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = HNS3_MAX_RING_DESC,
+		.nb_min = HNS3_MIN_RING_DESC,
+		.nb_align = HNS3_ALIGN_RING_DESC,
+	};
+
+	info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = HNS3_MAX_RING_DESC,
+		.nb_min = HNS3_MIN_RING_DESC,
+		.nb_align = HNS3_ALIGN_RING_DESC,
+		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
+		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
+	};
+
+	info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
+		/*
+		 * If there are no available Rx buffer descriptors, incoming
+		 * packets are always dropped by hardware based on hns3 network
+		 * engine.
+		 */
+		.rx_drop_en = 1,
+		.offloads = 0,
+	};
+	info->default_txconf = (struct rte_eth_txconf) {
+		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
+		.offloads = 0,
+	};
+
+	info->reta_size = hw->rss_ind_tbl_size;
+	info->hash_key_size = HNS3_RSS_KEY_SIZE;
+	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
+
+	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
+	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
+	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
+	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
+	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
+	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
+
+	/*
+	 * Next is the PF/VF difference section.
+	 */
+	if (!hns->is_vf) {
+		info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
+		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
+		info->speed_capa = hns3_get_speed_capa(hw);
+	} else {
+		info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
+	}
+
+	return 0;
+}
 
 static int
 hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
@@ -68,6 +213,12 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 	RTE_SET_USED(key);
 
 	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
+
+	/*
+	 * 500ms is empirical value in process of mailbox communication. If
+	 * the delay value is set to one lower thanthe empirical value, mailbox
+	 * communication may fail.
+	 */
 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
 		*(uint16_t *)extra_args = val;
 
@@ -116,6 +267,11 @@ hns3_parse_devargs(struct rte_eth_dev *dev)
 		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
 			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
 	hns->dev_caps_mask = dev_caps_mask;
+
+	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
+		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
+				mbx_time_limit_ms);
+	hns->mbx_time_limit_ms = mbx_time_limit_ms;
 }
 
 void
@@ -424,3 +580,184 @@ hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
 			 ret);
 	}
 }
+
+int
+hns3_init_ring_with_vector(struct hns3_hw *hw)
+{
+	uint16_t vec;
+	int ret;
+	int i;
+
+	/*
+	 * In hns3 network engine, vector 0 is always the misc interrupt of this
+	 * function, vector 1~N can be used respectively for the queues of the
+	 * function. Tx and Rx queues with the same number share the interrupt
+	 * vector. In the initialization clearing the all hardware mapping
+	 * relationship configurations between queues and interrupt vectors is
+	 * needed, so some error caused by the residual configurations, such as
+	 * the unexpected Tx interrupt, can be avoid.
+	 */
+	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
+	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
+		vec = vec - 1; /* the last interrupt is reserved */
+	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
+	for (i = 0; i < hw->intr_tqps_num; i++) {
+		/*
+		 * Set gap limiter/rate limiter/quanity limiter algorithm
+		 * configuration for interrupt coalesce of queue's interrupt.
+		 */
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
+		/*
+		 * QL(quantity limiter) is not used currently, just set 0 to
+		 * close it.
+		 */
+		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
+
+		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
+						    HNS3_RING_TYPE_TX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "fail to unbind TX ring(%d) with "
+					  "vector: %u, ret=%d", i, vec, ret);
+			return ret;
+		}
+
+		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
+						    HNS3_RING_TYPE_RX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "fail to unbind RX ring(%d) with "
+					  "vector: %u, ret=%d", i, vec, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int
+hns3_map_rx_interrupt(struct rte_eth_dev *dev)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
+	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
+	uint32_t intr_vector;
+	uint16_t q_id;
+	int ret;
+
+	/*
+	 * hns3 needs a separate interrupt to be used as event interrupt which
+	 * could not be shared with task queue pair, so KERNEL drivers need
+	 * support multiple interrupt vectors.
+	 */
+	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
+	    !rte_intr_cap_multiple(intr_handle))
+		return 0;
+
+	rte_intr_disable(intr_handle);
+	intr_vector = hw->used_rx_queues;
+	/* creates event fd for each intr vector when MSIX is used */
+	if (rte_intr_efd_enable(intr_handle, intr_vector))
+		return -EINVAL;
+
+	/* Allocate vector list */
+	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
+				    hw->used_rx_queues)) {
+		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
+			 hw->used_rx_queues);
+		ret = -ENOMEM;
+		goto alloc_intr_vec_error;
+	}
+
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+
+	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+		ret = hw->ops.bind_ring_with_vector(hw, vec, true,
+						    HNS3_RING_TYPE_RX, q_id);
+		if (ret)
+			goto bind_vector_error;
+
+		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
+			goto bind_vector_error;
+		/*
+		 * If there are not enough efds (e.g. not enough interrupt),
+		 * remaining queues will be bond to the last interrupt.
+		 */
+		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
+			vec++;
+	}
+	rte_intr_enable(intr_handle);
+	return 0;
+
+bind_vector_error:
+	rte_intr_vec_list_free(intr_handle);
+alloc_intr_vec_error:
+	rte_intr_efd_disable(intr_handle);
+	return ret;
+}
+
+void
+hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
+	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
+	uint16_t q_id;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return;
+
+	/* unmap the ring with vector */
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			(void)hw->ops.bind_ring_with_vector(hw, vec, false,
+							HNS3_RING_TYPE_RX,
+							q_id);
+			if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
+				vec++;
+		}
+	}
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	rte_intr_vec_list_free(intr_handle);
+}
+
+int
+hns3_restore_rx_interrupt(struct hns3_hw *hw)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	uint16_t q_id;
+	int ret;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hw->ops.bind_ring_with_vector(hw,
+				rte_intr_vec_list_index_get(intr_handle,
+								   q_id),
+				true, HNS3_RING_TYPE_RX, q_id);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
\ No newline at end of file
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 68f9b1b96a..0dbb1c0413 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -30,6 +30,11 @@ enum {
 #define MSEC_PER_SEC              1000L
 #define USEC_PER_MSEC             1000L
 
+int hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+			size_t fw_size);
+int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
+		       struct rte_eth_dev_info *info);
+
 void hns3_clock_gettime(struct timeval *tv);
 uint64_t hns3_clock_calctime_ms(struct timeval *tv);
 uint64_t hns3_clock_gettime_ms(void);
@@ -48,4 +53,9 @@ int hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
 void hns3_ether_format_addr(char *buf, uint16_t size,
 			    const struct rte_ether_addr *ether_addr);
 
+int hns3_init_ring_with_vector(struct hns3_hw *hw);
+int hns3_map_rx_interrupt(struct rte_eth_dev *dev);
+void hns3_unmap_rx_interrupt(struct rte_eth_dev *dev);
+int hns3_restore_rx_interrupt(struct hns3_hw *hw);
+
 #endif /* _HNS3_COMMON_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 181694bf8c..847e660f44 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -1929,62 +1929,6 @@ hns3_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id, bool en,
 	return 0;
 }
 
-static int
-hns3_init_ring_with_vector(struct hns3_hw *hw)
-{
-	uint16_t vec;
-	int ret;
-	int i;
-
-	/*
-	 * In hns3 network engine, vector 0 is always the misc interrupt of this
-	 * function, vector 1~N can be used respectively for the queues of the
-	 * function. Tx and Rx queues with the same number share the interrupt
-	 * vector. In the initialization clearing the all hardware mapping
-	 * relationship configurations between queues and interrupt vectors is
-	 * needed, so some error caused by the residual configurations, such as
-	 * the unexpected Tx interrupt, can be avoid.
-	 */
-	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
-	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
-		vec = vec - 1; /* the last interrupt is reserved */
-	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
-	for (i = 0; i < hw->intr_tqps_num; i++) {
-		/*
-		 * Set gap limiter/rate limiter/quanity limiter algorithm
-		 * configuration for interrupt coalesce of queue's interrupt.
-		 */
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
-		/*
-		 * QL(quantity limiter) is not used currently, just set 0 to
-		 * close it.
-		 */
-		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
-
-		ret = hns3_bind_ring_with_vector(hw, vec, false,
-						 HNS3_RING_TYPE_TX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "PF fail to unbind TX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-
-		ret = hns3_bind_ring_with_vector(hw, vec, false,
-						 HNS3_RING_TYPE_RX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "PF fail to unbind RX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3_setup_dcb(struct rte_eth_dev *dev)
 {
@@ -2255,7 +2199,7 @@ hns3_get_firber_port_speed_capa(uint32_t supported_speed)
 	return speed_capa;
 }
 
-static uint32_t
+uint32_t
 hns3_get_speed_capa(struct hns3_hw *hw)
 {
 	struct hns3_mac *mac = &hw->mac;
@@ -2274,135 +2218,6 @@ hns3_get_speed_capa(struct hns3_hw *hw)
 	return speed_capa;
 }
 
-int
-hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint16_t queue_num = hw->tqps_num;
-
-	/*
-	 * In interrupt mode, 'max_rx_queues' is set based on the number of
-	 * MSI-X interrupt resources of the hardware.
-	 */
-	if (hw->data->dev_conf.intr_conf.rxq == 1)
-		queue_num = hw->intr_tqps_num;
-
-	info->max_rx_queues = queue_num;
-	info->max_tx_queues = hw->tqps_num;
-	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
-	info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
-	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
-	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
-	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_KEEP_CRC |
-				 RTE_ETH_RX_OFFLOAD_SCATTER |
-				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
-				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
-				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
-				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
-	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
-				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
-				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
-				 hns3_txvlan_cap_get(hw));
-
-	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
-		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
-
-	if (hns3_dev_get_support(hw, INDEP_TXRX))
-		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
-				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
-	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
-
-	if (hns3_dev_get_support(hw, PTP))
-		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
-
-	info->rx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-	};
-
-	info->tx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
-		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
-	};
-
-	info->speed_capa = hns3_get_speed_capa(hw);
-	info->default_rxconf = (struct rte_eth_rxconf) {
-		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
-		/*
-		 * If there are no available Rx buffer descriptors, incoming
-		 * packets are always dropped by hardware based on hns3 network
-		 * engine.
-		 */
-		.rx_drop_en = 1,
-		.offloads = 0,
-	};
-	info->default_txconf = (struct rte_eth_txconf) {
-		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
-		.offloads = 0,
-	};
-
-	info->reta_size = hw->rss_ind_tbl_size;
-	info->hash_key_size = HNS3_RSS_KEY_SIZE;
-	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
-
-	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-
-	return 0;
-}
-
-static int
-hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
-		    size_t fw_size)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint32_t version = hw->fw_version;
-	int ret;
-
-	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
-				      HNS3_FW_VERSION_BYTE3_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
-				      HNS3_FW_VERSION_BYTE2_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
-				      HNS3_FW_VERSION_BYTE1_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
-				      HNS3_FW_VERSION_BYTE0_S));
-	if (ret < 0)
-		return -EINVAL;
-
-	ret += 1; /* add the size of '\0' */
-	if (fw_size < (size_t)ret)
-		return ret;
-	else
-		return 0;
-}
-
 static int
 hns3_update_port_link_info(struct rte_eth_dev *eth_dev)
 {
@@ -5281,98 +5096,6 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue)
 	return ret;
 }
 
-static int
-hns3_map_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint32_t intr_vector;
-	uint16_t q_id;
-	int ret;
-
-	/*
-	 * hns3 needs a separate interrupt to be used as event interrupt which
-	 * could not be shared with task queue pair, so KERNEL drivers need
-	 * support multiple interrupt vectors.
-	 */
-	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
-	    !rte_intr_cap_multiple(intr_handle))
-		return 0;
-
-	rte_intr_disable(intr_handle);
-	intr_vector = hw->used_rx_queues;
-	/* creates event fd for each intr vector when MSIX is used */
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -EINVAL;
-
-	/* Allocate vector list */
-	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
-				    hw->used_rx_queues)) {
-		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
-			 hw->used_rx_queues);
-		ret = -ENOMEM;
-		goto alloc_intr_vec_error;
-	}
-
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-
-	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-		ret = hns3_bind_ring_with_vector(hw, vec, true,
-						 HNS3_RING_TYPE_RX, q_id);
-		if (ret)
-			goto bind_vector_error;
-
-		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
-			goto bind_vector_error;
-		/*
-		 * If there are not enough efds (e.g. not enough interrupt),
-		 * remaining queues will be bond to the last interrupt.
-		 */
-		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
-			vec++;
-	}
-	rte_intr_enable(intr_handle);
-	return 0;
-
-bind_vector_error:
-	rte_intr_vec_list_free(intr_handle);
-alloc_intr_vec_error:
-	rte_intr_efd_disable(intr_handle);
-	return ret;
-}
-
-static int
-hns3_restore_rx_interrupt(struct hns3_hw *hw)
-{
-	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint16_t q_id;
-	int ret;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return 0;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			ret = hns3_bind_ring_with_vector(hw,
-				rte_intr_vec_list_index_get(intr_handle,
-								   q_id),
-				true, HNS3_RING_TYPE_RX, q_id);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
 static void
 hns3_restore_filter(struct rte_eth_dev *dev)
 {
@@ -5503,40 +5226,6 @@ hns3_do_stop(struct hns3_adapter *hns)
 	return 0;
 }
 
-static void
-hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_adapter *hns = dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t q_id;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return;
-
-	/* unmap the ring with vector */
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			(void)hns3_bind_ring_with_vector(hw, vec, false,
-							 HNS3_RING_TYPE_RX,
-							 q_id);
-			if (vec < base + rte_intr_nb_efd_get(intr_handle)
-									- 1)
-				vec++;
-		}
-	}
-	/* Clean datapath event and queue/vec mapping */
-	rte_intr_efd_disable(intr_handle);
-	rte_intr_vec_list_free(intr_handle);
-}
-
 static int
 hns3_dev_stop(struct rte_eth_dev *dev)
 {
@@ -6927,6 +6616,7 @@ hns3_init_hw_ops(struct hns3_hw *hw)
 	hw->ops.del_mc_mac_addr = hns3_remove_mc_mac_addr;
 	hw->ops.add_uc_mac_addr = hns3_add_uc_mac_addr;
 	hw->ops.del_uc_mac_addr = hns3_remove_uc_mac_addr;
+	hw->ops.bind_ring_with_vector = hns3_bind_ring_with_vector;
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 67e506f6df..55518a913d 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -437,6 +437,9 @@ struct hns3_hw_ops {
 				struct rte_ether_addr *mac_addr);
 	int (*del_uc_mac_addr)(struct hns3_hw *hw,
 				struct rte_ether_addr *mac_addr);
+	int (*bind_ring_with_vector)(struct hns3_hw *hw, uint16_t vector_id,
+				bool en, enum hns3_ring_type queue_type,
+				uint16_t queue_id);
 };
 
 #define HNS3_INTR_MAPPING_VEC_RSV_ONE		0
@@ -1032,12 +1035,12 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 	return __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED) & mask;
 }
 
+uint32_t hns3_get_speed_capa(struct hns3_hw *hw);
+
 int hns3_buffer_alloc(struct hns3_hw *hw);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
-int hns3_dev_infos_get(struct rte_eth_dev *eth_dev,
-		       struct rte_eth_dev_info *info);
 void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
 void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
@@ -1069,13 +1072,4 @@ is_reset_pending(struct hns3_adapter *hns)
 	return ret;
 }
 
-static inline uint64_t
-hns3_txvlan_cap_get(struct hns3_hw *hw)
-{
-	if (hw->port_base_vlan_cfg.state)
-		return RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
-	else
-		return RTE_ETH_TX_OFFLOAD_VLAN_INSERT | RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
-}
-
 #endif /* _HNS3_ETHDEV_H_ */
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 8632c8f19b..d8a99693e0 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -422,7 +422,7 @@ hns3vf_restore_promisc(struct hns3_adapter *hns)
 }
 
 static int
-hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
+hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint16_t vector_id,
 			     bool mmap, enum hns3_ring_type queue_type,
 			     uint16_t queue_id)
 {
@@ -434,7 +434,7 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
 	memset(&bind_msg, 0, sizeof(bind_msg));
 	code = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :
 		HNS3_MBX_UNMAP_RING_TO_VECTOR;
-	bind_msg.vector_id = vector_id;
+	bind_msg.vector_id = (uint8_t)vector_id;
 
 	if (queue_type == HNS3_RING_TYPE_RX)
 		bind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;
@@ -454,62 +454,6 @@ hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
 	return ret;
 }
 
-static int
-hns3vf_init_ring_with_vector(struct hns3_hw *hw)
-{
-	uint16_t vec;
-	int ret;
-	int i;
-
-	/*
-	 * In hns3 network engine, vector 0 is always the misc interrupt of this
-	 * function, vector 1~N can be used respectively for the queues of the
-	 * function. Tx and Rx queues with the same number share the interrupt
-	 * vector. In the initialization clearing the all hardware mapping
-	 * relationship configurations between queues and interrupt vectors is
-	 * needed, so some error caused by the residual configurations, such as
-	 * the unexpected Tx interrupt, can be avoid.
-	 */
-	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
-	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
-		vec = vec - 1; /* the last interrupt is reserved */
-	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
-	for (i = 0; i < hw->intr_tqps_num; i++) {
-		/*
-		 * Set gap limiter/rate limiter/quanity limiter algorithm
-		 * configuration for interrupt coalesce of queue's interrupt.
-		 */
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
-				       HNS3_TQP_INTR_GL_DEFAULT);
-		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
-		/*
-		 * QL(quantity limiter) is not used currently, just set 0 to
-		 * close it.
-		 */
-		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
-
-		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
-						   HNS3_RING_TYPE_TX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "VF fail to unbind TX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-
-		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
-						   HNS3_RING_TYPE_RX, i);
-		if (ret) {
-			PMD_INIT_LOG(ERR, "VF fail to unbind RX ring(%d) with "
-					  "vector: %u, ret=%d", i, vec, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
 static int
 hns3vf_dev_configure(struct rte_eth_dev *dev)
 {
@@ -649,103 +593,6 @@ hns3vf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	return 0;
 }
 
-static int
-hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint16_t q_num = hw->tqps_num;
-
-	/*
-	 * In interrupt mode, 'max_rx_queues' is set based on the number of
-	 * MSI-X interrupt resources of the hardware.
-	 */
-	if (hw->data->dev_conf.intr_conf.rxq == 1)
-		q_num = hw->intr_tqps_num;
-
-	info->max_rx_queues = q_num;
-	info->max_tx_queues = hw->tqps_num;
-	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
-	info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
-	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
-	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
-
-	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
-				 RTE_ETH_RX_OFFLOAD_SCATTER |
-				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
-				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
-				 RTE_ETH_RX_OFFLOAD_RSS_HASH |
-				 RTE_ETH_RX_OFFLOAD_TCP_LRO);
-	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
-				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
-				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
-				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
-				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
-				 hns3_txvlan_cap_get(hw));
-
-	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
-		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
-
-	if (hns3_dev_get_support(hw, INDEP_TXRX))
-		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
-				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
-	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
-
-	info->rx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-	};
-
-	info->tx_desc_lim = (struct rte_eth_desc_lim) {
-		.nb_max = HNS3_MAX_RING_DESC,
-		.nb_min = HNS3_MIN_RING_DESC,
-		.nb_align = HNS3_ALIGN_RING_DESC,
-		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
-		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
-	};
-
-	info->default_rxconf = (struct rte_eth_rxconf) {
-		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
-		/*
-		 * If there are no available Rx buffer descriptors, incoming
-		 * packets are always dropped by hardware based on hns3 network
-		 * engine.
-		 */
-		.rx_drop_en = 1,
-		.offloads = 0,
-	};
-	info->default_txconf = (struct rte_eth_txconf) {
-		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
-		.offloads = 0,
-	};
-
-	info->reta_size = hw->rss_ind_tbl_size;
-	info->hash_key_size = HNS3_RSS_KEY_SIZE;
-	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
-
-	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
-	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
-	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
-
-	return 0;
-}
-
 static void
 hns3vf_clear_event_cause(struct hns3_hw *hw, uint32_t regclr)
 {
@@ -1634,7 +1481,7 @@ hns3vf_init_hardware(struct hns3_adapter *hns)
 	 * some error caused by the residual configurations, such as the
 	 * unexpected interrupt, can be avoid.
 	 */
-	ret = hns3vf_init_ring_with_vector(hw);
+	ret = hns3_init_ring_with_vector(hw);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to init ring intr vector: %d", ret);
 		goto err_init_hardware;
@@ -1821,41 +1668,6 @@ hns3vf_do_stop(struct hns3_adapter *hns)
 	return 0;
 }
 
-static void
-hns3vf_unmap_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint16_t q_id;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return;
-
-	/* unmap the ring with vector */
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			(void)hns3vf_bind_ring_with_vector(hw, vec, false,
-							   HNS3_RING_TYPE_RX,
-							   q_id);
-			if (vec < base + rte_intr_nb_efd_get(intr_handle)
-			    - 1)
-				vec++;
-		}
-	}
-	/* Clean datapath event and queue/vec mapping */
-	rte_intr_efd_disable(intr_handle);
-
-	/* Cleanup vector list */
-	rte_intr_vec_list_free(intr_handle);
-}
-
 static int
 hns3vf_dev_stop(struct rte_eth_dev *dev)
 {
@@ -1877,7 +1689,7 @@ hns3vf_dev_stop(struct rte_eth_dev *dev)
 	if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0) {
 		hns3_stop_tqps(hw);
 		hns3vf_do_stop(hns);
-		hns3vf_unmap_rx_interrupt(dev);
+		hns3_unmap_rx_interrupt(dev);
 		hw->adapter_state = HNS3_NIC_CONFIGURED;
 	}
 	hns3_rx_scattered_reset(dev);
@@ -1918,34 +1730,6 @@ hns3vf_dev_close(struct rte_eth_dev *eth_dev)
 	return ret;
 }
 
-static int
-hns3vf_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
-		      size_t fw_size)
-{
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	uint32_t version = hw->fw_version;
-	int ret;
-
-	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
-				      HNS3_FW_VERSION_BYTE3_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
-				      HNS3_FW_VERSION_BYTE2_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
-				      HNS3_FW_VERSION_BYTE1_S),
-		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
-				      HNS3_FW_VERSION_BYTE0_S));
-	if (ret < 0)
-		return -EINVAL;
-
-	ret += 1; /* add the size of '\0' */
-	if (fw_size < (size_t)ret)
-		return ret;
-	else
-		return 0;
-}
-
 static int
 hns3vf_dev_link_update(struct rte_eth_dev *eth_dev,
 		       __rte_unused int wait_to_complete)
@@ -2007,99 +1791,6 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 	return ret;
 }
 
-static int
-hns3vf_map_rx_interrupt(struct rte_eth_dev *dev)
-{
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
-	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
-	uint32_t intr_vector;
-	uint16_t q_id;
-	int ret;
-
-	/*
-	 * hns3 needs a separate interrupt to be used as event interrupt which
-	 * could not be shared with task queue pair, so KERNEL drivers need
-	 * support multiple interrupt vectors.
-	 */
-	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
-	    !rte_intr_cap_multiple(intr_handle))
-		return 0;
-
-	rte_intr_disable(intr_handle);
-	intr_vector = hw->used_rx_queues;
-	/* It creates event fd for each intr vector when MSIX is used */
-	if (rte_intr_efd_enable(intr_handle, intr_vector))
-		return -EINVAL;
-
-	/* Allocate vector list */
-	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
-				    hw->used_rx_queues)) {
-		hns3_err(hw, "Failed to allocate %u rx_queues"
-			 " intr_vec", hw->used_rx_queues);
-		ret = -ENOMEM;
-		goto vf_alloc_intr_vec_error;
-	}
-
-	if (rte_intr_allow_others(intr_handle)) {
-		vec = RTE_INTR_VEC_RXTX_OFFSET;
-		base = RTE_INTR_VEC_RXTX_OFFSET;
-	}
-
-	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-		ret = hns3vf_bind_ring_with_vector(hw, vec, true,
-						   HNS3_RING_TYPE_RX, q_id);
-		if (ret)
-			goto vf_bind_vector_error;
-
-		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
-			goto vf_bind_vector_error;
-
-		/*
-		 * If there are not enough efds (e.g. not enough interrupt),
-		 * remaining queues will be bond to the last interrupt.
-		 */
-		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
-			vec++;
-	}
-	rte_intr_enable(intr_handle);
-	return 0;
-
-vf_bind_vector_error:
-	rte_intr_vec_list_free(intr_handle);
-vf_alloc_intr_vec_error:
-	rte_intr_efd_disable(intr_handle);
-	return ret;
-}
-
-static int
-hns3vf_restore_rx_interrupt(struct hns3_hw *hw)
-{
-	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
-	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
-	uint16_t q_id;
-	int ret;
-
-	if (dev->data->dev_conf.intr_conf.rxq == 0)
-		return 0;
-
-	if (rte_intr_dp_is_en(intr_handle)) {
-		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
-			ret = hns3vf_bind_ring_with_vector(hw,
-				rte_intr_vec_list_index_get(intr_handle,
-								   q_id),
-				true, HNS3_RING_TYPE_RX, q_id);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
 static void
 hns3vf_restore_filter(struct rte_eth_dev *dev)
 {
@@ -2125,7 +1816,7 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
-	ret = hns3vf_map_rx_interrupt(dev);
+	ret = hns3_map_rx_interrupt(dev);
 	if (ret)
 		goto map_rx_inter_err;
 
@@ -2442,7 +2133,7 @@ hns3vf_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_vlan_table;
 
-	ret = hns3vf_restore_rx_interrupt(hw);
+	ret = hns3_restore_rx_interrupt(hw);
 	if (ret)
 		goto err_vlan_table;
 
@@ -2616,8 +2307,8 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.xstats_reset       = hns3_dev_xstats_reset,
 	.xstats_get_by_id   = hns3_dev_xstats_get_by_id,
 	.xstats_get_names_by_id = hns3_dev_xstats_get_names_by_id,
-	.dev_infos_get      = hns3vf_dev_infos_get,
-	.fw_version_get     = hns3vf_fw_version_get,
+	.dev_infos_get      = hns3_dev_infos_get,
+	.fw_version_get     = hns3_fw_version_get,
 	.rx_queue_setup     = hns3_rx_queue_setup,
 	.tx_queue_setup     = hns3_tx_queue_setup,
 	.rx_queue_release   = hns3_dev_rx_queue_release,
@@ -2666,6 +2357,7 @@ hns3vf_init_hw_ops(struct hns3_hw *hw)
 	hw->ops.del_mc_mac_addr = hns3vf_remove_mc_mac_addr;
 	hw->ops.add_uc_mac_addr = hns3vf_add_uc_mac_addr;
 	hw->ops.del_uc_mac_addr = hns3vf_remove_uc_mac_addr;
+	hw->ops.bind_ring_with_vector = hns3vf_bind_ring_with_vector;
 }
 
 static int
diff --git a/drivers/net/hns3/hns3_tm.c b/drivers/net/hns3/hns3_tm.c
index 44b607af7a..e1089b6bd0 100644
--- a/drivers/net/hns3/hns3_tm.c
+++ b/drivers/net/hns3/hns3_tm.c
@@ -4,7 +4,7 @@
 
 #include <rte_malloc.h>
 
-#include "hns3_ethdev.h"
+#include "hns3_common.h"
 #include "hns3_dcb.h"
 #include "hns3_logs.h"
 #include "hns3_tm.h"
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD
  2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
                     ` (8 preceding siblings ...)
  2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
@ 2021-11-08 15:13   ` Ferruh Yigit
  9 siblings, 0 replies; 38+ messages in thread
From: Ferruh Yigit @ 2021-11-08 15:13 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: andrew.rybchenko

On 11/6/2021 1:42 AM, Min Hu (Connor) wrote:
> This patch set contains refactor patches and code check patches.
> 
> Chengwen Feng (1):
>    net/hns3: remove PF/VF duplicate code
> 
> Huisong Li (7):
>    net/hns3: fix the shift of DMA address in Rx/Tx queue
>    net/hns3: remove a redundant function declaration
>    net/hns3: modifying code alignment
>    net/hns3: use unsigned integer for bitwise operations
>    net/hns3: extract a common file
>    net/hns3: remove magic numbers
>    net/hns3: fix the return value of the function
> 
> Min Hu (Connor) (1):
>    net/hns3: add hns3 flow header file
> ---
> v3:
> * fixed build error and some other adjustment.
> 
> v2:
> * rebase patch on top of latest next-net.
> 

Series applied to dpdk-next-net/main, thanks.

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2021-11-08 15:13 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-02  3:17 [dpdk-dev] [PATCH 0/9] code optimization for hns3 PMD Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 3/9] net/hns3: modifying code alignment Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 5/9] net/hns3: extract a common file Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 7/9] net/hns3: remove magic numbers Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
2021-11-02  3:17 ` [dpdk-dev] [PATCH 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
2021-11-04 14:55   ` Ferruh Yigit
2021-11-05  2:49     ` Min Hu (Connor)
2021-11-05  2:46 ` [dpdk-dev] [PATCH v2 0/9] code optimization for hns3 PMD Min Hu (Connor)
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
2021-11-05 17:03     ` Ferruh Yigit
2021-11-05 17:05     ` Ferruh Yigit
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 3/9] net/hns3: modifying code alignment Min Hu (Connor)
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 5/9] net/hns3: extract a common file Min Hu (Connor)
2021-11-05 17:11     ` Ferruh Yigit
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 7/9] net/hns3: remove magic numbers Min Hu (Connor)
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
2021-11-05 17:04     ` Ferruh Yigit
2021-11-05  2:46   ` [dpdk-dev] [PATCH v2 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
2021-11-05 17:02     ` Ferruh Yigit
2021-11-06  1:42 ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Min Hu (Connor)
2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 1/9] net/hns3: fix the shift of DMA address in Rx/Tx queue Min Hu (Connor)
2021-11-06  1:42   ` [dpdk-dev] [PATCH v3 2/9] net/hns3: remove a redundant function declaration Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 3/9] net/hns3: modifying code alignment Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 4/9] net/hns3: use unsigned integer for bitwise operations Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 5/9] net/hns3: extract a common file Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 6/9] net/hns3: add hns3 flow header file Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 7/9] net/hns3: remove magic numbers Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 8/9] net/hns3: fix the return value of the function Min Hu (Connor)
2021-11-06  1:43   ` [dpdk-dev] [PATCH v3 9/9] net/hns3: remove PF/VF duplicate code Min Hu (Connor)
2021-11-08 15:13   ` [dpdk-dev] [PATCH v3 0/9] code optimization for hns3 PMD Ferruh Yigit

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.