f0422d53c5c8ddd63cb663f80ed5e648b5ab8f2c
[deb_dpdk.git] / drivers / net / sfc / base / efx_intr.c
1 /*
2  * Copyright (c) 2007-2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30
31 #include "efx.h"
32 #include "efx_impl.h"
33
34
35 #if EFSYS_OPT_SIENA
36
37 static  __checkReturn   efx_rc_t
38 siena_intr_init(
39         __in            efx_nic_t *enp,
40         __in            efx_intr_type_t type,
41         __in            efsys_mem_t *esmp);
42
43 static                  void
44 siena_intr_enable(
45         __in            efx_nic_t *enp);
46
47 static                  void
48 siena_intr_disable(
49         __in            efx_nic_t *enp);
50
51 static                  void
52 siena_intr_disable_unlocked(
53         __in            efx_nic_t *enp);
54
55 static  __checkReturn   efx_rc_t
56 siena_intr_trigger(
57         __in            efx_nic_t *enp,
58         __in            unsigned int level);
59
60 static                  void
61 siena_intr_fini(
62         __in            efx_nic_t *enp);
63
64 static                  void
65 siena_intr_status_line(
66         __in            efx_nic_t *enp,
67         __out           boolean_t *fatalp,
68         __out           uint32_t *qmaskp);
69
70 static                  void
71 siena_intr_status_message(
72         __in            efx_nic_t *enp,
73         __in            unsigned int message,
74         __out           boolean_t *fatalp);
75
76 static                  void
77 siena_intr_fatal(
78         __in            efx_nic_t *enp);
79
80 static  __checkReturn   boolean_t
81 siena_intr_check_fatal(
82         __in            efx_nic_t *enp);
83
84
85 #endif /* EFSYS_OPT_SIENA */
86
87
88 #if EFSYS_OPT_SIENA
89 static const efx_intr_ops_t     __efx_intr_siena_ops = {
90         siena_intr_init,                /* eio_init */
91         siena_intr_enable,              /* eio_enable */
92         siena_intr_disable,             /* eio_disable */
93         siena_intr_disable_unlocked,    /* eio_disable_unlocked */
94         siena_intr_trigger,             /* eio_trigger */
95         siena_intr_status_line,         /* eio_status_line */
96         siena_intr_status_message,      /* eio_status_message */
97         siena_intr_fatal,               /* eio_fatal */
98         siena_intr_fini,                /* eio_fini */
99 };
100 #endif  /* EFSYS_OPT_SIENA */
101
102 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
103 static const efx_intr_ops_t     __efx_intr_ef10_ops = {
104         ef10_intr_init,                 /* eio_init */
105         ef10_intr_enable,               /* eio_enable */
106         ef10_intr_disable,              /* eio_disable */
107         ef10_intr_disable_unlocked,     /* eio_disable_unlocked */
108         ef10_intr_trigger,              /* eio_trigger */
109         ef10_intr_status_line,          /* eio_status_line */
110         ef10_intr_status_message,       /* eio_status_message */
111         ef10_intr_fatal,                /* eio_fatal */
112         ef10_intr_fini,                 /* eio_fini */
113 };
114 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
115
116         __checkReturn   efx_rc_t
117 efx_intr_init(
118         __in            efx_nic_t *enp,
119         __in            efx_intr_type_t type,
120         __in            efsys_mem_t *esmp)
121 {
122         efx_intr_t *eip = &(enp->en_intr);
123         const efx_intr_ops_t *eiop;
124         efx_rc_t rc;
125
126         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
127         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
128
129         if (enp->en_mod_flags & EFX_MOD_INTR) {
130                 rc = EINVAL;
131                 goto fail1;
132         }
133
134         eip->ei_esmp = esmp;
135         eip->ei_type = type;
136         eip->ei_level = 0;
137
138         enp->en_mod_flags |= EFX_MOD_INTR;
139
140         switch (enp->en_family) {
141 #if EFSYS_OPT_SIENA
142         case EFX_FAMILY_SIENA:
143                 eiop = &__efx_intr_siena_ops;
144                 break;
145 #endif  /* EFSYS_OPT_SIENA */
146
147 #if EFSYS_OPT_HUNTINGTON
148         case EFX_FAMILY_HUNTINGTON:
149                 eiop = &__efx_intr_ef10_ops;
150                 break;
151 #endif  /* EFSYS_OPT_HUNTINGTON */
152
153 #if EFSYS_OPT_MEDFORD
154         case EFX_FAMILY_MEDFORD:
155                 eiop = &__efx_intr_ef10_ops;
156                 break;
157 #endif  /* EFSYS_OPT_MEDFORD */
158
159         default:
160                 EFSYS_ASSERT(B_FALSE);
161                 rc = ENOTSUP;
162                 goto fail2;
163         }
164
165         if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
166                 goto fail3;
167
168         eip->ei_eiop = eiop;
169
170         return (0);
171
172 fail3:
173         EFSYS_PROBE(fail3);
174 fail2:
175         EFSYS_PROBE(fail2);
176 fail1:
177         EFSYS_PROBE1(fail1, efx_rc_t, rc);
178
179         return (rc);
180 }
181
182                 void
183 efx_intr_fini(
184         __in    efx_nic_t *enp)
185 {
186         efx_intr_t *eip = &(enp->en_intr);
187         const efx_intr_ops_t *eiop = eip->ei_eiop;
188
189         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
190         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
191         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
192
193         eiop->eio_fini(enp);
194
195         enp->en_mod_flags &= ~EFX_MOD_INTR;
196 }
197
198                         void
199 efx_intr_enable(
200         __in            efx_nic_t *enp)
201 {
202         efx_intr_t *eip = &(enp->en_intr);
203         const efx_intr_ops_t *eiop = eip->ei_eiop;
204
205         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
206         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
207
208         eiop->eio_enable(enp);
209 }
210
211                         void
212 efx_intr_disable(
213         __in            efx_nic_t *enp)
214 {
215         efx_intr_t *eip = &(enp->en_intr);
216         const efx_intr_ops_t *eiop = eip->ei_eiop;
217
218         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
219         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
220
221         eiop->eio_disable(enp);
222 }
223
224                         void
225 efx_intr_disable_unlocked(
226         __in            efx_nic_t *enp)
227 {
228         efx_intr_t *eip = &(enp->en_intr);
229         const efx_intr_ops_t *eiop = eip->ei_eiop;
230
231         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
232         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
233
234         eiop->eio_disable_unlocked(enp);
235 }
236
237
238         __checkReturn   efx_rc_t
239 efx_intr_trigger(
240         __in            efx_nic_t *enp,
241         __in            unsigned int level)
242 {
243         efx_intr_t *eip = &(enp->en_intr);
244         const efx_intr_ops_t *eiop = eip->ei_eiop;
245
246         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
247         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
248
249         return (eiop->eio_trigger(enp, level));
250 }
251
252                         void
253 efx_intr_status_line(
254         __in            efx_nic_t *enp,
255         __out           boolean_t *fatalp,
256         __out           uint32_t *qmaskp)
257 {
258         efx_intr_t *eip = &(enp->en_intr);
259         const efx_intr_ops_t *eiop = eip->ei_eiop;
260
261         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
262         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
263
264         eiop->eio_status_line(enp, fatalp, qmaskp);
265 }
266
267                         void
268 efx_intr_status_message(
269         __in            efx_nic_t *enp,
270         __in            unsigned int message,
271         __out           boolean_t *fatalp)
272 {
273         efx_intr_t *eip = &(enp->en_intr);
274         const efx_intr_ops_t *eiop = eip->ei_eiop;
275
276         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
277         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
278
279         eiop->eio_status_message(enp, message, fatalp);
280 }
281
282                 void
283 efx_intr_fatal(
284         __in    efx_nic_t *enp)
285 {
286         efx_intr_t *eip = &(enp->en_intr);
287         const efx_intr_ops_t *eiop = eip->ei_eiop;
288
289         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
290         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
291
292         eiop->eio_fatal(enp);
293 }
294
295
296 /* ************************************************************************* */
297 /* ************************************************************************* */
298 /* ************************************************************************* */
299
300 #if EFSYS_OPT_SIENA
301
302 static  __checkReturn   efx_rc_t
303 siena_intr_init(
304         __in            efx_nic_t *enp,
305         __in            efx_intr_type_t type,
306         __in            efsys_mem_t *esmp)
307 {
308         efx_intr_t *eip = &(enp->en_intr);
309         efx_oword_t oword;
310
311         /*
312          * bug17213 workaround.
313          *
314          * Under legacy interrupts, don't share a level between fatal
315          * interrupts and event queue interrupts. Under MSI-X, they
316          * must share, or we won't get an interrupt.
317          */
318         if (enp->en_family == EFX_FAMILY_SIENA &&
319             eip->ei_type == EFX_INTR_LINE)
320                 eip->ei_level = 0x1f;
321         else
322                 eip->ei_level = 0;
323
324         /* Enable all the genuinely fatal interrupts */
325         EFX_SET_OWORD(oword);
326         EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0);
327         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0);
328         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0);
329         if (enp->en_family >= EFX_FAMILY_SIENA)
330                 EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0);
331         EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword);
332
333         /* Set up the interrupt address register */
334         EFX_POPULATE_OWORD_3(oword,
335             FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0,
336             FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
337             FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32);
338         EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
339
340         return (0);
341 }
342
343 static                  void
344 siena_intr_enable(
345         __in            efx_nic_t *enp)
346 {
347         efx_intr_t *eip = &(enp->en_intr);
348         efx_oword_t oword;
349
350         EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
351
352         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
353         EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1);
354         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
355 }
356
357 static                  void
358 siena_intr_disable(
359         __in            efx_nic_t *enp)
360 {
361         efx_oword_t oword;
362
363         EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
364         EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
365         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
366
367         EFSYS_SPIN(10);
368 }
369
370 static                  void
371 siena_intr_disable_unlocked(
372         __in            efx_nic_t *enp)
373 {
374         efx_oword_t oword;
375
376         EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
377                         &oword, B_FALSE);
378         EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
379         EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
380             &oword, B_FALSE);
381 }
382
383 static  __checkReturn   efx_rc_t
384 siena_intr_trigger(
385         __in            efx_nic_t *enp,
386         __in            unsigned int level)
387 {
388         efx_intr_t *eip = &(enp->en_intr);
389         efx_oword_t oword;
390         unsigned int count;
391         uint32_t sel;
392         efx_rc_t rc;
393
394         /* bug16757: No event queues can be initialized */
395         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
396
397         if (level >= EFX_NINTR_SIENA) {
398                 rc = EINVAL;
399                 goto fail1;
400         }
401
402         if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
403                 return (ENOTSUP); /* avoid EFSYS_PROBE() */
404
405         sel = level;
406
407         /* Trigger a test interrupt */
408         EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
409         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
410         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
411         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
412
413         /*
414          * Wait up to 100ms for the interrupt to be raised before restoring
415          * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
416          * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
417          */
418         count = 0;
419         do {
420                 EFSYS_SPIN(100);        /* 100us */
421
422                 EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
423         } while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);
424
425         EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
426         EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
427
428         return (0);
429
430 fail1:
431         EFSYS_PROBE1(fail1, efx_rc_t, rc);
432
433         return (rc);
434 }
435
436 static  __checkReturn   boolean_t
437 siena_intr_check_fatal(
438         __in            efx_nic_t *enp)
439 {
440         efx_intr_t *eip = &(enp->en_intr);
441         efsys_mem_t *esmp = eip->ei_esmp;
442         efx_oword_t oword;
443
444         /* Read the syndrome */
445         EFSYS_MEM_READO(esmp, 0, &oword);
446
447         if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
448                 EFSYS_PROBE(fatal);
449
450                 /* Clear the fatal interrupt condition */
451                 EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0);
452                 EFSYS_MEM_WRITEO(esmp, 0, &oword);
453
454                 return (B_TRUE);
455         }
456
457         return (B_FALSE);
458 }
459
460 static                  void
461 siena_intr_status_line(
462         __in            efx_nic_t *enp,
463         __out           boolean_t *fatalp,
464         __out           uint32_t *qmaskp)
465 {
466         efx_intr_t *eip = &(enp->en_intr);
467         efx_dword_t dword;
468
469         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
470         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
471
472         /*
473          * Read the queue mask and implicitly acknowledge the
474          * interrupt.
475          */
476         EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
477         *qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
478
479         EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
480
481         if (*qmaskp & (1U << eip->ei_level))
482                 *fatalp = siena_intr_check_fatal(enp);
483         else
484                 *fatalp = B_FALSE;
485 }
486
487 static                  void
488 siena_intr_status_message(
489         __in            efx_nic_t *enp,
490         __in            unsigned int message,
491         __out           boolean_t *fatalp)
492 {
493         efx_intr_t *eip = &(enp->en_intr);
494
495         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
496         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
497
498         if (message == eip->ei_level)
499                 *fatalp = siena_intr_check_fatal(enp);
500         else
501                 *fatalp = B_FALSE;
502 }
503
504
505 static          void
506 siena_intr_fatal(
507         __in    efx_nic_t *enp)
508 {
509 #if EFSYS_OPT_DECODE_INTR_FATAL
510         efx_oword_t fatal;
511         efx_oword_t mem_per;
512
513         EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
514         EFX_ZERO_OWORD(mem_per);
515
516         if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 ||
517             EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
518                 EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per);
519
520         if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0)
521                 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0);
522
523         if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0)
524                 EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0);
525
526         if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
527                 EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR,
528                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
529                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
530
531         if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0)
532                 EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0);
533
534         if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0)
535                 EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0);
536
537         if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0)
538                 EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0);
539
540         if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0)
541                 EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0);
542
543         if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0)
544                 EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0);
545
546         if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0)
547                 EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0);
548
549         if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0)
550                 EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0);
551
552         if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0)
553                 EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR,
554                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
555                     EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
556 #else
557         EFSYS_ASSERT(0);
558 #endif
559 }
560
561 static          void
562 siena_intr_fini(
563         __in    efx_nic_t *enp)
564 {
565         efx_oword_t oword;
566
567         /* Clear the interrupt address register */
568         EFX_ZERO_OWORD(oword);
569         EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
570 }
571
572 #endif /* EFSYS_OPT_SIENA */