summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorchris hyser <chris.hyser@oracle.com>2015-04-22 12:28:31 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-22 15:42:56 -0400
commitacc455cffa75070d55e74fc7802b49edbc080e92 (patch)
tree5db4c6179acf7f899baceff40fe528200355ff1c /arch
parenta62d016cece2fce1d5e4eedf36b17f03a7a5c78e (diff)
downloadlinux-acc455cffa75070d55e74fc7802b49edbc080e92.tar.gz
linux-acc455cffa75070d55e74fc7802b49edbc080e92.tar.bz2
linux-acc455cffa75070d55e74fc7802b49edbc080e92.zip
sparc64: Setup sysfs to mark LDOM sockets, cores and threads correctly
commit 5f4826a362405748bbf73957027b77993e61e1af Author: chris hyser <chris.hyser@oracle.com> Date: Tue Apr 21 10:31:38 2015 -0400 sparc64: Setup sysfs to mark LDOM sockets, cores and threads correctly The current sparc kernel has no representation for sockets though tools like lscpu can pull this from sysfs. This patch walks the machine description cache and socket hierarchy and marks sockets as well as cores and threads such that a representative sysfs is created by drivers/base/topology.c. Before this patch: $ lscpu Architecture: sparc64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Big Endian CPU(s): 1024 On-line CPU(s) list: 0-1023 Thread(s) per core: 8 Core(s) per socket: 1 <--- wrong Socket(s): 128 <--- wrong NUMA node(s): 4 NUMA node0 CPU(s): 0-255 NUMA node1 CPU(s): 256-511 NUMA node2 CPU(s): 512-767 NUMA node3 CPU(s): 768-1023 After this patch: $ lscpu Architecture: sparc64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Big Endian CPU(s): 1024 On-line CPU(s) list: 0-1023 Thread(s) per core: 8 Core(s) per socket: 32 Socket(s): 4 NUMA node(s): 4 NUMA node0 CPU(s): 0-255 NUMA node1 CPU(s): 256-511 NUMA node2 CPU(s): 512-767 NUMA node3 CPU(s): 768-1023 Most of this patch was done by Chris with updates by David. Signed-off-by: Chris Hyser <chris.hyser@oracle.com> Signed-off-by: David Ahern <david.ahern@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/include/asm/cpudata_64.h3
-rw-r--r--arch/sparc/include/asm/topology_64.h3
-rw-r--r--arch/sparc/kernel/mdesc.c136
-rw-r--r--arch/sparc/kernel/smp_64.c13
4 files changed, 127 insertions, 28 deletions
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h
index a6e424d185d0..a6cfdabb6054 100644
--- a/arch/sparc/include/asm/cpudata_64.h
+++ b/arch/sparc/include/asm/cpudata_64.h
@@ -24,7 +24,8 @@ typedef struct {
unsigned int icache_line_size;
unsigned int ecache_size;
unsigned int ecache_line_size;
- int core_id;
+ unsigned short sock_id;
+ unsigned short core_id;
int proc_id;
} cpuinfo_sparc;
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
index ed8f071132e4..d1761df5cca6 100644
--- a/arch/sparc/include/asm/topology_64.h
+++ b/arch/sparc/include/asm/topology_64.h
@@ -40,11 +40,12 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
#ifdef CONFIG_SMP
#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
-#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
+#define topology_core_cpumask(cpu) (&cpu_core_sib_map[cpu])
#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
#endif /* CONFIG_SMP */
extern cpumask_t cpu_core_map[NR_CPUS];
+extern cpumask_t cpu_core_sib_map[NR_CPUS];
static inline const struct cpumask *cpu_coregroup_mask(int cpu)
{
return &cpu_core_map[cpu];
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 26c80e18d7b1..6f80936e0eea 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -614,45 +614,68 @@ static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
}
}
-static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
+static void find_back_node_value(struct mdesc_handle *hp, u64 node,
+ char *srch_val,
+ void (*func)(struct mdesc_handle *, u64, int),
+ u64 val, int depth)
{
- u64 a;
-
- mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
- u64 t = mdesc_arc_target(hp, a);
- const char *name;
- const u64 *id;
+ u64 arc;
- name = mdesc_node_name(hp, t);
- if (!strcmp(name, "cpu")) {
- id = mdesc_get_property(hp, t, "id", NULL);
- if (*id < NR_CPUS)
- cpu_data(*id).core_id = core_id;
- } else {
- u64 j;
+ /* Since we have an estimate of recursion depth, do a sanity check. */
+ if (depth == 0)
+ return;
- mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
- u64 n = mdesc_arc_target(hp, j);
- const char *n_name;
+ mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
+ u64 n = mdesc_arc_target(hp, arc);
+ const char *name = mdesc_node_name(hp, n);
- n_name = mdesc_node_name(hp, n);
- if (strcmp(n_name, "cpu"))
- continue;
+ if (!strcmp(srch_val, name))
+ (*func)(hp, n, val);
- id = mdesc_get_property(hp, n, "id", NULL);
- if (*id < NR_CPUS)
- cpu_data(*id).core_id = core_id;
- }
- }
+ find_back_node_value(hp, n, srch_val, func, val, depth-1);
}
}
+static void __mark_core_id(struct mdesc_handle *hp, u64 node,
+ int core_id)
+{
+ const u64 *id = mdesc_get_property(hp, node, "id", NULL);
+
+ if (*id < num_possible_cpus())
+ cpu_data(*id).core_id = core_id;
+}
+
+static void __mark_sock_id(struct mdesc_handle *hp, u64 node,
+ int sock_id)
+{
+ const u64 *id = mdesc_get_property(hp, node, "id", NULL);
+
+ if (*id < num_possible_cpus())
+ cpu_data(*id).sock_id = sock_id;
+}
+
+static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
+ int core_id)
+{
+ find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
+}
+
+static void mark_sock_ids(struct mdesc_handle *hp, u64 mp,
+ int sock_id)
+{
+ find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10);
+}
+
static void set_core_ids(struct mdesc_handle *hp)
{
int idx;
u64 mp;
idx = 1;
+
+ /* Identify unique cores by looking for cpus backpointed to by
+ * level 1 instruction caches.
+ */
mdesc_for_each_node_by_name(hp, mp, "cache") {
const u64 *level;
const char *type;
@@ -667,11 +690,72 @@ static void set_core_ids(struct mdesc_handle *hp)
continue;
mark_core_ids(hp, mp, idx);
+ idx++;
+ }
+}
+
+static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
+{
+ u64 mp;
+ int idx = 1;
+ int fnd = 0;
+
+ /* Identify unique sockets by looking for cpus backpointed to by
+ * shared level n caches.
+ */
+ mdesc_for_each_node_by_name(hp, mp, "cache") {
+ const u64 *cur_lvl;
+
+ cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
+ if (*cur_lvl != level)
+ continue;
+
+ mark_sock_ids(hp, mp, idx);
+ idx++;
+ fnd = 1;
+ }
+ return fnd;
+}
+
+static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
+{
+ int idx = 1;
+ mdesc_for_each_node_by_name(hp, mp, "socket") {
+ u64 a;
+
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+ u64 t = mdesc_arc_target(hp, a);
+ const char *name;
+ const u64 *id;
+
+ name = mdesc_node_name(hp, t);
+ if (strcmp(name, "cpu"))
+ continue;
+
+ id = mdesc_get_property(hp, t, "id", NULL);
+ if (*id < num_possible_cpus())
+ cpu_data(*id).sock_id = idx;
+ }
idx++;
}
}
+static void set_sock_ids(struct mdesc_handle *hp)
+{
+ u64 mp;
+
+ /* If machine description exposes sockets data use it.
+ * Otherwise fallback to use shared L3 or L2 caches.
+ */
+ mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
+ if (mp != MDESC_NODE_NULL)
+ return set_sock_ids_by_socket(hp, mp);
+
+ if (!set_sock_ids_by_cache(hp, 3))
+ set_sock_ids_by_cache(hp, 2);
+}
+
static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
{
u64 a;
@@ -707,7 +791,6 @@ static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
continue;
mark_proc_ids(hp, mp, idx);
-
idx++;
}
}
@@ -900,6 +983,7 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
set_core_ids(hp);
set_proc_ids(hp);
+ set_sock_ids(hp);
mdesc_release(hp);
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 61139d9924ca..19cd08d18672 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -60,8 +60,12 @@ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = {
+ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
EXPORT_SYMBOL(cpu_core_map);
+EXPORT_SYMBOL(cpu_core_sib_map);
static cpumask_t smp_commenced_mask;
@@ -1243,6 +1247,15 @@ void smp_fill_in_sib_core_maps(void)
}
}
+ for_each_present_cpu(i) {
+ unsigned int j;
+
+ for_each_present_cpu(j) {
+ if (cpu_data(i).sock_id == cpu_data(j).sock_id)
+ cpumask_set_cpu(j, &cpu_core_sib_map[i]);
+ }
+ }
+
for_each_present_cpu(i) {
unsigned int j;
&Z/-bk<e2jHC#P(6&q?.s/l# w0yB^4@-yV]7K4(i,YʥSLXߟ%ѩW/LGϙ! B {iлڪI/Sn6OݶОGwLԞW!AuE=}#,>ڜO؊:Tal{{=hnI#Y/|¥D"%A`XZP-ݵMJyڎg1aH?=D'Ә9:=?nkU:iPNjlVմ=j_DsTE&פ:mN K^%;-g64wz}Z^}nz5x7 ǐ Yeo6U_B#,4QXVY ӧ{tl8~c2=RKKf_\O\$Hh]g0H:YnV?|Bk{j^0i/BwYNFfH:*EcL,i}t1YV.\ ,ѡ(j미 _yihIAe{@zMG–B8]Es$O*d:qJQuڪSӱjDCQj8FF Rڍ_txrTUl ֡83ƾ,CDh!+;$pj#1*3rd5nm#/DFQLa+L)j C'sP3If|aZViذ e"'JPN7D(7z Ν!Ryge+Uٮ:4p#V&ۤ:V>Uثi$K`KdCkmm-/q]?'ct و >3:uf!;jg$shljU]c/u3^bh"7.Gޯ^9CJlUI^X,=lHk]zTU g> .mą 'E'Md0#nk*4@H6QQj$ɲE쨻U3y F ~p-b;G]t획a~{s9J|,ίL/9sARh Z3 0GH$ 9͵6Xel_WIS7 Sܴxm/y.d9хG#K*}BX<2,Xׇ|@\ &ʡCB.h$ǖy4C[d h9AU.F?~Xy+¸@ְ3.l1wlH̡"rPvKv)4b׀:I#a&+n: ةOZSl֚>iq6IQZak5p] KxM&Uk:db'0Y'zKZ"='V0H1WW{WJPcD-Ew"w5{]1E,Z%(B>gyb`!MNpvԠWpF+5&P#a ICpc{ZrqТQ6sH73}Ťf 2R86L< ~xO-z&ٷQ">cM@">NlmES4=l$in@Cg2֣*3YӐ08js\}!$]fWv\*YINWj-U5'ժ:Z`4| ǴTZA2y~ropK}a)JQzI/!&'#xKدZ +7;teonridR)5vZ@|ܙGwo?h{=;n7 ❐kIc4#%a&dVtjQArpNpg쒪*MO)b54;CTѼY'j'+:9Z24߸0݇Z32Bj~tA rleo{2(hY:q~H<'0zJ{rGVICЂ1V+)Wvw^ӞFY6| ftp DkVF0P9](bz}nȪiI$T<\`R;d0 b@z1rYK|>jb!2{,BI h\m!NA'4h]9k/86{/ "`W9`2kF< B(](hO8@iaUL^v?9tc6:KӶ17yj8!-O5ۤn;-ծ% Ø-GS#zs8]C!Y4,~O&ңRAuJ0b($}t-\K1`8$iR=ɓŃ. 'F?>\4szFR6^&Cw;<_&ɈR;p%}LPAdLP}zm[tDH=ۋ>5jo;KW<&]U0_RIﰣ!$ԃP\kme+'KNllbїwNYz`m99%W;"AqRV9wBZF@ITMui[uՑOxQF|5Co8 VZW]0A$w/ZQWq#!2pC/$YJh!i2HQː9W7nvݎۏc'V@/#c9G8L+v'۫8t1Ym ]RvA;Gdh%DGgTƣ2+WL}0-k;Y)iu Vw|74?"q4|<-p̤K4yXq^RIu觏?&A?ʐ XQ_>I7ں[_BhA~&͢-V-" Ŭ\b_D>F5i>=-vKݣP*:=ky4m $]$XIsBPz+iԝx.)}ɉH?6HRq"!bxSy 9̫ણ7q4"4CI^lfWWa:Ƨp`T8;V§Ä6K|ig.];FMM̂=1iIs!;^+I]i_+!s`?@U $QGF惎;yCrǀ P,^%1۠~z\ޙf:Yw6ӺkzGu;㎪M뤇M=3Ƶj[Æ -uQ-r9V0D$ ;y4?ةv y ́ EmH>`7~ɜ{(|CL]^Z]5|Wg|h mS/ȵ(g:90@T$[|^v-S^3HW|Dv&´2QX*؇W`1ʟRj)0$‚nK0Po DhZzϳO s}>eRƨ8C:YphqB'. uVD`]OùuUW U="_;OM۲E~{Al!W=:`>DTgt',% ڴxt -z%G.ƗQv8^ H /ysL?َKNqF'^ &Xw~q<h3ˉT=H%|A&!v->`&llrа=Um5hjNUq:U:ImSW& KK, %ȧHYio/ +DHom&Yk #b` {D) F [7CfOjZHk]::Ǩ5w ¸Y((I[óDŽ$D~DOP} SoV~W_f%Nӧ3GBw x֮/3Z$K! G琍vO]Ω'bQͯw U7vEʡZ- 0y/TA@4f W(~(~3 / dc6t'r[,e$D3@y_|+N6@ԍO'55AfB axd UJVPV%2ibJjɪd ^>zj9G`4VtH X,8P6k ̋vm/w)]9ASZ.C##mYIAOdXqd]E[NuҹA^ƊqAHfM2DŤp'H*1./{~Ts(9]Z$ IlY PV$A* A!IFchAL ׽Ӯ#P93rك2J< d<؟ tq݌Vc[j~EO `k1UN+`{e//|P@qDu;NˠQB=Pe&>*/鎾Fv 61| ۻ qDm&9W\ ޙF5TK Mդڤm4դ]5 ^ T"'t^@rgs:Ki#]@w&d@kl_k=V2$KUhGo6о麢%_I\iz;Za',eg+)15F=Д 2~*F=$'ժ M+1ȋf`7 Pi!LjzsK.M-d @Jr2 Cojf`!wdOE93h>F*=Oڢpe0Isl溰v]"´M`OF|jWt}5iXtb"&7dmH30:펌bTo/n?ߖl:`69P~;.XwniL.T{Xdh?vdD\КXmBusxib^'^*nǜ6a{}V(:q$㍵oq)3)Ihe4hWe~|Wqj2.>ucl>_YHاs2C:KV7$K09߸̽oҚZ ҭ|zu|HlA;Àv߱Gm4c_{*| ~^Y}v'O>唰S n)}묁qiAת;QY3_B5:-u,DPƎòBUq ,W$1E^~!sMG_h+0w,58/vST=jL!IBIL%Νd3:8].pRgz`TOԁq|=Wy!,S$fjL86~e % Ǘ_{$yRҵɬY|)fs+ '̐*17k ۬f{ FNiĊ TMHL85΋}Xpf G[X3؎ *_1kˇN}_DHjDz.l4n_:MFQψ-I q`$ Hi^~h%r8-u@#=Ǡ66?+hxV6C<}13#m=BQ UF'];uly,X"㺫+xzHLvNMQD;D !&xۮi T#AP_G{^玈8]puy8EU 0)j;^SU, B.25ks;!U =1؉crE$!>V~8HUr(j@˸!x#ilUR&{O'C}0#=vZT^#֑؃"qO4'|`i4Pf[#u/PtM!HH EeN*Aysϔ&*W:G<:&Op1P6A i}@B7wd󧲽1x2dq9nm{wf&M4EޑMv HuGX{`)ǒ"-=v P%^J VVՅ"a`$,f L=6پ0ud=JZ#BxZ\%u=W"gvGF.H9&ኤD\5rdMa6Ap` 4!2[Y7RtZ'|nU(]]xdEj1үuc*XСCâX[ZL6pݾ FIx=IMrKK@S1$>%dqI[j`ktASmPƔ$_:P a`;|jmP8ѣJK>O'pv1P^@Th`\M%"9v{љmʷB#=&#R_]-yJey7pLm'\h~tea*uO7y4(Qw{ΰLn4,X8˨~z[.ǧ:nl8MYZ: '֋ WqcvɭGY vzT Op `n!^FjS I|BDN" #YO|L%hz#dwf>?@/JN4= Oɾ/MZ&(?gHJY|>fM ;@O 7ՠj`{C`sNQ=a3=Ӹa'1صZ®Q$™8Hڳ}mJ0"iY^-NV~4oW& +a):w{ \'>PA *ŵ҃"âM~e^\C#\ ʵVa&fOQ5kHc!OS7~6uw3ʏr"N&)NQD0}dǦaIo&J쮎Ptׇ`u;-MkԉgV J.֊\`OBѿ^c/sU߫l_.jj{H. #KCygl!N(xi3`wc$8L%4;N+epu k;MP_8$=Ѯ1@n=Z?ݭ<A(lt09F@Ij5)7ukpURzHOD}kaDHJu h`St2v5Ԩ1G[E&]gL8eLC|,oPUrg_hgDRd)-i})业cTn GX%,u WxH9d$LjL]ش FF!wu XH@|5B$}IzcSԫa%{;z,7~ٿ~my#t+09bXZq\:sdɒӵL|&R˧>J --aM~;IdI^zjq)IM\7ib;Hȶ+?PqWf/ٱ#o<{3o̾5nGjN;ܩsnX:͂}ke&!w1ɬ>ǾlU9[^ 1Aدs)^oRn:VhJJ.-MZՠFپX&z Yo<}ҙ({tf%Mqi)t:$;L,&4[};d͆A8Q+@4D& kp{^s [criN\H uE\Zifm%X@'ԙҜׅV^qTh!RHZzȾ:8|j^24k֭cJejBP3a9|1?G{ LݛK/|{R2"Xn$,Khqκ-Pv||C6vU*QEIcVKY&&-V,|`G&no\ 5ܨq> ǸϱDCZo⅟[7128Ėb? N!p Z{87ԇ'|]sh! ˢY%ѻKH֟UR+%Z:8ѴrDB, mmhsۏVf PXN'=3Ң`P];4w_u5g]JeV6X% ~شb EEwI}dN$ 8Xc܈ 3Bxk @qlR2K-r3o\Ǫ ޔfs|e:9wNi[ZY뤬/ʏr4ټ4:-X1qNCA3K9 yaٳޮGuJ"wc.NAM祴WW3UZQa¹=%k;Uu浧7*O ˁ<u5{:XW!2;*l2뤕mhh, ˌ5׆9G#s3Bj"%0` ^hWi86yfY@uۥF(5$W~m0HYܡ("/&6AX, >.雑[)H̶bzeLcSJ!y1y ˻OknvSkQ8lmIjoZS8Yr[WJH!kJlƹ4WWkZ ݚÁ> ̓}?6δZkҡ@4T7k  Uu*YT{JQoQKFIOF ըU;J&)pW(\]̼2Ӓ:B9Ou?C~Nu+ܼOB  8ej4@3M܌ds@zGGv}t -˫(SY+`\,=<ܘK  g ˀ}TՂ'wGNwJn-HW,)oh-EYBtHs ~>B7Y_ɪEq =#' 5.-jv͔F+?mK׼s_:Ou%Mg ^;L4!KQVnv&y@.,Nw8J֕8 v'^sC"F0/6\rs΋ot>d>yr W{DӲULY`BHՏ4hi!2*4^WuDM!(Uf.ERqVĪGO1מwqfuNP;=Y2& 6ǩWg )^M1I9n{F#_vzx\4T(tiP\>B֒&҉6UvsQyBCU[?Fk#6]OO >r=u$]Ltsiu$Qz#yu Pf3+P?Oa-2M68b^VٻC_@3B,LqW >H;M{6Kp1RwD6WAIgϬݩ̪,`Iyi GKB[HjYd@̍(-j9&=hӿ!د8E^eV'|ZږD_`$ z}8mek_J'ŎUlX)oV% _ͅO{Kd$˥lI?Kb!ᾟLȸ>GN6 Fi=Pf+f/FxܕMi[֮T^&!9*xn+r@}\Qs֌ݟ唾|Bk{{`yԊv9 xZNpv1x]3O+ .;AԕG^ #{/N1lxڎٟ&RZv&` i%bQ-@QCrU4. izuوXDݝC-ڬ4 Sεܳ``lء.hHAP_5lK"ZI|@#,ȴRN]79fmVf9@`0yUvQ;9 n0wIoi/|bZp£,QG16bdI=B#;-r@g8Y뵵L|9SZPr#5lzUf ,UuΫ4P_^ݖ~Vԙީ gHu 񼓚P[["Ϩ :S_XE{yeD>p#}h0_䠾N(FFk4iMԤUV5TdI[ BYtjרȲ FO*sCB_HzHɡƞ߿hM}*.T1DGGnTC9kѣyбcx, D}v/l5ڃx5nWU{d&jUYvIRn6w錷>e҂l=dl;9ʵ),_ GvbZfAf)-ĥ^TӪ5nH$Srusp;xFχAq" j ]tk'y!ΊF3rGի:-|g~{ME͉ulX*ªR+(?3oA.?QtT8ـt[dc=h`=lÚIIhFjm5Jux4$q%h 42h"7uU?Pi6 )m |/uEKV?ڂ?&/j[hzl=..BFGW ^4t82N0ۮWBkBsFC-{7 rPZoHS4ڠt:u#V#ϑ+Rs#I~yP¸Tɔ&tڠ1QָխHtGjء+.9ztH~L|)iMu=`/'P9 6\0ӗtonj.r>ǷHWMt*¤zSFBFl0|ťØQKq; I;:>K!C%3r7n(ѫ3uRNz#?H3sĉR@(&LkH|3C;-ƹ뻑go0d1Z/3@}WQgҠHj<#5۠FQfN -.%\p +TۗDPo.+K+^I/.5ޑm{Ó씻J#6؀82`w$jU4\lRַI?MTN$sS')P$%㩮K}owzV%@<%M)gc Sc$ђ8$qaҝ;rC$&@odo<&̈C8vd6^b<&3T%=c(2PN#0N' ۶o'` 1CX${}0Ps\aJI)XYq"|@J51jJd_5 cH*T?KBD]qJO8O9WOG0>1^ws«Yz*N×cM"%l`M;wi FRՀ_#H!g }=.<.!mk|"aBcKGX(/彖Pr^?.zaX  `#}oaazoRgrr@"HWVxh96 h}3=mΎiEV&&٬*hAu a=֎ eQK?aH-GNz5LNvRf#^ܥ35)ؼ DTǻ`uUz:9s{y GRg-"LnYyơ-s|8W䂊Y0jjA/5[L)est+Rh˭!rreIE$D2i9$G ܮp"ɬ Ngɟ㮝d=wmK)5gh﷚Z&'E/\V3//8 i<#4)ZnȈYU2j\Sd^L ظf!Θ՘44L.tp GPz/!^+ }^x?Y$ ," +q&U%LpEwUIHx.CC 0m Z#Xt~rL.WR8~!D6DЭ/#WӀdh=;|r7 FuYΧvŝgjbGX7o[j-tԏ,a\ Ϣ=< ]HWwKr~6{Zzռƣi_9O]3"`J }*So4ڈ֞&[u+čmC \ķ]H87mC哽Gõv?YeپͿa& A] Z^Gz/:G:}'IǨ9emS)l3 JyDʧ휴 ~s9q#Ma֩U{]a@ڕ&ae\bkӏ3? zbDbn ,M2瞊ȌKYL6@-I5lZ\{+#o$dEԙ\( Z9U%kEL!L͊i"AS8FggLYuó;viZuɕZdLM`Z719c36&! );6%j]8P\ƝbO'tupzibɕXxlvb>`K8L ;{XI^5ha5ՈpYs*Z$bdsst*4긎Ƈl[SAs@gl#k\S*5E?#舙V컎 _n7z>w0g@#ȹ'?GIV%.3{+{-$/$5}(f؍4o>jHdj٨, lvsɔK3߅-Bl:]{Mg굲`́r\ML"+ ). йuhs>^\O`yE&}H˱&rg_%|,sL_dɨ" |HSI v >xF]=\kZc5WWY&aN9lv{%1rq z+f1i-~ !)y(svB U$z|evJ4 +aEIl]B9t~e(׌23V Pg:bm1x@r ?ը&WkJtar>طPِ$m“?EM4I0QuA״-m h7WVVofۨ|AJH)$W gsc J3^ZOz/D򏉫Rh4N ̈)3"pG{) Dcy_e^)w}o`"{_2f)@]9+4C)OfNgyθ9v[(d;FQDaW ͩ A?nhOdz.#ND5Gv"UjWjB,>a~^.Q%5^]zws5Yڟtn~\@Mc);P؏[Vu;k[>л.obZ;ORؘ6ŇL|rYVcc6%2V:j4MZV>!Ygg<7 呚7@l?u ~uK3&G % ,H*s]q^街4xJK"ٜH!BGԪGIX84(5E8ӊեzDVĖ-BSaBKg,Fw{r,Z^YWrXJ/sI z(j+k[`\ͫ{$`'vp`W \|{E*ўδԅm<C0_0˴J,8&D \FqT mwEϦ]i]!542a>gҡ9; N0*1N4?)M-S{5m5i4? t0g2fkFdr9KHf>\t$hи0=OWJR[]İjr31qۅD"F%뽺3qYUo՚(IJ/B毤ut)qoHvkWM-rvk{1᧼$xC`*?U$5?䘿$w/4քzV)@*BIIǽ. moUDVȹ*Zc&vYj9" v4h_KQ_ +&D ȗdi8a BzP#w<[5gJ O~E mJ Q[&!IgA꘮$*/?Ό _2«JLѢ^mW4MiĊSCQ(+$ѥ/T{ސ&LIPZZdpjjE 0cWX}$%t/*#oU 1;O+-kR:ZX'|߷T Aݝ:IBtGЙvW?^izVJkWYbXEF;W']g<?#YDțd.kpbͰtĞ'K6vqiWN~Nhjo~tҊ)DOB*5AMfqtWvQKpN1XgW\Vk2jj7;55nL4޴S$F @>͐UB 9aǃ񐰢%*rg AVc^K wC^L)~)jO@efe*- w MADWH1Oc\nJ4^RlQh]Ǐ4 mФzf#=YTU( kh;Ҫ ;@H8'7ѤYу`W@M)"%$ѷD حv`,1St>&jN՛Lj:7i5j"3U UUm K5aC/=}XFX%~hT5neiĉ$[Lr[߄u-ATڡ ̒ǵW"Ѣ`{zI#)lr7pxgSywE,ltΖY{h+Z7'-sq] e@˕D@t (<@,i.mL/aݕZ)?~^̏Ü:\{J8+[v!w~_Zݧ$_Oؖ^^s}჻ۜ-Zۤt;}yh;@ϋ 4@hί'im)Lps IS(K[5Ò~hZ p~F ) bh90lUQW]us#E;k[~w(d~{-_Ҋw 6{KHAtn!SF lO"l9˨CTQ//OBauQ5;a{ l+8P"N_>۠1,B4c@7٭x^LEjS, URD`G?QYaF0 NFo? Ԩ =LnV$1V.@ TGEܤu79@Bb\9ˍk ,ڼJyNAO8vlACG=D,vM!Eڦ8@Pϡ{vB$i`IֿzPzGǃjLm eVZ#Vn,-՝_Z4OwreM$' cƷ%)naǺ/Fj|r͒tr1Y#H@b<(C.3 eXӤuDVzv'=VDgz~k?fAv 9 Sg/Gk_/_5ӥRZ:=T sVi T;ڰSC2d=UFmp%lW" V9OsG@ҵ੡צY32^֩{Sҧӵ1} ;=:Y^h4;7DۓY-F2Ш6BM(i '#S*}YZ -LZ:cZhSdԇ8uE=Q ^If0]p Z#kpPzOvT]p5Uŝ8Gz1P?:A~L]"h!L'6{Rނ5^&4Z^- ߡ8;LRg8KEuQQ:n9uiJ1u3pԠ6{?y< cg oG.GGߣvOQl,l ʭ*H/Z@%~׎Ў^bcѺo/ږl^_Z4=xnzQ0jT>9AqH9]q@B0v֞N).M|r^N55nj.ͨ#ښvc@ ۃjԛ | pJjTҲgy\f|j{ 4-h-ɂNKlOSTAٝFcV 5 sEkHgchpnBgǫtL5DIxHmLHm=n&!ܒ_.v7Phl{֙] xD~QkZmza193:n9W! 2r ZCf xi4RLn͠b>"]],h#wR2Dx%uՙK">v7xgQڐ dCפ-UMz⌞:sQv>4 _ i5ߜ}>Ɉ$w>f:{ &Comec;!¡A cE Ir G64,oQk)3ڵYd=,BgN䓣  A~wĈ@*NycكUu2tdt.W/y{dqwwv Jr@V]SRӢv@C%%P1(j_\f,1$ɖS).~8ae貏ƣ3{?Q.rI#0C96zsYBW)uMMxqu5֬U ;VW{;O< e*?+8&0)B^]۟ABTCɧ%x$wc]'1W1[z\+.r}jԊ:cJ8i]ښl"j"eRZIA-p!־kv!ď"r[7~$L9p Xq9z OԠ^D&ø#Bڮh$x|W,½l#&'h z<0_uBi!Z?:.u9\nu% \&lqpe(EnG5ob2HzVurvl\mMPJ#]KfM r#iUFKrIW3j|˜|LI}s3!PF: O{”^WM sdlnAJ֭U22DD6yDT]YMؐB,4p;4Y;x!KrIS"5CFRAnCuE98Y+OXNC?T-!oa-خ̨F*yв$[foS KO_o9}hf 'ͭB-7ɲI2u)\䨸@ɕFbb&vdy,{2}Xt>04S/gtJIC 5#WADhEH9,/Zj X@3@m6b=xepRDLIRȑX FVjtnjNjF1m5VUn#&QEM>3usu})1;BX4#"5U VFa`waRnثY͝翧E䐽ӢρXS/V~1 N bw4PU"h*]+\fWb\ fC14#$hJr YOqȍ3H$2fo K[[XpWƸmd:V!͓!(xǝI]{öRICf{jC d>HDk` b}VAm zaq2 o_G19AS_ (5"F>ۘڎV qyyvUrXgs~t+s SC|0' ˇ]TU4*Vﶛ IN2K &hP9=x>JWW'TIt\6L\$% QeAb4dd-ɒGXMAC%"W3_bθO*S |p@S[4vn'kr1k8vq^!#i!-{9sXôzԢ/' 5'dezě2ٯ&^펫XC^N(ݹ"OukPUsM܃VQ4|ȇn: s.}H+DP:t!+'99%8fXFz\z4F\@-F>zwYD[6ؗTIo_c}uY5:h<7h%-.3^v!lU /dZm\OkUMЛOhJfH]3P]R{DJhQmc栗4ƷlB1gfOJ<ȞRXLل.*2X3,`}:qgG*?ҙIqcPCFhi. ƀT VʧYpLe9y+sbNՏσJ3G t M9$ nQ^6x@6xxQ/kPOAi.%(k4}gp :Xi<v0.n?Ra@R?oջwI#/:84hm򤤱hswvk1EP s% \n_{s  1 JZS UiX|j+F ՞tƴ~٫=ظɱc,2- ht@5#[[ti,](\Vm5M0ꪝ'AK쓊ɑރpv7UU^!Ll3j _g^)_\Xo# e箏^du;M=sC3=VݱOUcRȀ%>8~nQ*5k>:O[+Z`goE8M•+6쇼$i:繛ma>[|1 9lmPyUv򣾂4_7Mjz1W#DsJNAU#ɪM682T´}ixXQ}3Y--7U!tt9 6"FtyS}|NcGAb dRB7ϼǃG:_;Tw*oFЏ-~'fr]/p,mD~\0ԗrVJg ~HhQUPҥxjZnH :i l(}{D;Ao#o'}첤fN}?-H]sރ"&L阳9';Y oaDg[bљIT[̮>re?D\kj 059ƿT܏@>Q5bE'sɩ2jC> eLڥS\ÍF)gF^kuS8QSn^ks`k'Ub/F_^O1S)|tT j}őq*~M-@|H} uF;msWaMιzʏkm#0 l +%2Y |-ԔF> VH(nWU+޹;撾sŰ |)3)vHJ**r AyBثSINebfcM-3 ^4냐^VZUyHi5PW0Pa.X H'7n*JMXN+̜Φrw&)'((J}gy\45cqkB)vC+QȚHrXlg.!328E8UڃZڇ|Aפ_ ^WըnFc9Oi~UD/Eo+}Tt"lhnMNH7HԛM赺Jͪꁜ5P's*ot;:H,b#RhΊ^F*ag/ܷkj-aVϿQA=z l$J䶲$rA~̎oUVa6A &IT<.Q :Xye\?!ʏ漓'qu)W:Axϛ~t\GDy QFYQa[#HhKRW[ќh@Pp3JRJފYI:> Bs,I1-|C#.z 0Fxҵ;2.0ܺJβ&S㶆dkQ9;arه% 2hmF۽Zԝi,}W߃+{PS୿r|`LUZyB߻`K>?;"(׾Q U>1Ȼ-vcݢ 5?& WYR{Q=B\gi(5qvv z)-'֊0pCŬ{]I2ȲTI K8]hɆT')k}p'9]~̅5сF e8|4$.ufB%^&˵!< K+ -A NlJ q2ӁɁh+[oZu<+ |<Ig/hT3jnVˍ:A-3 8tQE,/>䭾{xxphaF-/ \9@֢a+fN|qh'dE''h;oMz2G>>gd\|2k YyG"9q?5t-;?VGRK¤P'L- Yh|h; WSώGH5"ጵ?29:먂iz1U5;j蟝S0[h}z?~~y!6,Oi _cP~JGe#/+ -]1=O"՜9dE` 8 Yċ̤@~9Agp+|3Ҭe}PhvZdO<[1콽ԧ>Z5y^lLz-~PHi(djK a9̀g'NpFgq9{il+͖Z@tG6k7lc^~Nկ+9K~ns/^rn\ֆSK_/b!Ȥ(:xfJ!"wMgO͑}J.*E@pR4:)H"|P*- ?RPYG%tCJAhWuhWŶ0C<|ϦJ~y}7z9|2C٦x{"σu4-5R(驺U> *6`@mrr̓d ")N55+Tm2,ޡ٧3sL˼?9x'H2C\V5U%]I=%]t8Wp&B~b''Ԭs^]J)TI.e~&B\q{󺓥&l>iʷ-iQi]6*dq}ki'w1='K^VI!ʨ>*RjpyQvS]rVi/fp2[*:DF ^{%k7G.Q6X92~SPɈ 穯%a`ɪV/MkG)y ^Z dj(#u2$/C^d'.PNaDάbx$5jN=9pB ԂLC 8&"/ 2eكI eSy:c 2yo<?݈ՃNO@ h/ʭe]9hw{2a@Ŧ3KYfL#r$oLl+ H";,a*~GB٭zcק`un/Pc5HU{ؘY22`~K B-q7gAiRW wtU ѷkX/ "ΤL4:s$۠ᢇ:sG] @,e(ZjW^+U39xce)5|HZkLZ .=ͨ'9!D`R qvt@U7l){!XEvAtnfIjfTRw\.PV[4P&IIsժu|Mhb;"*j՚1ηsP]5Tv6e?pm8OR(]^\ *,Km1枽 0'+SMӺ%SbHsA=Y%䖡h/iq?–n6*A[ޫ|0uy:X6<ug2+hF OIR w'"&A$xԈ0lR#;QήS ]|k/-#lIA>)hl A=eXòIhKϛm @8Vu}>jfb5RPQ:.2?TnghEq ,?rɿφyPW0h{gbJ`%g~Xa΄·MGʷ1=*>Wb;X%/.y}}fO.O@'s[3vp$/@9,tji{`iO+2vREn4Eݖ9x7 QssX7S]'oV 2̘zshKj _-hk%\vUtHwv:s8]gBّP+{d.1 nZYJ"-쨪NVzmӲ<`”){P; 9:89/_vuHV0|'>0euHOD^:GJARcAT䆖#ڎ+Bf|.k x ԗSӎ$>Z糪.#~wZ]5$;F*1c{219$tkf&ni|']S3ԇHh2î;*bQYW(4 tQºߐWB^CIb>/j*ot%Rȼ*cؖRH2K,g1_^ǨK3d8Z^)vc\GRWԞjp vl]!Id6ܱ]%^FI ' y)y,>'H4B7w4Wmh0i5۝)6zMƛG O-2u5m+.)xrTz@e.G序XjW28/0tKU%>s'#\qiU}s`壳x90*Y A.G6Jdq-l5UtAV#ֿI+tx0БweC "9N4|: '~fs1(LN;B8]g&3H:Z6m&IAZ'>&v,'r$BZщ3%(_u獜Vll1ȸ$tB_=qQR29NA9+K%U)ųt$xnҋ451L^>S.^|a.>\t1]+3VܿV!>GB?$ӕF۰?v3MRCp0y [2Moi~lHxV9-^PbPd[a KH$'_speZh;BI†Fz-lKBAr+U}6vrn;+rp1XT;y&}탵^Kp#Z#QL*[4em띦nN;Q,&^G5$#үHr;:Hl W(\  *^H]9>qDe 5Mvrß'@8'wPNqv*NK'ŏXblu HfxEY?"^C<Iol|' p.5MR궗n̘!KX[r+Y~<;$E@;rMr;-{z*6$5j XMx[Ri5OPƯnTVɈ<\,WWo= 0doF[bYo6 ,e@l:Ľ: }1N Q$=k5AsV`y?bJؠf ',e(K'iב/e> U2p!Q{S9PwxNϝSc|@.]` =8Icix(4#85lZrFXeGc T5x6\[HA3඄G,($jNsӣe|_e4kXMP.M5fd#NBKT1Id2N:fSH!jtuBST\JZq,1']c.YX?WF(ǦYNΜm69`,@ Iz([55T^ʧ(U|%4z}SkVlz0~; ;5eDkurHlF3ˆaƞ,pbSPՊ糚0Ơَ *ȯ>I}U=y1SG֭##>l;$#VޛzQ<` ʀ4( Nfch$\H'\NdDЈF ]ҧy@XP ^vdU. (r>22Qw\P.k2^٫}6p~f82%ȎSJV795d2<لbםnM$[]Wo W@ KGϮ Fj fy&fȗӴ~:;'CmWnxjIЫp"5cad# X\o )ښ!cMR̵jᾇc%5kO>0EhxPpORts \ͰN%:$ WIhPfI%r|.9w JN(mY,Bt$Zvщ%zrۮjXffͽrQ79 ]NiE+1˒F>F̓>dJΪFf͚ wu^j:$_$C&/v?s2V t$NiшܧTbg.pSY=-Iq2WLf) ܣYJk%|x3@%P%m@Iշ^m)-zZzPl@5Drn+:Q@Sjj-%G 耒|@rJ?|C^mr;W'i.r{*?j}a%D`P>&peᅣx}wi>pdx?[rΜգXn\c&@{> . )[VSyz ٜvҋ0|#)iț}chIL >ۃP 9By\rٯ*Io` iIp=-Ǜ2 veC U-DWONZuۨIJCeL55At?qjZa@߻{zD/xht6{$ŎL;Zjd?}EU/[qzݨ%> >j,/i}i&7}ǜN 5Nu&>VCb Jeƣfg4 K3MTuJ|giiT= j\kNVB]vʏTD{xӀL*rEq=sQ~rHkS0D4GY{~IcSC$wX=aAdy@* ɈT'K 5]j@^)YsWoJj2)1Y+]vr\);ۏ6SǠ?9^yo+OczSJ/E+J܄c 'PiWSl^4vަ ǚʓ-Y!Jkza0AVC^XRoN `}-=ҩ_t0 :/Yd֙4:ӆ]e{!s?v%姜SgS}'%x;>QhG=$qEũ"ߔۉ3W-2,F):W=aT]:X $KYS#HWA:Y6&wgE%0"㺪[?<@MX'ppJ}-xV4/?͎0"61.Dι8MZ] pQO鼞wt~T~ wLã L|E9 Nݪ2 $/W^_/UGԇW6ukC9eԁ6]9(8qd9h={9EZURv7uDsP0x- 7"֫ui#`);4=k!7eCN@3cF:Y e!ݧәGm(fL;AFo.VEp%+/PzAFS[g0GN5N5'& ء@uSo&8=X|Vſ ҈|Ƭ? ֮QlYpt<6)jOP1@_q-\ )I&lH-1l.kLw]f>#dZIfZd`|;y4d2 X(ͣQt~ٞ>"1Y BCx l1Rƕ B=o#|%ΚY6@XA460u`Axqd;ݻ db\#YV!r e/563 4|V ҖuAFMFJi^ޖN(C\-{4b)e?d8#o?h֋4Xв}*?j^V;ڡ\}a'4߹DGx%5Vwor 0HK5_N숤WT %uo87-rh NYDB~q﬉?C7>Si !,+; ?r] 01 џ>245##a0okO G Ig ?3 U$d۩TT!rQ g2 N¾G.2~+6]V]$\>s0u9qjw쀚e4>DTϼ<18u+5-I1#I#Jʞ({~v;'a~H!PL";wV-yKBRx;J}OkB 1dpm\/UIeIFf1 RzIn+W.U~T <ٹRj'>8J푝 6