]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ocs_fc/sli4.c
Mana: move mana polling from EQ to CQ
[FreeBSD/FreeBSD.git] / sys / dev / ocs_fc / sli4.c
1 /*-
2  * Copyright (c) 2017 Broadcom. All rights reserved.
3  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
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  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33
34 /**
35  * @defgroup sli SLI-4 Base APIs
36  */
37
38 /**
39  * @file
40  * All common (i.e. transport-independent) SLI-4 functions are implemented
41  * in this file.
42  */
43
44 #include "sli4.h"
45
46 #if defined(OCS_INCLUDE_DEBUG)
47 #include "ocs_utils.h"
48 #endif
49
50 #define SLI4_BMBX_DELAY_US 1000 /* 1 ms */
51 #define SLI4_INIT_PORT_DELAY_US 10000 /* 10 ms */
52
53 static int32_t sli_fw_init(sli4_t *);
54 static int32_t sli_fw_term(sli4_t *);
55 static int32_t sli_sliport_control(sli4_t *sli4, uint32_t endian);
56 static int32_t sli_cmd_fw_deinitialize(sli4_t *, void *, size_t);
57 static int32_t sli_cmd_fw_initialize(sli4_t *, void *, size_t);
58 static int32_t sli_queue_doorbell(sli4_t *, sli4_queue_t *);
59 static uint8_t sli_queue_entry_is_valid(sli4_queue_t *, uint8_t *, uint8_t);
60
61 const uint8_t sli4_fw_initialize[] = {
62         0xff, 0x12, 0x34, 0xff,
63         0xff, 0x56, 0x78, 0xff,
64 };
65
66 const uint8_t sli4_fw_deinitialize[] = {
67         0xff, 0xaa, 0xbb, 0xff,
68         0xff, 0xcc, 0xdd, 0xff,
69 };
70
71 typedef struct {
72         uint32_t rev_id;
73         uint32_t family;        /* generation */
74         sli4_asic_type_e type;
75         sli4_asic_rev_e rev;
76 } sli4_asic_entry_t;
77
78 sli4_asic_entry_t sli4_asic_table[] = {
79         {       0x00,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_A0},
80         {       0x01,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_A1},
81         {       0x02,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_A2},
82         {       0x00,   4,      SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0},
83         {       0x00,   2,      SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0},
84         {       0x10,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_B0},
85         {       0x10,   0x04,   SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_B0},
86         {       0x11,   0x04,   SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_B1},
87         {       0x0,    0x0a,   SLI4_ASIC_TYPE_LANCER,  SLI4_ASIC_REV_A0},
88         {       0x10,   0x0b,   SLI4_ASIC_TYPE_LANCER,  SLI4_ASIC_REV_B0},
89         {       0x30,   0x0b,   SLI4_ASIC_TYPE_LANCER,  SLI4_ASIC_REV_D0},
90         {       0x3,    0x0b,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3},
91         {       0x0,    0x0c,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A0},
92         {       0x1,    0x0c,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A1},
93         {       0x3,    0x0c,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3},
94         {       0x1,    0x0d,   SLI4_ASIC_TYPE_LANCERG7,SLI4_ASIC_REV_A1}, 
95         {       0x10,   0x0d,   SLI4_ASIC_TYPE_LANCERG7,SLI4_ASIC_REV_B0}, 
96         {       0x00,   0x05,   SLI4_ASIC_TYPE_CORSAIR, SLI4_ASIC_REV_A0},
97 };
98
99 /*
100  * @brief Convert queue type enum (SLI_QTYPE_*) into a string.
101  */
102 const char *SLI_QNAME[] = {
103         "Event Queue",
104         "Completion Queue",
105         "Mailbox Queue",
106         "Work Queue",
107         "Receive Queue",
108         "Undefined"
109 };
110
111 /**
112  * @brief Define the mapping of registers to their BAR and offset.
113  *
114  * @par Description
115  * Although SLI-4 specification defines a common set of registers, their locations
116  * (both BAR and offset) depend on the interface type. This array maps a register
117  * enum to an array of BAR/offset pairs indexed by the interface type. For
118  * example, to access the bootstrap mailbox register on an interface type 0
119  * device, code can refer to the offset using regmap[SLI4_REG_BMBX][0].offset.
120  *
121  * @b Note: A value of UINT32_MAX for either the register set (rset) or offset (off)
122  * indicates an invalid mapping.
123  */
124 const sli4_reg_t regmap[SLI4_REG_MAX][SLI4_MAX_IF_TYPES] = {
125         /* SLI4_REG_BMBX */
126         {
127                 { 2, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG },
128                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX } , { 0, SLI4_BMBX_REG },
129         },
130         /* SLI4_REG_EQCQ_DOORBELL */
131         {
132                 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
133                 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
134                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
135                 { 1, SLI4_IF6_EQ_DOORBELL_REG }
136         },
137         // SLI4_REG_CQ_DOORBELL
138         {
139                 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
140                 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
141                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
142                 { 1, SLI4_IF6_CQ_DOORBELL_REG }
143         },
144         /* SLI4_REG_FCOE_RQ_DOORBELL */
145         {
146                 { 2, SLI4_RQ_DOORBELL_REG }, { 0, SLI4_RQ_DOORBELL_REG },
147                 { 0, SLI4_RQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
148                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
149                 { 1, SLI4_IF6_RQ_DOORBELL_REG }
150         },
151         /* SLI4_REG_IO_WQ_DOORBELL */
152         {
153                 { 2, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG },
154                 { 0, SLI4_IO_WQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
155                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
156                 { 1, SLI4_IF6_WQ_DOORBELL_REG }
157         },
158         /* SLI4_REG_MQ_DOORBELL */
159         {
160                 { 2, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
161                 { 0, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
162                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
163                 { 1, SLI4_IF6_MQ_DOORBELL_REG }
164         },
165         /* SLI4_REG_PHYSDEV_CONTROL */
166         {
167                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
168                 { 0, SLI4_PHSDEV_CONTROL_REG_236 }, { 0, SLI4_PHSDEV_CONTROL_REG_236 },
169                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
170                 { 0, SLI4_PHSDEV_CONTROL_REG_236 }
171         },
172         /* SLI4_REG_SLIPORT_CONTROL */
173         {
174                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
175                 { 0, SLI4_SLIPORT_CONTROL_REG }, { UINT32_MAX, UINT32_MAX },
176                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
177                 { 0, SLI4_SLIPORT_CONTROL_REG },
178         },
179         /* SLI4_REG_SLIPORT_ERROR1 */
180         {
181                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
182                 { 0, SLI4_SLIPORT_ERROR1 }, { UINT32_MAX, UINT32_MAX },
183                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
184                 { 0, SLI4_SLIPORT_ERROR1 },
185         },
186         /* SLI4_REG_SLIPORT_ERROR2 */
187         {
188                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
189                 { 0, SLI4_SLIPORT_ERROR2 }, { UINT32_MAX, UINT32_MAX },
190                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
191                 { 0, SLI4_SLIPORT_ERROR2 },
192         },
193         /* SLI4_REG_SLIPORT_SEMAPHORE */
194         {
195                 { 1, SLI4_PORT_SEMAPHORE_REG_0 },  { 0, SLI4_PORT_SEMAPHORE_REG_1 },
196                 { 0, SLI4_PORT_SEMAPHORE_REG_236 }, { 0, SLI4_PORT_SEMAPHORE_REG_236 },
197                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 
198                 { 0, SLI4_PORT_SEMAPHORE_REG_236 },
199         },
200         /* SLI4_REG_SLIPORT_STATUS */
201         {
202                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
203                 { 0, SLI4_PORT_STATUS_REG_236 }, { 0, SLI4_PORT_STATUS_REG_236 },
204                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
205                 { 0, SLI4_PORT_STATUS_REG_236 },
206         },
207         /* SLI4_REG_UERR_MASK_HI */
208         {
209                 { 0, SLI4_UERR_MASK_HIGH_REG }, { UINT32_MAX, UINT32_MAX },
210                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
211                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
212                 { UINT32_MAX, UINT32_MAX }
213         },
214         /* SLI4_REG_UERR_MASK_LO */
215         {
216                 { 0, SLI4_UERR_MASK_LOW_REG }, { UINT32_MAX, UINT32_MAX },
217                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
218                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
219                 { UINT32_MAX, UINT32_MAX }
220         },
221         /* SLI4_REG_UERR_STATUS_HI */
222         {
223                 { 0, SLI4_UERR_STATUS_HIGH_REG }, { UINT32_MAX, UINT32_MAX },
224                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
225                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
226                 { UINT32_MAX, UINT32_MAX }
227         },
228         /* SLI4_REG_UERR_STATUS_LO */
229         {
230                 { 0, SLI4_UERR_STATUS_LOW_REG }, { UINT32_MAX, UINT32_MAX },
231                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
232                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
233                 { UINT32_MAX, UINT32_MAX }
234         },
235         /* SLI4_REG_SW_UE_CSR1 */
236         {
237                 { 1, SLI4_SW_UE_CSR1}, { UINT32_MAX, UINT32_MAX },
238                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
239                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
240                 { UINT32_MAX, UINT32_MAX }
241         },
242         /* SLI4_REG_SW_UE_CSR2 */
243         {
244                 { 1, SLI4_SW_UE_CSR2}, { UINT32_MAX, UINT32_MAX },
245                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
246                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
247                 { UINT32_MAX, UINT32_MAX }
248         },
249 };
250
251 /**
252  * @brief Read the given SLI register.
253  *
254  * @param sli Pointer to the SLI context.
255  * @param reg Register name enum.
256  *
257  * @return Returns the register value.
258  */
259 uint32_t
260 sli_reg_read(sli4_t *sli, sli4_regname_e reg)
261 {
262         const sli4_reg_t        *r = &(regmap[reg][sli->if_type]);
263
264         if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
265                 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
266                 return UINT32_MAX;
267         }
268
269         return ocs_reg_read32(sli->os, r->rset, r->off);
270 }
271
272 /**
273  * @brief Write the value to the given SLI register.
274  *
275  * @param sli Pointer to the SLI context.
276  * @param reg Register name enum.
277  * @param val Value to write.
278  *
279  * @return None.
280  */
281 void
282 sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
283 {
284         const sli4_reg_t        *r = &(regmap[reg][sli->if_type]);
285
286         if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
287                 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
288                 return;
289         }
290
291         ocs_reg_write32(sli->os, r->rset, r->off, val);
292 }
293
294 /**
295  * @brief Check if the SLI_INTF register is valid.
296  *
297  * @param val 32-bit SLI_INTF register value.
298  *
299  * @return Returns 0 on success, or a non-zero value on failure.
300  */
301 static uint8_t
302 sli_intf_valid_check(uint32_t val)
303 {
304         return ((val >> SLI4_INTF_VALID_SHIFT) & SLI4_INTF_VALID_MASK) != SLI4_INTF_VALID;
305 }
306
307 /**
308  * @brief Retrieve the SLI revision level.
309  *
310  * @param val 32-bit SLI_INTF register value.
311  *
312  * @return Returns the SLI revision level.
313  */
314 static uint8_t
315 sli_intf_sli_revision(uint32_t val)
316 {
317         return ((val >> SLI4_INTF_SLI_REVISION_SHIFT) & SLI4_INTF_SLI_REVISION_MASK);
318 }
319
320 static uint8_t
321 sli_intf_sli_family(uint32_t val)
322 {
323         return ((val >> SLI4_INTF_SLI_FAMILY_SHIFT) & SLI4_INTF_SLI_FAMILY_MASK);
324 }
325
326 /**
327  * @brief Retrieve the SLI interface type.
328  *
329  * @param val 32-bit SLI_INTF register value.
330  *
331  * @return Returns the SLI interface type.
332  */
333 static uint8_t
334 sli_intf_if_type(uint32_t val)
335 {
336         return ((val >> SLI4_INTF_IF_TYPE_SHIFT) & SLI4_INTF_IF_TYPE_MASK);
337 }
338
339 /**
340  * @brief Retrieve PCI revision ID.
341  *
342  * @param val 32-bit PCI CLASS_REVISION register value.
343  *
344  * @return Returns the PCI revision ID.
345  */
346 static uint8_t
347 sli_pci_rev_id(uint32_t val)
348 {
349         return ((val >> SLI4_PCI_REV_ID_SHIFT) & SLI4_PCI_REV_ID_MASK);
350 }
351
352 /**
353  * @brief retrieve SLI ASIC generation
354  *
355  * @param val 32-bit SLI_ASIC_ID register value
356  *
357  * @return SLI ASIC generation
358  */
359 static uint8_t
360 sli_asic_gen(uint32_t val)
361 {
362         return ((val >> SLI4_ASIC_GEN_SHIFT) & SLI4_ASIC_GEN_MASK);
363 }
364
365 /**
366  * @brief Wait for the bootstrap mailbox to report "ready".
367  *
368  * @param sli4 SLI context pointer.
369  * @param msec Number of milliseconds to wait.
370  *
371  * @return Returns 0 if BMBX is ready, or non-zero otherwise (i.e. time out occurred).
372  */
373 static int32_t
374 sli_bmbx_wait(sli4_t *sli4, uint32_t msec)
375 {
376         uint32_t        val = 0;
377
378         do {
379                 ocs_udelay(SLI4_BMBX_DELAY_US);
380                 val = sli_reg_read(sli4, SLI4_REG_BMBX);
381                 msec--;
382         } while(msec && !(val & SLI4_BMBX_RDY));
383
384         return(!(val & SLI4_BMBX_RDY));
385 }
386
387 /**
388  * @brief Write bootstrap mailbox.
389  *
390  * @param sli4 SLI context pointer.
391  *
392  * @return Returns 0 if command succeeded, or non-zero otherwise.
393  */
394 static int32_t
395 sli_bmbx_write(sli4_t *sli4)
396 {
397         uint32_t        val = 0;
398
399         /* write buffer location to bootstrap mailbox register */
400         ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_PREWRITE);
401         val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys);
402         sli_reg_write(sli4, SLI4_REG_BMBX, val);
403
404         if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
405                 ocs_log_crit(sli4->os, "BMBX WRITE_HI failed\n");
406                 return -1;
407         }
408         val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys);
409         sli_reg_write(sli4, SLI4_REG_BMBX, val);
410
411         /* wait for SLI Port to set ready bit */
412         return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC/*XXX*/);
413 }
414
415 #if defined(OCS_INCLUDE_DEBUG)
416 /**
417  * @ingroup sli
418  * @brief Dump BMBX mailbox command.
419  *
420  * @par Description
421  * Convenience function for dumping BMBX mailbox commands. Takes
422  * into account which mailbox command is given since SLI_CONFIG
423  * commands are special.
424  *
425  * @b Note: This function takes advantage of
426  * the one-command-at-a-time nature of the BMBX to be able to
427  * display non-embedded SLI_CONFIG commands. This will not work
428  * for mailbox commands on the MQ. Luckily, all current non-emb
429  * mailbox commands go through the BMBX.
430  *
431  * @param sli4 SLI context pointer.
432  * @param mbx Pointer to mailbox command to dump.
433  * @param prefix Prefix for dump label.
434  *
435  * @return None.
436  */
437 static void
438 sli_dump_bmbx_command(sli4_t *sli4, void *mbx, const char *prefix)
439 {
440         uint32_t size = 0;
441         char label[64];
442         uint32_t i;
443         /* Mailbox diagnostic logging */
444         sli4_mbox_command_header_t *hdr = (sli4_mbox_command_header_t *)mbx;
445
446         if (!ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP)) {
447                 return;
448         }
449
450         if (hdr->command == SLI4_MBOX_COMMAND_SLI_CONFIG) {
451                 sli4_cmd_sli_config_t *sli_config = (sli4_cmd_sli_config_t *)hdr;
452                 sli4_req_hdr_t  *sli_config_hdr;
453                 if (sli_config->emb) {
454                         ocs_snprintf(label, sizeof(label), "%s (emb)", prefix);
455
456                         /*  if embedded, dump entire command */
457                         sli_config_hdr = (sli4_req_hdr_t *)sli_config->payload.embed;
458                         size = sizeof(*sli_config) - sizeof(sli_config->payload) +
459                                 sli_config_hdr->request_length + (4*sizeof(uint32_t));
460                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
461                                    (uint8_t *)sli4->bmbx.virt, size);
462                 } else {
463                         sli4_sli_config_pmd_t *pmd;
464                         ocs_snprintf(label, sizeof(label), "%s (non-emb hdr)", prefix);
465
466                         /* if non-embedded, break up into two parts: SLI_CONFIG hdr
467                            and the payload(s) */
468                         size = sizeof(*sli_config) - sizeof(sli_config->payload) + (12 * sli_config->pmd_count);
469                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
470                                    (uint8_t *)sli4->bmbx.virt, size);
471
472                         /* as sanity check, make sure first PMD matches what was saved */
473                         pmd = &sli_config->payload.mem;
474                         if ((pmd->address_high == ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys)) &&
475                             (pmd->address_low == ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys))) {
476                                 for (i = 0; i < sli_config->pmd_count; i++, pmd++) {
477                                         sli_config_hdr = sli4->bmbx_non_emb_pmd->virt;
478                                         ocs_snprintf(label, sizeof(label), "%s (non-emb pay[%d])",
479                                                      prefix, i);
480                                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
481                                                    (uint8_t *)sli4->bmbx_non_emb_pmd->virt,
482                                                    sli_config_hdr->request_length + (4*sizeof(uint32_t)));
483                                 }
484                         } else {
485                                 ocs_log_debug(sli4->os, "pmd addr does not match pmd:%x %x (%x %x)\n",
486                                         pmd->address_high, pmd->address_low,
487                                         ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys),
488                                         ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys));
489                         }
490                 }
491         } else {
492                 /* not an SLI_CONFIG command, just display first 64 bytes, like we do
493                    for MQEs */
494                 size = 64;
495                 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, prefix,
496                            (uint8_t *)mbx, size);
497         }
498 }
499 #endif
500
501 /**
502  * @ingroup sli
503  * @brief Submit a command to the bootstrap mailbox and check the status.
504  *
505  * @param sli4 SLI context pointer.
506  *
507  * @return Returns 0 on success, or a non-zero value on failure.
508  */
509 int32_t
510 sli_bmbx_command(sli4_t *sli4)
511 {
512         void *cqe = (uint8_t *)sli4->bmbx.virt + SLI4_BMBX_SIZE;
513
514 #if defined(OCS_INCLUDE_DEBUG)
515         sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmd");
516 #endif
517
518         if (sli_fw_error_status(sli4) > 0) {
519                 ocs_log_crit(sli4->os, "Chip is in an error state - Mailbox "
520                         "command rejected status=%#x error1=%#x error2=%#x\n",
521                         sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
522                         sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
523                         sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
524                 return -1;
525         }
526
527         if (sli_bmbx_write(sli4)) {
528                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail phys=%p reg=%#x\n",
529                         (void*)sli4->bmbx.phys,
530                         sli_reg_read(sli4, SLI4_REG_BMBX));
531                 return -1;
532         }
533
534         /* check completion queue entry status */
535         ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_POSTREAD);
536         if (((sli4_mcqe_t *)cqe)->val) {
537 #if defined(OCS_INCLUDE_DEBUG)
538                 sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmpl");
539         ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "bmbx cqe", cqe, sizeof(sli4_mcqe_t));
540 #endif
541                 return sli_cqe_mq(cqe);
542         } else {
543                 ocs_log_err(sli4->os, "invalid or wrong type\n");
544                 return -1;
545         }
546 }
547
548 /****************************************************************************
549  * Messages
550  */
551
552 /**
553  * @ingroup sli
554  * @brief Write a CONFIG_LINK command to the provided buffer.
555  *
556  * @param sli4 SLI context pointer.
557  * @param buf Virtual pointer to the destination buffer.
558  * @param size Buffer size, in bytes.
559  *
560  * @return Returns the number of bytes written.
561  */
562 int32_t
563 sli_cmd_config_link(sli4_t *sli4, void *buf, size_t size)
564 {
565         sli4_cmd_config_link_t  *config_link = buf;
566
567         ocs_memset(buf, 0, size);
568
569         config_link->hdr.command = SLI4_MBOX_COMMAND_CONFIG_LINK;
570
571         /* Port interprets zero in a field as "use default value" */
572
573         return sizeof(sli4_cmd_config_link_t);
574 }
575
576 /**
577  * @ingroup sli
578  * @brief Write a DOWN_LINK command to the provided buffer.
579  *
580  * @param sli4 SLI context pointer.
581  * @param buf Virtual pointer to the destination buffer.
582  * @param size Buffer size, in bytes.
583  *
584  * @return Returns the number of bytes written.
585  */
586 int32_t
587 sli_cmd_down_link(sli4_t *sli4, void *buf, size_t size)
588 {
589         sli4_mbox_command_header_t      *hdr = buf;
590
591         ocs_memset(buf, 0, size);
592
593         hdr->command = SLI4_MBOX_COMMAND_DOWN_LINK;
594
595         /* Port interprets zero in a field as "use default value" */
596
597         return sizeof(sli4_mbox_command_header_t);
598 }
599
600 /**
601  * @ingroup sli
602  * @brief Write a DUMP Type 4 command to the provided buffer.
603  *
604  * @param sli4 SLI context pointer.
605  * @param buf Virtual pointer to the destination buffer.
606  * @param size Buffer size, in bytes.
607  * @param wki The well known item ID.
608  *
609  * @return Returns the number of bytes written.
610  */
611 int32_t
612 sli_cmd_dump_type4(sli4_t *sli4, void *buf, size_t size, uint16_t wki)
613 {
614         sli4_cmd_dump4_t        *cmd = buf;
615
616         ocs_memset(buf, 0, size);
617
618         cmd->hdr.command = SLI4_MBOX_COMMAND_DUMP;
619         cmd->type = 4;
620         cmd->wki_selection = wki;
621         return sizeof(sli4_cmd_dump4_t);
622 }
623
624 /**
625  * @ingroup sli
626  * @brief Write a COMMON_READ_TRANSCEIVER_DATA command.
627  *
628  * @param sli4 SLI context.
629  * @param buf Destination buffer for the command.
630  * @param size Buffer size, in bytes.
631  * @param page_num The page of SFP data to retrieve (0xa0 or 0xa2).
632  * @param dma DMA structure from which the data will be copied.
633  *
634  * @note This creates a Version 0 message.
635  *
636  * @return Returns the number of bytes written.
637  */
638 int32_t
639 sli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size, uint32_t page_num,
640                                      ocs_dma_t *dma)
641 {
642         sli4_req_common_read_transceiver_data_t *req = NULL;
643         uint32_t        sli_config_off = 0;
644         uint32_t        payload_size;
645
646         if (dma == NULL) {
647                 /* Payload length must accommodate both request and response */
648                 payload_size = max(sizeof(sli4_req_common_read_transceiver_data_t),
649                                    sizeof(sli4_res_common_read_transceiver_data_t));
650         } else {
651                 payload_size = dma->size;
652         }
653
654         if (sli4->port_type == SLI4_PORT_TYPE_FC) {
655                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, dma);
656         }
657
658         if (dma == NULL) {
659                 req = (sli4_req_common_read_transceiver_data_t *)((uint8_t *)buf + sli_config_off);
660         } else {
661                 req = (sli4_req_common_read_transceiver_data_t *)dma->virt;
662                 ocs_memset(req, 0, dma->size);
663         }
664
665         req->hdr.opcode = SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA;
666         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
667         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
668
669         req->page_number = page_num;
670         req->port = sli4->physical_port;
671
672         return(sli_config_off + sizeof(sli4_req_common_read_transceiver_data_t));
673 }
674
675 /**
676  * @ingroup sli
677  * @brief Write a READ_LINK_STAT command to the provided buffer.
678  *
679  * @param sli4 SLI context pointer.
680  * @param buf Virtual pointer to the destination buffer.
681  * @param size Buffer size, in bytes.
682  * @param req_ext_counters If TRUE, then the extended counters will be requested.
683  * @param clear_overflow_flags If TRUE, then overflow flags will be cleared.
684  * @param clear_all_counters If TRUE, the counters will be cleared.
685  *
686  * @return Returns the number of bytes written.
687  */
688 int32_t
689 sli_cmd_read_link_stats(sli4_t *sli4, void *buf, size_t size,
690                         uint8_t req_ext_counters,
691                         uint8_t clear_overflow_flags,
692                         uint8_t clear_all_counters)
693 {
694         sli4_cmd_read_link_stats_t      *cmd = buf;
695
696         ocs_memset(buf, 0, size);
697
698         cmd->hdr.command = SLI4_MBOX_COMMAND_READ_LNK_STAT;
699         cmd->rec = req_ext_counters;
700         cmd->clrc = clear_all_counters;
701         cmd->clof = clear_overflow_flags;
702         return sizeof(sli4_cmd_read_link_stats_t);
703 }
704
705 /**
706  * @ingroup sli
707  * @brief Write a READ_STATUS command to the provided buffer.
708  *
709  * @param sli4 SLI context pointer.
710  * @param buf Virtual pointer to the destination buffer.
711  * @param size Buffer size, in bytes.
712  * @param clear_counters If TRUE, the counters will be cleared.
713  *
714  * @return Returns the number of bytes written.
715  */
716 int32_t
717 sli_cmd_read_status(sli4_t *sli4, void *buf, size_t size,
718                         uint8_t clear_counters)
719 {
720         sli4_cmd_read_status_t  *cmd = buf;
721
722         ocs_memset(buf, 0, size);
723
724         cmd->hdr.command = SLI4_MBOX_COMMAND_READ_STATUS;
725         cmd->cc = clear_counters;
726         return sizeof(sli4_cmd_read_status_t);
727 }
728
729 /**
730  * @brief Write a FW_DEINITIALIZE command to the provided buffer.
731  *
732  * @param sli4 SLI context pointer.
733  * @param buf Virtual pointer to the destination buffer.
734  * @param size Buffer size, in bytes.
735  *
736  * @return Returns the number of bytes written.
737  */
738 static int32_t
739 sli_cmd_fw_deinitialize(sli4_t *sli4, void *buf, size_t size)
740 {
741
742         ocs_memset(buf, 0, size);
743         ocs_memcpy(buf, sli4_fw_deinitialize, sizeof(sli4_fw_deinitialize));
744
745         return sizeof(sli4_fw_deinitialize);
746 }
747
748 /**
749  * @brief Write a FW_INITIALIZE command to the provided buffer.
750  *
751  * @param sli4 SLI context pointer.
752  * @param buf Virtual pointer to the destination buffer.
753  * @param size Buffer size, in bytes.
754  *
755  * @return Returns the number of bytes written.
756  */
757 static int32_t
758 sli_cmd_fw_initialize(sli4_t *sli4, void *buf, size_t size)
759 {
760
761         ocs_memset(buf, 0, size);
762         ocs_memcpy(buf, sli4_fw_initialize, sizeof(sli4_fw_initialize));
763
764         return sizeof(sli4_fw_initialize);
765 }
766
767 /**
768  * @ingroup sli
769  * @brief Write an INIT_LINK command to the provided buffer.
770  *
771  * @param sli4 SLI context pointer.
772  * @param buf Virtual pointer to the destination buffer.
773  * @param size Buffer size, in bytes.
774  * @param speed Link speed.
775  * @param reset_alpa For native FC, this is the selective reset AL_PA
776  *
777  * @return Returns the number of bytes written.
778  */
779 int32_t
780 sli_cmd_init_link(sli4_t *sli4, void *buf, size_t size, uint32_t speed, uint8_t reset_alpa)
781 {
782         sli4_cmd_init_link_t    *init_link = buf;
783
784         ocs_memset(buf, 0, size);
785
786         init_link->hdr.command = SLI4_MBOX_COMMAND_INIT_LINK;
787
788         /* Most fields only have meaning for FC links */
789         if (sli4->config.topology != SLI4_READ_CFG_TOPO_FCOE) {
790                 init_link->selective_reset_al_pa = reset_alpa;
791                 init_link->link_flags.loopback = FALSE;
792
793                 init_link->link_speed_selection_code = speed;
794                 switch (speed) {
795                 case FC_LINK_SPEED_1G:
796                 case FC_LINK_SPEED_2G:
797                 case FC_LINK_SPEED_4G:
798                 case FC_LINK_SPEED_8G:
799                 case FC_LINK_SPEED_16G:
800                 case FC_LINK_SPEED_32G:
801                         init_link->link_flags.fixed_speed = TRUE;
802                         break;
803                 case FC_LINK_SPEED_10G:
804                         ocs_log_test(sli4->os, "unsupported FC speed %d\n", speed);
805                         return 0;
806                 }
807
808                 switch (sli4->config.topology) {
809                 case SLI4_READ_CFG_TOPO_FC:
810                         /* Attempt P2P but failover to FC-AL */
811                         init_link->link_flags.enable_topology_failover = TRUE;
812
813                         if (sli_get_asic_type(sli4) == SLI4_ASIC_TYPE_LANCER)
814                                 init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_FAIL_OVER;
815                         else
816                                 init_link->link_flags.topology = SLI4_INIT_LINK_F_P2P_FAIL_OVER;
817
818                         break;
819                 case SLI4_READ_CFG_TOPO_FC_AL:
820                         init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_ONLY;
821                         if ((init_link->link_speed_selection_code == FC_LINK_SPEED_16G) ||
822                             (init_link->link_speed_selection_code == FC_LINK_SPEED_32G)) {
823                                 ocs_log_test(sli4->os, "unsupported FC-AL speed %d\n", speed);
824                                 return 0;
825                         }
826                         break;
827                 case SLI4_READ_CFG_TOPO_FC_DA:
828                         init_link->link_flags.topology = FC_TOPOLOGY_P2P;
829                         break;
830                 default:
831                         ocs_log_test(sli4->os, "unsupported topology %#x\n", sli4->config.topology);
832                         return 0;
833                 }
834
835                 init_link->link_flags.unfair = FALSE;
836                 init_link->link_flags.skip_lirp_lilp = FALSE;
837                 init_link->link_flags.gen_loop_validity_check = FALSE;
838                 init_link->link_flags.skip_lisa = FALSE;
839                 init_link->link_flags.select_hightest_al_pa = FALSE;
840         }
841
842         return sizeof(sli4_cmd_init_link_t);
843 }
844
845 /**
846  * @ingroup sli
847  * @brief Write an INIT_VFI command to the provided buffer.
848  *
849  * @param sli4 SLI context pointer.
850  * @param buf Virtual pointer to the destination buffer.
851  * @param size Buffer size, in bytes.
852  * @param vfi VFI
853  * @param fcfi FCFI
854  * @param vpi VPI (Set to -1 if unused.)
855  *
856  * @return Returns the number of bytes written.
857  */
858 int32_t
859 sli_cmd_init_vfi(sli4_t *sli4, void *buf, size_t size, uint16_t vfi,
860                 uint16_t fcfi, uint16_t vpi)
861 {
862         sli4_cmd_init_vfi_t     *init_vfi = buf;
863
864         ocs_memset(buf, 0, size);
865
866         init_vfi->hdr.command = SLI4_MBOX_COMMAND_INIT_VFI;
867
868         init_vfi->vfi = vfi;
869         init_vfi->fcfi = fcfi;
870
871         /*
872          * If the VPI is valid, initialize it at the same time as
873          * the VFI
874          */
875         if (0xffff != vpi) {
876                 init_vfi->vp  = TRUE;
877                 init_vfi->vpi = vpi;
878         }
879
880         return sizeof(sli4_cmd_init_vfi_t);
881 }
882
883 /**
884  * @ingroup sli
885  * @brief Write an INIT_VPI command to the provided buffer.
886  *
887  * @param sli4 SLI context pointer.
888  * @param buf Virtual pointer to the destination buffer.
889  * @param size Buffer size, in bytes.
890  * @param vpi VPI allocated.
891  * @param vfi VFI associated with this VPI.
892  *
893  * @return Returns the number of bytes written.
894  */
895 int32_t
896 sli_cmd_init_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t vpi, uint16_t vfi)
897 {
898         sli4_cmd_init_vpi_t     *init_vpi = buf;
899
900         ocs_memset(buf, 0, size);
901
902         init_vpi->hdr.command = SLI4_MBOX_COMMAND_INIT_VPI;
903         init_vpi->vpi = vpi;
904         init_vpi->vfi = vfi;
905
906         return sizeof(sli4_cmd_init_vpi_t);
907 }
908
909 /**
910  * @ingroup sli
911  * @brief Write a POST_XRI command to the provided buffer.
912  *
913  * @param sli4 SLI context pointer.
914  * @param buf Virtual pointer to the destination buffer.
915  * @param size Buffer size, in bytes.
916  * @param xri_base Starting XRI value for range of XRI given to SLI Port.
917  * @param xri_count Number of XRIs provided to the SLI Port.
918  *
919  * @return Returns the number of bytes written.
920  */
921 int32_t
922 sli_cmd_post_xri(sli4_t *sli4, void *buf, size_t size,  uint16_t xri_base, uint16_t xri_count)
923 {
924         sli4_cmd_post_xri_t     *post_xri = buf;
925
926         ocs_memset(buf, 0, size);
927
928         post_xri->hdr.command = SLI4_MBOX_COMMAND_POST_XRI;
929         post_xri->xri_base = xri_base;
930         post_xri->xri_count = xri_count;
931
932         if (sli4->config.auto_xfer_rdy == 0) {
933                 post_xri->enx = TRUE;
934                 post_xri->val = TRUE;
935         }
936
937         return sizeof(sli4_cmd_post_xri_t);
938 }
939
940 /**
941  * @ingroup sli
942  * @brief Write a RELEASE_XRI command to the provided buffer.
943  *
944  * @param sli4 SLI context pointer.
945  * @param buf Virtual pointer to the destination buffer.
946  * @param size Buffer size, in bytes.
947  * @param num_xri The number of XRIs to be released.
948  *
949  * @return Returns the number of bytes written.
950  */
951 int32_t
952 sli_cmd_release_xri(sli4_t *sli4, void *buf, size_t size,  uint8_t num_xri)
953 {
954         sli4_cmd_release_xri_t  *release_xri = buf;
955
956         ocs_memset(buf, 0, size);
957
958         release_xri->hdr.command = SLI4_MBOX_COMMAND_RELEASE_XRI;
959         release_xri->xri_count = num_xri;
960
961         return sizeof(sli4_cmd_release_xri_t);
962 }
963
964 /**
965  * @brief Write a READ_CONFIG command to the provided buffer.
966  *
967  * @param sli4 SLI context pointer.
968  * @param buf Virtual pointer to the destination buffer.
969  * @param size Buffer size, in bytes
970  *
971  * @return Returns the number of bytes written.
972  */
973 static int32_t
974 sli_cmd_read_config(sli4_t *sli4, void *buf, size_t size)
975 {
976         sli4_cmd_read_config_t  *read_config = buf;
977
978         ocs_memset(buf, 0, size);
979
980         read_config->hdr.command = SLI4_MBOX_COMMAND_READ_CONFIG;
981
982         return sizeof(sli4_cmd_read_config_t);
983 }
984
985 /**
986  * @brief Write a READ_NVPARMS command to the provided buffer.
987  *
988  * @param sli4 SLI context pointer.
989  * @param buf Virtual pointer to the destination buffer.
990  * @param size Buffer size, in bytes.
991  *
992  * @return Returns the number of bytes written.
993  */
994 int32_t
995 sli_cmd_read_nvparms(sli4_t *sli4, void *buf, size_t size)
996 {
997         sli4_cmd_read_nvparms_t *read_nvparms = buf;
998
999         ocs_memset(buf, 0, size);
1000
1001         read_nvparms->hdr.command = SLI4_MBOX_COMMAND_READ_NVPARMS;
1002
1003         return sizeof(sli4_cmd_read_nvparms_t);
1004 }
1005
1006 /**
1007  * @brief Write a WRITE_NVPARMS command to the provided buffer.
1008  *
1009  * @param sli4 SLI context pointer.
1010  * @param buf Virtual pointer to the destination buffer.
1011  * @param size Buffer size, in bytes.
1012  * @param wwpn WWPN to write - pointer to array of 8 uint8_t.
1013  * @param wwnn WWNN to write - pointer to array of 8 uint8_t.
1014  * @param hard_alpa Hard ALPA to write.
1015  * @param preferred_d_id  Preferred D_ID to write.
1016  *
1017  * @return Returns the number of bytes written.
1018  */
1019 int32_t
1020 sli_cmd_write_nvparms(sli4_t *sli4, void *buf, size_t size, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
1021                 uint32_t preferred_d_id)
1022 {
1023         sli4_cmd_write_nvparms_t        *write_nvparms = buf;
1024
1025         ocs_memset(buf, 0, size);
1026
1027         write_nvparms->hdr.command = SLI4_MBOX_COMMAND_WRITE_NVPARMS;
1028         ocs_memcpy(write_nvparms->wwpn, wwpn, 8);
1029         ocs_memcpy(write_nvparms->wwnn, wwnn, 8);
1030         write_nvparms->hard_alpa = hard_alpa;
1031         write_nvparms->preferred_d_id = preferred_d_id;
1032
1033         return sizeof(sli4_cmd_write_nvparms_t);
1034 }
1035
1036 /**
1037  * @brief Write a READ_REV command to the provided buffer.
1038  *
1039  * @param sli4 SLI context pointer.
1040  * @param buf Virtual pointer to the destination buffer.
1041  * @param size Buffer size, in bytes.
1042  * @param vpd Pointer to the buffer.
1043  *
1044  * @return Returns the number of bytes written.
1045  */
1046 static int32_t
1047 sli_cmd_read_rev(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *vpd)
1048 {
1049         sli4_cmd_read_rev_t     *read_rev = buf;
1050
1051         ocs_memset(buf, 0, size);
1052
1053         read_rev->hdr.command = SLI4_MBOX_COMMAND_READ_REV;
1054
1055         if (vpd && vpd->size) {
1056                 read_rev->vpd = TRUE;
1057
1058                 read_rev->available_length = vpd->size;
1059
1060                 read_rev->physical_address_low  = ocs_addr32_lo(vpd->phys);
1061                 read_rev->physical_address_high = ocs_addr32_hi(vpd->phys);
1062         }
1063
1064         return sizeof(sli4_cmd_read_rev_t);
1065 }
1066
1067 /**
1068  * @ingroup sli
1069  * @brief Write a READ_SPARM64 command to the provided buffer.
1070  *
1071  * @param sli4 SLI context pointer.
1072  * @param buf Virtual pointer to the destination buffer.
1073  * @param size Buffer size, in bytes.
1074  * @param dma DMA buffer for the service parameters.
1075  * @param vpi VPI used to determine the WWN.
1076  *
1077  * @return Returns the number of bytes written.
1078  */
1079 int32_t
1080 sli_cmd_read_sparm64(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
1081                 uint16_t vpi)
1082 {
1083         sli4_cmd_read_sparm64_t *read_sparm64 = buf;
1084
1085         ocs_memset(buf, 0, size);
1086
1087         if (SLI4_READ_SPARM64_VPI_SPECIAL == vpi) {
1088                 ocs_log_test(sli4->os, "special VPI not supported!!!\n");
1089                 return -1;
1090         }
1091
1092         if (!dma || !dma->phys) {
1093                 ocs_log_test(sli4->os, "bad DMA buffer\n");
1094                 return -1;
1095         }
1096
1097         read_sparm64->hdr.command = SLI4_MBOX_COMMAND_READ_SPARM64;
1098
1099         read_sparm64->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
1100         read_sparm64->bde_64.buffer_length = dma->size;
1101         read_sparm64->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
1102         read_sparm64->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
1103
1104         read_sparm64->vpi = vpi;
1105
1106         return sizeof(sli4_cmd_read_sparm64_t);
1107 }
1108
1109 /**
1110  * @ingroup sli
1111  * @brief Write a READ_TOPOLOGY command to the provided buffer.
1112  *
1113  * @param sli4 SLI context pointer.
1114  * @param buf Virtual pointer to the destination buffer.
1115  * @param size Buffer size, in bytes.
1116  * @param dma DMA buffer for loop map (optional).
1117  *
1118  * @return Returns the number of bytes written.
1119  */
1120 int32_t
1121 sli_cmd_read_topology(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
1122 {
1123         sli4_cmd_read_topology_t *read_topo = buf;
1124
1125         ocs_memset(buf, 0, size);
1126
1127         read_topo->hdr.command = SLI4_MBOX_COMMAND_READ_TOPOLOGY;
1128
1129         if (dma && dma->size) {
1130                 if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) {
1131                         ocs_log_test(sli4->os, "loop map buffer too small %jd\n",
1132                                         dma->size);
1133                         return 0;
1134                 }
1135
1136                 ocs_memset(dma->virt, 0, dma->size);
1137
1138                 read_topo->bde_loop_map.bde_type = SLI4_BDE_TYPE_BDE_64;
1139                 read_topo->bde_loop_map.buffer_length = dma->size;
1140                 read_topo->bde_loop_map.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
1141                 read_topo->bde_loop_map.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
1142         }
1143
1144         return sizeof(sli4_cmd_read_topology_t);
1145 }
1146
1147 /**
1148  * @ingroup sli
1149  * @brief Write a REG_FCFI command to the provided buffer.
1150  *
1151  * @param sli4 SLI context pointer.
1152  * @param buf Virtual pointer to the destination buffer.
1153  * @param size Buffer size, in bytes.
1154  * @param index FCF index returned by READ_FCF_TABLE.
1155  * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
1156  * @param vlan_id VLAN ID tag.
1157  *
1158  * @return Returns the number of bytes written.
1159  */
1160 int32_t
1161 sli_cmd_reg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t index, sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG], uint16_t vlan_id)
1162 {
1163         sli4_cmd_reg_fcfi_t     *reg_fcfi = buf;
1164         uint32_t                i;
1165
1166         ocs_memset(buf, 0, size);
1167
1168         reg_fcfi->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI;
1169
1170         reg_fcfi->fcf_index = index;
1171
1172         for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
1173                 switch(i) {
1174                 case 0: reg_fcfi->rq_id_0 = rq_cfg[0].rq_id; break;
1175                 case 1: reg_fcfi->rq_id_1 = rq_cfg[1].rq_id; break;
1176                 case 2: reg_fcfi->rq_id_2 = rq_cfg[2].rq_id; break;
1177                 case 3: reg_fcfi->rq_id_3 = rq_cfg[3].rq_id; break;
1178                 }
1179                 reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
1180                 reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
1181                 reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
1182                 reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match;
1183         }
1184
1185         if (vlan_id) {
1186                 reg_fcfi->vv = TRUE;
1187                 reg_fcfi->vlan_tag = vlan_id;
1188         }
1189
1190         return sizeof(sli4_cmd_reg_fcfi_t);
1191 }
1192
1193 /**
1194  * @brief Write REG_FCFI_MRQ to provided command buffer
1195  *
1196  * @param sli4 SLI context pointer.
1197  * @param buf Virtual pointer to the destination buffer.
1198  * @param size Buffer size, in bytes.
1199  * @param fcf_index FCF index returned by READ_FCF_TABLE.
1200  * @param vlan_id VLAN ID tag.
1201  * @param rr_quant Round robin quanta if RQ selection policy is 2
1202  * @param rq_selection_policy RQ selection policy
1203  * @param num_rqs Array of count of RQs per filter
1204  * @param rq_ids Array of RQ ids per filter
1205  * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
1206  *
1207  * @return returns 0 for success, a negative error code value for failure.
1208  */
1209 int32_t
1210 sli_cmd_reg_fcfi_mrq(sli4_t *sli4, void *buf, size_t size, uint8_t mode,
1211                      uint16_t fcf_index, uint16_t vlan_id, uint8_t rq_selection_policy,
1212                      uint8_t mrq_bit_mask, uint16_t num_mrqs,
1213                      sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG])
1214 {
1215         sli4_cmd_reg_fcfi_mrq_t *reg_fcfi_mrq = buf;
1216         uint32_t i;
1217
1218         ocs_memset(buf, 0, size);
1219
1220         reg_fcfi_mrq->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI_MRQ;
1221         if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) {
1222                 reg_fcfi_mrq->fcf_index = fcf_index;
1223                 if (vlan_id) {
1224                         reg_fcfi_mrq->vv = TRUE;
1225                         reg_fcfi_mrq->vlan_tag = vlan_id;
1226                 }
1227                 goto done;
1228         }
1229
1230         reg_fcfi_mrq->mode = mode;
1231         for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
1232                 reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
1233                 reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
1234                 reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
1235                 reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match;
1236
1237                 switch(i) {
1238                 case 3: reg_fcfi_mrq->rq_id_3 = rq_cfg[i].rq_id; break;
1239                 case 2: reg_fcfi_mrq->rq_id_2 = rq_cfg[i].rq_id; break;
1240                 case 1: reg_fcfi_mrq->rq_id_1 = rq_cfg[i].rq_id; break;
1241                 case 0: reg_fcfi_mrq->rq_id_0 = rq_cfg[i].rq_id; break;
1242                 }
1243         }
1244
1245         reg_fcfi_mrq->rq_selection_policy = rq_selection_policy;
1246         reg_fcfi_mrq->mrq_filter_bitmask = mrq_bit_mask;
1247         reg_fcfi_mrq->num_mrq_pairs = num_mrqs;
1248 done:
1249         return sizeof(sli4_cmd_reg_fcfi_mrq_t);
1250 }
1251
1252 /**
1253  * @ingroup sli
1254  * @brief Write a REG_RPI command to the provided buffer.
1255  *
1256  * @param sli4 SLI context pointer.
1257  * @param buf Virtual pointer to the destination buffer.
1258  * @param size Buffer size, in bytes.
1259  * @param nport_id Remote F/N_Port_ID.
1260  * @param rpi Previously-allocated Remote Port Indicator.
1261  * @param vpi Previously-allocated Virtual Port Indicator.
1262  * @param dma DMA buffer that contains the remote port's service parameters.
1263  * @param update Boolean indicating an update to an existing RPI (TRUE)
1264  * or a new registration (FALSE).
1265  *
1266  * @return Returns the number of bytes written.
1267  */
1268 int32_t
1269 sli_cmd_reg_rpi(sli4_t *sli4, void *buf, size_t size, uint32_t nport_id, uint16_t rpi, 
1270                         uint16_t vpi, ocs_dma_t *dma, uint8_t update,  uint8_t enable_t10_pi)
1271 {
1272         sli4_cmd_reg_rpi_t *reg_rpi = buf;
1273
1274         ocs_memset(buf, 0, size);
1275
1276         reg_rpi->hdr.command = SLI4_MBOX_COMMAND_REG_RPI;
1277
1278         reg_rpi->rpi = rpi;
1279         reg_rpi->remote_n_port_id = nport_id;
1280         reg_rpi->upd = update;
1281         reg_rpi->etow = enable_t10_pi;
1282
1283         reg_rpi->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
1284         reg_rpi->bde_64.buffer_length = SLI4_REG_RPI_BUF_LEN;
1285         reg_rpi->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
1286         reg_rpi->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
1287
1288         reg_rpi->vpi = vpi;
1289
1290         return sizeof(sli4_cmd_reg_rpi_t);
1291 }
1292
1293 /**
1294  * @ingroup sli
1295  * @brief Write a REG_VFI command to the provided buffer.
1296  *
1297  * @param sli4 SLI context pointer.
1298  * @param buf Virtual pointer to the destination buffer.
1299  * @param size Buffer size, in bytes.
1300  * @param domain Pointer to the domain object.
1301  *
1302  * @return Returns the number of bytes written.
1303  */
1304 int32_t
1305 sli_cmd_reg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain)
1306 {
1307         sli4_cmd_reg_vfi_t      *reg_vfi = buf;
1308
1309         if (!sli4 || !buf || !domain) {
1310                 return 0;
1311         }
1312
1313         ocs_memset(buf, 0, size);
1314
1315         reg_vfi->hdr.command = SLI4_MBOX_COMMAND_REG_VFI;
1316
1317         reg_vfi->vfi = domain->indicator;
1318
1319         reg_vfi->fcfi = domain->fcf_indicator;
1320
1321         /* TODO contents of domain->dma only valid if topo == FABRIC */
1322         reg_vfi->sparm.bde_type = SLI4_BDE_TYPE_BDE_64;
1323         reg_vfi->sparm.buffer_length = 0x70;
1324         reg_vfi->sparm.u.data.buffer_address_low  = ocs_addr32_lo(domain->dma.phys);
1325         reg_vfi->sparm.u.data.buffer_address_high = ocs_addr32_hi(domain->dma.phys);
1326
1327         reg_vfi->e_d_tov = sli4->config.e_d_tov;
1328         reg_vfi->r_a_tov = sli4->config.r_a_tov;
1329
1330         reg_vfi->vp = TRUE;
1331         reg_vfi->vpi = domain->sport->indicator;
1332         ocs_memcpy(reg_vfi->wwpn, &domain->sport->sli_wwpn, sizeof(reg_vfi->wwpn));
1333         reg_vfi->local_n_port_id = domain->sport->fc_id;
1334
1335         return sizeof(sli4_cmd_reg_vfi_t);
1336 }
1337
1338 /**
1339  * @ingroup sli
1340  * @brief Write a REG_VPI command to the provided buffer.
1341  *
1342  * @param sli4 SLI context pointer.
1343  * @param buf Virtual pointer to the destination buffer.
1344  * @param size Buffer size, in bytes.
1345  * @param sport Point to SLI Port object.
1346  * @param update Boolean indicating whether to update the existing VPI (true)
1347  * or create a new VPI (false).
1348  *
1349  * @return Returns the number of bytes written.
1350  */
1351 int32_t
1352 sli_cmd_reg_vpi(sli4_t *sli4, void *buf, size_t size, ocs_sli_port_t *sport, uint8_t update)
1353 {
1354         sli4_cmd_reg_vpi_t      *reg_vpi = buf;
1355
1356         if (!sli4 || !buf || !sport) {
1357                 return 0;
1358         }
1359
1360         ocs_memset(buf, 0, size);
1361
1362         reg_vpi->hdr.command = SLI4_MBOX_COMMAND_REG_VPI;
1363
1364         reg_vpi->local_n_port_id = sport->fc_id;
1365         reg_vpi->upd = update != 0;
1366         ocs_memcpy(reg_vpi->wwpn, &sport->sli_wwpn, sizeof(reg_vpi->wwpn));
1367         reg_vpi->vpi = sport->indicator;
1368         reg_vpi->vfi = sport->domain->indicator;
1369
1370         return sizeof(sli4_cmd_reg_vpi_t);
1371 }
1372
1373 /**
1374  * @brief Write a REQUEST_FEATURES command to the provided buffer.
1375  *
1376  * @param sli4 SLI context pointer.
1377  * @param buf Virtual pointer to the destination buffer.
1378  * @param size Buffer size, in bytes.
1379  * @param mask Features to request.
1380  * @param query Use feature query mode (does not change FW).
1381  *
1382  * @return Returns the number of bytes written.
1383  */
1384 static int32_t
1385 sli_cmd_request_features(sli4_t *sli4, void *buf, size_t size, sli4_features_t mask, uint8_t query)
1386 {
1387         sli4_cmd_request_features_t *features = buf;
1388
1389         ocs_memset(buf, 0, size);
1390
1391         features->hdr.command = SLI4_MBOX_COMMAND_REQUEST_FEATURES;
1392
1393         if (query) {
1394                 features->qry = TRUE;
1395         }
1396         features->command.dword = mask.dword;
1397
1398         return sizeof(sli4_cmd_request_features_t);
1399 }
1400
1401 /**
1402  * @ingroup sli
1403  * @brief Write a SLI_CONFIG command to the provided buffer.
1404  *
1405  * @param sli4 SLI context pointer.
1406  * @param buf Virtual pointer to the destination buffer.
1407  * @param size Buffer size, in bytes.
1408  * @param length Length in bytes of attached command.
1409  * @param dma DMA buffer for non-embedded commands.
1410  *
1411  * @return Returns the number of bytes written.
1412  */
1413 int32_t
1414 sli_cmd_sli_config(sli4_t *sli4, void *buf, size_t size, uint32_t length, ocs_dma_t *dma)
1415 {
1416         sli4_cmd_sli_config_t   *sli_config = NULL;
1417
1418         if ((length > sizeof(sli_config->payload.embed)) && (dma == NULL)) {
1419                 ocs_log_test(sli4->os, "length(%d) > payload(%ld)\n",
1420                                 length, sizeof(sli_config->payload.embed));
1421                 return -1;
1422         }
1423
1424         sli_config = buf;
1425
1426         ocs_memset(buf, 0, size);
1427
1428         sli_config->hdr.command = SLI4_MBOX_COMMAND_SLI_CONFIG;
1429         if (NULL == dma) {
1430                 sli_config->emb = TRUE;
1431                 sli_config->payload_length = length;
1432         } else {
1433                 sli_config->emb = FALSE;
1434
1435                 sli_config->pmd_count = 1;
1436
1437                 sli_config->payload.mem.address_low = ocs_addr32_lo(dma->phys);
1438                 sli_config->payload.mem.address_high = ocs_addr32_hi(dma->phys);
1439                 sli_config->payload.mem.length = dma->size;
1440                 sli_config->payload_length = dma->size;
1441 #if defined(OCS_INCLUDE_DEBUG)
1442                 /* save pointer to DMA for BMBX dumping purposes */
1443                 sli4->bmbx_non_emb_pmd = dma;
1444 #endif
1445         }
1446
1447         return offsetof(sli4_cmd_sli_config_t, payload.embed);
1448 }
1449
1450 /**
1451  * @brief Initialize SLI Port control register.
1452  *
1453  * @param sli4 SLI context pointer.
1454  * @param endian Endian value to write.
1455  *
1456  * @return Returns 0 on success, or a negative error code value on failure.
1457  */
1458
1459 static int32_t
1460 sli_sliport_control(sli4_t *sli4, uint32_t endian)
1461 {
1462         uint32_t iter;
1463         int32_t rc;
1464
1465         rc = -1;
1466
1467         /* Initialize port, endian */
1468         sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, endian | SLI4_SLIPORT_CONTROL_IP);
1469
1470         for (iter = 0; iter < 3000; iter ++) {
1471                 ocs_udelay(SLI4_INIT_PORT_DELAY_US);
1472                 if (sli_fw_ready(sli4) == 1) {
1473                         rc = 0;
1474                         break;
1475                 }
1476         }
1477
1478         if (rc != 0) {
1479                 ocs_log_crit(sli4->os, "port failed to become ready after initialization\n");
1480         }
1481
1482         return rc;
1483 }
1484
1485 /**
1486  * @ingroup sli
1487  * @brief Write a UNREG_FCFI command to the provided buffer.
1488  *
1489  * @param sli4 SLI context pointer.
1490  * @param buf Virtual pointer to the destination buffer.
1491  * @param size Buffer size, in bytes.
1492  * @param indicator Indicator value.
1493  *
1494  * @return Returns the number of bytes written.
1495  */
1496 int32_t
1497 sli_cmd_unreg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator)
1498 {
1499         sli4_cmd_unreg_fcfi_t   *unreg_fcfi = buf;
1500
1501         if (!sli4 || !buf) {
1502                 return 0;
1503         }
1504
1505         ocs_memset(buf, 0, size);
1506
1507         unreg_fcfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_FCFI;
1508
1509         unreg_fcfi->fcfi = indicator;
1510
1511         return sizeof(sli4_cmd_unreg_fcfi_t);
1512 }
1513
1514 /**
1515  * @ingroup sli
1516  * @brief Write an UNREG_RPI command to the provided buffer.
1517  *
1518  * @param sli4 SLI context pointer.
1519  * @param buf Virtual pointer to the destination buffer.
1520  * @param size Buffer size, in bytes.
1521  * @param indicator Indicator value.
1522  * @param which Type of unregister, such as node, port, domain, or FCF.
1523  * @param fc_id FC address.
1524  *
1525  * @return Returns the number of bytes written.
1526  */
1527 int32_t
1528 sli_cmd_unreg_rpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, sli4_resource_e which,
1529                 uint32_t fc_id)
1530 {
1531         sli4_cmd_unreg_rpi_t    *unreg_rpi = buf;
1532         uint8_t         index_indicator = 0;
1533
1534         if (!sli4 || !buf) {
1535                 return 0;
1536         }
1537
1538         ocs_memset(buf, 0, size);
1539
1540         unreg_rpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_RPI;
1541
1542         switch (which) {
1543         case SLI_RSRC_FCOE_RPI:
1544                 index_indicator = SLI4_UNREG_RPI_II_RPI;
1545                 if (fc_id != UINT32_MAX) {
1546                         unreg_rpi->dp = TRUE;
1547                         unreg_rpi->destination_n_port_id = fc_id & 0x00ffffff;
1548                 }
1549                 break;
1550         case SLI_RSRC_FCOE_VPI:
1551                 index_indicator = SLI4_UNREG_RPI_II_VPI;
1552                 break;
1553         case SLI_RSRC_FCOE_VFI:
1554                 index_indicator = SLI4_UNREG_RPI_II_VFI;
1555                 break;
1556         case SLI_RSRC_FCOE_FCFI:
1557                 index_indicator = SLI4_UNREG_RPI_II_FCFI;
1558                 break;
1559         default:
1560                 ocs_log_test(sli4->os, "unknown type %#x\n", which);
1561                 return 0;
1562         }
1563
1564         unreg_rpi->ii = index_indicator;
1565         unreg_rpi->index = indicator;
1566
1567         return sizeof(sli4_cmd_unreg_rpi_t);
1568 }
1569
1570 /**
1571  * @ingroup sli
1572  * @brief Write an UNREG_VFI command to the provided buffer.
1573  *
1574  * @param sli4 SLI context pointer.
1575  * @param buf Virtual pointer to the destination buffer.
1576  * @param size Buffer size, in bytes.
1577  * @param domain Pointer to the domain object
1578  * @param which Type of unregister, such as domain, FCFI, or everything.
1579  *
1580  * @return Returns the number of bytes written.
1581  */
1582 int32_t
1583 sli_cmd_unreg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain, uint32_t which)
1584 {
1585         sli4_cmd_unreg_vfi_t    *unreg_vfi = buf;
1586
1587         if (!sli4 || !buf || !domain) {
1588                 return 0;
1589         }
1590
1591         ocs_memset(buf, 0, size);
1592
1593         unreg_vfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VFI;
1594         switch (which) {
1595         case SLI4_UNREG_TYPE_DOMAIN:
1596                 unreg_vfi->index = domain->indicator;
1597                 break;
1598         case SLI4_UNREG_TYPE_FCF:
1599                 unreg_vfi->index = domain->fcf_indicator;
1600                 break;
1601         case SLI4_UNREG_TYPE_ALL:
1602                 unreg_vfi->index = UINT16_MAX;
1603                 break;
1604         default:
1605                 return 0;
1606         }
1607
1608         if (SLI4_UNREG_TYPE_DOMAIN != which) {
1609                 unreg_vfi->ii = SLI4_UNREG_VFI_II_FCFI;
1610         }
1611
1612         return sizeof(sli4_cmd_unreg_vfi_t);
1613 }
1614
1615 /**
1616  * @ingroup sli
1617  * @brief Write an UNREG_VPI command to the provided buffer.
1618  *
1619  * @param sli4 SLI context pointer.
1620  * @param buf Virtual pointer to the destination buffer.
1621  * @param size Buffer size, in bytes.
1622  * @param indicator Indicator value.
1623  * @param which Type of unregister: port, domain, FCFI, everything
1624  *
1625  * @return Returns the number of bytes written.
1626  */
1627 int32_t
1628 sli_cmd_unreg_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, uint32_t which)
1629 {
1630         sli4_cmd_unreg_vpi_t    *unreg_vpi = buf;
1631
1632         if (!sli4 || !buf) {
1633                 return 0;
1634         }
1635
1636         ocs_memset(buf, 0, size);
1637
1638         unreg_vpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VPI;
1639         unreg_vpi->index = indicator;
1640         switch (which) {
1641         case SLI4_UNREG_TYPE_PORT:
1642                 unreg_vpi->ii = SLI4_UNREG_VPI_II_VPI;
1643                 break;
1644         case SLI4_UNREG_TYPE_DOMAIN:
1645                 unreg_vpi->ii = SLI4_UNREG_VPI_II_VFI;
1646                 break;
1647         case SLI4_UNREG_TYPE_FCF:
1648                 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
1649                 break;
1650         case SLI4_UNREG_TYPE_ALL:
1651                 unreg_vpi->index = UINT16_MAX;  /* override indicator */
1652                 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
1653                 break;
1654         default:
1655                 return 0;
1656         }
1657
1658         return sizeof(sli4_cmd_unreg_vpi_t);
1659 }
1660
1661 /**
1662  * @ingroup sli
1663  * @brief Write an CONFIG_AUTO_XFER_RDY command to the provided buffer.
1664  *
1665  * @param sli4 SLI context pointer.
1666  * @param buf Virtual pointer to the destination buffer.
1667  * @param size Buffer size, in bytes.
1668  * @param max_burst_len if the write FCP_DL is less than this size,
1669  * then the SLI port will generate the auto XFER_RDY.
1670  *
1671  * @return Returns the number of bytes written.
1672  */
1673 int32_t
1674 sli_cmd_config_auto_xfer_rdy(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len)
1675 {
1676         sli4_cmd_config_auto_xfer_rdy_t *req = buf;
1677
1678         if (!sli4 || !buf) {
1679                 return 0;
1680         }
1681
1682         ocs_memset(buf, 0, size);
1683
1684         req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY;
1685         req->max_burst_len = max_burst_len;
1686
1687         return sizeof(sli4_cmd_config_auto_xfer_rdy_t);
1688 }
1689
1690 /**
1691  * @ingroup sli
1692  * @brief Write an CONFIG_AUTO_XFER_RDY_HP command to the provided buffer.
1693  *
1694  * @param sli4 SLI context pointer.
1695  * @param buf Virtual pointer to the destination buffer.
1696  * @param size Buffer size, in bytes.
1697  * @param max_burst_len if the write FCP_DL is less than this size,
1698  * @param esoc enable start offset computation,
1699  * @param block_size block size,
1700  * then the SLI port will generate the auto XFER_RDY.
1701  *
1702  * @return Returns the number of bytes written.
1703  */
1704 int32_t
1705 sli_cmd_config_auto_xfer_rdy_hp(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len,
1706                                                 uint32_t esoc, uint32_t block_size )
1707 {
1708         sli4_cmd_config_auto_xfer_rdy_hp_t      *req = buf;
1709
1710         if (!sli4 || !buf) {
1711                 return 0;
1712         }
1713
1714         ocs_memset(buf, 0, size);
1715
1716         req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY_HP;
1717         req->max_burst_len = max_burst_len;
1718         req->esoc = esoc;
1719         req->block_size = block_size;
1720         return sizeof(sli4_cmd_config_auto_xfer_rdy_hp_t);
1721 }
1722
1723 /**
1724  * @brief Write a COMMON_FUNCTION_RESET command.
1725  *
1726  * @param sli4 SLI context.
1727  * @param buf Destination buffer for the command.
1728  * @param size Buffer size, in bytes.
1729  *
1730  * @return Returns the number of bytes written.
1731  */
1732 static int32_t
1733 sli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size)
1734 {
1735         sli4_req_common_function_reset_t *reset = NULL;
1736         uint32_t        sli_config_off = 0;
1737
1738         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1739                 uint32_t payload_size;
1740
1741                 /* Payload length must accommodate both request and response */
1742                 payload_size = max(sizeof(sli4_req_common_function_reset_t),
1743                                 sizeof(sli4_res_common_function_reset_t));
1744
1745                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
1746                                 NULL);
1747         }
1748         reset = (sli4_req_common_function_reset_t *)((uint8_t *)buf + sli_config_off);
1749
1750         reset->hdr.opcode = SLI4_OPC_COMMON_FUNCTION_RESET;
1751         reset->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1752
1753         return(sli_config_off + sizeof(sli4_req_common_function_reset_t));
1754 }
1755
1756 /**
1757  * @brief Write a COMMON_CREATE_CQ command.
1758  *
1759  * @param sli4 SLI context.
1760  * @param buf Destination buffer for the command.
1761  * @param size Buffer size, in bytes.
1762  * @param qmem DMA memory for the queue.
1763  * @param eq_id Associated EQ_ID
1764  * @param ignored This parameter carries the ULP which is only used for WQ and RQs
1765  *
1766  * @note This creates a Version 0 message.
1767  *
1768  * @return Returns the number of bytes written.
1769  */
1770 static int32_t
1771 sli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size,
1772                 ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored)
1773 {
1774         sli4_req_common_create_cq_v0_t  *cqv0 = NULL;
1775         sli4_req_common_create_cq_v2_t  *cqv2 = NULL;
1776         uint32_t        sli_config_off = 0;
1777         uint32_t        p;
1778         uintptr_t       addr;
1779         uint32_t        if_type = sli4->if_type;
1780         uint32_t        page_bytes = 0;
1781         uint32_t        num_pages = 0;
1782         uint32_t        cmd_size = 0;
1783         uint32_t        page_size = 0;
1784         uint32_t        n_cqe = 0;
1785
1786         /* First calculate number of pages and the mailbox cmd length */
1787         switch (if_type)
1788         {
1789         case SLI4_IF_TYPE_BE3_SKH_PF:
1790                 page_bytes = SLI_PAGE_SIZE;
1791                 num_pages = sli_page_count(qmem->size, page_bytes);
1792                 cmd_size = sizeof(sli4_req_common_create_cq_v0_t) + (8 * num_pages);
1793                 break;
1794         case SLI4_IF_TYPE_LANCER_FC_ETH:
1795         case SLI4_IF_TYPE_LANCER_G7:
1796                 n_cqe = qmem->size / SLI4_CQE_BYTES;
1797                 switch (n_cqe) {
1798                 case 256:
1799                 case 512:
1800                 case 1024:
1801                 case 2048:
1802                         page_size = 1;
1803                         break;
1804                 case 4096:
1805                         page_size = 2;
1806                         break;
1807                 default:
1808                         return 0;
1809                 }
1810                 page_bytes = page_size * SLI_PAGE_SIZE;
1811                 num_pages = sli_page_count(qmem->size, page_bytes);
1812                 cmd_size = sizeof(sli4_req_common_create_cq_v2_t) + (8 * num_pages);
1813                 break;
1814         default:
1815                 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", if_type);
1816                 return -1;
1817         }
1818
1819         /* now that we have the mailbox command size, we can set SLI_CONFIG fields */
1820         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1821                 uint32_t payload_size;
1822
1823                 /* Payload length must accommodate both request and response */
1824                 payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_t));
1825
1826                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
1827                                 NULL);
1828         }
1829
1830         switch (if_type)
1831         {
1832         case SLI4_IF_TYPE_BE3_SKH_PF:
1833                 cqv0 = (sli4_req_common_create_cq_v0_t *)((uint8_t *)buf + sli_config_off);
1834                 cqv0->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
1835                 cqv0->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1836                 cqv0->hdr.version = 0;
1837                 cqv0->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
1838
1839                 /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
1840                 cqv0->num_pages = num_pages;
1841                 switch (cqv0->num_pages) {
1842                 case 1:
1843                         cqv0->cqecnt = SLI4_CQ_CNT_256;
1844                         break;
1845                 case 2:
1846                         cqv0->cqecnt = SLI4_CQ_CNT_512;
1847                         break;
1848                 case 4:
1849                         cqv0->cqecnt = SLI4_CQ_CNT_1024;
1850                         break;
1851                 default:
1852                         ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv0->num_pages);
1853                         return -1;
1854                 }
1855                 cqv0->evt = TRUE;
1856                 cqv0->valid = TRUE;
1857                 /* TODO cq->nodelay = ???; */
1858                 /* TODO cq->clswm = ???; */
1859                 cqv0->arm = FALSE;
1860                 cqv0->eq_id = eq_id;
1861
1862                 for (p = 0, addr = qmem->phys;
1863                                 p < cqv0->num_pages;
1864                                 p++, addr += page_bytes) {
1865                         cqv0->page_physical_address[p].low = ocs_addr32_lo(addr);
1866                         cqv0->page_physical_address[p].high = ocs_addr32_hi(addr);
1867                 }
1868
1869                 break;
1870         case SLI4_IF_TYPE_LANCER_FC_ETH:
1871         case SLI4_IF_TYPE_LANCER_G7:
1872         {
1873                 cqv2 = (sli4_req_common_create_cq_v2_t *)((uint8_t *)buf + sli_config_off);
1874                 cqv2->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
1875                 cqv2->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1876                 cqv2->hdr.version = 2;
1877                 cqv2->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
1878
1879                 if (if_type == SLI4_IF_TYPE_LANCER_G7)
1880                         cqv2->autovalid = TRUE;
1881
1882                 cqv2->page_size = page_size;
1883
1884                 /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.3) */
1885                 cqv2->num_pages = num_pages;
1886                 if (!cqv2->num_pages || (cqv2->num_pages > SLI4_COMMON_CREATE_CQ_V2_MAX_PAGES)) {
1887                         return 0;
1888                 }
1889
1890                 switch (cqv2->num_pages) {
1891                 case 1:
1892                         cqv2->cqecnt = SLI4_CQ_CNT_256;
1893                         break;
1894                 case 2:
1895                         cqv2->cqecnt = SLI4_CQ_CNT_512;
1896                         break;
1897                 case 4:
1898                         cqv2->cqecnt = SLI4_CQ_CNT_1024;
1899                         break;
1900                 case 8:
1901                         cqv2->cqecnt = SLI4_CQ_CNT_LARGE;
1902                         cqv2->cqe_count = n_cqe;
1903                         break;
1904                 default:
1905                         ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv2->num_pages);
1906                         return -1;
1907                 }
1908
1909                 cqv2->evt = TRUE;
1910                 cqv2->valid = TRUE;
1911                 /* TODO cq->nodelay = ???; */
1912                 /* TODO cq->clswm = ???; */
1913                 cqv2->arm = FALSE;
1914                 cqv2->eq_id = eq_id;
1915
1916                 for (p = 0, addr = qmem->phys;
1917                                 p < cqv2->num_pages;
1918                                 p++, addr += page_bytes) {
1919                         cqv2->page_physical_address[p].low = ocs_addr32_lo(addr);
1920                         cqv2->page_physical_address[p].high = ocs_addr32_hi(addr);
1921                 }
1922         }
1923                 break;
1924         }       
1925
1926         return (sli_config_off + cmd_size);
1927 }
1928
1929 /**
1930  * @brief Write a COMMON_DESTROY_CQ command.
1931  *
1932  * @param sli4 SLI context.
1933  * @param buf Destination buffer for the command.
1934  * @param size Buffer size, in bytes.
1935  * @param cq_id CQ ID
1936  *
1937  * @note This creates a Version 0 message.
1938  *
1939  * @return Returns the number of bytes written.
1940  */
1941 static int32_t
1942 sli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint16_t cq_id)
1943 {
1944         sli4_req_common_destroy_cq_t    *cq = NULL;
1945         uint32_t        sli_config_off = 0;
1946
1947         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1948                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
1949                                 /* Payload length must accommodate both request and response */
1950                                 max(sizeof(sli4_req_common_destroy_cq_t),
1951                                         sizeof(sli4_res_hdr_t)),
1952                                 NULL);
1953         }
1954         cq = (sli4_req_common_destroy_cq_t *)((uint8_t *)buf + sli_config_off);
1955
1956         cq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_CQ;
1957         cq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1958         cq->hdr.request_length = sizeof(sli4_req_common_destroy_cq_t) -
1959                                         sizeof(sli4_req_hdr_t);
1960         cq->cq_id = cq_id;
1961
1962         return(sli_config_off + sizeof(sli4_req_common_destroy_cq_t));
1963 }
1964
1965 /**
1966  * @brief Write a COMMON_MODIFY_EQ_DELAY command.
1967  *
1968  * @param sli4 SLI context.
1969  * @param buf Destination buffer for the command.
1970  * @param size Buffer size, in bytes.
1971  * @param q Queue object array.
1972  * @param num_q Queue object array count.
1973  * @param shift Phase shift for staggering interrupts.
1974  * @param delay_mult Delay multiplier for limiting interrupt frequency.
1975  *
1976  * @return Returns the number of bytes written.
1977  */
1978 static int32_t
1979 sli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift,
1980                                 uint32_t delay_mult)
1981 {
1982         sli4_req_common_modify_eq_delay_t *modify_delay = NULL;
1983         uint32_t        sli_config_off = 0;
1984         int i;
1985
1986         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1987                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
1988                                 /* Payload length must accommodate both request and response */
1989                                 max(sizeof(sli4_req_common_modify_eq_delay_t), sizeof(sli4_res_hdr_t)),
1990                                 NULL);
1991         }
1992
1993         modify_delay = (sli4_req_common_modify_eq_delay_t *)((uint8_t *)buf + sli_config_off);
1994
1995         modify_delay->hdr.opcode = SLI4_OPC_COMMON_MODIFY_EQ_DELAY;
1996         modify_delay->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1997         modify_delay->hdr.request_length = sizeof(sli4_req_common_modify_eq_delay_t) -
1998                                         sizeof(sli4_req_hdr_t);
1999
2000         modify_delay->num_eq = num_q;
2001
2002         for (i = 0; i<num_q; i++) {
2003                 modify_delay->eq_delay_record[i].eq_id = q[i].id;
2004                 modify_delay->eq_delay_record[i].phase = shift;
2005                 modify_delay->eq_delay_record[i].delay_multiplier = delay_mult;
2006         }
2007
2008         return(sli_config_off + sizeof(sli4_req_common_modify_eq_delay_t));
2009 }
2010
2011 /**
2012  * @brief Write a COMMON_CREATE_EQ command.
2013  *
2014  * @param sli4 SLI context.
2015  * @param buf Destination buffer for the command.
2016  * @param size Buffer size, in bytes.
2017  * @param qmem DMA memory for the queue.
2018  * @param ignored1 Ignored (used for consistency among queue creation functions).
2019  * @param ignored2 Ignored (used for consistency among queue creation functions).
2020  *
2021  * @note Other queue creation routines use the last parameter to pass in
2022  * the associated Q_ID and ULP. EQ doesn't have an associated queue or ULP,
2023  * so these parameters are ignored
2024  *
2025  * @note This creates a Version 0 message
2026  *
2027  * @return Returns the number of bytes written.
2028  */
2029 static int32_t
2030 sli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
2031                 uint16_t ignored1, uint16_t ignored2)
2032 {
2033         sli4_req_common_create_eq_t     *eq = NULL;
2034         uint32_t        sli_config_off = 0;
2035         uint32_t        p;
2036         uintptr_t       addr;
2037
2038         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2039                 uint32_t payload_size;
2040
2041                 /* Payload length must accommodate both request and response */
2042                 payload_size = max(sizeof(sli4_req_common_create_eq_t),
2043                                 sizeof(sli4_res_common_create_queue_t));
2044
2045                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
2046                                 NULL);
2047         }
2048         eq = (sli4_req_common_create_eq_t *)((uint8_t *)buf + sli_config_off);
2049
2050         eq->hdr.opcode = SLI4_OPC_COMMON_CREATE_EQ;
2051         eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2052         eq->hdr.request_length = sizeof(sli4_req_common_create_eq_t) -
2053                                         sizeof(sli4_req_hdr_t);
2054         if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) {
2055                 eq->hdr.version = 2;
2056                 eq->autovalid = TRUE;
2057         }
2058         /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
2059         eq->num_pages = qmem->size / SLI_PAGE_SIZE;
2060         switch (eq->num_pages) {
2061         case 1:
2062                 eq->eqesz = SLI4_EQE_SIZE_4;
2063                 eq->count = SLI4_EQ_CNT_1024;
2064                 break;
2065         case 2:
2066                 eq->eqesz = SLI4_EQE_SIZE_4;
2067                 eq->count = SLI4_EQ_CNT_2048;
2068                 break;
2069         case 4:
2070                 eq->eqesz = SLI4_EQE_SIZE_4;
2071                 eq->count = SLI4_EQ_CNT_4096;
2072                 break;
2073         default:
2074                 ocs_log_test(sli4->os, "num_pages %d not valid\n", eq->num_pages);
2075                 return -1;
2076         }
2077         eq->valid = TRUE;
2078         eq->arm = FALSE;
2079         eq->delay_multiplier = 32;
2080
2081         for (p = 0, addr = qmem->phys;
2082                         p < eq->num_pages;
2083                         p++, addr += SLI_PAGE_SIZE) {
2084                 eq->page_address[p].low = ocs_addr32_lo(addr);
2085                 eq->page_address[p].high = ocs_addr32_hi(addr);
2086         }
2087
2088         return(sli_config_off + sizeof(sli4_req_common_create_eq_t));
2089 }
2090
2091 /**
2092  * @brief Write a COMMON_DESTROY_EQ command.
2093  *
2094  * @param sli4 SLI context.
2095  * @param buf Destination buffer for the command.
2096  * @param size Buffer size, in bytes.
2097  * @param eq_id Queue ID to destroy.
2098  *
2099  * @note Other queue creation routines use the last parameter to pass in
2100  * the associated Q_ID. EQ doesn't have an associated queue so this
2101  * parameter is ignored.
2102  *
2103  * @note This creates a Version 0 message.
2104  *
2105  * @return Returns the number of bytes written.
2106  */
2107 static int32_t
2108 sli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint16_t eq_id)
2109 {
2110         sli4_req_common_destroy_eq_t    *eq = NULL;
2111         uint32_t        sli_config_off = 0;
2112
2113         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2114                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2115                                 /* Payload length must accommodate both request and response */
2116                                 max(sizeof(sli4_req_common_destroy_eq_t),
2117                                         sizeof(sli4_res_hdr_t)),
2118                                 NULL);
2119         }
2120         eq = (sli4_req_common_destroy_eq_t *)((uint8_t *)buf + sli_config_off);
2121
2122         eq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_EQ;
2123         eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2124         eq->hdr.request_length = sizeof(sli4_req_common_destroy_eq_t) -
2125                                         sizeof(sli4_req_hdr_t);
2126
2127         eq->eq_id = eq_id;
2128
2129         return(sli_config_off + sizeof(sli4_req_common_destroy_eq_t));
2130 }
2131
2132 /**
2133  * @brief Write a LOWLEVEL_SET_WATCHDOG command.
2134  *
2135  * @param sli4 SLI context.
2136  * @param buf Destination buffer for the command.
2137  * @param size Buffer size, in bytes.
2138  * @param timeout watchdog timer timeout in seconds
2139  *
2140  * @return void
2141  */
2142 void
2143 sli4_cmd_lowlevel_set_watchdog(sli4_t *sli4, void *buf, size_t size, uint16_t timeout)
2144 {
2145
2146         sli4_req_lowlevel_set_watchdog_t *req = NULL;
2147         uint32_t        sli_config_off = 0;
2148
2149         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2150                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2151                                 /* Payload length must accommodate both request and response */
2152                                 max(sizeof(sli4_req_lowlevel_set_watchdog_t),
2153                                         sizeof(sli4_res_lowlevel_set_watchdog_t)),
2154                                 NULL);
2155         }
2156         req = (sli4_req_lowlevel_set_watchdog_t *)((uint8_t *)buf + sli_config_off);
2157
2158         req->hdr.opcode = SLI4_OPC_LOWLEVEL_SET_WATCHDOG;
2159         req->hdr.subsystem = SLI4_SUBSYSTEM_LOWLEVEL;
2160         req->hdr.request_length = sizeof(sli4_req_lowlevel_set_watchdog_t) - sizeof(sli4_req_hdr_t);
2161         req->watchdog_timeout = timeout;
2162
2163         return;
2164 }
2165
2166 static int32_t
2167 sli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
2168 {
2169         sli4_req_hdr_t *hdr = NULL;
2170         uint32_t        sli_config_off = 0;
2171
2172         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2173                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2174                                 sizeof(sli4_req_hdr_t),
2175                                 dma);
2176         }
2177
2178         if (dma == NULL) {
2179                 return 0;
2180         }
2181
2182         ocs_memset(dma->virt, 0, dma->size);
2183
2184         hdr = dma->virt;
2185
2186         hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ATTRIBUTES;
2187         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
2188         hdr->request_length = dma->size;
2189
2190         return(sli_config_off + sizeof(sli4_req_hdr_t));
2191 }
2192
2193 /**
2194  * @brief Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command.
2195  *
2196  * @param sli4 SLI context.
2197  * @param buf Destination buffer for the command.
2198  * @param size Buffer size, in bytes.
2199  * @param dma DMA structure from which the data will be copied.
2200  *
2201  * @note This creates a Version 0 message.
2202  *
2203  * @return Returns the number of bytes written.
2204  */
2205 static int32_t
2206 sli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
2207 {
2208         sli4_req_hdr_t *hdr = NULL;
2209         uint32_t        sli_config_off = 0;
2210
2211         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2212                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, sizeof(sli4_req_hdr_t), dma);
2213         }
2214
2215         if (dma == NULL) {
2216                 return 0;
2217         }
2218
2219         ocs_memset(dma->virt, 0, dma->size);
2220
2221         hdr = dma->virt;
2222
2223         hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ADDL_ATTRIBUTES;
2224         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
2225         hdr->request_length = dma->size;
2226
2227         return(sli_config_off + sizeof(sli4_req_hdr_t));
2228 }
2229
2230 /**
2231  * @brief Write a COMMON_CREATE_MQ_EXT command.
2232  *
2233  * @param sli4 SLI context.
2234  * @param buf Destination buffer for the command.
2235  * @param size Buffer size, in bytes.
2236  * @param qmem DMA memory for the queue.
2237  * @param cq_id Associated CQ_ID.
2238  * @param ignored This parameter carries the ULP which is only used for WQ and RQs
2239  *
2240  * @note This creates a Version 0 message.
2241  *
2242  * @return Returns the number of bytes written.
2243  */
2244 static int32_t
2245 sli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size,
2246                              ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored)
2247 {
2248         sli4_req_common_create_mq_ext_t *mq = NULL;
2249         uint32_t        sli_config_off = 0;
2250         uint32_t        p;
2251         uintptr_t       addr;
2252
2253         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2254                 uint32_t payload_size;
2255
2256                 /* Payload length must accommodate both request and response */
2257                 payload_size = max(sizeof(sli4_req_common_create_mq_ext_t),
2258                                 sizeof(sli4_res_common_create_queue_t));
2259
2260                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
2261                                 NULL);
2262         }
2263         mq = (sli4_req_common_create_mq_ext_t *)((uint8_t *)buf + sli_config_off);
2264
2265         mq->hdr.opcode = SLI4_OPC_COMMON_CREATE_MQ_EXT;
2266         mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2267         mq->hdr.request_length = sizeof(sli4_req_common_create_mq_ext_t) -
2268                                         sizeof(sli4_req_hdr_t);
2269         /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */
2270         mq->num_pages = qmem->size / SLI_PAGE_SIZE;
2271         switch (mq->num_pages) {
2272         case 1:
2273                 mq->ring_size = SLI4_MQE_SIZE_16;
2274                 break;
2275         case 2:
2276                 mq->ring_size = SLI4_MQE_SIZE_32;
2277                 break;
2278         case 4:
2279                 mq->ring_size = SLI4_MQE_SIZE_64;
2280                 break;
2281         case 8:
2282                 mq->ring_size = SLI4_MQE_SIZE_128;
2283                 break;
2284         default:
2285                 ocs_log_test(sli4->os, "num_pages %d not valid\n", mq->num_pages);
2286                 return -1;
2287         }
2288
2289         /* TODO break this down by sli4->config.topology */
2290         mq->async_event_bitmap = SLI4_ASYNC_EVT_FC_FCOE;
2291
2292         if (sli4->config.mq_create_version) {
2293                 mq->cq_id_v1 = cq_id;
2294                 mq->hdr.version = 1;
2295         }
2296         else {
2297                 mq->cq_id_v0 = cq_id;
2298         }
2299         mq->val = TRUE;
2300
2301         for (p = 0, addr = qmem->phys;
2302                         p < mq->num_pages;
2303                         p++, addr += SLI_PAGE_SIZE) {
2304                 mq->page_physical_address[p].low = ocs_addr32_lo(addr);
2305                 mq->page_physical_address[p].high = ocs_addr32_hi(addr);
2306         }
2307
2308         return(sli_config_off + sizeof(sli4_req_common_create_mq_ext_t));
2309 }
2310
2311 /**
2312  * @brief Write a COMMON_DESTROY_MQ command.
2313  *
2314  * @param sli4 SLI context.
2315  * @param buf Destination buffer for the command.
2316  * @param size Buffer size, in bytes.
2317  * @param mq_id MQ ID
2318  *
2319  * @note This creates a Version 0 message.
2320  *
2321  * @return Returns the number of bytes written.
2322  */
2323 static int32_t
2324 sli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint16_t mq_id)
2325 {
2326         sli4_req_common_destroy_mq_t    *mq = NULL;
2327         uint32_t        sli_config_off = 0;
2328
2329         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2330                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2331                                 /* Payload length must accommodate both request and response */
2332                                 max(sizeof(sli4_req_common_destroy_mq_t),
2333                                         sizeof(sli4_res_hdr_t)),
2334                                 NULL);
2335         }
2336         mq = (sli4_req_common_destroy_mq_t *)((uint8_t *)buf + sli_config_off);
2337
2338         mq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_MQ;
2339         mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2340         mq->hdr.request_length = sizeof(sli4_req_common_destroy_mq_t) -
2341                                         sizeof(sli4_req_hdr_t);
2342
2343         mq->mq_id = mq_id;
2344
2345         return(sli_config_off + sizeof(sli4_req_common_destroy_mq_t));
2346 }
2347
2348 /**
2349  * @ingroup sli
2350  * @brief Write a COMMON_NOP command
2351  *
2352  * @param sli4 SLI context.
2353  * @param buf Destination buffer for the command.
2354  * @param size Buffer size, in bytes.
2355  * @param context NOP context value (passed to response, except on FC/FCoE).
2356  *
2357  * @return Returns the number of bytes written.
2358  */
2359 int32_t
2360 sli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t context)
2361 {
2362         sli4_req_common_nop_t *nop = NULL;
2363         uint32_t        sli_config_off = 0;
2364
2365         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2366                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2367                                 /* Payload length must accommodate both request and response */
2368                                 max(sizeof(sli4_req_common_nop_t), sizeof(sli4_res_common_nop_t)),
2369                                 NULL);
2370         }
2371
2372         nop = (sli4_req_common_nop_t *)((uint8_t *)buf + sli_config_off);
2373
2374         nop->hdr.opcode = SLI4_OPC_COMMON_NOP;
2375         nop->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2376         nop->hdr.request_length = 8;
2377
2378         ocs_memcpy(&nop->context, &context, sizeof(context));
2379
2380         return(sli_config_off + sizeof(sli4_req_common_nop_t));
2381 }
2382
2383 /**
2384  * @ingroup sli
2385  * @brief Write a COMMON_GET_RESOURCE_EXTENT_INFO command.
2386  *
2387  * @param sli4 SLI context.
2388  * @param buf Destination buffer for the command.
2389  * @param size Buffer size, in bytes.
2390  * @param rtype Resource type (for example, XRI, VFI, VPI, and RPI).
2391  *
2392  * @return Returns the number of bytes written.
2393  */
2394 int32_t
2395 sli_cmd_common_get_resource_extent_info(sli4_t *sli4, void *buf, size_t size, uint16_t rtype)
2396 {
2397         sli4_req_common_get_resource_extent_info_t *extent = NULL;
2398         uint32_t        sli_config_off = 0;
2399
2400         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2401                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2402                                 sizeof(sli4_req_common_get_resource_extent_info_t),
2403                                 NULL);
2404         }
2405
2406         extent = (sli4_req_common_get_resource_extent_info_t *)((uint8_t *)buf + sli_config_off);
2407
2408         extent->hdr.opcode = SLI4_OPC_COMMON_GET_RESOURCE_EXTENT_INFO;
2409         extent->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2410         extent->hdr.request_length = 4;
2411
2412         extent->resource_type = rtype;
2413
2414         return(sli_config_off + sizeof(sli4_req_common_get_resource_extent_info_t));
2415 }
2416
2417 /**
2418  * @ingroup sli
2419  * @brief Write a COMMON_GET_SLI4_PARAMETERS command.
2420  *
2421  * @param sli4 SLI context.
2422  * @param buf Destination buffer for the command.
2423  * @param size Buffer size, in bytes.
2424  *
2425  * @return Returns the number of bytes written.
2426  */
2427 int32_t
2428 sli_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size)
2429 {
2430         sli4_req_hdr_t  *hdr = NULL;
2431         uint32_t        sli_config_off = 0;
2432
2433         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2434                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2435                                 sizeof(sli4_res_common_get_sli4_parameters_t),
2436                                 NULL);
2437         }
2438
2439         hdr = (sli4_req_hdr_t *)((uint8_t *)buf + sli_config_off);
2440
2441         hdr->opcode = SLI4_OPC_COMMON_GET_SLI4_PARAMETERS;
2442         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
2443         hdr->request_length = 0x50;
2444
2445         return(sli_config_off + sizeof(sli4_req_hdr_t));
2446 }
2447
2448 /**
2449  * @brief Write a COMMON_QUERY_FW_CONFIG command to the provided buffer.
2450  *
2451  * @param sli4 SLI context pointer.
2452  * @param buf Virtual pointer to destination buffer.
2453  * @param size Buffer size in bytes.
2454  *
2455  * @return Returns the number of bytes written
2456  */
2457 static int32_t
2458 sli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size)
2459 {
2460         sli4_req_common_query_fw_config_t   *fw_config;
2461         uint32_t        sli_config_off = 0;
2462         uint32_t payload_size;
2463
2464         /* Payload length must accommodate both request and response */
2465         payload_size = max(sizeof(sli4_req_common_query_fw_config_t),
2466                            sizeof(sli4_res_common_query_fw_config_t));
2467
2468         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2469                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2470                                 payload_size,
2471                                 NULL);
2472         }
2473
2474         fw_config = (sli4_req_common_query_fw_config_t*)((uint8_t*)buf + sli_config_off);
2475         fw_config->hdr.opcode         = SLI4_OPC_COMMON_QUERY_FW_CONFIG;
2476         fw_config->hdr.subsystem      = SLI4_SUBSYSTEM_COMMON;
2477         fw_config->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2478         return sli_config_off + sizeof(sli4_req_common_query_fw_config_t);
2479 }
2480
2481 /**
2482  * @brief Write a COMMON_GET_PORT_NAME command to the provided buffer.
2483  *
2484  * @param sli4 SLI context pointer.
2485  * @param buf Virtual pointer to destination buffer.
2486  * @param size Buffer size in bytes.
2487  *
2488  * @note Function supports both version 0 and 1 forms of this command via
2489  * the IF_TYPE.
2490  *
2491  * @return Returns the number of bytes written.
2492  */
2493 static int32_t
2494 sli_cmd_common_get_port_name(sli4_t *sli4, void *buf, size_t size)
2495 {
2496         sli4_req_common_get_port_name_t *port_name;
2497         uint32_t        sli_config_off = 0;
2498         uint32_t        payload_size;
2499         uint8_t         version = 0;
2500         uint8_t         pt = 0;
2501
2502         /* Select command version according to IF_TYPE */
2503         switch (sli4->if_type) {
2504         case SLI4_IF_TYPE_BE3_SKH_PF:
2505         case SLI4_IF_TYPE_BE3_SKH_VF:
2506                 version = 0;
2507                 break;
2508         case SLI4_IF_TYPE_LANCER_FC_ETH:
2509         case SLI4_IF_TYPE_LANCER_RDMA:
2510         case SLI4_IF_TYPE_LANCER_G7:
2511                 version = 1;
2512                 break;
2513         default:
2514                 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", sli4->if_type);
2515                 return 0;
2516         }
2517
2518         /* Payload length must accommodate both request and response */
2519         payload_size = max(sizeof(sli4_req_common_get_port_name_t),
2520                            sizeof(sli4_res_common_get_port_name_t));
2521
2522         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2523                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2524                                 payload_size,
2525                                 NULL);
2526
2527                 pt = 1;
2528         }
2529
2530         port_name = (sli4_req_common_get_port_name_t *)((uint8_t *)buf + sli_config_off);
2531
2532         port_name->hdr.opcode           = SLI4_OPC_COMMON_GET_PORT_NAME;
2533         port_name->hdr.subsystem        = SLI4_SUBSYSTEM_COMMON;
2534         port_name->hdr.request_length   = sizeof(sli4_req_hdr_t) + (version * sizeof(uint32_t));
2535         port_name->hdr.version          = version;
2536
2537         /* Set the port type value (ethernet=0, FC=1) for V1 commands */
2538         if (version == 1) {
2539                 port_name->pt = pt;
2540         }
2541
2542         return sli_config_off + port_name->hdr.request_length;
2543 }
2544
2545 /**
2546  * @ingroup sli
2547  * @brief Write a COMMON_WRITE_OBJECT command.
2548  *
2549  * @param sli4 SLI context.
2550  * @param buf Destination buffer for the command.
2551  * @param size Buffer size, in bytes.
2552  * @param noc True if the object should be written but not committed to flash.
2553  * @param eof True if this is the last write for this object.
2554  * @param desired_write_length Number of bytes of data to write to the object.
2555  * @param offset Offset, in bytes, from the start of the object.
2556  * @param object_name Name of the object to write.
2557  * @param dma DMA structure from which the data will be copied.
2558  *
2559  * @return Returns the number of bytes written.
2560  */
2561 int32_t
2562 sli_cmd_common_write_object(sli4_t *sli4, void *buf, size_t size,
2563                 uint16_t noc, uint16_t eof, uint32_t desired_write_length,
2564                 uint32_t offset,
2565                 char *object_name,
2566                 ocs_dma_t *dma)
2567 {
2568         sli4_req_common_write_object_t *wr_obj = NULL;
2569         uint32_t        sli_config_off = 0;
2570         sli4_bde_t *host_buffer;
2571
2572         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2573                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2574                                 sizeof (sli4_req_common_write_object_t) + sizeof (sli4_bde_t),
2575                                 NULL);
2576         }
2577
2578         wr_obj = (sli4_req_common_write_object_t *)((uint8_t *)buf + sli_config_off);
2579
2580         wr_obj->hdr.opcode = SLI4_OPC_COMMON_WRITE_OBJECT;
2581         wr_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2582         wr_obj->hdr.request_length = sizeof(*wr_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
2583         wr_obj->hdr.timeout = 0;
2584         wr_obj->hdr.version = 0;
2585
2586         wr_obj->noc = noc;
2587         wr_obj->eof = eof;
2588         wr_obj->desired_write_length = desired_write_length;
2589         wr_obj->write_offset = offset;
2590         ocs_strncpy(wr_obj->object_name, object_name, sizeof(wr_obj->object_name));
2591         wr_obj->host_buffer_descriptor_count = 1;
2592
2593         host_buffer = (sli4_bde_t *)wr_obj->host_buffer_descriptor;
2594
2595         /* Setup to transfer xfer_size bytes to device */
2596         host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
2597         host_buffer->buffer_length = desired_write_length;
2598         host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
2599         host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
2600
2601         return(sli_config_off + sizeof(sli4_req_common_write_object_t) + sizeof (sli4_bde_t));
2602 }
2603
2604 /**
2605  * @ingroup sli
2606  * @brief Write a COMMON_DELETE_OBJECT command.
2607  *
2608  * @param sli4 SLI context.
2609  * @param buf Destination buffer for the command.
2610  * @param size Buffer size, in bytes.
2611  * @param object_name Name of the object to write.
2612  *
2613  * @return Returns the number of bytes written.
2614  */
2615 int32_t
2616 sli_cmd_common_delete_object(sli4_t *sli4, void *buf, size_t size,
2617                 char *object_name)
2618 {
2619         sli4_req_common_delete_object_t *del_obj = NULL;
2620         uint32_t        sli_config_off = 0;
2621
2622         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2623                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2624                                 sizeof (sli4_req_common_delete_object_t),
2625                                 NULL);
2626         }
2627
2628         del_obj = (sli4_req_common_delete_object_t *)((uint8_t *)buf + sli_config_off);
2629
2630         del_obj->hdr.opcode = SLI4_OPC_COMMON_DELETE_OBJECT;
2631         del_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2632         del_obj->hdr.request_length = sizeof(*del_obj);
2633         del_obj->hdr.timeout = 0;
2634         del_obj->hdr.version = 0;
2635
2636         ocs_strncpy(del_obj->object_name, object_name, sizeof(del_obj->object_name));
2637         return(sli_config_off + sizeof(sli4_req_common_delete_object_t));
2638 }
2639
2640 /**
2641  * @ingroup sli
2642  * @brief Write a COMMON_READ_OBJECT command.
2643  *
2644  * @param sli4 SLI context.
2645  * @param buf Destination buffer for the command.
2646  * @param size Buffer size, in bytes.
2647  * @param desired_read_length Number of bytes of data to read from the object.
2648  * @param offset Offset, in bytes, from the start of the object.
2649  * @param object_name Name of the object to read.
2650  * @param dma DMA structure from which the data will be copied.
2651  *
2652  * @return Returns the number of bytes written.
2653  */
2654 int32_t
2655 sli_cmd_common_read_object(sli4_t *sli4, void *buf, size_t size,
2656                 uint32_t desired_read_length,
2657                 uint32_t offset,
2658                 char *object_name,
2659                 ocs_dma_t *dma)
2660 {
2661         sli4_req_common_read_object_t *rd_obj = NULL;
2662         uint32_t        sli_config_off = 0;
2663         sli4_bde_t *host_buffer;
2664
2665         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2666                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2667                                 sizeof (sli4_req_common_read_object_t) + sizeof (sli4_bde_t),
2668                                 NULL);
2669         }
2670
2671         rd_obj = (sli4_req_common_read_object_t *)((uint8_t *)buf + sli_config_off);
2672
2673         rd_obj->hdr.opcode = SLI4_OPC_COMMON_READ_OBJECT;
2674         rd_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2675         rd_obj->hdr.request_length = sizeof(*rd_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
2676         rd_obj->hdr.timeout = 0;
2677         rd_obj->hdr.version = 0;
2678
2679         rd_obj->desired_read_length = desired_read_length;
2680         rd_obj->read_offset = offset;
2681         ocs_strncpy(rd_obj->object_name, object_name, sizeof(rd_obj->object_name));
2682         rd_obj->host_buffer_descriptor_count = 1;
2683
2684         host_buffer = (sli4_bde_t *)rd_obj->host_buffer_descriptor;
2685
2686         /* Setup to transfer xfer_size bytes to device */
2687         host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
2688         host_buffer->buffer_length = desired_read_length;
2689         if (dma != NULL) {
2690                 host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
2691                 host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
2692         } else {
2693                 host_buffer->u.data.buffer_address_low = 0;
2694                 host_buffer->u.data.buffer_address_high = 0;
2695         }
2696
2697         return(sli_config_off + sizeof(sli4_req_common_read_object_t) + sizeof (sli4_bde_t));
2698 }
2699
2700 /**
2701  * @ingroup sli
2702  * @brief Write a DMTF_EXEC_CLP_CMD command.
2703  *
2704  * @param sli4 SLI context.
2705  * @param buf Destination buffer for the command.
2706  * @param size Buffer size, in bytes.
2707  * @param cmd DMA structure that describes the buffer for the command.
2708  * @param resp DMA structure that describes the buffer for the response.
2709  *
2710  * @return Returns the number of bytes written.
2711  */
2712 int32_t
2713 sli_cmd_dmtf_exec_clp_cmd(sli4_t *sli4, void *buf, size_t size,
2714                 ocs_dma_t *cmd,
2715                 ocs_dma_t *resp)
2716 {
2717         sli4_req_dmtf_exec_clp_cmd_t *clp_cmd = NULL;
2718         uint32_t        sli_config_off = 0;
2719
2720         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2721                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2722                                 sizeof (sli4_req_dmtf_exec_clp_cmd_t),
2723                                 NULL);
2724         }
2725
2726         clp_cmd = (sli4_req_dmtf_exec_clp_cmd_t*)((uint8_t *)buf + sli_config_off);
2727
2728         clp_cmd->hdr.opcode = SLI4_OPC_DMTF_EXEC_CLP_CMD;
2729         clp_cmd->hdr.subsystem = SLI4_SUBSYSTEM_DMTF;
2730         clp_cmd->hdr.request_length = sizeof(sli4_req_dmtf_exec_clp_cmd_t) -
2731                                         sizeof(sli4_req_hdr_t);
2732         clp_cmd->hdr.timeout = 0;
2733         clp_cmd->hdr.version = 0;
2734         clp_cmd->cmd_buf_length = cmd->size;
2735         clp_cmd->cmd_buf_addr_low = ocs_addr32_lo(cmd->phys);
2736         clp_cmd->cmd_buf_addr_high = ocs_addr32_hi(cmd->phys);
2737         clp_cmd->resp_buf_length = resp->size;
2738         clp_cmd->resp_buf_addr_low = ocs_addr32_lo(resp->phys);
2739         clp_cmd->resp_buf_addr_high = ocs_addr32_hi(resp->phys);
2740
2741         return(sli_config_off + sizeof(sli4_req_dmtf_exec_clp_cmd_t));
2742 }
2743
2744 /**
2745  * @ingroup sli
2746  * @brief Write a COMMON_SET_DUMP_LOCATION command.
2747  *
2748  * @param sli4 SLI context.
2749  * @param buf Destination buffer for the command.
2750  * @param size Buffer size, in bytes.
2751  * @param query Zero to set dump location, non-zero to query dump size
2752  * @param is_buffer_list Set to one if the buffer is a set of buffer descriptors or
2753  *                       set to 0 if the buffer is a contiguous dump area.
2754  * @param buffer DMA structure to which the dump will be copied.
2755  *
2756  * @return Returns the number of bytes written.
2757  */
2758 int32_t
2759 sli_cmd_common_set_dump_location(sli4_t *sli4, void *buf, size_t size,
2760                                  uint8_t query, uint8_t is_buffer_list,
2761                                  ocs_dma_t *buffer, uint8_t fdb)
2762 {
2763         sli4_req_common_set_dump_location_t *set_dump_loc = NULL;
2764         uint32_t        sli_config_off = 0;
2765
2766         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2767                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2768                                 sizeof (sli4_req_common_set_dump_location_t),
2769                                 NULL);
2770         }
2771
2772         set_dump_loc = (sli4_req_common_set_dump_location_t *)((uint8_t *)buf + sli_config_off);
2773
2774         set_dump_loc->hdr.opcode = SLI4_OPC_COMMON_SET_DUMP_LOCATION;
2775         set_dump_loc->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2776         set_dump_loc->hdr.request_length = sizeof(sli4_req_common_set_dump_location_t) - sizeof(sli4_req_hdr_t);
2777         set_dump_loc->hdr.timeout = 0;
2778         set_dump_loc->hdr.version = 0;
2779
2780         set_dump_loc->blp = is_buffer_list;
2781         set_dump_loc->qry = query;
2782         set_dump_loc->fdb = fdb;
2783
2784         if (buffer) {
2785                 set_dump_loc->buf_addr_low = ocs_addr32_lo(buffer->phys);
2786                 set_dump_loc->buf_addr_high = ocs_addr32_hi(buffer->phys);
2787                 set_dump_loc->buffer_length = buffer->len;
2788         } else {
2789                 set_dump_loc->buf_addr_low = 0;
2790                 set_dump_loc->buf_addr_high = 0;
2791                 set_dump_loc->buffer_length = 0;
2792         }
2793
2794         return(sli_config_off + sizeof(sli4_req_common_set_dump_location_t));
2795 }
2796
2797 /**
2798  * @ingroup sli
2799  * @brief Write a COMMON_SET_FEATURES command.
2800  *
2801  * @param sli4 SLI context.
2802  * @param buf Destination buffer for the command.
2803  * @param size Buffer size, in bytes.
2804  * @param feature Feature to set.
2805  * @param param_len Length of the parameter (must be a multiple of 4 bytes).
2806  * @param parameter Pointer to the parameter value.
2807  *
2808  * @return Returns the number of bytes written.
2809  */
2810 int32_t
2811 sli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size,
2812                             uint32_t feature,
2813                             uint32_t param_len,
2814                             void* parameter)
2815 {
2816         sli4_req_common_set_features_t *cmd = NULL;
2817         uint32_t        sli_config_off = 0;
2818
2819         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2820                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2821                                 sizeof (sli4_req_common_set_features_t),
2822                                 NULL);
2823         }
2824
2825         cmd = (sli4_req_common_set_features_t *)((uint8_t *)buf + sli_config_off);
2826
2827         cmd->hdr.opcode = SLI4_OPC_COMMON_SET_FEATURES;
2828         cmd->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2829         cmd->hdr.request_length = sizeof(sli4_req_common_set_features_t) - sizeof(sli4_req_hdr_t);
2830         cmd->hdr.timeout = 0;
2831         cmd->hdr.version = 0;
2832
2833         cmd->feature = feature;
2834         cmd->param_len = param_len;
2835         ocs_memcpy(cmd->params, parameter, param_len);
2836
2837         return(sli_config_off + sizeof(sli4_req_common_set_features_t));
2838 }
2839
2840 /**
2841  * @ingroup sli
2842  * @brief Write a COMMON_COMMON_GET_PROFILE_CONFIG command.
2843  *
2844  * @param sli4 SLI context.
2845  * @param buf Destination buffer for the command.
2846  * @param size Buffer size in bytes.
2847  * @param dma DMA capable memory used to retrieve profile.
2848  *
2849  * @return Returns the number of bytes written.
2850  */
2851 int32_t
2852 sli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
2853 {
2854         sli4_req_common_get_profile_config_t *req = NULL;
2855         uint32_t        sli_config_off = 0;
2856         uint32_t        payload_size;
2857
2858         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2859                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2860                                 sizeof (sli4_req_common_get_profile_config_t),
2861                                 dma);
2862         }
2863
2864         if (dma != NULL) {
2865                 req = dma->virt;
2866                 ocs_memset(req, 0, dma->size);
2867                 payload_size = dma->size;
2868         } else {
2869                 req = (sli4_req_common_get_profile_config_t *)((uint8_t *)buf + sli_config_off);
2870                 payload_size = sizeof(sli4_req_common_get_profile_config_t);
2871         }
2872
2873         req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_CONFIG;
2874         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2875         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2876         req->hdr.version = 1;
2877
2878         return(sli_config_off + sizeof(sli4_req_common_get_profile_config_t));
2879 }
2880
2881 /**
2882  * @ingroup sli
2883  * @brief Write a COMMON_COMMON_SET_PROFILE_CONFIG command.
2884  *
2885  * @param sli4 SLI context.
2886  * @param buf Destination buffer for the command.
2887  * @param size Buffer size, in bytes.
2888  * @param dma DMA capable memory containing profile.
2889  * @param profile_id Profile ID to configure.
2890  * @param descriptor_count Number of descriptors in DMA buffer.
2891  * @param isap Implicit Set Active Profile value to use.
2892  *
2893  * @return Returns the number of bytes written.
2894  */
2895 int32_t
2896 sli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
2897                 uint8_t profile_id, uint32_t descriptor_count, uint8_t isap)
2898 {
2899         sli4_req_common_set_profile_config_t *req = NULL;
2900         uint32_t cmd_off = 0;
2901         uint32_t payload_size;
2902
2903         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2904                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
2905                                                     sizeof (sli4_req_common_set_profile_config_t),
2906                                                     dma);
2907         }
2908
2909         if (dma != NULL) {
2910                 req = dma->virt;
2911                 ocs_memset(req, 0, dma->size);
2912                 payload_size = dma->size;
2913         } else {
2914                 req = (sli4_req_common_set_profile_config_t *)((uint8_t *)buf + cmd_off);
2915                 payload_size = sizeof(sli4_req_common_set_profile_config_t);
2916         }
2917
2918         req->hdr.opcode = SLI4_OPC_COMMON_SET_PROFILE_CONFIG;
2919         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2920         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2921         req->hdr.version = 1;
2922         req->profile_id = profile_id;
2923         req->desc_count = descriptor_count;
2924         req->isap = isap;
2925
2926         return(cmd_off + sizeof(sli4_req_common_set_profile_config_t));
2927 }
2928
2929 /**
2930  * @ingroup sli
2931  * @brief Write a COMMON_COMMON_GET_PROFILE_LIST command.
2932  *
2933  * @param sli4 SLI context.
2934  * @param buf Destination buffer for the command.
2935  * @param size Buffer size in bytes.
2936  * @param start_profile_index First profile index to return.
2937  * @param dma Buffer into which the list will be written.
2938  *
2939  * @return Returns the number of bytes written.
2940  */
2941 int32_t
2942 sli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size,
2943                                    uint32_t start_profile_index, ocs_dma_t *dma)
2944 {
2945         sli4_req_common_get_profile_list_t *req = NULL;
2946         uint32_t cmd_off = 0;
2947         uint32_t payload_size;
2948
2949         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2950                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
2951                                              sizeof (sli4_req_common_get_profile_list_t),
2952                                              dma);
2953         }
2954
2955         if (dma != NULL) {
2956                 req = dma->virt;
2957                 ocs_memset(req, 0, dma->size);
2958                 payload_size = dma->size;
2959         } else {
2960                 req = (sli4_req_common_get_profile_list_t *)((uint8_t *)buf + cmd_off);
2961                 payload_size = sizeof(sli4_req_common_get_profile_list_t);
2962         }
2963
2964         req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_LIST;
2965         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2966         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2967         req->hdr.version = 0;
2968
2969         req->start_profile_index = start_profile_index;
2970
2971         return(cmd_off + sizeof(sli4_req_common_get_profile_list_t));
2972 }
2973
2974 /**
2975  * @ingroup sli
2976  * @brief Write a COMMON_COMMON_GET_ACTIVE_PROFILE command.
2977  *
2978  * @param sli4 SLI context.
2979  * @param buf Destination buffer for the command.
2980  * @param size Buffer size in bytes.
2981  *
2982  * @return Returns the number of bytes written.
2983  */
2984 int32_t
2985 sli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size)
2986 {
2987         sli4_req_common_get_active_profile_t *req = NULL;
2988         uint32_t cmd_off = 0;
2989         uint32_t payload_size;
2990
2991         /* Payload length must accommodate both request and response */
2992         payload_size = max(sizeof(sli4_req_common_get_active_profile_t),
2993                            sizeof(sli4_res_common_get_active_profile_t));
2994
2995         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2996                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
2997                                 payload_size,
2998                                 NULL);
2999         }
3000
3001         req = (sli4_req_common_get_active_profile_t *)
3002                 ((uint8_t*)buf + cmd_off);
3003
3004         req->hdr.opcode = SLI4_OPC_COMMON_GET_ACTIVE_PROFILE;
3005         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
3006         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
3007         req->hdr.version = 0;
3008
3009         return(cmd_off + sizeof(sli4_req_common_get_active_profile_t));
3010 }
3011
3012 /**
3013  * @ingroup sli
3014  * @brief Write a COMMON_COMMON_SET_ACTIVE_PROFILE command.
3015  *
3016  * @param sli4 SLI context.
3017  * @param buf Destination buffer for the command.
3018  * @param size Buffer size in bytes.
3019  * @param fd If non-zero, set profile to factory default.
3020  * @param active_profile_id ID of new active profile.
3021  *
3022  * @return Returns the number of bytes written.
3023  */
3024 int32_t
3025 sli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size,
3026                                   uint32_t fd, uint32_t active_profile_id)
3027 {
3028         sli4_req_common_set_active_profile_t *req = NULL;
3029         uint32_t cmd_off = 0;
3030         uint32_t payload_size;
3031
3032         /* Payload length must accommodate both request and response */
3033         payload_size = max(sizeof(sli4_req_common_set_active_profile_t),
3034                            sizeof(sli4_res_common_set_active_profile_t));
3035
3036         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3037                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
3038                                 payload_size,
3039                                 NULL);
3040         }
3041
3042         req = (sli4_req_common_set_active_profile_t *)
3043                 ((uint8_t*)buf + cmd_off);
3044
3045         req->hdr.opcode = SLI4_OPC_COMMON_SET_ACTIVE_PROFILE;
3046         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
3047         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
3048         req->hdr.version = 0;
3049         req->fd = fd;
3050         req->active_profile_id = active_profile_id;
3051
3052         return(cmd_off + sizeof(sli4_req_common_set_active_profile_t));
3053 }
3054
3055 /**
3056  * @ingroup sli
3057  * @brief Write a COMMON_GET_RECONFIG_LINK_INFO command.
3058  *
3059  * @param sli4 SLI context.
3060  * @param buf Destination buffer for the command.
3061  * @param size Buffer size in bytes.
3062  * @param dma Buffer to store the supported link configuration modes from the physical device.
3063  *
3064  * @return Returns the number of bytes written.
3065  */
3066 int32_t
3067 sli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
3068 {
3069         sli4_req_common_get_reconfig_link_info_t *req = NULL;
3070         uint32_t cmd_off = 0;
3071         uint32_t payload_size;
3072
3073         /* Payload length must accommodate both request and response */
3074         payload_size = max(sizeof(sli4_req_common_get_reconfig_link_info_t),
3075                            sizeof(sli4_res_common_get_reconfig_link_info_t));
3076
3077         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3078                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
3079                                 payload_size,
3080                                 dma);
3081         }
3082
3083         if (dma != NULL) {
3084                 req = dma->virt;
3085                 ocs_memset(req, 0, dma->size);
3086                 payload_size = dma->size;
3087         } else {
3088                 req = (sli4_req_common_get_reconfig_link_info_t *)((uint8_t *)buf + cmd_off);
3089                 payload_size = sizeof(sli4_req_common_get_reconfig_link_info_t);
3090         }
3091
3092         req->hdr.opcode = SLI4_OPC_COMMON_GET_RECONFIG_LINK_INFO;
3093         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
3094         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
3095         req->hdr.version = 0;
3096
3097         return(cmd_off + sizeof(sli4_req_common_get_reconfig_link_info_t));
3098 }
3099
3100 /**
3101  * @ingroup sli
3102  * @brief Write a COMMON_SET_RECONFIG_LINK_ID command.
3103  *
3104  * @param sli4 SLI context.
3105  * @param buf destination buffer for the command.
3106  * @param size buffer size in bytes.
3107  * @param fd If non-zero, set link config to factory default.
3108  * @param active_link_config_id ID of new active profile.
3109  * @param dma Buffer to assign the link configuration mode that is to become active from the physical device.
3110  *
3111  * @return Returns the number of bytes written.
3112  */
3113 int32_t
3114 sli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
3115                                   uint32_t fd, uint32_t active_link_config_id)
3116 {
3117         sli4_req_common_set_reconfig_link_id_t *req = NULL;
3118         uint32_t cmd_off = 0;
3119         uint32_t payload_size;
3120
3121         /* Payload length must accommodate both request and response */
3122         payload_size = max(sizeof(sli4_req_common_set_reconfig_link_id_t),
3123                            sizeof(sli4_res_common_set_reconfig_link_id_t));
3124
3125         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3126                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
3127                                 payload_size,
3128                                 NULL);
3129         }
3130
3131                 if (dma != NULL) {
3132                 req = dma->virt;
3133                 ocs_memset(req, 0, dma->size);
3134                 payload_size = dma->size;
3135         } else {
3136                 req = (sli4_req_common_set_reconfig_link_id_t *)((uint8_t *)buf + cmd_off);
3137                 payload_size = sizeof(sli4_req_common_set_reconfig_link_id_t);
3138         }
3139
3140         req->hdr.opcode = SLI4_OPC_COMMON_SET_RECONFIG_LINK_ID;
3141         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
3142         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
3143         req->hdr.version = 0;
3144         req->fd = fd;
3145         req->next_link_config_id = active_link_config_id;
3146
3147         return(cmd_off + sizeof(sli4_req_common_set_reconfig_link_id_t));
3148 }
3149
3150 /**
3151  * @ingroup sli
3152  * @brief Check the mailbox/queue completion entry.
3153  *
3154  * @param buf Pointer to the MCQE.
3155  *
3156  * @return Returns 0 on success, or a non-zero value on failure.
3157  */
3158 int32_t
3159 sli_cqe_mq(void *buf)
3160 {
3161         sli4_mcqe_t     *mcqe = buf;
3162
3163         /*
3164          * Firmware can split mbx completions into two MCQEs: first with only
3165          * the "consumed" bit set and a second with the "complete" bit set.
3166          * Thus, ignore MCQE unless "complete" is set.
3167          */
3168         if (!mcqe->cmp) {
3169                 return -2;
3170         }
3171
3172         if (mcqe->completion_status) {
3173                 ocs_log_debug(NULL, "bad status (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
3174                                 mcqe->completion_status,
3175                                 mcqe->extended_status,
3176                                 mcqe->con,
3177                                 mcqe->cmp,
3178                                 mcqe->ae,
3179                                 mcqe->val);
3180         }
3181
3182         return mcqe->completion_status;
3183 }
3184
3185 /**
3186  * @ingroup sli
3187  * @brief Check the asynchronous event completion entry.
3188  *
3189  * @param sli4 SLI context.
3190  * @param buf Pointer to the ACQE.
3191  *
3192  * @return Returns 0 on success, or a non-zero value on failure.
3193  */
3194 int32_t
3195 sli_cqe_async(sli4_t *sli4, void *buf)
3196 {
3197         sli4_acqe_t     *acqe = buf;
3198         int32_t         rc = -1;
3199
3200         if (!sli4 || !buf) {
3201                 ocs_log_err(NULL, "bad parameter sli4=%p buf=%p\n", sli4, buf);
3202                 return -1;
3203         }
3204
3205         switch (acqe->event_code) {
3206         case SLI4_ACQE_EVENT_CODE_LINK_STATE:
3207                 rc = sli_fc_process_link_state(sli4, buf);
3208                 break;
3209         case SLI4_ACQE_EVENT_CODE_FCOE_FIP:
3210                 rc = sli_fc_process_fcoe(sli4, buf);
3211                 break;
3212         case SLI4_ACQE_EVENT_CODE_GRP_5:
3213                 /*TODO*/ocs_log_debug(sli4->os, "ACQE GRP5\n");
3214                 break;
3215         case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT:
3216         ocs_log_debug(sli4->os,"ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n",
3217                 acqe->event_type, acqe->event_data[0], acqe->event_data[1]);
3218 #if defined(OCS_INCLUDE_DEBUG)
3219                 ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "acq", acqe, sizeof(*acqe));
3220 #endif
3221                 break;
3222         case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT:
3223                 rc = sli_fc_process_link_attention(sli4, buf);
3224                 break;
3225         default:
3226                 /*TODO*/ocs_log_test(sli4->os, "ACQE unknown=%#x\n", acqe->event_code);
3227         }
3228
3229         return rc;
3230 }
3231
3232 /**
3233  * @brief Check the SLI_CONFIG response.
3234  *
3235  * @par Description
3236  * Function checks the SLI_CONFIG response and the payload status.
3237  *
3238  * @param buf Pointer to SLI_CONFIG response.
3239  *
3240  * @return Returns 0 on success, or a non-zero value on failure.
3241  */
3242 static int32_t
3243 sli_res_sli_config(void *buf)
3244 {
3245         sli4_cmd_sli_config_t   *sli_config = buf;
3246
3247         if (!buf || (SLI4_MBOX_COMMAND_SLI_CONFIG != sli_config->hdr.command)) {
3248                 ocs_log_err(NULL, "bad parameter buf=%p cmd=%#x\n", buf,
3249                                 buf ? sli_config->hdr.command : -1);
3250                 return -1;
3251         }
3252
3253         if (sli_config->hdr.status) {
3254                 return sli_config->hdr.status;
3255         }
3256
3257         if (sli_config->emb) {
3258                 return sli_config->payload.embed[4];
3259         } else {
3260                 ocs_log_test(NULL, "external buffers not supported\n");
3261                 return -1;
3262         }
3263 }
3264
3265 /**
3266  * @brief Issue a COMMON_FUNCTION_RESET command.
3267  *
3268  * @param sli4 SLI context.
3269  *
3270  * @return Returns 0 on success, or a non-zero value on failure.
3271  */
3272 static int32_t
3273 sli_common_function_reset(sli4_t *sli4)
3274 {
3275
3276         if (sli_cmd_common_function_reset(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3277                 if (sli_bmbx_command(sli4)) {
3278                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COM_FUNC_RESET)\n");
3279                         return -1;
3280                 }
3281                 if (sli_res_sli_config(sli4->bmbx.virt)) {
3282                         ocs_log_err(sli4->os, "bad status COM_FUNC_RESET\n");
3283                         return -1;
3284                 }
3285         } else {
3286                 ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
3287                 return -1;
3288         }
3289
3290         return 0;
3291 }
3292
3293 /**
3294  * @brief check to see if the FW is ready.
3295  *
3296  * @par Description
3297  * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
3298  *
3299  * @param sli4 SLI context.
3300  * @param timeout_ms Time, in milliseconds, to wait for the port to be ready
3301  *  before failing.
3302  *
3303  * @return Returns TRUE for ready, or FALSE otherwise.
3304  */
3305 static int32_t
3306 sli_wait_for_fw_ready(sli4_t *sli4, uint32_t timeout_ms)
3307 {
3308         uint32_t        iter = timeout_ms / (SLI4_INIT_PORT_DELAY_US / 1000);
3309         uint32_t        ready = FALSE;
3310
3311         do {
3312                 iter--;
3313                 ocs_udelay(SLI4_INIT_PORT_DELAY_US);
3314                 if (sli_fw_ready(sli4) == 1) {
3315                         ready = TRUE;
3316                 }
3317         } while (!ready && (iter > 0));
3318
3319         return ready;
3320 }
3321
3322 /**
3323  * @brief Initialize the firmware.
3324  *
3325  * @par Description
3326  * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
3327  *
3328  * @param sli4 SLI context.
3329  *
3330  * @return Returns 0 on success, or a non-zero value on failure.
3331  */
3332 static int32_t
3333 sli_fw_init(sli4_t *sli4)
3334 {
3335         uint32_t ready;
3336         uint32_t endian;
3337
3338         /*
3339          * Is firmware ready for operation?
3340          */
3341         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
3342         if (!ready) {
3343                 ocs_log_crit(sli4->os, "FW status is NOT ready\n");
3344                 return -1;
3345         }
3346
3347         /*
3348          * Reset port to a known state
3349          */
3350         switch (sli4->if_type) {
3351         case SLI4_IF_TYPE_BE3_SKH_PF:
3352         case SLI4_IF_TYPE_BE3_SKH_VF:
3353                 /* No SLIPORT_CONTROL register so use command sequence instead */
3354                 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
3355                         ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
3356                         return -1;
3357                 }
3358
3359                 if (sli_cmd_fw_initialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3360                         if (sli_bmbx_command(sli4)) {
3361                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_INIT)\n");
3362                                 return -1;
3363                         }
3364                 } else {
3365                         ocs_log_crit(sli4->os, "bad FW_INIT write\n");
3366                         return -1;
3367                 }
3368
3369                 if (sli_common_function_reset(sli4)) {
3370                         ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
3371                         return -1;
3372                 }
3373                 break;
3374         case SLI4_IF_TYPE_LANCER_FC_ETH:
3375         case SLI4_IF_TYPE_LANCER_G7:
3376 #if BYTE_ORDER == LITTLE_ENDIAN
3377                 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
3378 #else
3379                 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
3380 #endif
3381
3382                 if (sli_sliport_control(sli4, endian))
3383                         return -1;
3384                 break;
3385         default:
3386                 ocs_log_test(sli4->os, "if_type %d not supported\n", sli4->if_type);
3387                 return -1;
3388         }
3389
3390         return 0;
3391 }
3392
3393 /**
3394  * @brief Terminate the firmware.
3395  *
3396  * @param sli4 SLI context.
3397  *
3398  * @return Returns 0 on success, or a non-zero value on failure.
3399  */
3400 static int32_t
3401 sli_fw_term(sli4_t *sli4)
3402 {
3403         uint32_t endian;
3404
3405         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF ||
3406             sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF) {
3407                 /* No SLIPORT_CONTROL register so use command sequence instead */
3408                 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
3409                         ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
3410                         return -1;
3411                 }
3412
3413                 if (sli_common_function_reset(sli4)) {
3414                         ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
3415                         return -1;
3416                 }
3417
3418                 if (sli_cmd_fw_deinitialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3419                         if (sli_bmbx_command(sli4)) {
3420                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_DEINIT)\n");
3421                                 return -1;
3422                         }
3423                 } else {
3424                         ocs_log_test(sli4->os, "bad FW_DEINIT write\n");
3425                         return -1;
3426                 }
3427         } else {
3428 #if BYTE_ORDER == LITTLE_ENDIAN
3429                 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
3430 #else
3431                 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
3432 #endif
3433                 /* type 2 etc. use SLIPORT_CONTROL to initialize port */
3434                 sli_sliport_control(sli4, endian);
3435         }
3436         return 0;
3437 }
3438
3439 /**
3440  * @brief Write the doorbell register associated with the queue object.
3441  *
3442  * @param sli4 SLI context.
3443  * @param q Queue object.
3444  *
3445  * @return Returns 0 on success, or a non-zero value on failure.
3446  */
3447 static int32_t
3448 sli_queue_doorbell(sli4_t *sli4, sli4_queue_t *q)
3449 {
3450         uint32_t        val = 0;
3451
3452         switch (q->type) {
3453         case SLI_QTYPE_EQ:
3454                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
3455                         val = sli_iftype6_eq_doorbell(q->n_posted, q->id, FALSE);
3456                 else
3457                         val = sli_eq_doorbell(q->n_posted, q->id, FALSE);
3458                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3459                 break;
3460         case SLI_QTYPE_CQ:
3461                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
3462                         val = sli_iftype6_cq_doorbell(q->n_posted, q->id, FALSE);
3463                 else
3464                         val = sli_cq_doorbell(q->n_posted, q->id, FALSE);
3465                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3466                 break;
3467         case SLI_QTYPE_MQ:
3468                 val = SLI4_MQ_DOORBELL(q->n_posted, q->id);
3469                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3470                 break;
3471         case SLI_QTYPE_RQ:
3472         {
3473                 uint32_t        n_posted = q->n_posted;
3474                 /*
3475                  * FC/FCoE has different rules for Receive Queues. The host
3476                  * should only update the doorbell of the RQ-pair containing
3477                  * the headers since the header / payload RQs are treated
3478                  * as a matched unit.
3479                  */
3480                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3481                         /*
3482                          * In RQ-pair, an RQ either contains the FC header
3483                          * (i.e. is_hdr == TRUE) or the payload.
3484                          *
3485                          * Don't ring doorbell for payload RQ
3486                          */
3487                         if (!q->u.flag.is_hdr) {
3488                                 break;
3489                         }
3490                         /*
3491                          * Some RQ cannot be incremented one entry at a time. Instead,
3492                          * the driver collects a number of entries and updates the
3493                          * RQ in batches.
3494                          */
3495                         if (q->u.flag.rq_batch) {
3496                                 if (((q->index + q->n_posted) % SLI4_QUEUE_RQ_BATCH)) {
3497                                         break;
3498                                 }
3499                                 n_posted = SLI4_QUEUE_RQ_BATCH;
3500                         }
3501                 }
3502
3503                 val = SLI4_RQ_DOORBELL(n_posted, q->id);
3504                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3505                 break;
3506         }
3507         case SLI_QTYPE_WQ:
3508                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) {
3509                         val = SLI4_WQ_DOORBELL(q->n_posted, 0, q->id);
3510                 } else {
3511                         /* For iftype = 2 and 3, q->index value is ignored */
3512                         val = SLI4_WQ_DOORBELL(q->n_posted, q->index, q->id);
3513                 }
3514
3515                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3516                 break;
3517         default:
3518                 ocs_log_test(sli4->os, "bad queue type %d\n", q->type);
3519                 return -1;
3520         }
3521
3522         return 0;
3523 }
3524
3525 static int32_t
3526 sli_request_features(sli4_t *sli4, sli4_features_t *features, uint8_t query)
3527 {
3528
3529         if (sli_cmd_request_features(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
3530                                 *features, query)) {
3531                 sli4_cmd_request_features_t *req_features = sli4->bmbx.virt;
3532
3533                 if (sli_bmbx_command(sli4)) {
3534                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (REQUEST_FEATURES)\n");
3535                         return -1;
3536                 }
3537                 if (req_features->hdr.status) {
3538                         ocs_log_err(sli4->os, "REQUEST_FEATURES bad status %#x\n",
3539                                         req_features->hdr.status);
3540                         return -1;
3541                 }
3542                 features->dword = req_features->response.dword;
3543         } else {
3544                 ocs_log_err(sli4->os, "bad REQUEST_FEATURES write\n");
3545                 return -1;
3546         }
3547
3548         return 0;
3549 }
3550
3551 /**
3552  * @brief Calculate max queue entries.
3553  *
3554  * @param sli4 SLI context.
3555  *
3556  * @return Returns 0 on success, or a non-zero value on failure.
3557  */
3558 void
3559 sli_calc_max_qentries(sli4_t *sli4)
3560 {
3561         sli4_qtype_e q;
3562         uint32_t alloc_size, qentries, qentry_size;
3563
3564         for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
3565                 sli4->config.max_qentries[q] = sli_convert_mask_to_count(sli4->config.count_method[q],
3566                                                                          sli4->config.count_mask[q]);
3567         }
3568
3569         /* single, continguous DMA allocations will be called for each queue
3570          * of size (max_qentries * queue entry size); since these can be large,
3571          * check against the OS max DMA allocation size
3572          */
3573         for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
3574                 qentries = sli4->config.max_qentries[q];
3575                 qentry_size = sli_get_queue_entry_size(sli4, q);
3576                 alloc_size = qentries * qentry_size;
3577                 if (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
3578                         while (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
3579                                 /* cut the qentries in hwf until alloc_size <= max DMA alloc size */
3580                                 qentries >>= 1;
3581                                 alloc_size = qentries * qentry_size;
3582                         }
3583                         ocs_log_debug(sli4->os, "[%s]: max_qentries from %d to %d (max dma %d)\n",
3584                                 SLI_QNAME[q], sli4->config.max_qentries[q],
3585                                 qentries, ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE));
3586                         sli4->config.max_qentries[q] = qentries;
3587                 }
3588         }
3589 }
3590
3591 /**
3592  * @brief Issue a FW_CONFIG mailbox command and store the results.
3593  *
3594  * @param sli4 SLI context.
3595  *
3596  * @return Returns 0 on success, or a non-zero value on failure.
3597  */
3598 static int32_t
3599 sli_query_fw_config(sli4_t *sli4)
3600 {
3601         /*
3602          * Read the device configuration
3603          *
3604          * Note: Only ulp0 fields contain values
3605          */
3606         if (sli_cmd_common_query_fw_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3607                 sli4_res_common_query_fw_config_t   *fw_config =
3608                         (sli4_res_common_query_fw_config_t *)
3609                         (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
3610
3611                 if (sli_bmbx_command(sli4)) {
3612                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (QUERY_FW_CONFIG)\n");
3613                         return -1;
3614                 }
3615                 if (fw_config->hdr.status) {
3616                         ocs_log_err(sli4->os, "COMMON_QUERY_FW_CONFIG bad status %#x\n",
3617                                 fw_config->hdr.status);
3618                         return -1;
3619                 }
3620
3621                 sli4->physical_port = fw_config->physical_port;
3622                 sli4->config.dual_ulp_capable = ((fw_config->function_mode & SLI4_FUNCTION_MODE_DUA_MODE) == 0 ? 0 : 1);
3623                 sli4->config.is_ulp_fc[0] = ((fw_config->ulp0_mode &
3624                                               (SLI4_ULP_MODE_FCOE_INI |
3625                                                SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
3626                 sli4->config.is_ulp_fc[1] = ((fw_config->ulp1_mode &
3627                                               (SLI4_ULP_MODE_FCOE_INI |
3628                                                SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
3629
3630                 if (sli4->config.dual_ulp_capable) {
3631                         /*
3632                          * Lancer will not support this, so we use the values
3633                          * from the READ_CONFIG.
3634                          */
3635                         if (sli4->config.is_ulp_fc[0] &&
3636                             sli4->config.is_ulp_fc[1]) {
3637                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total + fw_config->ulp1_toe_wq_total;
3638                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total + fw_config->ulp1_toe_defrq_total;
3639                         } else if (sli4->config.is_ulp_fc[0]) {
3640                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total;
3641                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total;
3642                         } else {
3643                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp1_toe_wq_total;
3644                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp1_toe_defrq_total;
3645                         }
3646                 }
3647         } else {
3648                 ocs_log_err(sli4->os, "bad QUERY_FW_CONFIG write\n");
3649                 return -1;
3650         }
3651         return 0;
3652 }
3653
3654 static int32_t
3655 sli_get_config(sli4_t *sli4)
3656 {
3657         ocs_dma_t       get_cntl_addl_data;
3658
3659         /*
3660          * Read the device configuration
3661          */
3662         if (sli_cmd_read_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3663                 sli4_res_read_config_t  *read_config = sli4->bmbx.virt;
3664                 uint32_t        i;
3665                 uint32_t        total;
3666
3667                 if (sli_bmbx_command(sli4)) {
3668                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n");
3669                         return -1;
3670                 }
3671                 if (read_config->hdr.status) {
3672                         ocs_log_err(sli4->os, "READ_CONFIG bad status %#x\n",
3673                                         read_config->hdr.status);
3674                         return -1;
3675                 }
3676
3677                 sli4->config.has_extents = read_config->ext;
3678                 if (FALSE == sli4->config.has_extents) {
3679                         uint32_t        i = 0;
3680                         uint32_t        *base = sli4->config.extent[0].base;
3681
3682                         if (!base) {
3683                                 if (NULL == (base = ocs_malloc(sli4->os, SLI_RSRC_MAX * sizeof(uint32_t),
3684                                                                 OCS_M_ZERO | OCS_M_NOWAIT))) {
3685                                         ocs_log_err(sli4->os, "memory allocation failed for sli4_resource_t\n");
3686                                         return -1;
3687                                 }
3688                         }
3689
3690                         for (i = 0; i < SLI_RSRC_MAX; i++) {
3691                                 sli4->config.extent[i].number = 1;
3692                                 sli4->config.extent[i].n_alloc = 0;
3693                                 sli4->config.extent[i].base = &base[i];
3694                         }
3695
3696                         sli4->config.extent[SLI_RSRC_FCOE_VFI].base[0] = read_config->vfi_base;
3697                         sli4->config.extent[SLI_RSRC_FCOE_VFI].size = read_config->vfi_count;
3698
3699                         sli4->config.extent[SLI_RSRC_FCOE_VPI].base[0] = read_config->vpi_base;
3700                         sli4->config.extent[SLI_RSRC_FCOE_VPI].size = read_config->vpi_count;
3701
3702                         sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0] = read_config->rpi_base;
3703                         sli4->config.extent[SLI_RSRC_FCOE_RPI].size = read_config->rpi_count;
3704
3705                         sli4->config.extent[SLI_RSRC_FCOE_XRI].base[0] = read_config->xri_base;
3706                         sli4->config.extent[SLI_RSRC_FCOE_XRI].size = OCS_MIN(255,read_config->xri_count);
3707
3708                         sli4->config.extent[SLI_RSRC_FCOE_FCFI].base[0] = 0;
3709                         sli4->config.extent[SLI_RSRC_FCOE_FCFI].size = read_config->fcfi_count;
3710                 } else {
3711                         /* TODO extents*/
3712                         ;
3713                 }
3714
3715                 for (i = 0; i < SLI_RSRC_MAX; i++) {
3716                         total = sli4->config.extent[i].number * sli4->config.extent[i].size;
3717                         sli4->config.extent[i].use_map = ocs_bitmap_alloc(total);
3718                         if (NULL == sli4->config.extent[i].use_map) {
3719                                 ocs_log_err(sli4->os, "bitmap memory allocation failed "
3720                                                 "resource %d\n", i);
3721                                 return -1;
3722                         }
3723                         sli4->config.extent[i].map_size = total;
3724                 }
3725
3726                 sli4->config.topology = read_config->topology;
3727                 switch (sli4->config.topology) {
3728                 case SLI4_READ_CFG_TOPO_FCOE:
3729                         ocs_log_debug(sli4->os, "FCoE\n");
3730                         break;
3731                 case SLI4_READ_CFG_TOPO_FC:
3732                         ocs_log_debug(sli4->os, "FC (unknown)\n");
3733                         break;
3734                 case SLI4_READ_CFG_TOPO_FC_DA:
3735                         ocs_log_debug(sli4->os, "FC (direct attach)\n");
3736                         break;
3737                 case SLI4_READ_CFG_TOPO_FC_AL:
3738                         ocs_log_debug(sli4->os, "FC (arbitrated loop)\n");
3739                         break;
3740                 default:
3741                         ocs_log_test(sli4->os, "bad topology %#x\n", sli4->config.topology);
3742                 }
3743
3744                 sli4->config.e_d_tov = read_config->e_d_tov;
3745                 sli4->config.r_a_tov = read_config->r_a_tov;
3746
3747                 sli4->config.link_module_type = read_config->lmt;
3748
3749                 sli4->config.max_qcount[SLI_QTYPE_EQ] = read_config->eq_count;
3750                 sli4->config.max_qcount[SLI_QTYPE_CQ] = read_config->cq_count;
3751                 sli4->config.max_qcount[SLI_QTYPE_WQ] = read_config->wq_count;
3752                 sli4->config.max_qcount[SLI_QTYPE_RQ] = read_config->rq_count;
3753
3754                 /*
3755                  * READ_CONFIG doesn't give the max number of MQ. Applications
3756                  * will typically want 1, but we may need another at some future
3757                  * date. Dummy up a "max" MQ count here.
3758                  */
3759                 sli4->config.max_qcount[SLI_QTYPE_MQ] = SLI_USER_MQ_COUNT;
3760         } else {
3761                 ocs_log_err(sli4->os, "bad READ_CONFIG write\n");
3762                 return -1;
3763         }
3764
3765         if (sli_cmd_common_get_sli4_parameters(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3766                 sli4_res_common_get_sli4_parameters_t   *parms = (sli4_res_common_get_sli4_parameters_t *)
3767                         (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
3768
3769                 if (sli_bmbx_command(sli4)) {
3770                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_SLI4_PARAMETERS)\n");
3771                         return -1;
3772                 } else if (parms->hdr.status) {
3773                         ocs_log_err(sli4->os, "COMMON_GET_SLI4_PARAMETERS bad status %#x att'l %#x\n",
3774                                         parms->hdr.status, parms->hdr.additional_status);
3775                         return -1;
3776                 }
3777
3778                 sli4->config.auto_reg = parms->areg;
3779                 sli4->config.auto_xfer_rdy = parms->agxf;
3780                 sli4->config.hdr_template_req = parms->hdrr;
3781                 sli4->config.t10_dif_inline_capable = parms->timm;
3782                 sli4->config.t10_dif_separate_capable = parms->tsmm;
3783
3784                 sli4->config.mq_create_version = parms->mqv;
3785                 sli4->config.cq_create_version = parms->cqv;
3786                 sli4->config.rq_min_buf_size = parms->min_rq_buffer_size;
3787                 sli4->config.rq_max_buf_size = parms->max_rq_buffer_size;
3788
3789                 sli4->config.qpage_count[SLI_QTYPE_EQ] = parms->eq_page_cnt;
3790                 sli4->config.qpage_count[SLI_QTYPE_CQ] = parms->cq_page_cnt;
3791                 sli4->config.qpage_count[SLI_QTYPE_MQ] = parms->mq_page_cnt;
3792                 sli4->config.qpage_count[SLI_QTYPE_WQ] = parms->wq_page_cnt;
3793                 sli4->config.qpage_count[SLI_QTYPE_RQ] = parms->rq_page_cnt;
3794
3795                 /* save count methods and masks for each queue type */
3796                 sli4->config.count_mask[SLI_QTYPE_EQ] = parms->eqe_count_mask;
3797                 sli4->config.count_method[SLI_QTYPE_EQ] = parms->eqe_count_method;
3798                 sli4->config.count_mask[SLI_QTYPE_CQ] = parms->cqe_count_mask;
3799                 sli4->config.count_method[SLI_QTYPE_CQ] = parms->cqe_count_method;
3800                 sli4->config.count_mask[SLI_QTYPE_MQ] = parms->mqe_count_mask;
3801                 sli4->config.count_method[SLI_QTYPE_MQ] = parms->mqe_count_method;
3802                 sli4->config.count_mask[SLI_QTYPE_WQ] = parms->wqe_count_mask;
3803                 sli4->config.count_method[SLI_QTYPE_WQ] = parms->wqe_count_method;
3804                 sli4->config.count_mask[SLI_QTYPE_RQ] = parms->rqe_count_mask;
3805                 sli4->config.count_method[SLI_QTYPE_RQ] = parms->rqe_count_method;
3806
3807                 /* now calculate max queue entries */
3808                 sli_calc_max_qentries(sli4);
3809
3810                 sli4->config.max_sgl_pages = parms->sgl_page_cnt;       /* max # of pages */
3811                 sli4->config.sgl_page_sizes = parms->sgl_page_sizes;    /* bit map of available sizes */
3812                 /* ignore HLM here. Use value from REQUEST_FEATURES */
3813                 
3814                 sli4->config.sge_supported_length = parms->sge_supported_length;
3815                 if (sli4->config.sge_supported_length > OCS_MAX_SGE_SIZE)
3816                         sli4->config.sge_supported_length = OCS_MAX_SGE_SIZE;
3817
3818                 sli4->config.sgl_pre_registration_required = parms->sglr;
3819                 /* default to using pre-registered SGL's */
3820                 sli4->config.sgl_pre_registered = TRUE;
3821
3822                 sli4->config.perf_hint = parms->phon;
3823                 sli4->config.perf_wq_id_association = parms->phwq;
3824
3825                 sli4->config.rq_batch = parms->rq_db_window;
3826
3827                 /* save the fields for skyhawk SGL chaining */
3828                 sli4->config.sgl_chaining_params.chaining_capable =
3829                         (parms->sglc == 1);
3830                 sli4->config.sgl_chaining_params.frag_num_field_offset =
3831                         parms->frag_num_field_offset;
3832                 sli4->config.sgl_chaining_params.frag_num_field_mask =
3833                         (1ull << parms->frag_num_field_size) - 1;
3834                 sli4->config.sgl_chaining_params.sgl_index_field_offset =
3835                         parms->sgl_index_field_offset;
3836                 sli4->config.sgl_chaining_params.sgl_index_field_mask =
3837                         (1ull << parms->sgl_index_field_size) - 1;
3838                 sli4->config.sgl_chaining_params.chain_sge_initial_value_lo =
3839                         parms->chain_sge_initial_value_lo;
3840                 sli4->config.sgl_chaining_params.chain_sge_initial_value_hi =
3841                         parms->chain_sge_initial_value_hi;
3842
3843                 /* Use the highest available WQE size. */
3844                 if (parms->wqe_sizes & SLI4_128BYTE_WQE_SUPPORT) {
3845                         sli4->config.wqe_size = SLI4_WQE_EXT_BYTES;
3846                 } else {
3847                         sli4->config.wqe_size = SLI4_WQE_BYTES;
3848                 }
3849         }
3850
3851         if (sli_query_fw_config(sli4)) {
3852                 ocs_log_err(sli4->os, "Error sending QUERY_FW_CONFIG\n");
3853                 return -1;
3854         }
3855
3856         sli4->config.port_number = 0;
3857
3858         /*
3859          * Issue COMMON_GET_CNTL_ATTRIBUTES to get port_number. Temporarily
3860          * uses VPD DMA buffer as the response won't fit in the embedded
3861          * buffer.
3862          */
3863         if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
3864                 sli4_res_common_get_cntl_attributes_t *attr = sli4->vpd.data.virt;
3865
3866                 if (sli_bmbx_command(sli4)) {
3867                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ATTRIBUTES)\n");
3868                         return -1;
3869                 } else if (attr->hdr.status) {
3870                         ocs_log_err(sli4->os, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x att'l %#x\n",
3871                                         attr->hdr.status, attr->hdr.additional_status);
3872                         return -1;
3873                 }
3874
3875                 sli4->config.port_number = attr->port_number;
3876
3877                 ocs_memcpy(sli4->config.bios_version_string, attr->bios_version_string,
3878                                 sizeof(sli4->config.bios_version_string));
3879         } else {
3880                 ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ATTRIBUTES write\n");
3881                 return -1;
3882         }
3883
3884         if (ocs_dma_alloc(sli4->os, &get_cntl_addl_data, sizeof(sli4_res_common_get_cntl_addl_attributes_t),
3885                           OCS_MIN_DMA_ALIGNMENT)) {
3886                 ocs_log_err(sli4->os, "Failed to allocate memory for GET_CNTL_ADDL_ATTR data\n");
3887         } else {
3888                 if (sli_cmd_common_get_cntl_addl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
3889                                                             &get_cntl_addl_data)) {
3890                         sli4_res_common_get_cntl_addl_attributes_t *attr = get_cntl_addl_data.virt;
3891
3892                         if (sli_bmbx_command(sli4)) {
3893                                 ocs_log_crit(sli4->os,
3894                                              "bootstrap mailbox write fail (COMMON_GET_CNTL_ADDL_ATTRIBUTES)\n");
3895                                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
3896                                 return -1;
3897                         }
3898                         if (attr->hdr.status) {
3899                                 ocs_log_err(sli4->os, "COMMON_GET_CNTL_ADDL_ATTRIBUTES bad status %#x\n",
3900                                             attr->hdr.status);
3901                                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
3902                                 return -1;
3903                         }
3904
3905                         ocs_memcpy(sli4->config.ipl_name, attr->ipl_file_name, sizeof(sli4->config.ipl_name));
3906
3907                         ocs_log_debug(sli4->os, "IPL:%s \n", (char*)sli4->config.ipl_name);
3908                 } else {
3909                         ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ADDL_ATTRIBUTES write\n");
3910                         ocs_dma_free(sli4->os, &get_cntl_addl_data);
3911                         return -1;
3912                 }
3913
3914                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
3915         }
3916
3917         if (sli_cmd_common_get_port_name(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3918                 sli4_res_common_get_port_name_t *port_name = (sli4_res_common_get_port_name_t *)(((uint8_t *)sli4->bmbx.virt) +
3919                         offsetof(sli4_cmd_sli_config_t, payload.embed));
3920
3921                 if (sli_bmbx_command(sli4)) {
3922                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_PORT_NAME)\n");
3923                         return -1;
3924                 }
3925
3926                 sli4->config.port_name[0] = port_name->port_name[sli4->config.port_number];
3927         }
3928         sli4->config.port_name[1] = '\0';
3929
3930         if (sli_cmd_read_rev(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
3931                 sli4_cmd_read_rev_t     *read_rev = sli4->bmbx.virt;
3932
3933                 if (sli_bmbx_command(sli4)) {
3934                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_REV)\n");
3935                         return -1;
3936                 }
3937                 if (read_rev->hdr.status) {
3938                         ocs_log_err(sli4->os, "READ_REV bad status %#x\n",
3939                                         read_rev->hdr.status);
3940                         return -1;
3941                 }
3942
3943                 sli4->config.fw_rev[0] = read_rev->first_fw_id;
3944                 ocs_memcpy(sli4->config.fw_name[0],read_rev->first_fw_name, sizeof(sli4->config.fw_name[0]));
3945
3946                 sli4->config.fw_rev[1] = read_rev->second_fw_id;
3947                 ocs_memcpy(sli4->config.fw_name[1],read_rev->second_fw_name, sizeof(sli4->config.fw_name[1]));
3948
3949                 sli4->config.hw_rev[0] = read_rev->first_hw_revision;
3950                 sli4->config.hw_rev[1] = read_rev->second_hw_revision;
3951                 sli4->config.hw_rev[2] = read_rev->third_hw_revision;
3952
3953                 ocs_log_debug(sli4->os, "FW1:%s (%08x) / FW2:%s (%08x)\n",
3954                                 read_rev->first_fw_name, read_rev->first_fw_id,
3955                                 read_rev->second_fw_name, read_rev->second_fw_id);
3956
3957                 ocs_log_debug(sli4->os, "HW1: %08x / HW2: %08x\n", read_rev->first_hw_revision,
3958                                 read_rev->second_hw_revision);
3959
3960                 /* Check that all VPD data was returned */
3961                 if (read_rev->returned_vpd_length != read_rev->actual_vpd_length) {
3962                         ocs_log_test(sli4->os, "VPD length: available=%d returned=%d actual=%d\n",
3963                                         read_rev->available_length,
3964                                         read_rev->returned_vpd_length,
3965                                         read_rev->actual_vpd_length);
3966                 }
3967                 sli4->vpd.length = read_rev->returned_vpd_length;
3968         } else {
3969                 ocs_log_err(sli4->os, "bad READ_REV write\n");
3970                 return -1;
3971         }
3972
3973         if (sli_cmd_read_nvparms(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3974                 sli4_cmd_read_nvparms_t *read_nvparms = sli4->bmbx.virt;
3975
3976                 if (sli_bmbx_command(sli4)) {
3977                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_NVPARMS)\n");
3978                         return -1;
3979                 }
3980                 if (read_nvparms->hdr.status) {
3981                         ocs_log_err(sli4->os, "READ_NVPARMS bad status %#x\n",
3982                                         read_nvparms->hdr.status);
3983                         return -1;
3984                 }
3985
3986                 ocs_memcpy(sli4->config.wwpn, read_nvparms->wwpn, sizeof(sli4->config.wwpn));
3987                 ocs_memcpy(sli4->config.wwnn, read_nvparms->wwnn, sizeof(sli4->config.wwnn));
3988
3989                 ocs_log_debug(sli4->os, "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
3990                                 sli4->config.wwpn[0],
3991                                 sli4->config.wwpn[1],
3992                                 sli4->config.wwpn[2],
3993                                 sli4->config.wwpn[3],
3994                                 sli4->config.wwpn[4],
3995                                 sli4->config.wwpn[5],
3996                                 sli4->config.wwpn[6],
3997                                 sli4->config.wwpn[7]);
3998                 ocs_log_debug(sli4->os, "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
3999                                 sli4->config.wwnn[0],
4000                                 sli4->config.wwnn[1],
4001                                 sli4->config.wwnn[2],
4002                                 sli4->config.wwnn[3],
4003                                 sli4->config.wwnn[4],
4004                                 sli4->config.wwnn[5],
4005                                 sli4->config.wwnn[6],
4006                                 sli4->config.wwnn[7]);
4007         } else {
4008                 ocs_log_err(sli4->os, "bad READ_NVPARMS write\n");
4009                 return -1;
4010         }
4011
4012         return 0;
4013 }
4014
4015 /****************************************************************************
4016  * Public functions
4017  */
4018
4019 /**
4020  * @ingroup sli
4021  * @brief Set up the SLI context.
4022  *
4023  * @param sli4 SLI context.
4024  * @param os Device abstraction.
4025  * @param port_type Protocol type of port (for example, FC and NIC).
4026  *
4027  * @return Returns 0 on success, or a non-zero value on failure.
4028  */
4029 int32_t
4030 sli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type)
4031 {
4032         uint32_t sli_intf = UINT32_MAX;
4033         uint32_t pci_class_rev = 0;
4034         uint32_t rev_id = 0;
4035         uint32_t family = 0;
4036         uint32_t i;
4037         sli4_asic_entry_t *asic;
4038
4039         ocs_memset(sli4, 0, sizeof(sli4_t));
4040
4041         sli4->os = os;
4042         sli4->port_type = port_type;
4043
4044         /*
4045          * Read the SLI_INTF register to discover the register layout
4046          * and other capability information
4047          */
4048         sli_intf = ocs_config_read32(os, SLI4_INTF_REG);
4049
4050         if (sli_intf_valid_check(sli_intf)) {
4051                 ocs_log_err(os, "SLI_INTF is not valid\n");
4052                 return -1;
4053         }
4054
4055         /* driver only support SLI-4 */
4056         sli4->sli_rev = sli_intf_sli_revision(sli_intf);
4057         if (4 != sli4->sli_rev) {
4058                 ocs_log_err(os, "Unsupported SLI revision (intf=%#x)\n",
4059                                 sli_intf);
4060                 return -1;
4061         }
4062
4063         sli4->sli_family = sli_intf_sli_family(sli_intf);
4064
4065         sli4->if_type = sli_intf_if_type(sli_intf);
4066
4067         if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) ||
4068            (SLI4_IF_TYPE_LANCER_G7 == sli4->if_type)) {
4069                 ocs_log_debug(os, "status=%#x error1=%#x error2=%#x\n",
4070                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
4071                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
4072                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
4073         }
4074
4075         /*
4076          * set the ASIC type and revision
4077          */
4078         pci_class_rev = ocs_config_read32(os, SLI4_PCI_CLASS_REVISION);
4079         rev_id = sli_pci_rev_id(pci_class_rev);
4080         family = sli4->sli_family;
4081         if (family == SLI4_FAMILY_CHECK_ASIC_TYPE) {
4082                 uint32_t asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG);
4083                 family = sli_asic_gen(asic_id);
4084         }
4085
4086         for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table); i++, asic++) {
4087                 if ((rev_id == asic->rev_id) && (family == asic->family)) {
4088                         sli4->asic_type = asic->type;
4089                         sli4->asic_rev = asic->rev;
4090                         break;
4091                 }
4092         }
4093         /* Fail if no matching asic type/rev was found */
4094         if( (sli4->asic_type == 0) || (sli4->asic_rev == 0)) {
4095                 ocs_log_err(os, "no matching asic family/rev found: %02x/%02x\n", family, rev_id);
4096                 return -1;
4097         }
4098
4099         /*
4100          * The bootstrap mailbox is equivalent to a MQ with a single 256 byte
4101          * entry, a CQ with a single 16 byte entry, and no event queue.
4102          * Alignment must be 16 bytes as the low order address bits in the
4103          * address register are also control / status.
4104          */
4105         if (ocs_dma_alloc(sli4->os, &sli4->bmbx, SLI4_BMBX_SIZE +
4106                                 sizeof(sli4_mcqe_t), 16)) {
4107                 ocs_log_err(os, "bootstrap mailbox allocation failed\n");
4108                 return -1;
4109         }
4110
4111         if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) {
4112                 ocs_log_err(os, "bad alignment for bootstrap mailbox\n");
4113                 return -1;
4114         }
4115
4116         ocs_log_debug(os, "bmbx v=%p p=0x%x %08x s=%zd\n", sli4->bmbx.virt,
4117                 ocs_addr32_hi(sli4->bmbx.phys),
4118                 ocs_addr32_lo(sli4->bmbx.phys),
4119                 sli4->bmbx.size);
4120
4121         /* TODO 4096 is arbitrary. What should this value actually be? */
4122         if (ocs_dma_alloc(sli4->os, &sli4->vpd.data, 4096/*TODO*/, 4096)) {
4123                 /* Note that failure isn't fatal in this specific case */
4124                 sli4->vpd.data.size = 0;
4125                 ocs_log_test(os, "VPD buffer allocation failed\n");
4126         }
4127
4128         if (sli_fw_init(sli4)) {
4129                 ocs_log_err(sli4->os, "FW initialization failed\n");
4130                 return -1;
4131         }
4132
4133         /*
4134          * Set one of fcpi(initiator), fcpt(target), fcpc(combined) to true
4135          * in addition to any other desired features
4136          */
4137         sli4->config.features.flag.iaab = TRUE;
4138         sli4->config.features.flag.npiv = TRUE;
4139         sli4->config.features.flag.dif = TRUE;
4140         sli4->config.features.flag.vf = TRUE;
4141         sli4->config.features.flag.fcpc = TRUE;
4142         sli4->config.features.flag.iaar = TRUE;
4143         sli4->config.features.flag.hlm = TRUE;
4144         sli4->config.features.flag.perfh = TRUE;
4145         sli4->config.features.flag.rxseq = TRUE;
4146         sli4->config.features.flag.rxri = TRUE;
4147         sli4->config.features.flag.mrqp = TRUE;
4148
4149         /* use performance hints if available */
4150         if (sli4->config.perf_hint) {
4151                 sli4->config.features.flag.perfh = TRUE;
4152         }
4153
4154         if (sli_request_features(sli4, &sli4->config.features, TRUE)) {
4155                 return -1;
4156         }
4157
4158         if (sli_get_config(sli4)) {
4159                 return -1;
4160         }
4161
4162         return 0;
4163 }
4164
4165 int32_t
4166 sli_init(sli4_t *sli4)
4167 {
4168
4169         if (sli4->config.has_extents) {
4170                 /* TODO COMMON_ALLOC_RESOURCE_EXTENTS */;
4171                 ocs_log_test(sli4->os, "XXX need to implement extent allocation\n");
4172                 return -1;
4173         }
4174
4175         sli4->config.features.flag.hlm = sli4->config.high_login_mode;
4176         sli4->config.features.flag.rxseq = FALSE;
4177         sli4->config.features.flag.rxri  = FALSE;
4178
4179         if (sli_request_features(sli4, &sli4->config.features, FALSE)) {
4180                 return -1;
4181         }
4182
4183         return 0;
4184 }
4185
4186 int32_t
4187 sli_reset(sli4_t *sli4)
4188 {
4189         uint32_t        i;
4190
4191         if (sli_fw_init(sli4)) {
4192                 ocs_log_crit(sli4->os, "FW initialization failed\n");
4193                 return -1;
4194         }
4195
4196         if (sli4->config.extent[0].base) {
4197                 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
4198                 sli4->config.extent[0].base = NULL;
4199         }
4200
4201         for (i = 0; i < SLI_RSRC_MAX; i++) {
4202                 if (sli4->config.extent[i].use_map) {
4203                         ocs_bitmap_free(sli4->config.extent[i].use_map);
4204                         sli4->config.extent[i].use_map = NULL;
4205                 }
4206                 sli4->config.extent[i].base = NULL;
4207         }
4208
4209         if (sli_get_config(sli4)) {
4210                 return -1;
4211         }
4212
4213         return 0;
4214 }
4215
4216 /**
4217  * @ingroup sli
4218  * @brief Issue a Firmware Reset.
4219  *
4220  * @par Description
4221  * Issues a Firmware Reset to the chip.  This reset affects the entire chip,
4222  * so all PCI function on the same PCI bus and device are affected.
4223  * @n @n This type of reset can be used to activate newly downloaded firmware.
4224  * @n @n The driver should be considered to be in an unknown state after this
4225  * reset and should be reloaded.
4226  *
4227  * @param sli4 SLI context.
4228  *
4229  * @return Returns 0 on success, or -1 otherwise.
4230  */
4231
4232 int32_t
4233 sli_fw_reset(sli4_t *sli4)
4234 {
4235         uint32_t val;
4236         uint32_t ready;
4237
4238         /*
4239          * Firmware must be ready before issuing the reset.
4240          */
4241         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
4242         if (!ready) {
4243                 ocs_log_crit(sli4->os, "FW status is NOT ready\n");
4244                 return -1;
4245         }
4246         switch(sli4->if_type) {
4247         case SLI4_IF_TYPE_BE3_SKH_PF:
4248                 /* BE3 / Skyhawk use PCICFG_SOFT_RESET_CSR */
4249                 val = ocs_config_read32(sli4->os, SLI4_PCI_SOFT_RESET_CSR);
4250                 val |= SLI4_PCI_SOFT_RESET_MASK;
4251                 ocs_config_write32(sli4->os, SLI4_PCI_SOFT_RESET_CSR, val);
4252                 break;
4253         case SLI4_IF_TYPE_LANCER_FC_ETH:
4254                 /* Lancer uses PHYDEV_CONTROL */
4255
4256                 val = SLI4_PHYDEV_CONTROL_FRST;
4257                 sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, val);
4258                 break;
4259         default:
4260                 ocs_log_test(sli4->os, "Unexpected iftype %d\n", sli4->if_type);
4261                 return -1;
4262                 break;
4263         }
4264
4265         /* wait for the FW to become ready after the reset */
4266         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
4267         if (!ready) {
4268                 ocs_log_crit(sli4->os, "Failed to become ready after firmware reset\n");
4269                 return -1;
4270         }
4271         return 0;
4272 }
4273
4274 /**
4275  * @ingroup sli
4276  * @brief Tear down a SLI context.
4277  *
4278  * @param sli4 SLI context.
4279  *
4280  * @return Returns 0 on success, or non-zero otherwise.
4281  */
4282 int32_t
4283 sli_teardown(sli4_t *sli4)
4284 {
4285         uint32_t i;
4286
4287         if (sli4->config.extent[0].base) {
4288                 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
4289                 sli4->config.extent[0].base = NULL;
4290         }
4291
4292         for (i = 0; i < SLI_RSRC_MAX; i++) {
4293                 if (sli4->config.has_extents) {
4294                         /* TODO COMMON_DEALLOC_RESOURCE_EXTENTS */;
4295                 }
4296
4297                 sli4->config.extent[i].base = NULL;
4298
4299                 ocs_bitmap_free(sli4->config.extent[i].use_map);
4300                 sli4->config.extent[i].use_map = NULL;
4301         }
4302
4303         if (sli_fw_term(sli4)) {
4304                 ocs_log_err(sli4->os, "FW deinitialization failed\n");
4305         }
4306
4307         ocs_dma_free(sli4->os, &sli4->vpd.data);
4308         ocs_dma_free(sli4->os, &sli4->bmbx);
4309
4310         return 0;
4311 }
4312
4313 /**
4314  * @ingroup sli
4315  * @brief Register a callback for the given event.
4316  *
4317  * @param sli4 SLI context.
4318  * @param which Event of interest.
4319  * @param func Function to call when the event occurs.
4320  * @param arg Argument passed to the callback function.
4321  *
4322  * @return Returns 0 on success, or non-zero otherwise.
4323  */
4324 int32_t
4325 sli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg)
4326 {
4327
4328         if (!sli4 || !func || (which >= SLI4_CB_MAX)) {
4329                 ocs_log_err(NULL, "bad parameter sli4=%p which=%#x func=%p\n",
4330                             sli4, which, func);
4331                 return -1;
4332         }
4333
4334         switch (which) {
4335         case SLI4_CB_LINK:
4336                 sli4->link = func;
4337                 sli4->link_arg = arg;
4338                 break;
4339         case SLI4_CB_FIP:
4340                 sli4->fip = func;
4341                 sli4->fip_arg = arg;
4342                 break;
4343         default:
4344                 ocs_log_test(sli4->os, "unknown callback %#x\n", which);
4345                 return -1;
4346         }
4347
4348         return 0;
4349 }
4350
4351 /**
4352  * @ingroup sli
4353  * @brief Initialize a queue object.
4354  *
4355  * @par Description
4356  * This initializes the sli4_queue_t object members, including the underlying
4357  * DMA memory.
4358  *
4359  * @param sli4 SLI context.
4360  * @param q Pointer to queue object.
4361  * @param qtype Type of queue to create.
4362  * @param size Size of each entry.
4363  * @param n_entries Number of entries to allocate.
4364  * @param align Starting memory address alignment.
4365  *
4366  * @note Checks if using the existing DMA memory (if any) is possible. If not,
4367  * it frees the existing memory and re-allocates.
4368  *
4369  * @return Returns 0 on success, or non-zero otherwise.
4370  */
4371 int32_t
4372 __sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype,
4373                 size_t size, uint32_t n_entries, uint32_t align)
4374 {
4375
4376         if ((q->dma.virt == NULL) || (size != q->size) || (n_entries != q->length)) {
4377                 if (q->dma.size) {
4378                         ocs_dma_free(sli4->os, &q->dma);
4379                 }
4380
4381                 ocs_memset(q, 0, sizeof(sli4_queue_t));
4382
4383                 if (ocs_dma_alloc(sli4->os, &q->dma, size * n_entries, align)) {
4384                         ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
4385                         return -1;
4386                 }
4387
4388                 ocs_memset(q->dma.virt, 0, size * n_entries);
4389
4390                 ocs_lock_init(sli4->os, &q->lock, "%s lock[%d:%p]", 
4391                         SLI_QNAME[qtype], ocs_instance(sli4->os), &q->lock);
4392
4393                 q->type = qtype;
4394                 q->size = size;
4395                 q->length = n_entries;
4396
4397                 /* Limit to hwf the queue size per interrupt */
4398                 q->proc_limit = n_entries / 2;
4399
4400                 if ( (q->type == SLI_QTYPE_EQ) || (q->type == SLI_QTYPE_CQ) ) {
4401                 /* For prism, phase will be flipped after a sweep through eq and cq */
4402                         q->phase = 1;
4403                 }
4404
4405                 switch(q->type) {
4406                 case SLI_QTYPE_EQ:
4407                         q->posted_limit = q->length / 2;
4408                         break;
4409                 default:
4410                         if ((sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) ||
4411                             (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF)) {
4412                                 /* For Skyhawk, ring the doorbell more often */
4413                                 q->posted_limit = 8;
4414                         } else {
4415                                 q->posted_limit = 64;
4416                         }
4417                         break;
4418                 }
4419         }
4420
4421         return 0;
4422 }
4423
4424 /**
4425  * @ingroup sli
4426  * @brief Issue the command to create a queue.
4427  *
4428  * @param sli4 SLI context.
4429  * @param q Pointer to queue object.
4430  *
4431  * @return Returns 0 on success, or non-zero otherwise.
4432  */
4433 int32_t
4434 __sli_create_queue(sli4_t *sli4, sli4_queue_t *q)
4435 {
4436         sli4_res_common_create_queue_t *res_q = NULL;
4437
4438         if (sli_bmbx_command(sli4)){
4439                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail %s\n",
4440                                 SLI_QNAME[q->type]);
4441                 ocs_dma_free(sli4->os, &q->dma);
4442                 return -1;
4443         }
4444         if (sli_res_sli_config(sli4->bmbx.virt)) {
4445                 ocs_log_err(sli4->os, "bad status create %s\n", SLI_QNAME[q->type]);
4446                 ocs_dma_free(sli4->os, &q->dma);
4447                 return -1;
4448         }
4449         res_q = (void *)((uint8_t *)sli4->bmbx.virt +
4450                         offsetof(sli4_cmd_sli_config_t, payload));
4451
4452         if (res_q->hdr.status) {
4453                 ocs_log_err(sli4->os, "bad create %s status=%#x addl=%#x\n",
4454                                 SLI_QNAME[q->type],
4455                                 res_q->hdr.status, res_q->hdr.additional_status);
4456                 ocs_dma_free(sli4->os, &q->dma);
4457                 return -1;
4458         } else {
4459                 q->id = res_q->q_id;
4460                 q->doorbell_offset = res_q->db_offset;
4461                 q->doorbell_rset = res_q->db_rs;
4462
4463                 switch (q->type) {
4464                 case SLI_QTYPE_EQ:
4465                         /* No doorbell information in response for EQs */
4466                         q->doorbell_offset = regmap[SLI4_REG_EQ_DOORBELL][sli4->if_type].off;
4467                         q->doorbell_rset   = regmap[SLI4_REG_EQ_DOORBELL][sli4->if_type].rset;
4468                         break;
4469                 case SLI_QTYPE_CQ:
4470                         /* No doorbell information in response for CQs */
4471                         q->doorbell_offset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].off;
4472                         q->doorbell_rset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].rset;
4473                         break;
4474                 case SLI_QTYPE_MQ:
4475                         /* No doorbell information in response for MQs */
4476                         q->doorbell_offset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].off;
4477                         q->doorbell_rset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].rset;
4478                         break;
4479                 case SLI_QTYPE_RQ:
4480                         /* set the doorbell for non-skyhawks */
4481                         if (!sli4->config.dual_ulp_capable) {
4482                                 q->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
4483                                 q->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
4484                         }
4485                         break;
4486                 case SLI_QTYPE_WQ:
4487                         /* set the doorbell for non-skyhawks */
4488                         if (!sli4->config.dual_ulp_capable) {
4489                                 q->doorbell_offset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].off;
4490                                 q->doorbell_rset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].rset;
4491                         }
4492                         break;
4493                 default:
4494                         break;
4495                 }
4496         }
4497
4498         return 0;
4499 }
4500
4501 /**
4502  * @ingroup sli
4503  * @brief Get queue entry size.
4504  *
4505  * Get queue entry size given queue type.
4506  *
4507  * @param sli4 SLI context
4508  * @param qtype Type for which the entry size is returned.
4509  *
4510  * @return Returns > 0 on success (queue entry size), or a negative value on failure.
4511  */
4512 int32_t
4513 sli_get_queue_entry_size(sli4_t *sli4, uint32_t qtype)
4514 {
4515         uint32_t        size = 0;
4516
4517         if (!sli4) {
4518                 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
4519                 return -1;
4520         }
4521
4522         switch (qtype) {
4523         case SLI_QTYPE_EQ:
4524                 size = sizeof(uint32_t);
4525                 break;
4526         case SLI_QTYPE_CQ:
4527                 size = 16;
4528                 break;
4529         case SLI_QTYPE_MQ:
4530                 size = 256;
4531                 break;
4532         case SLI_QTYPE_WQ:
4533                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4534                         size = sli4->config.wqe_size;
4535                 } else {
4536                         /* TODO */
4537                         ocs_log_test(sli4->os, "unsupported queue entry size\n");
4538                         return -1;
4539                 }
4540                 break;
4541         case SLI_QTYPE_RQ:
4542                 size = SLI4_FCOE_RQE_SIZE;
4543                 break;
4544         default:
4545                 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
4546                 return -1;
4547         }
4548         return size;
4549 }
4550
4551 /**
4552  * @ingroup sli
4553  * @brief Modify the delay timer for all the EQs
4554  *
4555  * @param sli4 SLI context.
4556  * @param eq Array of EQs.
4557  * @param num_eq Count of EQs.
4558  * @param shift Phase shift for staggering interrupts.
4559  * @param delay_mult Delay multiplier for limiting interrupt frequency.
4560  *
4561  * @return Returns 0 on success, or -1 otherwise.
4562  */
4563 int32_t
4564 sli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult)
4565 {
4566
4567         sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, eq, num_eq, shift, delay_mult);
4568
4569         if (sli_bmbx_command(sli4)) {
4570                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n");
4571                 return -1;
4572         }
4573         if (sli_res_sli_config(sli4->bmbx.virt)) {
4574                 ocs_log_err(sli4->os, "bad status MODIFY EQ DELAY\n");
4575                 return -1;
4576         }
4577
4578         return 0;
4579 }
4580
4581 /**
4582  * @ingroup sli
4583  * @brief Allocate a queue.
4584  *
4585  * @par Description
4586  * Allocates DMA memory and configures the requested queue type.
4587  *
4588  * @param sli4 SLI context.
4589  * @param qtype Type of queue to create.
4590  * @param q Pointer to the queue object.
4591  * @param n_entries Number of entries to allocate.
4592  * @param assoc Associated queue (that is, the EQ for a CQ, the CQ for a MQ, and so on).
4593  * @param ulp The ULP to bind, which is only used for WQ and RQs
4594  *
4595  * @return Returns 0 on success, or -1 otherwise.
4596  */
4597 int32_t
4598 sli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries,
4599                 sli4_queue_t *assoc, uint16_t ulp)
4600 {
4601         int32_t         size;
4602         uint32_t        align = 0;
4603         sli4_create_q_fn_t create = NULL;
4604
4605         if (!sli4 || !q) {
4606                 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
4607                 return -1;
4608         }
4609
4610         /* get queue size */
4611         size = sli_get_queue_entry_size(sli4, qtype);
4612         if (size < 0)
4613                 return -1;
4614         align = SLI_PAGE_SIZE;
4615
4616         switch (qtype) {
4617         case SLI_QTYPE_EQ:
4618                 create = sli_cmd_common_create_eq;
4619                 break;
4620         case SLI_QTYPE_CQ:
4621                 create = sli_cmd_common_create_cq;
4622                 break;
4623         case SLI_QTYPE_MQ:
4624                 /* Validate the number of entries */
4625                 switch (n_entries) {
4626                 case 16:
4627                 case 32:
4628                 case 64:
4629                 case 128:
4630                         break;
4631                 default:
4632                         ocs_log_test(sli4->os, "illegal n_entries value %d for MQ\n", n_entries);
4633                         return -1;
4634                 }
4635                 assoc->u.flag.is_mq = TRUE;
4636                 create = sli_cmd_common_create_mq_ext;
4637                 break;
4638         case SLI_QTYPE_WQ:
4639                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4640                         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
4641                                 create = sli_cmd_fcoe_wq_create;
4642                         } else {
4643                                 create = sli_cmd_fcoe_wq_create_v1;
4644                         }
4645                 } else {
4646                         /* TODO */
4647                         ocs_log_test(sli4->os, "unsupported WQ create\n");
4648                         return -1;
4649                 }
4650                 break;
4651         default:
4652                 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
4653                 return -1;
4654         }
4655
4656         if (__sli_queue_init(sli4, q, qtype, size, n_entries, align)) {
4657                 ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
4658                 return -1;
4659         }
4660
4661         if (create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma, assoc ? assoc->id : 0, ulp)) {
4662                 if (__sli_create_queue(sli4, q)) {
4663                         ocs_log_err(sli4->os, "create %s failed\n", SLI_QNAME[qtype]);
4664                         return -1;
4665                 }
4666                 q->ulp = ulp;
4667         } else {
4668                 ocs_log_err(sli4->os, "cannot create %s\n", SLI_QNAME[qtype]);
4669                 return -1;
4670         }
4671
4672         return 0;
4673 }
4674
4675 /**
4676  * @ingroup sli
4677  * @brief Allocate a c queue set.
4678  *
4679  * @param sli4 SLI context.
4680  * @param num_cqs to create
4681  * @param qs Pointers to the queue objects.
4682  * @param n_entries Number of entries to allocate per CQ.
4683  * @param eqs Associated event queues
4684  *
4685  * @return Returns 0 on success, or -1 otherwise.
4686  */
4687 int32_t
4688 sli_cq_alloc_set(sli4_t *sli4, sli4_queue_t *qs[], uint32_t num_cqs,
4689                  uint32_t n_entries, sli4_queue_t *eqs[])
4690 {
4691         uint32_t i, offset = 0,  page_bytes = 0, payload_size, cmd_size = 0;
4692         uint32_t p = 0, page_size = 0, n_cqe = 0, num_pages_cq;
4693         uintptr_t addr;
4694         ocs_dma_t dma;
4695         sli4_req_common_create_cq_set_v0_t  *req = NULL;
4696         sli4_res_common_create_queue_set_t *res = NULL;
4697
4698         if (!sli4) {
4699                 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
4700                 return -1;
4701         }
4702
4703         memset(&dma, 0, sizeof(dma));
4704
4705         /* Align the queue DMA memory */
4706         for (i = 0; i < num_cqs; i++) {
4707                 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_CQ, SLI4_CQE_BYTES,
4708                         n_entries, SLI_PAGE_SIZE)) {
4709                         ocs_log_err(sli4->os, "Queue init failed.\n");
4710                         goto error;
4711                 }
4712         }
4713
4714         n_cqe = qs[0]->dma.size / SLI4_CQE_BYTES;
4715         switch (n_cqe) {
4716         case 256:
4717         case 512:
4718         case 1024:
4719         case 2048:
4720                 page_size = 1;
4721                 break;
4722         case 4096:
4723                 page_size = 2;
4724                 break;
4725         default:
4726                 return -1;
4727         }
4728
4729         page_bytes = page_size * SLI_PAGE_SIZE;
4730         num_pages_cq = sli_page_count(qs[0]->dma.size, page_bytes);
4731         cmd_size = sizeof(sli4_req_common_create_cq_set_v0_t) + (8 * num_pages_cq * num_cqs);
4732         payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_set_t));
4733
4734         if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
4735                 ocs_log_err(sli4->os, "DMA allocation failed\n");
4736                 goto error;
4737         }
4738         ocs_memset(dma.virt, 0, payload_size);
4739
4740         if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 
4741                         payload_size, &dma) == -1) {
4742                 goto error;
4743         }
4744
4745         /* Fill the request structure */
4746
4747         req = (sli4_req_common_create_cq_set_v0_t *)((uint8_t *)dma.virt);
4748         req->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ_SET;
4749         req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
4750         req->hdr.version = 0;
4751         req->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
4752         req->page_size = page_size;
4753
4754         req->num_pages = num_pages_cq;
4755         switch (req->num_pages) {
4756         case 1:
4757                 req->cqecnt = SLI4_CQ_CNT_256;
4758                 break;
4759         case 2:
4760                 req->cqecnt = SLI4_CQ_CNT_512;
4761                 break;
4762         case 4:
4763                 req->cqecnt = SLI4_CQ_CNT_1024;
4764                 break;
4765         case 8:
4766                 req->cqecnt = SLI4_CQ_CNT_LARGE;
4767                 req->cqe_count = n_cqe;
4768                 break;
4769         default:
4770                 ocs_log_test(sli4->os, "num_pages %d not valid\n", req->num_pages);
4771                 goto error;
4772         }
4773
4774         req->evt = TRUE;
4775         req->valid = TRUE;
4776         req->arm = FALSE;
4777         req->num_cq_req = num_cqs;
4778
4779         if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
4780                 req->autovalid = TRUE;
4781
4782         /* Fill page addresses of all the CQs. */
4783         for (i = 0; i < num_cqs; i++) {
4784                 req->eq_id[i] = eqs[i]->id;
4785                 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += page_bytes) {
4786                         req->page_physical_address[offset].low = ocs_addr32_lo(addr);
4787                         req->page_physical_address[offset].high = ocs_addr32_hi(addr);
4788                         offset++;
4789                 }
4790         }
4791
4792         if (sli_bmbx_command(sli4)) {
4793                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail CQSet\n");
4794                 goto error;
4795         }
4796
4797         res = (void *)((uint8_t *)dma.virt);
4798         if (res->hdr.status) {
4799                 ocs_log_err(sli4->os, "bad create CQSet status=%#x addl=%#x\n",
4800                         res->hdr.status, res->hdr.additional_status);
4801                 goto error;
4802         } else {
4803                 /* Check if we got all requested CQs. */
4804                 if (res->num_q_allocated != num_cqs) {
4805                         ocs_log_crit(sli4->os, "Requested count CQs doesnt match.\n");
4806                         goto error;
4807                 }
4808
4809                 /* Fill the resp cq ids. */
4810                 for (i = 0; i < num_cqs; i++) {
4811                         qs[i]->id = res->q_id + i;
4812                         qs[i]->doorbell_offset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].off;
4813                         qs[i]->doorbell_rset   = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].rset;
4814                 }
4815         }
4816
4817         ocs_dma_free(sli4->os, &dma);
4818
4819         return 0;
4820
4821 error:
4822         for (i = 0; i < num_cqs; i++) {
4823                 if (qs[i]->dma.size) {
4824                         ocs_dma_free(sli4->os, &qs[i]->dma);
4825                 }
4826         }
4827
4828         if (dma.size) {
4829                 ocs_dma_free(sli4->os, &dma);
4830         }
4831
4832         return -1;
4833 }
4834
4835 /**
4836  * @ingroup sli
4837  * @brief Free a queue.
4838  *
4839  * @par Description
4840  * Frees DMA memory and de-registers the requested queue.
4841  *
4842  * @param sli4 SLI context.
4843  * @param q Pointer to the queue object.
4844  * @param destroy_queues Non-zero if the mailbox commands should be sent to destroy the queues.
4845  * @param free_memory Non-zero if the DMA memory associated with the queue should be freed.
4846  *
4847  * @return Returns 0 on success, or -1 otherwise.
4848  */
4849 int32_t
4850 sli_queue_free(sli4_t *sli4, sli4_queue_t *q, uint32_t destroy_queues, uint32_t free_memory)
4851 {
4852         sli4_destroy_q_fn_t destroy = NULL;
4853         int32_t         rc = -1;
4854
4855         if (!sli4 || !q) {
4856                 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
4857                 return -1;
4858         }
4859
4860         if (destroy_queues) {
4861                 switch (q->type) {
4862                 case SLI_QTYPE_EQ:
4863                         destroy = sli_cmd_common_destroy_eq;
4864                         break;
4865                 case SLI_QTYPE_CQ:
4866                         destroy = sli_cmd_common_destroy_cq;
4867                         break;
4868                 case SLI_QTYPE_MQ:
4869                         destroy = sli_cmd_common_destroy_mq;
4870                         break;
4871                 case SLI_QTYPE_WQ:
4872                         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4873                                 destroy = sli_cmd_fcoe_wq_destroy;
4874                         } else {
4875                                 /* TODO */
4876                                 ocs_log_test(sli4->os, "unsupported WQ destroy\n");
4877                                 return -1;
4878                         }
4879                         break;
4880                 case SLI_QTYPE_RQ:
4881                         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4882                                 destroy = sli_cmd_fcoe_rq_destroy;
4883                         } else {
4884                                 /* TODO */
4885                                 ocs_log_test(sli4->os, "unsupported RQ destroy\n");
4886                                 return -1;
4887                         }
4888                         break;
4889                 default:
4890                         ocs_log_test(sli4->os, "bad queue type %d\n",
4891                                         q->type);
4892                         return -1;
4893                 }
4894
4895                 /*
4896                  * Destroying queues makes BE3 sad (version 0 interface type). Rely
4897                  * on COMMON_FUNCTION_RESET to free host allocated queue resources
4898                  * inside the SLI Port.
4899                  */
4900                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
4901                         destroy = NULL;
4902                 }
4903
4904                 /* Destroy the queue if the operation is defined */
4905                 if (destroy && destroy(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, q->id)) {
4906                         sli4_res_hdr_t  *res = NULL;
4907
4908                         if (sli_bmbx_command(sli4)){
4909                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail destroy %s\n",
4910                                                 SLI_QNAME[q->type]);
4911                         } else if (sli_res_sli_config(sli4->bmbx.virt)) {
4912                                 ocs_log_err(sli4->os, "bad status destroy %s\n", SLI_QNAME[q->type]);
4913                         } else {
4914                                 res = (void *)((uint8_t *)sli4->bmbx.virt +
4915                                                 offsetof(sli4_cmd_sli_config_t, payload));
4916
4917                                 if (res->status) {
4918                                         ocs_log_err(sli4->os, "bad destroy %s status=%#x addl=%#x\n",
4919                                                         SLI_QNAME[q->type],
4920                                                         res->status, res->additional_status);
4921                                 } else {
4922                                         rc = 0;
4923                                 }
4924                         }
4925                 }
4926         }
4927
4928         if (free_memory) {
4929                 ocs_lock_free(&q->lock);
4930
4931                 if (ocs_dma_free(sli4->os, &q->dma)) {
4932                         ocs_log_err(sli4->os, "%s queue ID %d free failed\n",
4933                                     SLI_QNAME[q->type], q->id);
4934                         rc = -1;
4935                 }
4936         }
4937
4938         return rc;
4939 }
4940
4941 int32_t
4942 sli_queue_reset(sli4_t *sli4, sli4_queue_t *q)
4943 {
4944
4945         ocs_lock(&q->lock);
4946
4947         q->index = 0;
4948         q->n_posted = 0;
4949
4950         if (SLI_QTYPE_MQ == q->type) {
4951                 q->u.r_idx = 0;
4952         }
4953
4954         if (q->dma.virt != NULL) {
4955                 ocs_memset(q->dma.virt, 0, (q->size * (uint64_t)q->length));
4956         }
4957
4958         ocs_unlock(&q->lock);
4959
4960         return 0;
4961 }
4962
4963 /**
4964  * @ingroup sli
4965  * @brief Check if the given queue is empty.
4966  *
4967  * @par Description
4968  * If the valid bit of the current entry is unset, the queue is empty.
4969  *
4970  * @param sli4 SLI context.
4971  * @param q Pointer to the queue object.
4972  *
4973  * @return Returns TRUE if empty, or FALSE otherwise.
4974  */
4975 int32_t
4976 sli_queue_is_empty(sli4_t *sli4, sli4_queue_t *q)
4977 {
4978         int32_t         rc = TRUE;
4979         uint8_t         *qe = q->dma.virt;
4980
4981         ocs_lock(&q->lock);
4982
4983         ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
4984
4985         qe += q->index * q->size;
4986
4987         rc = !sli_queue_entry_is_valid(q, qe, FALSE);
4988
4989         ocs_unlock(&q->lock);
4990
4991         return rc;
4992 }
4993
4994 /**
4995  * @ingroup sli
4996  * @brief Arm an EQ.
4997  *
4998  * @param sli4 SLI context.
4999  * @param q Pointer to queue object.
5000  * @param arm If TRUE, arm the EQ.
5001  *
5002  * @return Returns 0 on success, or non-zero otherwise.
5003  */
5004 int32_t
5005 sli_queue_eq_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
5006 {
5007         uint32_t        val = 0;
5008
5009         ocs_lock(&q->lock);
5010         if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
5011                 val = sli_iftype6_eq_doorbell(q->n_posted, q->id, arm);
5012         else
5013                 val = sli_eq_doorbell(q->n_posted, q->id, arm);
5014
5015         ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
5016         q->n_posted = 0;
5017         ocs_unlock(&q->lock);
5018
5019         return 0;
5020 }
5021
5022 /**
5023  * @ingroup sli
5024  * @brief Arm a queue.
5025  *
5026  * @param sli4 SLI context.
5027  * @param q Pointer to queue object.
5028  * @param arm If TRUE, arm the queue.
5029  *
5030  * @return Returns 0 on success, or non-zero otherwise.
5031  */
5032 int32_t
5033 sli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
5034 {
5035         uint32_t        val = 0;
5036
5037         ocs_lock(&q->lock);
5038
5039         switch (q->type) {
5040         case SLI_QTYPE_EQ:
5041                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
5042                         val = sli_iftype6_eq_doorbell(q->n_posted, q->id, arm);
5043                 else
5044                         val = sli_eq_doorbell(q->n_posted, q->id, arm);
5045                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
5046                 q->n_posted = 0;
5047                 break;
5048         case SLI_QTYPE_CQ:
5049                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
5050                         val = sli_iftype6_cq_doorbell(q->n_posted, q->id, arm);
5051                 else
5052                         val = sli_cq_doorbell(q->n_posted, q->id, arm);
5053                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
5054                 q->n_posted = 0;
5055                 break;
5056         default:
5057                 ocs_log_test(sli4->os, "should only be used for EQ/CQ, not %s\n",
5058                              SLI_QNAME[q->type]);
5059         }
5060
5061         ocs_unlock(&q->lock);
5062
5063         return 0;
5064 }
5065
5066 /**
5067  * @ingroup sli
5068  * @brief Write an entry to the queue object.
5069  *
5070  * Note: Assumes the q->lock will be locked and released by the caller.
5071  *
5072  * @param sli4 SLI context.
5073  * @param q Pointer to the queue object.
5074  * @param entry Pointer to the entry contents.
5075  *
5076  * @return Returns queue index on success, or negative error value otherwise.
5077  */
5078 int32_t
5079 _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
5080 {
5081         int32_t         rc = 0;
5082         uint8_t         *qe = q->dma.virt;
5083         uint32_t        qindex;
5084
5085         qindex = q->index;
5086         qe += q->index * q->size;
5087
5088         if (entry) {
5089                 if ((SLI_QTYPE_WQ == q->type) && sli4->config.perf_wq_id_association) {
5090                         sli_set_wq_id_association(entry, q->id);
5091                 }
5092 #if defined(OCS_INCLUDE_DEBUG)
5093                 switch (q->type) {
5094                 case SLI_QTYPE_WQ: {
5095                         ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, "wqe", entry, q->size);
5096                         break;
5097                 }
5098                 case SLI_QTYPE_MQ:
5099                         /* Note: we don't really need to dump the whole 
5100                          * 256 bytes, just do 64 */
5101                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mqe outbound", entry, 64);
5102                         break;
5103
5104                 default:
5105                         break;
5106                 }
5107 #endif
5108                 ocs_memcpy(qe, entry, q->size);
5109                 q->n_posted = 1;
5110         }
5111
5112         ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
5113
5114         rc = sli_queue_doorbell(sli4, q);
5115
5116         q->index = (q->index + q->n_posted) & (q->length - 1);
5117         q->n_posted = 0;
5118
5119         if (rc < 0) {
5120                 /* failure */
5121                 return rc;
5122         } else if (rc > 0) {
5123                 /* failure, but we need to return a negative value on failure */
5124                 return -rc;
5125         } else {
5126                 return qindex;
5127         }
5128 }
5129
5130 /**
5131  * @ingroup sli
5132  * @brief Write an entry to the queue object.
5133  *
5134  * Note: Assumes the q->lock will be locked and released by the caller.
5135  *
5136  * @param sli4 SLI context.
5137  * @param q Pointer to the queue object.
5138  * @param entry Pointer to the entry contents.
5139  *
5140  * @return Returns queue index on success, or negative error value otherwise.
5141  */
5142 int32_t
5143 sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
5144 {
5145         int32_t rc;
5146
5147         ocs_lock(&q->lock);
5148                 rc = _sli_queue_write(sli4, q, entry);
5149         ocs_unlock(&q->lock);
5150
5151         return rc;
5152 }
5153
5154 /**
5155  * @brief Check if the current queue entry is valid.
5156  *
5157  * @param q Pointer to the queue object.
5158  * @param qe Pointer to the queue entry.
5159  * @param clear Boolean to clear valid bit.
5160  *
5161  * @return Returns TRUE if the entry is valid, or FALSE otherwise.
5162  */
5163 static uint8_t
5164 sli_queue_entry_is_valid(sli4_queue_t *q, uint8_t *qe, uint8_t clear)
5165 {
5166         uint8_t         valid = FALSE;
5167         uint8_t         valid_bit_set = 0;
5168
5169         switch (q->type) {
5170         case SLI_QTYPE_EQ:
5171                 valid = (((sli4_eqe_t *)qe)->vld == q->phase) ? 1 : 0;
5172                 if (valid && clear) {
5173                         ((sli4_eqe_t *)qe)->vld = 0;
5174                 }
5175                 break;
5176         case SLI_QTYPE_CQ:
5177                 /*
5178                  * For both MCQE and WCQE/RCQE, the valid bit
5179                  * is bit 31 of dword 3 (0 based)
5180                  */
5181                 valid_bit_set = (qe[15] & 0x80) != 0;
5182                 if (valid_bit_set == q->phase)
5183                         valid = 1;
5184
5185                 if (valid & clear) {
5186                         qe[15] &= ~0x80;
5187                 }
5188                 break;
5189         case SLI_QTYPE_MQ:
5190                 valid = q->index != q->u.r_idx;
5191                 break;
5192         case SLI_QTYPE_RQ:
5193                 valid = TRUE;
5194                 clear = FALSE;
5195                 break;
5196         default:
5197                 ocs_log_test(NULL, "doesn't handle type=%#x\n", q->type);
5198         }
5199
5200         if (clear) {
5201
5202                 ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
5203         }
5204
5205         return valid;
5206 }
5207
5208 /**
5209  * @ingroup sli
5210  * @brief Read an entry from the queue object.
5211  *
5212  * @param sli4 SLI context.
5213  * @param q Pointer to the queue object.
5214  * @param entry Destination pointer for the queue entry contents.
5215  *
5216  * @return Returns 0 on success, or non-zero otherwise.
5217  */
5218 int32_t
5219 sli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
5220 {
5221         int32_t         rc = 0;
5222         uint8_t         *qe = q->dma.virt;
5223         uint32_t        *qindex = NULL;
5224
5225         uint8_t         clear = (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4)) ?  FALSE : TRUE;
5226         if (SLI_QTYPE_MQ == q->type) {
5227                 qindex = &q->u.r_idx;
5228         } else {
5229                 qindex = &q->index;
5230         }
5231
5232         ocs_lock(&q->lock);
5233
5234         ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
5235
5236         qe += *qindex * q->size;
5237
5238         if (!sli_queue_entry_is_valid(q, qe, clear)) {
5239                 ocs_unlock(&q->lock);
5240                 return -1;
5241         }
5242
5243         if (entry) {
5244                 ocs_memcpy(entry, qe, q->size);
5245 #if defined(OCS_INCLUDE_DEBUG)
5246                 switch(q->type) {
5247                 case SLI_QTYPE_CQ:
5248                         ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "cq", entry, q->size);
5249                         break;
5250                 case SLI_QTYPE_MQ:
5251                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mq Compl", entry, 64);
5252                         break;
5253                 case SLI_QTYPE_EQ:
5254                         ocs_dump32(OCS_DEBUG_ENABLE_EQ_DUMP, sli4->os, "eq Compl", entry, q->size);
5255                         break;
5256                 default:
5257                         break;
5258                 }
5259 #endif
5260         }
5261
5262         switch (q->type) {
5263                 case SLI_QTYPE_EQ:
5264                 case SLI_QTYPE_CQ:
5265                 case SLI_QTYPE_MQ:
5266                         *qindex = (*qindex + 1) & (q->length - 1);
5267                         if (SLI_QTYPE_MQ != q->type) {
5268                                 q->n_posted++;
5269                                 /*
5270                                  * For prism, the phase value will be used to check the validity of eq/cq entries.
5271                                  * The value toggles after a complete sweep through the queue.
5272                                  */
5273                                 if ((SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4)) && (*qindex == 0)) {
5274                                         q->phase ^= (uint16_t) 0x1;
5275                                 }
5276                         }
5277                         break;
5278                 default:
5279                         /* reads don't update the index */
5280                         break;
5281         }
5282
5283         ocs_unlock(&q->lock);
5284
5285         return rc;
5286 }
5287
5288 int32_t
5289 sli_queue_index(sli4_t *sli4, sli4_queue_t *q)
5290 {
5291
5292         if (q) {
5293                 return q->index;
5294         } else {
5295                 return -1;
5296         }
5297 }
5298
5299 int32_t
5300 sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
5301 {
5302         int32_t rc;
5303
5304         ocs_lock(&q->lock);
5305                 rc = _sli_queue_poke(sli4, q, index, entry);
5306         ocs_unlock(&q->lock);
5307
5308         return rc;
5309 }
5310
5311 int32_t
5312 _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
5313 {
5314         int32_t         rc = 0;
5315         uint8_t         *qe = q->dma.virt;
5316
5317         if (index >= q->length) {
5318                 return -1;
5319         }
5320
5321         qe += index * q->size;
5322
5323         if (entry) {
5324                 ocs_memcpy(qe, entry, q->size);
5325         }
5326
5327         ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
5328
5329         return rc;
5330 }
5331
5332 /**
5333  * @ingroup sli
5334  * @brief Allocate SLI Port resources.
5335  *
5336  * @par Description
5337  * Allocate port-related resources, such as VFI, RPI, XRI, and so on.
5338  * Resources are modeled using extents, regardless of whether the underlying
5339  * device implements resource extents. If the device does not implement
5340  * extents, the SLI layer models this as a single (albeit large) extent.
5341  *
5342  * @param sli4 SLI context.
5343  * @param rtype Resource type (for example, RPI or XRI)
5344  * @param rid Allocated resource ID.
5345  * @param index Index into the bitmap.
5346  *
5347  * @return Returns 0 on success, or a non-zero value on failure.
5348  */
5349 int32_t
5350 sli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index)
5351 {
5352         int32_t         rc = 0;
5353         uint32_t        size;
5354         uint32_t        extent_idx;
5355         uint32_t        item_idx;
5356         int             status;
5357
5358         *rid = UINT32_MAX;
5359         *index = UINT32_MAX;
5360
5361         switch (rtype) {
5362         case SLI_RSRC_FCOE_VFI:
5363         case SLI_RSRC_FCOE_VPI:
5364         case SLI_RSRC_FCOE_RPI:
5365         case SLI_RSRC_FCOE_XRI:
5366                 status = ocs_bitmap_find(sli4->config.extent[rtype].use_map,
5367                                 sli4->config.extent[rtype].map_size);
5368                 if (status < 0) {
5369                         ocs_log_err(sli4->os, "out of resource %d (alloc=%d)\n",
5370                                         rtype, sli4->config.extent[rtype].n_alloc);
5371                         rc = -1;
5372                         break;
5373                 } else {
5374                         *index = status;
5375                 }
5376
5377                 size = sli4->config.extent[rtype].size;
5378
5379                 extent_idx = *index / size;
5380                 item_idx   = *index % size;
5381
5382                 *rid = sli4->config.extent[rtype].base[extent_idx] + item_idx;
5383
5384                 sli4->config.extent[rtype].n_alloc++;
5385                 break;
5386         default:
5387                 rc = -1;
5388         }
5389
5390         return rc;
5391 }
5392
5393 /**
5394  * @ingroup sli
5395  * @brief Free the SLI Port resources.
5396  *
5397  * @par Description
5398  * Free port-related resources, such as VFI, RPI, XRI, and so. See discussion of
5399  * "extent" usage in sli_resource_alloc.
5400  *
5401  * @param sli4 SLI context.
5402  * @param rtype Resource type (for example, RPI or XRI).
5403  * @param rid Allocated resource ID.
5404  *
5405  * @return Returns 0 on success, or a non-zero value on failure.
5406  */
5407 int32_t
5408 sli_resource_free(sli4_t *sli4, sli4_resource_e rtype, uint32_t rid)
5409 {
5410         int32_t         rc = -1;
5411         uint32_t        x;
5412         uint32_t        size, *base;
5413
5414         switch (rtype) {
5415         case SLI_RSRC_FCOE_VFI:
5416         case SLI_RSRC_FCOE_VPI:
5417         case SLI_RSRC_FCOE_RPI:
5418         case SLI_RSRC_FCOE_XRI:
5419                 /*
5420                  * Figure out which extent contains the resource ID. I.e. find
5421                  * the extent such that
5422                  *   extent->base <= resource ID < extent->base + extent->size
5423                  */
5424                 base = sli4->config.extent[rtype].base;
5425                 size = sli4->config.extent[rtype].size;
5426
5427                 /*
5428                  * In the case of FW reset, this may be cleared but the force_free path will
5429                  * still attempt to free the resource. Prevent a NULL pointer access.
5430                  */
5431                 if (base != NULL) {
5432                         for (x = 0; x < sli4->config.extent[rtype].number; x++) {
5433                                 if ((rid >= base[x]) && (rid < (base[x] + size))) {
5434                                         rid -= base[x];
5435                                         ocs_bitmap_clear(sli4->config.extent[rtype].use_map,
5436                                                          (x * size) + rid);
5437                                         rc = 0;
5438                                         break;
5439                                 }
5440                         }
5441                 }
5442                 break;
5443         default:
5444                 ;
5445         }
5446
5447         return rc;
5448 }
5449
5450 int32_t
5451 sli_resource_reset(sli4_t *sli4, sli4_resource_e rtype)
5452 {
5453         int32_t         rc = -1;
5454         uint32_t        i;
5455
5456         switch (rtype) {
5457         case SLI_RSRC_FCOE_VFI:
5458         case SLI_RSRC_FCOE_VPI:
5459         case SLI_RSRC_FCOE_RPI:
5460         case SLI_RSRC_FCOE_XRI:
5461                 for (i = 0; i < sli4->config.extent[rtype].map_size; i++) {
5462                         ocs_bitmap_clear(sli4->config.extent[rtype].use_map, i);
5463                 }
5464                 rc = 0;
5465                 break;
5466         default:
5467                 ;
5468         }
5469
5470         return rc;
5471 }
5472
5473 /**
5474  * @ingroup sli
5475  * @brief Parse an EQ entry to retrieve the CQ_ID for this event.
5476  *
5477  * @param sli4 SLI context.
5478  * @param buf Pointer to the EQ entry.
5479  * @param cq_id CQ_ID for this entry (only valid on success).
5480  *
5481  * @return
5482  * - 0 if success.
5483  * - < 0 if error.
5484  * - > 0 if firmware detects EQ overflow.
5485  */
5486 int32_t
5487 sli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id)
5488 {
5489         sli4_eqe_t      *eqe = (void *)buf;
5490         int32_t         rc = 0;
5491
5492         if (!sli4 || !buf || !cq_id) {
5493                 ocs_log_err(NULL, "bad parameters sli4=%p buf=%p cq_id=%p\n",
5494                                 sli4, buf, cq_id);
5495                 return -1;
5496         }
5497
5498         switch (eqe->major_code) {
5499         case SLI4_MAJOR_CODE_STANDARD:
5500                 *cq_id = eqe->resource_id;
5501                 break;
5502         case SLI4_MAJOR_CODE_SENTINEL:
5503                 ocs_log_debug(sli4->os, "sentinel EQE\n");
5504                 rc = 1;
5505                 break;
5506         default:
5507                 ocs_log_test(sli4->os, "Unsupported EQE: major %x minor %x\n",
5508                                 eqe->major_code, eqe->minor_code);
5509                 rc = -1;
5510         }
5511
5512         return rc;
5513 }
5514
5515 /**
5516  * @ingroup sli
5517  * @brief Parse a CQ entry to retrieve the event type and the associated queue.
5518  *
5519  * @param sli4 SLI context.
5520  * @param cq CQ to process.
5521  * @param cqe Pointer to the CQ entry.
5522  * @param etype CQ event type.
5523  * @param q_id Queue ID associated with this completion message
5524  * (that is, MQ_ID, RQ_ID, and so on).
5525  *
5526  * @return
5527  * - 0 if call completed correctly and CQE status is SUCCESS.
5528  * - -1 if call failed (no CQE status).
5529  * - Other value if call completed correctly and return value is a CQE status value.
5530  */
5531 int32_t
5532 sli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
5533                 uint16_t *q_id)
5534 {
5535         int32_t rc = 0;
5536
5537         if (!sli4 || !cq || !cqe || !etype) {
5538                 ocs_log_err(NULL, "bad parameters sli4=%p cq=%p cqe=%p etype=%p q_id=%p\n",
5539                             sli4, cq, cqe, etype, q_id);
5540                 return -1;
5541         }
5542
5543         if (cq->u.flag.is_mq) {
5544                 sli4_mcqe_t     *mcqe = (void *)cqe;
5545
5546                 if (mcqe->ae) {
5547                         *etype = SLI_QENTRY_ASYNC;
5548                 } else {
5549                         *etype = SLI_QENTRY_MQ;
5550                         rc = sli_cqe_mq(mcqe);
5551                 }
5552                 *q_id = -1;
5553         } else if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5554                 rc = sli_fc_cqe_parse(sli4, cq, cqe, etype, q_id);
5555         } else {
5556                 ocs_log_test(sli4->os, "implement CQE parsing type = %#x\n",
5557                              sli4->port_type);
5558                 rc = -1;
5559         }
5560
5561         return rc;
5562 }
5563
5564 /**
5565  * @ingroup sli
5566  * @brief Cause chip to enter an unrecoverable error state.
5567  *
5568  * @par Description
5569  * Cause chip to enter an unrecoverable error state. This is
5570  * used when detecting unexpected FW behavior so FW can be
5571  * hwted from the driver as soon as error is detected.
5572  *
5573  * @param sli4 SLI context.
5574  * @param dump Generate dump as part of reset.
5575  *
5576  * @return Returns 0 if call completed correctly, or -1 if call failed (unsupported chip).
5577  */
5578 int32_t sli_raise_ue(sli4_t *sli4, uint8_t dump)
5579 {
5580 #define FDD 2
5581         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
5582                 switch(sli_get_asic_type(sli4)) {
5583                 case SLI4_ASIC_TYPE_BE3: {
5584                         sli_reg_write(sli4, SLI4_REG_SW_UE_CSR1, 0xffffffff);
5585                         sli_reg_write(sli4, SLI4_REG_SW_UE_CSR2, 0);
5586                         break;
5587                 }
5588                 case SLI4_ASIC_TYPE_SKYHAWK: {
5589                         uint32_t value;
5590                         value = ocs_config_read32(sli4->os, SLI4_SW_UE_REG);
5591                         ocs_config_write32(sli4->os, SLI4_SW_UE_REG, (value | (1U << 24)));
5592                         break;
5593                 }
5594                 default:
5595                         ocs_log_test(sli4->os, "invalid asic type %d\n", sli_get_asic_type(sli4));
5596                         return -1;
5597                 }
5598         } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) ||
5599                    (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4))) {
5600                 if (FDD == dump) {
5601                         sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, SLI4_SLIPORT_CONTROL_FDD | SLI4_SLIPORT_CONTROL_IP);
5602                 } else {
5603                         uint32_t value = SLI4_PHYDEV_CONTROL_FRST;
5604                         if (dump == 1) {
5605                                 value |= SLI4_PHYDEV_CONTROL_DD;
5606                         }
5607                         sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, value);
5608                 }
5609         } else {
5610                 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
5611                 return -1;
5612         }
5613         return 0;
5614 }
5615
5616 /**
5617  * @ingroup sli
5618  * @brief Read the SLIPORT_STATUS register to to check if a dump is present.
5619  *
5620  * @param sli4 SLI context.
5621  *
5622  * @return  Returns 1 if the chip is ready, or 0 if the chip is not ready, 2 if fdp is present.
5623  */
5624 int32_t sli_dump_is_ready(sli4_t *sli4)
5625 {
5626         int32_t rc = 0;
5627         uint32_t port_val;
5628         uint32_t bmbx_val;
5629         uint32_t uerr_lo;
5630         uint32_t uerr_hi;
5631         uint32_t uerr_mask_lo;
5632         uint32_t uerr_mask_hi;
5633
5634         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
5635                 /* for iftype=0, dump ready when UE is encountered */
5636                 uerr_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
5637                 uerr_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
5638                 uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
5639                 uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
5640                 if ((uerr_lo & ~uerr_mask_lo) || (uerr_hi & ~uerr_mask_hi)) {
5641                         rc = 1;
5642                 }
5643
5644         } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) ||
5645                    (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4))) {
5646                 /*
5647                  * Ensure that the port is ready AND the mailbox is
5648                  * ready before signaling that the dump is ready to go.
5649                  */
5650                 port_val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5651                 bmbx_val = sli_reg_read(sli4, SLI4_REG_BMBX);
5652
5653                 if ((bmbx_val & SLI4_BMBX_RDY) &&
5654                     SLI4_PORT_STATUS_READY(port_val)) { 
5655                         if(SLI4_PORT_STATUS_DUMP_PRESENT(port_val)) {
5656                                 rc = 1;
5657                         }else if( SLI4_PORT_STATUS_FDP_PRESENT(port_val)) {
5658                                 rc = 2;
5659                         }
5660                 }
5661         } else {
5662                 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
5663                 return -1;
5664         }
5665         return rc;
5666 }
5667
5668 /**
5669  * @ingroup sli
5670  * @brief Read the SLIPORT_STATUS register to check if a dump is present.
5671  *
5672  * @param sli4 SLI context.
5673  *
5674  * @return
5675  * - 0 if call completed correctly and no dump is present.
5676  * - 1 if call completed and dump is present.
5677  * - -1 if call failed (unsupported chip).
5678  */
5679 int32_t sli_dump_is_present(sli4_t *sli4)
5680 {
5681         uint32_t val;
5682         uint32_t ready;
5683
5684         if ((SLI4_IF_TYPE_LANCER_FC_ETH != sli_get_if_type(sli4)) &&
5685             (SLI4_IF_TYPE_LANCER_G7 != sli_get_if_type(sli4))) {
5686                 ocs_log_test(sli4->os, "Function only supported for I/F type 2");
5687                 return -1;
5688         }
5689
5690         /* If the chip is not ready, then there cannot be a dump */
5691         ready = sli_wait_for_fw_ready(sli4, SLI4_INIT_PORT_DELAY_US);
5692         if (!ready) {
5693                 return 0;
5694         }
5695
5696         val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5697         if (UINT32_MAX == val) {
5698                 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
5699                 return -1;
5700         } else {
5701                 return ((val & SLI4_PORT_STATUS_DIP) ? 1 : 0);
5702         }
5703 }
5704
5705 /**
5706  * @ingroup sli
5707  * @brief Read the SLIPORT_STATUS register to check if the reset required is set.
5708  *
5709  * @param sli4 SLI context.
5710  *
5711  * @return
5712  * - 0 if call completed correctly and reset is not required.
5713  * - 1 if call completed and reset is required.
5714  * - -1 if call failed.
5715  */
5716 int32_t sli_reset_required(sli4_t *sli4)
5717 {
5718         uint32_t val;
5719
5720         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
5721                 ocs_log_test(sli4->os, "reset required N/A for iftype 0\n");
5722                 return 0;
5723         }
5724
5725         val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5726         if (UINT32_MAX == val) {
5727                 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
5728                 return -1;
5729         } else {
5730                 return ((val & SLI4_PORT_STATUS_RN) ? 1 : 0);
5731         }
5732 }
5733
5734 /**
5735  * @ingroup sli
5736  * @brief Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if
5737  * the port status indicates that a FW error has occurred.
5738  *
5739  * @param sli4 SLI context.
5740  *
5741  * @return
5742  * - 0 if call completed correctly and no FW error occurred.
5743  * - > 0 which indicates that a FW error has occurred.
5744  * - -1 if call failed.
5745  */
5746 int32_t sli_fw_error_status(sli4_t *sli4)
5747 {
5748         uint32_t sliport_semaphore;
5749         int32_t rc = 0;
5750
5751         sliport_semaphore = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
5752         if (UINT32_MAX == sliport_semaphore) {
5753                 ocs_log_err(sli4->os, "error reading SLIPORT_SEMAPHORE register\n");
5754                 return 1;
5755         }
5756         rc = (SLI4_PORT_SEMAPHORE_IN_ERR(sliport_semaphore) ? 1 : 0);
5757
5758         if (rc == 0) {
5759                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
5760                     (SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type)) {
5761                         uint32_t uerr_mask_lo, uerr_mask_hi;
5762                         uint32_t uerr_status_lo, uerr_status_hi;
5763
5764                         uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
5765                         uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
5766                         uerr_status_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
5767                         uerr_status_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
5768                         if ((uerr_mask_lo & uerr_status_lo) != 0 ||
5769                             (uerr_mask_hi & uerr_status_hi) != 0) {
5770                                 rc = 1;
5771                         }
5772                 } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type ||
5773                    SLI4_IF_TYPE_LANCER_G7 == sli4->if_type) {
5774                         uint32_t sliport_status;
5775
5776                         sliport_status = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5777                         rc = (SLI4_PORT_STATUS_ERROR(sliport_status) ? 1 : 0);
5778                 }
5779         }
5780         return rc;
5781 }
5782
5783 /**
5784  * @ingroup sli
5785  * @brief Determine if the chip FW is in a ready state
5786  *
5787  * @param sli4 SLI context.
5788  *
5789  * @return
5790  * - 0 if call completed correctly and FW is not ready.
5791  * - 1 if call completed correctly and FW is ready.
5792  * - -1 if call failed.
5793  */
5794 int32_t
5795 sli_fw_ready(sli4_t *sli4)
5796 {
5797         uint32_t val;
5798         int32_t rc = -1;
5799
5800         /*
5801          * Is firmware ready for operation? Check needed depends on IF_TYPE
5802          */
5803         if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
5804             SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type) {
5805                 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
5806                 rc = ((SLI4_PORT_SEMAPHORE_STATUS_POST_READY ==
5807                     SLI4_PORT_SEMAPHORE_PORT(val)) &&
5808                     (!SLI4_PORT_SEMAPHORE_IN_ERR(val)) ? 1 : 0);
5809         } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type ||
5810                    SLI4_IF_TYPE_LANCER_G7 == sli4->if_type) {
5811                 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5812                 rc = (SLI4_PORT_STATUS_READY(val) ? 1 : 0);
5813         }
5814         return rc;
5815 }
5816
5817 /**
5818  * @ingroup sli
5819  * @brief Determine if the link can be configured
5820  *
5821  * @param sli4 SLI context.
5822  *
5823  * @return
5824  * - 0 if link is not configurable.
5825  * - 1 if link is configurable.
5826  */
5827 int32_t sli_link_is_configurable(sli4_t *sli)
5828 {
5829         int32_t rc = 0;
5830         /*
5831          * Link config works on: Skyhawk and Lancer
5832          * Link config does not work on: LancerG6
5833          */
5834
5835         switch (sli_get_asic_type(sli)) {
5836         case SLI4_ASIC_TYPE_SKYHAWK:
5837         case SLI4_ASIC_TYPE_LANCER:
5838         case SLI4_ASIC_TYPE_CORSAIR:
5839                 rc = 1;
5840                 break;
5841         case SLI4_ASIC_TYPE_LANCERG6:
5842         case SLI4_ASIC_TYPE_LANCERG7:
5843         case SLI4_ASIC_TYPE_BE3:
5844         default:
5845                 rc = 0;
5846                 break;
5847         }
5848
5849         return rc;
5850
5851 }
5852
5853 /* vim: set noexpandtab textwidth=120: */
5854
5855 /**
5856  * @ingroup sli_fc
5857  * @brief Write an FCOE_WQ_CREATE command.
5858  *
5859  * @param sli4 SLI context.
5860  * @param buf Destination buffer for the command.
5861  * @param size Buffer size, in bytes.
5862  * @param qmem DMA memory for the queue.
5863  * @param cq_id Associated CQ_ID.
5864  * @param ulp The ULP to bind
5865  *
5866  * @note This creates a Version 0 message.
5867  *
5868  * @return Returns the number of bytes written.
5869  */
5870 int32_t
5871 sli_cmd_fcoe_wq_create(sli4_t *sli4, void *buf, size_t size,
5872                         ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp)
5873 {
5874         sli4_req_fcoe_wq_create_t       *wq = NULL;
5875         uint32_t        sli_config_off = 0;
5876         uint32_t        p;
5877         uintptr_t       addr;
5878
5879         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5880                 uint32_t payload_size;
5881
5882                 /* Payload length must accommodate both request and response */
5883                 payload_size = max(sizeof(sli4_req_fcoe_wq_create_t),
5884                                 sizeof(sli4_res_common_create_queue_t));
5885
5886                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
5887                                 NULL);
5888         }
5889         wq = (sli4_req_fcoe_wq_create_t *)((uint8_t *)buf + sli_config_off);
5890
5891         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
5892         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
5893         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_t) -
5894                                         sizeof(sli4_req_hdr_t);
5895         /* valid values for number of pages: 1-4 (sec 4.5.1) */
5896         wq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
5897         if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V0_MAX_PAGES)) {
5898                 return 0;
5899         }
5900
5901         wq->cq_id = cq_id;
5902
5903         if (sli4->config.dual_ulp_capable) {
5904                 wq->dua = 1;
5905                 wq->bqu = 1;
5906                 wq->ulp = ulp;
5907         }
5908
5909         for (p = 0, addr = qmem->phys;
5910                         p < wq->num_pages;
5911                         p++, addr += SLI_PAGE_SIZE) {
5912                 wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
5913                 wq->page_physical_address[p].high = ocs_addr32_hi(addr);
5914         }
5915
5916         return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_t));
5917 }
5918
5919 /**
5920  * @ingroup sli_fc
5921  * @brief Write an FCOE_WQ_CREATE_V1 command.
5922  *
5923  * @param sli4 SLI context.
5924  * @param buf Destination buffer for the command.
5925  * @param size Buffer size, in bytes.
5926  * @param qmem DMA memory for the queue.
5927  * @param cq_id Associated CQ_ID.
5928  * @param ignored This parameter carries the ULP for WQ (ignored for V1)
5929
5930  *
5931  * @return Returns the number of bytes written.
5932  */
5933 int32_t
5934 sli_cmd_fcoe_wq_create_v1(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
5935                           uint16_t cq_id, uint16_t ignored)
5936 {
5937         sli4_req_fcoe_wq_create_v1_t    *wq = NULL;
5938         uint32_t        sli_config_off = 0;
5939         uint32_t        p;
5940         uintptr_t       addr;
5941         uint32_t        page_size = 0;
5942         uint32_t        page_bytes = 0;
5943         uint32_t        n_wqe = 0;
5944
5945         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5946                 uint32_t payload_size;
5947
5948                 /* Payload length must accommodate both request and response */
5949                 payload_size = max(sizeof(sli4_req_fcoe_wq_create_v1_t),
5950                                 sizeof(sli4_res_common_create_queue_t));
5951
5952                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
5953                                 NULL);
5954         }
5955         wq = (sli4_req_fcoe_wq_create_v1_t *)((uint8_t *)buf + sli_config_off);
5956
5957         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
5958         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
5959         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_v1_t) -
5960                                         sizeof(sli4_req_hdr_t);
5961         wq->hdr.version = 1;
5962
5963         n_wqe = qmem->size / sli4->config.wqe_size;
5964
5965         /* This heuristic to determine the page size is simplistic 
5966          * but could be made more sophisticated
5967          */
5968         switch (qmem->size) {
5969         case 4096:
5970         case 8192:
5971         case 16384:
5972         case 32768:
5973                 page_size = 1;
5974                 break;
5975         case 65536:
5976                 page_size = 2;
5977                 break;
5978         case 131072:
5979                 page_size = 4;
5980                 break;
5981         case 262144:
5982                 page_size = 8;
5983                 break;
5984         case 524288:
5985                 page_size = 10;
5986                 break;
5987         default:
5988                 return 0;
5989         }
5990         page_bytes = page_size * SLI_PAGE_SIZE;
5991
5992         /* valid values for number of pages: 1-8 */
5993         wq->num_pages = sli_page_count(qmem->size, page_bytes);
5994         if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V1_MAX_PAGES)) {
5995                 return 0;
5996         }
5997
5998         wq->cq_id = cq_id;
5999
6000         wq->page_size = page_size;
6001
6002         if (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) {
6003                 wq->wqe_size = SLI4_WQE_EXT_SIZE;
6004         } else {
6005                 wq->wqe_size = SLI4_WQE_SIZE;
6006         }
6007
6008         wq->wqe_count = n_wqe;
6009
6010         for (p = 0, addr = qmem->phys;
6011                         p < wq->num_pages;
6012                         p++, addr += page_bytes) {
6013                 wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
6014                 wq->page_physical_address[p].high = ocs_addr32_hi(addr);
6015         }
6016
6017         return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_v1_t));
6018 }
6019
6020 /**
6021  * @ingroup sli_fc
6022  * @brief Write an FCOE_WQ_DESTROY command.
6023  *
6024  * @param sli4 SLI context.
6025  * @param buf Destination buffer for the command.
6026  * @param size Buffer size, in bytes.
6027  * @param wq_id WQ_ID.
6028  *
6029  * @return Returns the number of bytes written.
6030  */
6031 int32_t
6032 sli_cmd_fcoe_wq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t wq_id)
6033 {
6034         sli4_req_fcoe_wq_destroy_t      *wq = NULL;
6035         uint32_t        sli_config_off = 0;
6036
6037         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6038                 uint32_t payload_size;
6039
6040                 /* Payload length must accommodate both request and response */
6041                 payload_size = max(sizeof(sli4_req_fcoe_wq_destroy_t),
6042                                 sizeof(sli4_res_hdr_t));
6043
6044                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6045                                 NULL);
6046         }
6047         wq = (sli4_req_fcoe_wq_destroy_t *)((uint8_t *)buf + sli_config_off);
6048
6049         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_DESTROY;
6050         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6051         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_destroy_t) -
6052                                         sizeof(sli4_req_hdr_t);
6053
6054         wq->wq_id = wq_id;
6055
6056         return(sli_config_off + sizeof(sli4_req_fcoe_wq_destroy_t));
6057 }
6058
6059 /**
6060  * @ingroup sli_fc
6061  * @brief Write an FCOE_POST_SGL_PAGES command.
6062  *
6063  * @param sli4 SLI context.
6064  * @param buf Destination buffer for the command.
6065  * @param size Buffer size, in bytes.
6066  * @param xri starting XRI
6067  * @param xri_count XRI
6068  * @param page0 First SGL memory page.
6069  * @param page1 Second SGL memory page (optional).
6070  * @param dma DMA buffer for non-embedded mailbox command (options)
6071  *
6072  * if non-embedded mbx command is used, dma buffer must be at least (32 + xri_count*16) in length
6073  *
6074  * @return Returns the number of bytes written.
6075  */
6076 int32_t
6077 sli_cmd_fcoe_post_sgl_pages(sli4_t *sli4, void *buf, size_t size,
6078                 uint16_t xri, uint32_t xri_count, ocs_dma_t *page0[], ocs_dma_t *page1[], ocs_dma_t *dma)
6079 {
6080         sli4_req_fcoe_post_sgl_pages_t  *post = NULL;
6081         uint32_t        sli_config_off = 0;
6082         uint32_t        i;
6083
6084         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6085                 uint32_t payload_size;
6086
6087                 /* Payload length must accommodate both request and response */
6088                 payload_size = max(sizeof(sli4_req_fcoe_post_sgl_pages_t),
6089                                 sizeof(sli4_res_hdr_t));
6090
6091                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6092                                 dma);
6093         }
6094         if (dma) {
6095                 post = dma->virt;
6096                 ocs_memset(post, 0, dma->size);
6097         } else {
6098                 post = (sli4_req_fcoe_post_sgl_pages_t *)((uint8_t *)buf + sli_config_off);
6099         }
6100
6101         post->hdr.opcode = SLI4_OPC_FCOE_POST_SGL_PAGES;
6102         post->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6103         /* payload size calculation
6104          *   4 = xri_start + xri_count
6105          *   xri_count = # of XRI's registered
6106          *   sizeof(uint64_t) = physical address size
6107          *   2 = # of physical addresses per page set
6108          */
6109         post->hdr.request_length = 4 + (xri_count * (sizeof(uint64_t) * 2));
6110
6111         post->xri_start = xri;
6112         post->xri_count = xri_count;
6113
6114         for (i = 0; i < xri_count; i++) {
6115                 post->page_set[i].page0_low  = ocs_addr32_lo(page0[i]->phys);
6116                 post->page_set[i].page0_high = ocs_addr32_hi(page0[i]->phys);
6117         }
6118
6119         if (page1) {
6120                 for (i = 0; i < xri_count; i++) {
6121                         post->page_set[i].page1_low  = ocs_addr32_lo(page1[i]->phys);
6122                         post->page_set[i].page1_high = ocs_addr32_hi(page1[i]->phys);
6123                 }
6124         }
6125
6126         return dma ? sli_config_off : (sli_config_off + sizeof(sli4_req_fcoe_post_sgl_pages_t));
6127 }
6128
6129 /**
6130  * @ingroup sli_fc
6131  * @brief Write an FCOE_RQ_CREATE command.
6132  *
6133  * @param sli4 SLI context.
6134  * @param buf Destination buffer for the command.
6135  * @param size Buffer size, in bytes.
6136  * @param qmem DMA memory for the queue.
6137  * @param cq_id Associated CQ_ID.
6138  * @param ulp This parameter carries the ULP for the RQ
6139  * @param buffer_size Buffer size pointed to by each RQE.
6140  *
6141  * @note This creates a Version 0 message.
6142  *
6143  * @return Returns the number of bytes written.
6144  */
6145 int32_t
6146 sli_cmd_fcoe_rq_create(sli4_t *sli4, void *buf, size_t size,
6147                 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp, uint16_t buffer_size)
6148 {
6149         sli4_req_fcoe_rq_create_t       *rq = NULL;
6150         uint32_t        sli_config_off = 0;
6151         uint32_t        p;
6152         uintptr_t       addr;
6153
6154         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6155                 uint32_t payload_size;
6156
6157                 /* Payload length must accommodate both request and response */
6158                 payload_size = max(sizeof(sli4_req_fcoe_rq_create_t),
6159                                 sizeof(sli4_res_common_create_queue_t));
6160
6161                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6162                                 NULL);
6163         }
6164         rq = (sli4_req_fcoe_rq_create_t *)((uint8_t *)buf + sli_config_off);
6165
6166         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
6167         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6168         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_t) -
6169                                         sizeof(sli4_req_hdr_t);
6170         /* valid values for number of pages: 1-8 (sec 4.5.6) */
6171         rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
6172         if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V0_MAX_PAGES)) {
6173                 ocs_log_test(sli4->os, "num_pages %d not valid\n", rq->num_pages);
6174                 return 0;
6175         }
6176
6177         /*
6178          * RQE count is the log base 2 of the total number of entries
6179          */
6180         rq->rqe_count = ocs_lg2(qmem->size / SLI4_FCOE_RQE_SIZE);
6181
6182         if ((buffer_size < SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE) ||
6183                         (buffer_size > SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE)) {
6184                 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
6185                                 buffer_size,
6186                                 SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE,
6187                                 SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE);
6188                 return -1;
6189         }
6190         rq->buffer_size = buffer_size;
6191
6192         rq->cq_id = cq_id;
6193
6194         if (sli4->config.dual_ulp_capable) {
6195                 rq->dua = 1;
6196                 rq->bqu = 1;
6197                 rq->ulp = ulp;
6198         }
6199
6200         for (p = 0, addr = qmem->phys;
6201                         p < rq->num_pages;
6202                         p++, addr += SLI_PAGE_SIZE) {
6203                 rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
6204                 rq->page_physical_address[p].high = ocs_addr32_hi(addr);
6205         }
6206
6207         return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_t));
6208 }
6209
6210 /**
6211  * @ingroup sli_fc
6212  * @brief Write an FCOE_RQ_CREATE_V1 command.
6213  *
6214  * @param sli4 SLI context.
6215  * @param buf Destination buffer for the command.
6216  * @param size Buffer size, in bytes.
6217  * @param qmem DMA memory for the queue.
6218  * @param cq_id Associated CQ_ID.
6219  * @param ulp This parameter carries the ULP for RQ (ignored for V1)
6220  * @param buffer_size Buffer size pointed to by each RQE.
6221  *
6222  * @note This creates a Version 0 message
6223  *
6224  * @return Returns the number of bytes written.
6225  */
6226 int32_t
6227 sli_cmd_fcoe_rq_create_v1(sli4_t *sli4, void *buf, size_t size,
6228                           ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp,
6229                           uint16_t buffer_size)
6230 {
6231         sli4_req_fcoe_rq_create_v1_t    *rq = NULL;
6232         uint32_t        sli_config_off = 0;
6233         uint32_t        p;
6234         uintptr_t       addr;
6235
6236         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6237                 uint32_t payload_size;
6238
6239                 /* Payload length must accommodate both request and response */
6240                 payload_size = max(sizeof(sli4_req_fcoe_rq_create_v1_t),
6241                                 sizeof(sli4_res_common_create_queue_t));
6242
6243                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6244                                 NULL);
6245         }
6246         rq = (sli4_req_fcoe_rq_create_v1_t *)((uint8_t *)buf + sli_config_off);
6247
6248         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
6249         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6250         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v1_t) -
6251                                         sizeof(sli4_req_hdr_t);
6252         rq->hdr.version = 1;
6253
6254         /* Disable "no buffer warnings" to avoid Lancer bug */
6255         rq->dnb = TRUE;
6256
6257         /* valid values for number of pages: 1-8 (sec 4.5.6) */
6258         rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
6259         if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES)) {
6260                 ocs_log_test(sli4->os, "num_pages %d not valid, max %d\n",
6261                 rq->num_pages, SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES);
6262                 return 0;
6263         }
6264
6265         /*
6266          * RQE count is the total number of entries (note not lg2(# entries))
6267          */
6268         rq->rqe_count = qmem->size / SLI4_FCOE_RQE_SIZE;
6269
6270         rq->rqe_size = SLI4_FCOE_RQE_SIZE_8;
6271
6272         rq->page_size = SLI4_FCOE_RQ_PAGE_SIZE_4096;
6273
6274         if ((buffer_size < sli4->config.rq_min_buf_size) ||
6275             (buffer_size > sli4->config.rq_max_buf_size)) {
6276                 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
6277                                 buffer_size,
6278                                 sli4->config.rq_min_buf_size,
6279                                 sli4->config.rq_max_buf_size);
6280                 return -1;
6281         }
6282         rq->buffer_size = buffer_size;
6283
6284         rq->cq_id = cq_id;
6285
6286         for (p = 0, addr = qmem->phys;
6287                         p < rq->num_pages;
6288                         p++, addr += SLI_PAGE_SIZE) {
6289                 rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
6290                 rq->page_physical_address[p].high = ocs_addr32_hi(addr);
6291         }
6292
6293         return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_v1_t));
6294 }
6295
6296 /**
6297  * @ingroup sli_fc
6298  * @brief Write an FCOE_RQ_DESTROY command.
6299  *
6300  * @param sli4 SLI context.
6301  * @param buf Destination buffer for the command.
6302  * @param size Buffer size, in bytes.
6303  * @param rq_id RQ_ID.
6304  *
6305  * @return Returns the number of bytes written.
6306  */
6307 int32_t
6308 sli_cmd_fcoe_rq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t rq_id)
6309 {
6310         sli4_req_fcoe_rq_destroy_t      *rq = NULL;
6311         uint32_t        sli_config_off = 0;
6312
6313         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6314                 uint32_t payload_size;
6315
6316                 /* Payload length must accommodate both request and response */
6317                 payload_size = max(sizeof(sli4_req_fcoe_rq_destroy_t),
6318                                 sizeof(sli4_res_hdr_t));
6319
6320                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6321                                 NULL);
6322         }
6323         rq = (sli4_req_fcoe_rq_destroy_t *)((uint8_t *)buf + sli_config_off);
6324
6325         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_DESTROY;
6326         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6327         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_destroy_t) -
6328                                         sizeof(sli4_req_hdr_t);
6329
6330         rq->rq_id = rq_id;
6331
6332         return(sli_config_off + sizeof(sli4_req_fcoe_rq_destroy_t));
6333 }
6334
6335 /**
6336  * @ingroup sli_fc
6337  * @brief Write an FCOE_READ_FCF_TABLE command.
6338  *
6339  * @note
6340  * The response of this command exceeds the size of an embedded
6341  * command and requires an external buffer with DMA capability to hold the results.
6342  * The caller should allocate the ocs_dma_t structure / memory.
6343  *
6344  * @param sli4 SLI context.
6345  * @param buf Destination buffer for the command.
6346  * @param size Buffer size, in bytes.
6347  * @param dma Pointer to DMA memory structure. This is allocated by the caller.
6348  * @param index FCF table index to retrieve.
6349  *
6350  * @return Returns the number of bytes written.
6351  */
6352 int32_t
6353 sli_cmd_fcoe_read_fcf_table(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, uint16_t index)
6354 {
6355         sli4_req_fcoe_read_fcf_table_t *read_fcf = NULL;
6356
6357         if (SLI4_PORT_TYPE_FC != sli4->port_type) {
6358                 ocs_log_test(sli4->os, "FCOE_READ_FCF_TABLE only supported on FC\n");
6359                 return -1;
6360         }
6361
6362         read_fcf = dma->virt;
6363
6364         ocs_memset(read_fcf, 0, sizeof(sli4_req_fcoe_read_fcf_table_t));
6365
6366         read_fcf->hdr.opcode = SLI4_OPC_FCOE_READ_FCF_TABLE;
6367         read_fcf->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6368         read_fcf->hdr.request_length = dma->size -
6369                 sizeof(sli4_req_fcoe_read_fcf_table_t);
6370         read_fcf->fcf_index = index;
6371
6372         return sli_cmd_sli_config(sli4, buf, size, 0, dma);
6373 }
6374
6375 /**
6376  * @ingroup sli_fc
6377  * @brief Write an FCOE_POST_HDR_TEMPLATES command.
6378  *
6379  * @param sli4 SLI context.
6380  * @param buf Destination buffer for the command.
6381  * @param size Buffer size, in bytes.
6382  * @param dma Pointer to DMA memory structure. This is allocated by the caller.
6383  * @param rpi Starting RPI index for the header templates.
6384  * @param payload_dma Pointer to DMA memory used to hold larger descriptor counts.
6385  *
6386  * @return Returns the number of bytes written.
6387  */
6388 int32_t
6389 sli_cmd_fcoe_post_hdr_templates(sli4_t *sli4, void *buf, size_t size,
6390                 ocs_dma_t *dma, uint16_t rpi, ocs_dma_t *payload_dma)
6391 {
6392         sli4_req_fcoe_post_hdr_templates_t *template = NULL;
6393         uint32_t        sli_config_off = 0;
6394         uintptr_t       phys = 0;
6395         uint32_t        i = 0;
6396         uint32_t        page_count;
6397         uint32_t        payload_size;
6398
6399         page_count = sli_page_count(dma->size, SLI_PAGE_SIZE);
6400
6401         payload_size = sizeof(sli4_req_fcoe_post_hdr_templates_t) +
6402                                 page_count * sizeof(sli4_physical_page_descriptor_t);
6403
6404         if (page_count > 16) {
6405                 /* We can't fit more than 16 descriptors into an embedded mailbox
6406                    command, it has to be non-embedded */
6407                 if (ocs_dma_alloc(sli4->os, payload_dma, payload_size, 4)) {
6408                         ocs_log_err(sli4->os, "mailbox payload memory allocation fail\n");
6409                         return 0;
6410                 }
6411                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, payload_dma);
6412                 template = (sli4_req_fcoe_post_hdr_templates_t *)payload_dma->virt;
6413         } else {
6414                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, NULL);
6415                 template = (sli4_req_fcoe_post_hdr_templates_t *)((uint8_t *)buf + sli_config_off);
6416         }
6417
6418         if (UINT16_MAX == rpi) {
6419                 rpi = sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0];
6420         }
6421
6422         template->hdr.opcode = SLI4_OPC_FCOE_POST_HDR_TEMPLATES;
6423         template->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6424         template->hdr.request_length = sizeof(sli4_req_fcoe_post_hdr_templates_t) -
6425                                         sizeof(sli4_req_hdr_t);
6426
6427         template->rpi_offset = rpi;
6428         template->page_count = page_count;
6429         phys = dma->phys;
6430         for (i = 0; i < template->page_count; i++) {
6431                 template->page_descriptor[i].low  = ocs_addr32_lo(phys);
6432                 template->page_descriptor[i].high = ocs_addr32_hi(phys);
6433
6434                 phys += SLI_PAGE_SIZE;
6435         }
6436
6437         return(sli_config_off + payload_size);
6438 }
6439
6440 int32_t
6441 sli_cmd_fcoe_rediscover_fcf(sli4_t *sli4, void *buf, size_t size, uint16_t index)
6442 {
6443         sli4_req_fcoe_rediscover_fcf_t *redisc = NULL;
6444         uint32_t        sli_config_off = 0;
6445
6446         sli_config_off = sli_cmd_sli_config(sli4, buf, size,
6447                         sizeof(sli4_req_fcoe_rediscover_fcf_t),
6448                         NULL);
6449
6450         redisc = (sli4_req_fcoe_rediscover_fcf_t *)((uint8_t *)buf + sli_config_off);
6451
6452         redisc->hdr.opcode = SLI4_OPC_FCOE_REDISCOVER_FCF;
6453         redisc->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6454         redisc->hdr.request_length = sizeof(sli4_req_fcoe_rediscover_fcf_t) -
6455                                         sizeof(sli4_req_hdr_t);
6456
6457         if (index == UINT16_MAX) {
6458                 redisc->fcf_count = 0;
6459         } else {
6460                 redisc->fcf_count = 1;
6461                 redisc->fcf_index[0] = index;
6462         }
6463
6464         return(sli_config_off + sizeof(sli4_req_fcoe_rediscover_fcf_t));
6465 }
6466
6467 /**
6468  * @ingroup sli_fc
6469  * @brief Write an ABORT_WQE work queue entry.
6470  *
6471  * @param sli4 SLI context.
6472  * @param buf Destination buffer for the WQE.
6473  * @param size Buffer size, in bytes.
6474  * @param type Abort type, such as XRI, abort tag, and request tag.
6475  * @param send_abts Boolean to cause the hardware to automatically generate an ABTS.
6476  * @param ids ID of IOs to abort.
6477  * @param mask Mask applied to the ID values to abort.
6478  * @param tag Tag value associated with this abort.
6479  * @param cq_id The id of the completion queue where the WQE response is sent.
6480  * @param dnrx When set to 1, this field indicates that the SLI Port must not return the associated XRI to the SLI
6481  *             Port's optimized write XRI pool.
6482  *
6483  * @return Returns 0 on success, or a non-zero value on failure.
6484  */
6485 int32_t
6486 sli_abort_wqe(sli4_t *sli4, void *buf, size_t size, sli4_abort_type_e type, uint32_t send_abts,
6487               uint32_t ids, uint32_t mask, uint16_t tag, uint16_t cq_id)
6488 {
6489         sli4_abort_wqe_t        *abort = buf;
6490
6491         ocs_memset(buf, 0, size);
6492
6493         switch (type) {
6494         case SLI_ABORT_XRI:
6495                 abort->criteria = SLI4_ABORT_CRITERIA_XRI_TAG;
6496                 if (mask) {
6497                         ocs_log_warn(sli4->os, "warning non-zero mask %#x when aborting XRI %#x\n", mask, ids);
6498                         mask = 0;
6499                 }
6500                 break;
6501         case SLI_ABORT_ABORT_ID:
6502                 abort->criteria = SLI4_ABORT_CRITERIA_ABORT_TAG;
6503                 break;
6504         case SLI_ABORT_REQUEST_ID:
6505                 abort->criteria = SLI4_ABORT_CRITERIA_REQUEST_TAG;
6506                 break;
6507         default:
6508                 ocs_log_test(sli4->os, "unsupported type %#x\n", type);
6509                 return -1;
6510         }
6511
6512         abort->ia = send_abts ? 0 : 1;
6513
6514         /* Suppress ABTS retries */
6515         abort->ir = 1;
6516
6517         abort->t_mask = mask;
6518         abort->t_tag  = ids;
6519         abort->command = SLI4_WQE_ABORT;
6520         abort->request_tag = tag;
6521         abort->qosd = TRUE;
6522         abort->cq_id = cq_id;
6523         abort->cmd_type = SLI4_CMD_ABORT_WQE;
6524
6525         return 0;
6526 }
6527
6528 /**
6529  * @ingroup sli_fc
6530  * @brief Write an ELS_REQUEST64_WQE work queue entry.
6531  *
6532  * @param sli4 SLI context.
6533  * @param buf Destination buffer for the WQE.
6534  * @param size Buffer size, in bytes.
6535  * @param sgl DMA memory for the ELS request.
6536  * @param req_type ELS request type.
6537  * @param req_len Length of ELS request in bytes.
6538  * @param max_rsp_len Max length of ELS response in bytes.
6539  * @param timeout Time, in seconds, before an IO times out. Zero means 2 * R_A_TOV.
6540  * @param xri XRI for this exchange.
6541  * @param tag IO tag value.
6542  * @param cq_id The id of the completion queue where the WQE response is sent.
6543  * @param rnode Destination of ELS request (that is, the remote node).
6544  *
6545  * @return Returns 0 on success, or a non-zero value on failure.
6546  */
6547 int32_t
6548 sli_els_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint8_t req_type,
6549                       uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
6550                       uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode)
6551 {
6552         sli4_els_request64_wqe_t        *els = buf;
6553         sli4_sge_t      *sge = sgl->virt;
6554         uint8_t         is_fabric = FALSE;
6555
6556         ocs_memset(buf, 0, size);
6557
6558         if (sli4->config.sgl_pre_registered) {
6559                 els->xbl = FALSE;
6560
6561                 els->dbde = TRUE;
6562                 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
6563
6564                 els->els_request_payload.buffer_length = req_len;
6565                 els->els_request_payload.u.data.buffer_address_low  = sge[0].buffer_address_low;
6566                 els->els_request_payload.u.data.buffer_address_high = sge[0].buffer_address_high;
6567         } else {
6568                 els->xbl = TRUE;
6569
6570                 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BLP;
6571
6572                 els->els_request_payload.buffer_length = 2 * sizeof(sli4_sge_t);
6573                 els->els_request_payload.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6574                 els->els_request_payload.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6575         }
6576
6577         els->els_request_payload_length = req_len;
6578         els->max_response_payload_length = max_rsp_len;
6579
6580         els->xri_tag = xri;
6581         els->timer = timeout;
6582         els->class = SLI4_ELS_REQUEST64_CLASS_3;
6583
6584         els->command = SLI4_WQE_ELS_REQUEST64;
6585
6586         els->request_tag = tag;
6587
6588         if (rnode->node_group) {
6589                 els->hlm = TRUE;
6590                 els->remote_id = rnode->fc_id & 0x00ffffff;
6591         }
6592
6593         els->iod = SLI4_ELS_REQUEST64_DIR_READ;
6594
6595         els->qosd = TRUE;
6596
6597         /* figure out the ELS_ID value from the request buffer */
6598
6599         switch (req_type) {
6600         case FC_ELS_CMD_LOGO:
6601                 els->els_id = SLI4_ELS_REQUEST64_LOGO;
6602                 if (rnode->attached) {
6603                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6604                         els->context_tag = rnode->indicator;
6605                 } else {
6606                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6607                         els->context_tag = rnode->sport->indicator;
6608                 }
6609                 if (FC_ADDR_FABRIC == rnode->fc_id) {
6610                         is_fabric = TRUE;
6611                 }
6612                 break;
6613         case FC_ELS_CMD_FDISC:
6614                 if (FC_ADDR_FABRIC == rnode->fc_id) {
6615                         is_fabric = TRUE;
6616                 }
6617                 if (0 == rnode->sport->fc_id) {
6618                         els->els_id = SLI4_ELS_REQUEST64_FDISC;
6619                         is_fabric = TRUE;
6620                 } else {
6621                         els->els_id = SLI4_ELS_REQUEST64_OTHER;
6622                 }
6623                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6624                 els->context_tag = rnode->sport->indicator;
6625                 els->sp = TRUE;
6626                 break;
6627         case FC_ELS_CMD_FLOGI:
6628                 els->els_id = SLI4_ELS_REQUEST64_FLOGIN;
6629                 is_fabric = TRUE;
6630                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
6631                         if (!rnode->sport->domain) {
6632                                 ocs_log_test(sli4->os, "invalid domain handle\n");
6633                                 return -1;
6634                         }
6635                         /*
6636                          * IF_TYPE 0 skips INIT_VFI/INIT_VPI and therefore must use the
6637                          * FCFI here
6638                          */
6639                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_FCFI;
6640                         els->context_tag = rnode->sport->domain->fcf_indicator;
6641                         els->sp = TRUE;
6642                 } else {
6643                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6644                         els->context_tag = rnode->sport->indicator;
6645
6646                         /*
6647                          * Set SP here ... we haven't done a REG_VPI yet
6648                          * TODO: need to maybe not set this when we have
6649                          *       completed VFI/VPI registrations ...
6650                          *
6651                          * Use the FC_ID of the SPORT if it has been allocated, otherwise
6652                          * use an S_ID of zero.
6653                          */
6654                         els->sp = TRUE;
6655                         if (rnode->sport->fc_id != UINT32_MAX) {
6656                                 els->sid = rnode->sport->fc_id;
6657                         }
6658                 }
6659                 break;
6660         case FC_ELS_CMD_PLOGI:
6661                 els->els_id = SLI4_ELS_REQUEST64_PLOGI;
6662                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6663                 els->context_tag = rnode->sport->indicator;
6664                 break;
6665         case FC_ELS_CMD_SCR:
6666                 els->els_id = SLI4_ELS_REQUEST64_OTHER;
6667                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6668                 els->context_tag = rnode->sport->indicator;
6669                 break;
6670         default:
6671                 els->els_id = SLI4_ELS_REQUEST64_OTHER;
6672                 if (rnode->attached) {
6673                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6674                         els->context_tag = rnode->indicator;
6675                 } else {
6676                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6677                         els->context_tag = rnode->sport->indicator;
6678                 }
6679                 break;
6680         }
6681
6682         if (is_fabric) {
6683                 els->cmd_type = SLI4_ELS_REQUEST64_CMD_FABRIC;
6684         } else {
6685                 els->cmd_type = SLI4_ELS_REQUEST64_CMD_NON_FABRIC;
6686         }
6687
6688         els->cq_id = cq_id;
6689
6690         if (SLI4_ELS_REQUEST64_CONTEXT_RPI != els->ct) {
6691                 els->remote_id = rnode->fc_id;
6692         }
6693         if (SLI4_ELS_REQUEST64_CONTEXT_VPI == els->ct) {
6694                 els->temporary_rpi = rnode->indicator;
6695         }
6696
6697         return 0;
6698 }
6699
6700 /**
6701  * @ingroup sli_fc
6702  * @brief Write an FCP_ICMND64_WQE work queue entry.
6703  *
6704  * @param sli4 SLI context.
6705  * @param buf Destination buffer for the WQE.
6706  * @param size Buffer size, in bytes.
6707  * @param sgl DMA memory for the scatter gather list.
6708  * @param xri XRI for this exchange.
6709  * @param tag IO tag value.
6710  * @param cq_id The id of the completion queue where the WQE response is sent.
6711  * @param rpi remote node indicator (RPI)
6712  * @param rnode Destination request (that is, the remote node).
6713  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
6714  *
6715  * @return Returns 0 on success, or a non-zero value on failure.
6716  */
6717 int32_t
6718 sli_fcp_icmnd64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl,
6719                     uint16_t xri, uint16_t tag, uint16_t cq_id,
6720                     uint32_t rpi, ocs_remote_node_t *rnode, uint8_t timeout)
6721 {
6722         sli4_fcp_icmnd64_wqe_t *icmnd = buf;
6723         sli4_sge_t      *sge = NULL;
6724
6725         ocs_memset(buf, 0, size);
6726
6727         if (!sgl || !sgl->virt) {
6728                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6729                             sgl, sgl ? sgl->virt : NULL);
6730                 return -1;
6731         }
6732         sge = sgl->virt;
6733
6734         if (sli4->config.sgl_pre_registered) {
6735                 icmnd->xbl = FALSE;
6736
6737                 icmnd->dbde = TRUE;
6738                 icmnd->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6739
6740                 icmnd->bde.buffer_length = sge[0].buffer_length;
6741                 icmnd->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6742                 icmnd->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6743         } else {
6744                 icmnd->xbl = TRUE;
6745
6746                 icmnd->bde.bde_type = SLI4_BDE_TYPE_BLP;
6747
6748                 icmnd->bde.buffer_length = sgl->size;
6749                 icmnd->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6750                 icmnd->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6751         }
6752
6753         icmnd->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
6754         icmnd->xri_tag = xri;
6755         icmnd->context_tag = rpi;
6756         icmnd->timer = timeout;
6757
6758         icmnd->pu = 2;  /* WQE word 4 contains read transfer length */
6759         icmnd->class = SLI4_ELS_REQUEST64_CLASS_3;
6760         icmnd->command = SLI4_WQE_FCP_ICMND64;
6761         icmnd->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6762
6763         icmnd->abort_tag = xri;
6764
6765         icmnd->request_tag = tag;
6766         icmnd->len_loc = 3;
6767         if (rnode->node_group) {
6768                 icmnd->hlm = TRUE;
6769                 icmnd->remote_n_port_id = rnode->fc_id & 0x00ffffff;
6770         }
6771         if (((ocs_node_t *)rnode->node)->fcp2device) {
6772                 icmnd->erp = TRUE;
6773         }
6774         icmnd->cmd_type = SLI4_CMD_FCP_ICMND64_WQE;
6775         icmnd->cq_id = cq_id;
6776
6777         return  0;
6778 }
6779
6780 /**
6781  * @ingroup sli_fc
6782  * @brief Write an FCP_IREAD64_WQE work queue entry.
6783  *
6784  * @param sli4 SLI context.
6785  * @param buf Destination buffer for the WQE.
6786  * @param size Buffer size, in bytes.
6787  * @param sgl DMA memory for the scatter gather list.
6788  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
6789  * @param xfer_len Data transfer length.
6790  * @param xri XRI for this exchange.
6791  * @param tag IO tag value.
6792  * @param cq_id The id of the completion queue where the WQE response is sent.
6793  * @param rpi remote node indicator (RPI)
6794  * @param rnode Destination request (i.e. remote node).
6795  * @param dif T10 DIF operation, or 0 to disable.
6796  * @param bs T10 DIF block size, or 0 if DIF is disabled.
6797  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
6798  *
6799  * @return Returns 0 on success, or a non-zero value on failure.
6800  */
6801 int32_t
6802 sli_fcp_iread64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
6803                     uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
6804                     uint32_t rpi, ocs_remote_node_t *rnode,
6805                     uint8_t dif, uint8_t bs, uint8_t timeout)
6806 {
6807         sli4_fcp_iread64_wqe_t *iread = buf;
6808         sli4_sge_t      *sge = NULL;
6809
6810         ocs_memset(buf, 0, size);
6811
6812         if (!sgl || !sgl->virt) {
6813                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6814                             sgl, sgl ? sgl->virt : NULL);
6815                 return -1;
6816         }
6817         sge = sgl->virt;
6818
6819         if (sli4->config.sgl_pre_registered) {
6820                 iread->xbl = FALSE;
6821
6822                 iread->dbde = TRUE;
6823                 iread->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6824
6825                 iread->bde.buffer_length = sge[0].buffer_length;
6826                 iread->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6827                 iread->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6828         } else {
6829                 iread->xbl = TRUE;
6830
6831                 iread->bde.bde_type = SLI4_BDE_TYPE_BLP;
6832
6833                 iread->bde.buffer_length = sgl->size;
6834                 iread->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6835                 iread->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6836
6837                 /* fill out fcp_cmnd buffer len and change resp buffer to be of type
6838                  * "skip" (note: response will still be written to sge[1] if necessary) */
6839                 iread->fcp_cmd_buffer_length = sge[0].buffer_length;
6840                 sge[1].sge_type = SLI4_SGE_TYPE_SKIP;
6841         }
6842
6843         iread->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
6844         iread->total_transfer_length = xfer_len;
6845
6846         iread->xri_tag = xri;
6847         iread->context_tag = rpi;
6848
6849         iread->timer = timeout;
6850
6851         iread->pu = 2;  /* WQE word 4 contains read transfer length */
6852         iread->class = SLI4_ELS_REQUEST64_CLASS_3;
6853         iread->command = SLI4_WQE_FCP_IREAD64;
6854         iread->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6855         iread->dif = dif;
6856         iread->bs  = bs;
6857
6858         iread->abort_tag = xri;
6859
6860         iread->request_tag = tag;
6861         iread->len_loc = 3;
6862         if (rnode->node_group) {
6863                 iread->hlm = TRUE;
6864                 iread->remote_n_port_id = rnode->fc_id & 0x00ffffff;
6865         }
6866         if (((ocs_node_t *)rnode->node)->fcp2device) {
6867                 iread->erp = TRUE;
6868         }
6869         iread->iod = 1;
6870         iread->cmd_type = SLI4_CMD_FCP_IREAD64_WQE;
6871         iread->cq_id = cq_id;
6872
6873         if (sli4->config.perf_hint) {
6874                 iread->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6875                 iread->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
6876                 iread->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
6877                 iread->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
6878         }
6879
6880         return  0;
6881 }
6882
6883 /**
6884  * @ingroup sli_fc
6885  * @brief Write an FCP_IWRITE64_WQE work queue entry.
6886  *
6887  * @param sli4 SLI context.
6888  * @param buf Destination buffer for the WQE.
6889  * @param size Buffer size, in bytes.
6890  * @param sgl DMA memory for the scatter gather list.
6891  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
6892  * @param xfer_len Data transfer length.
6893  * @param first_burst The number of first burst bytes
6894  * @param xri XRI for this exchange.
6895  * @param tag IO tag value.
6896  * @param cq_id The id of the completion queue where the WQE response is sent.
6897  * @param rpi remote node indicator (RPI)
6898  * @param rnode Destination request (i.e. remote node)
6899  * @param dif T10 DIF operation, or 0 to disable
6900  * @param bs T10 DIF block size, or 0 if DIF is disabled
6901  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
6902  *
6903  * @return Returns 0 on success, or a non-zero value on failure.
6904  */
6905 int32_t
6906 sli_fcp_iwrite64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
6907                      uint32_t xfer_len, uint32_t first_burst, uint16_t xri, uint16_t tag, uint16_t cq_id,
6908                      uint32_t rpi, ocs_remote_node_t *rnode,
6909                      uint8_t dif, uint8_t bs, uint8_t timeout)
6910 {
6911         sli4_fcp_iwrite64_wqe_t *iwrite = buf;
6912         sli4_sge_t      *sge = NULL;
6913
6914         ocs_memset(buf, 0, size);
6915
6916         if (!sgl || !sgl->virt) {
6917                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6918                             sgl, sgl ? sgl->virt : NULL);
6919                 return -1;
6920         }
6921         sge = sgl->virt;
6922
6923         if (sli4->config.sgl_pre_registered) {
6924                 iwrite->xbl = FALSE;
6925
6926                 iwrite->dbde = TRUE;
6927                 iwrite->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6928
6929                 iwrite->bde.buffer_length = sge[0].buffer_length;
6930                 iwrite->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6931                 iwrite->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6932         } else {
6933                 iwrite->xbl = TRUE;
6934
6935                 iwrite->bde.bde_type = SLI4_BDE_TYPE_BLP;
6936
6937                 iwrite->bde.buffer_length = sgl->size;
6938                 iwrite->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6939                 iwrite->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6940
6941                 /* fill out fcp_cmnd buffer len and change resp buffer to be of type
6942                  * "skip" (note: response will still be written to sge[1] if necessary) */
6943                 iwrite->fcp_cmd_buffer_length = sge[0].buffer_length;
6944                 sge[1].sge_type = SLI4_SGE_TYPE_SKIP;
6945         }
6946
6947         iwrite->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
6948         iwrite->total_transfer_length = xfer_len;
6949         iwrite->initial_transfer_length = MIN(xfer_len, first_burst);
6950
6951         iwrite->xri_tag = xri;
6952         iwrite->context_tag = rpi;
6953
6954         iwrite->timer = timeout;
6955
6956         iwrite->pu = 2; /* WQE word 4 contains read transfer length */
6957         iwrite->class = SLI4_ELS_REQUEST64_CLASS_3;
6958         iwrite->command = SLI4_WQE_FCP_IWRITE64;
6959         iwrite->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6960         iwrite->dif = dif;
6961         iwrite->bs  = bs;
6962
6963         iwrite->abort_tag = xri;
6964
6965         iwrite->request_tag = tag;
6966         iwrite->len_loc = 3;
6967         if (rnode->node_group) {
6968                 iwrite->hlm = TRUE;
6969                 iwrite->remote_n_port_id = rnode->fc_id & 0x00ffffff;
6970         }
6971         if (((ocs_node_t *)rnode->node)->fcp2device) {
6972                 iwrite->erp = TRUE;
6973         }
6974         iwrite->cmd_type = SLI4_CMD_FCP_IWRITE64_WQE;
6975         iwrite->cq_id = cq_id;
6976
6977         if (sli4->config.perf_hint) {
6978                 iwrite->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6979                 iwrite->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
6980                 iwrite->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
6981                 iwrite->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
6982         }
6983
6984         return  0;
6985 }
6986
6987 /**
6988  * @ingroup sli_fc
6989  * @brief Write an FCP_TRECEIVE64_WQE work queue entry.
6990  *
6991  * @param sli4 SLI context.
6992  * @param buf Destination buffer for the WQE.
6993  * @param size Buffer size, in bytes.
6994  * @param sgl DMA memory for the Scatter-Gather List.
6995  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
6996  * @param relative_off Relative offset of the IO (if any).
6997  * @param xfer_len Data transfer length.
6998  * @param xri XRI for this exchange.
6999  * @param tag IO tag value.
7000  * @param xid OX_ID for the exchange.
7001  * @param cq_id The id of the completion queue where the WQE response is sent.
7002  * @param rpi remote node indicator (RPI)
7003  * @param rnode Destination request (i.e. remote node).
7004  * @param flags Optional attributes, including:
7005  *  - ACTIVE - IO is already active.
7006  *  - AUTO RSP - Automatically generate a good FCP_RSP.
7007  * @param dif T10 DIF operation, or 0 to disable.
7008  * @param bs T10 DIF block size, or 0 if DIF is disabled.
7009  * @param csctl value of csctl field.
7010  * @param app_id value for VM application header.
7011  *
7012  * @return Returns 0 on success, or a non-zero value on failure.
7013  */
7014 int32_t
7015 sli_fcp_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
7016                        uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
7017                        uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags, uint8_t dif, uint8_t bs,
7018                        uint8_t csctl, uint32_t app_id)
7019 {
7020         sli4_fcp_treceive64_wqe_t *trecv = buf;
7021         sli4_fcp_128byte_wqe_t *trecv_128 = buf;
7022         sli4_sge_t      *sge = NULL;
7023
7024         ocs_memset(buf, 0, size);
7025
7026         if (!sgl || !sgl->virt) {
7027                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7028                             sgl, sgl ? sgl->virt : NULL);
7029                 return -1;
7030         }
7031         sge = sgl->virt;
7032
7033         if (sli4->config.sgl_pre_registered) {
7034                 trecv->xbl = FALSE;
7035
7036                 trecv->dbde = TRUE;
7037                 trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7038
7039                 trecv->bde.buffer_length = sge[0].buffer_length;
7040                 trecv->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
7041                 trecv->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
7042
7043                 trecv->payload_offset_length = sge[0].buffer_length;
7044         } else {
7045                 trecv->xbl = TRUE;
7046
7047                 /* if data is a single physical address, use a BDE */
7048                 if (!dif && (xfer_len <= sge[2].buffer_length)) {
7049                         trecv->dbde = TRUE;
7050                         trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7051
7052                         trecv->bde.buffer_length = sge[2].buffer_length;
7053                         trecv->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
7054                         trecv->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
7055                 } else {
7056                         trecv->bde.bde_type = SLI4_BDE_TYPE_BLP;
7057                         trecv->bde.buffer_length = sgl->size;
7058                         trecv->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
7059                         trecv->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
7060                 }
7061         }
7062
7063         trecv->relative_offset = relative_off;
7064
7065         if (flags & SLI4_IO_CONTINUATION) {
7066                 trecv->xc = TRUE;
7067         }
7068         trecv->xri_tag = xri;
7069
7070         trecv->context_tag = rpi;
7071
7072         trecv->pu = TRUE;       /* WQE uses relative offset */
7073
7074         if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
7075                 trecv->ar = TRUE;
7076         }
7077
7078         trecv->command = SLI4_WQE_FCP_TRECEIVE64;
7079         trecv->class = SLI4_ELS_REQUEST64_CLASS_3;
7080         trecv->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7081         trecv->dif = dif;
7082         trecv->bs  = bs;
7083
7084         trecv->remote_xid = xid;
7085
7086         trecv->request_tag = tag;
7087
7088         trecv->iod = 1;
7089
7090         trecv->len_loc = 0x2;
7091
7092         if (rnode->node_group) {
7093                 trecv->hlm = TRUE;
7094                 trecv->dword5.dword = rnode->fc_id & 0x00ffffff;
7095         }
7096
7097         trecv->cmd_type = SLI4_CMD_FCP_TRECEIVE64_WQE;
7098
7099         trecv->cq_id = cq_id;
7100
7101         trecv->fcp_data_receive_length = xfer_len;
7102
7103         if (sli4->config.perf_hint) {
7104                 trecv->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7105                 trecv->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
7106                 trecv->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
7107                 trecv->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
7108         }
7109
7110         /* The upper 7 bits of csctl is the priority */
7111         if (csctl & SLI4_MASK_CCP) {
7112                 trecv->ccpe = 1;
7113                 trecv->ccp = (csctl & SLI4_MASK_CCP);
7114         }
7115
7116         if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trecv->eat) {
7117                 trecv->app_id_valid = 1;
7118                 trecv->wqes = 1;
7119                 trecv_128->dw[31] = app_id;
7120         }
7121         return 0;
7122 }
7123
7124 /**
7125  * @ingroup sli_fc
7126  * @brief Write an FCP_CONT_TRECEIVE64_WQE work queue entry.
7127  *
7128  * @param sli4 SLI context.
7129  * @param buf Destination buffer for the WQE.
7130  * @param size Buffer size, in bytes.
7131  * @param sgl DMA memory for the Scatter-Gather List.
7132  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
7133  * @param relative_off Relative offset of the IO (if any).
7134  * @param xfer_len Data transfer length.
7135  * @param xri XRI for this exchange.
7136  * @param sec_xri Secondary XRI for this exchange. (BZ 161832 workaround)
7137  * @param tag IO tag value.
7138  * @param xid OX_ID for the exchange.
7139  * @param cq_id The id of the completion queue where the WQE response is sent.
7140  * @param rpi remote node indicator (RPI)
7141  * @param rnode Destination request (i.e. remote node).
7142  * @param flags Optional attributes, including:
7143  *  - ACTIVE - IO is already active.
7144  *  - AUTO RSP - Automatically generate a good FCP_RSP.
7145  * @param dif T10 DIF operation, or 0 to disable.
7146  * @param bs T10 DIF block size, or 0 if DIF is disabled.
7147  * @param csctl value of csctl field.
7148  * @param app_id value for VM application header.
7149  *
7150  * @return Returns 0 on success, or a non-zero value on failure.
7151  */
7152 int32_t
7153 sli_fcp_cont_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
7154                         uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t sec_xri, uint16_t tag,
7155                         uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags,
7156                         uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id)
7157 {
7158         int32_t rc;
7159
7160         rc = sli_fcp_treceive64_wqe(sli4, buf, size, sgl, first_data_sge, relative_off, xfer_len, xri, tag,
7161                         cq_id, xid, rpi, rnode, flags, dif, bs, csctl, app_id);
7162         if (rc == 0) {
7163                 sli4_fcp_treceive64_wqe_t *trecv = buf;
7164
7165                 trecv->command = SLI4_WQE_FCP_CONT_TRECEIVE64;
7166                 trecv->dword5.sec_xri_tag = sec_xri;
7167         }
7168         return rc;
7169 }
7170
7171 /**
7172  * @ingroup sli_fc
7173  * @brief Write an FCP_TRSP64_WQE work queue entry.
7174  *
7175  * @param sli4 SLI context.
7176  * @param buf Destination buffer for the WQE.
7177  * @param size Buffer size, in bytes.
7178  * @param sgl DMA memory for the Scatter-Gather List.
7179  * @param rsp_len Response data length.
7180  * @param xri XRI for this exchange.
7181  * @param tag IO tag value.
7182  * @param cq_id The id of the completion queue where the WQE response is sent.
7183  * @param xid OX_ID for the exchange.
7184  * @param rpi remote node indicator (RPI)
7185  * @param rnode Destination request (i.e. remote node).
7186  * @param flags Optional attributes, including:
7187  *  - ACTIVE - IO is already active
7188  *  - AUTO RSP - Automatically generate a good FCP_RSP.
7189  * @param csctl value of csctl field.
7190  * @param port_owned 0/1 to indicate if the XRI is port owned (used to set XBL=0)
7191  * @param app_id value for VM application header.
7192  *
7193  * @return Returns 0 on success, or a non-zero value on failure.
7194  */
7195 int32_t
7196 sli_fcp_trsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t rsp_len,
7197                    uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode,
7198                    uint32_t flags, uint8_t csctl, uint8_t port_owned, uint32_t app_id)
7199 {
7200         sli4_fcp_trsp64_wqe_t *trsp = buf;
7201         sli4_fcp_128byte_wqe_t *trsp_128 = buf;
7202
7203         ocs_memset(buf, 0, size);
7204
7205         if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
7206                 trsp->ag = TRUE;
7207                 /*
7208                  * The SLI-4 documentation states that the BDE is ignored when
7209                  * using auto-good response, but, at least for IF_TYPE 0 devices,
7210                  * this does not appear to be true.
7211                  */
7212                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
7213                         trsp->bde.buffer_length = 12;   /* byte size of RSP */
7214                 }
7215         } else {
7216                 sli4_sge_t      *sge = sgl->virt;
7217
7218                 if (sli4->config.sgl_pre_registered || port_owned) {
7219                         trsp->dbde = TRUE;
7220                 } else {
7221                         trsp->xbl = TRUE;
7222                 }
7223
7224                 trsp->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7225                 trsp->bde.buffer_length = sge[0].buffer_length;
7226                 trsp->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
7227                 trsp->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
7228
7229                 trsp->fcp_response_length = rsp_len;
7230         }
7231
7232         if (flags & SLI4_IO_CONTINUATION) {
7233                 trsp->xc = TRUE;
7234         }
7235
7236         if (rnode->node_group) {
7237                 trsp->hlm = TRUE;
7238                 trsp->dword5 = rnode->fc_id & 0x00ffffff;
7239         }
7240
7241         trsp->xri_tag = xri;
7242         trsp->rpi = rpi;
7243
7244         trsp->command = SLI4_WQE_FCP_TRSP64;
7245         trsp->class = SLI4_ELS_REQUEST64_CLASS_3;
7246
7247         trsp->remote_xid = xid;
7248         trsp->request_tag = tag;
7249         trsp->dnrx = ((flags & SLI4_IO_DNRX) == 0 ? 0 : 1);
7250         trsp->len_loc = 0x1;
7251         trsp->cq_id = cq_id;
7252         trsp->cmd_type = SLI4_CMD_FCP_TRSP64_WQE;
7253
7254         /* The upper 7 bits of csctl is the priority */
7255         if (csctl & SLI4_MASK_CCP) {
7256                 trsp->ccpe = 1;
7257                 trsp->ccp = (csctl & SLI4_MASK_CCP);
7258         }
7259
7260         if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trsp->eat) {
7261                 trsp->app_id_valid = 1;
7262                 trsp->wqes = 1;
7263                 trsp_128->dw[31] = app_id;
7264         }
7265         return 0;
7266 }
7267
7268 /**
7269  * @ingroup sli_fc
7270  * @brief Write an FCP_TSEND64_WQE work queue entry.
7271  *
7272  * @param sli4 SLI context.
7273  * @param buf Destination buffer for the WQE.
7274  * @param size Buffer size, in bytes.
7275  * @param sgl DMA memory for the scatter gather list.
7276  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
7277  * @param relative_off Relative offset of the IO (if any).
7278  * @param xfer_len Data transfer length.
7279  * @param xri XRI for this exchange.
7280  * @param tag IO tag value.
7281  * @param cq_id The id of the completion queue where the WQE response is sent.
7282  * @param xid OX_ID for the exchange.
7283  * @param rpi remote node indicator (RPI)
7284  * @param rnode Destination request (i.e. remote node).
7285  * @param flags Optional attributes, including:
7286  *  - ACTIVE - IO is already active.
7287  *  - AUTO RSP - Automatically generate a good FCP_RSP.
7288  * @param dif T10 DIF operation, or 0 to disable.
7289  * @param bs T10 DIF block size, or 0 if DIF is disabled.
7290  * @param csctl value of csctl field.
7291  * @param app_id value for VM application header.
7292  *
7293  * @return Returns 0 on success, or a non-zero value on failure.
7294  */
7295 int32_t
7296 sli_fcp_tsend64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
7297                     uint32_t relative_off, uint32_t xfer_len,
7298                     uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode,
7299                     uint32_t flags, uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id)
7300 {
7301         sli4_fcp_tsend64_wqe_t *tsend = buf;
7302         sli4_fcp_128byte_wqe_t *tsend_128 = buf;
7303         sli4_sge_t      *sge = NULL;
7304
7305         ocs_memset(buf, 0, size);
7306
7307         if (!sgl || !sgl->virt) {
7308                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7309                             sgl, sgl ? sgl->virt : NULL);
7310                 return -1;
7311         }
7312         sge = sgl->virt;
7313
7314         if (sli4->config.sgl_pre_registered) {
7315                 tsend->xbl = FALSE;
7316
7317                 tsend->dbde = TRUE;
7318                 tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7319
7320                 /* TSEND64_WQE specifies first two SGE are skipped
7321                  * (i.e. 3rd is valid) */
7322                 tsend->bde.buffer_length = sge[2].buffer_length;
7323                 tsend->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
7324                 tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
7325         } else {
7326                 tsend->xbl = TRUE;
7327
7328                 /* if data is a single physical address, use a BDE */
7329                 if (!dif && (xfer_len <= sge[2].buffer_length)) {
7330                         tsend->dbde = TRUE;
7331                         tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7332                         /* TSEND64_WQE specifies first two SGE are skipped
7333                          * (i.e. 3rd is valid) */
7334                         tsend->bde.buffer_length = sge[2].buffer_length;
7335                         tsend->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
7336                         tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
7337                 } else {
7338                         tsend->bde.bde_type = SLI4_BDE_TYPE_BLP;
7339                         tsend->bde.buffer_length = sgl->size;
7340                         tsend->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
7341                         tsend->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
7342                 }
7343         }
7344
7345         tsend->relative_offset = relative_off;
7346
7347         if (flags & SLI4_IO_CONTINUATION) {
7348                 tsend->xc = TRUE;
7349         }
7350         tsend->xri_tag = xri;
7351
7352         tsend->rpi = rpi;
7353
7354         tsend->pu = TRUE;       /* WQE uses relative offset */
7355
7356         if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
7357                 tsend->ar = TRUE;
7358         }
7359
7360         tsend->command = SLI4_WQE_FCP_TSEND64;
7361         tsend->class = SLI4_ELS_REQUEST64_CLASS_3;
7362         tsend->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7363         tsend->dif = dif;
7364         tsend->bs  = bs;
7365
7366         tsend->remote_xid = xid;
7367
7368         tsend->request_tag = tag;
7369
7370         tsend->len_loc = 0x2;
7371
7372         if (rnode->node_group) {
7373                 tsend->hlm = TRUE;
7374                 tsend->dword5 = rnode->fc_id & 0x00ffffff;
7375         }
7376
7377         tsend->cq_id = cq_id;
7378
7379         tsend->cmd_type = SLI4_CMD_FCP_TSEND64_WQE;
7380
7381         tsend->fcp_data_transmit_length = xfer_len;
7382
7383         if (sli4->config.perf_hint) {
7384                 tsend->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7385                 tsend->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
7386                 tsend->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
7387                 tsend->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
7388         }
7389
7390         /* The upper 7 bits of csctl is the priority */
7391         if (csctl & SLI4_MASK_CCP) {
7392                 tsend->ccpe = 1;
7393                 tsend->ccp = (csctl & SLI4_MASK_CCP);
7394         }
7395
7396         if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !tsend->eat) {
7397                 tsend->app_id_valid = 1;
7398                 tsend->wqes = 1;
7399                 tsend_128->dw[31] = app_id;
7400         }
7401         return 0;
7402 }
7403
7404 /**
7405  * @ingroup sli_fc
7406  * @brief Write a GEN_REQUEST64 work queue entry.
7407  *
7408  * @note This WQE is only used to send FC-CT commands.
7409  *
7410  * @param sli4 SLI context.
7411  * @param buf Destination buffer for the WQE.
7412  * @param size Buffer size, in bytes.
7413  * @param sgl DMA memory for the request.
7414  * @param req_len Length of request.
7415  * @param max_rsp_len Max length of response.
7416  * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
7417  * @param xri XRI for this exchange.
7418  * @param tag IO tag value.
7419  * @param cq_id The id of the completion queue where the WQE response is sent.
7420  * @param rnode Destination of request (that is, the remote node).
7421  * @param r_ctl R_CTL value for sequence.
7422  * @param type TYPE value for sequence.
7423  * @param df_ctl DF_CTL value for sequence.
7424  *
7425  * @return Returns 0 on success, or a non-zero value on failure.
7426  */
7427 int32_t
7428 sli_gen_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl,
7429                       uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
7430                       uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode,
7431                       uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
7432 {
7433         sli4_gen_request64_wqe_t        *gen = buf;
7434         sli4_sge_t      *sge = NULL;
7435
7436         ocs_memset(buf, 0, size);
7437
7438         if (!sgl || !sgl->virt) {
7439                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7440                             sgl, sgl ? sgl->virt : NULL);
7441                 return -1;
7442         }
7443         sge = sgl->virt;
7444
7445         if (sli4->config.sgl_pre_registered) {
7446                 gen->xbl = FALSE;
7447
7448                 gen->dbde = TRUE;
7449                 gen->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7450
7451                 gen->bde.buffer_length = req_len;
7452                 gen->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
7453                 gen->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
7454         } else {
7455                 gen->xbl = TRUE;
7456
7457                 gen->bde.bde_type = SLI4_BDE_TYPE_BLP;
7458
7459                 gen->bde.buffer_length = 2 * sizeof(sli4_sge_t);
7460                 gen->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
7461                 gen->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
7462         }
7463
7464         gen->request_payload_length = req_len;
7465         gen->max_response_payload_length = max_rsp_len;
7466
7467         gen->df_ctl = df_ctl;
7468         gen->type = type;
7469         gen->r_ctl = r_ctl;
7470
7471         gen->xri_tag = xri;
7472
7473         gen->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7474         gen->context_tag = rnode->indicator;
7475
7476         gen->class = SLI4_ELS_REQUEST64_CLASS_3;
7477
7478         gen->command = SLI4_WQE_GEN_REQUEST64;
7479
7480         gen->timer = timeout;
7481
7482         gen->request_tag = tag;
7483
7484         gen->iod = SLI4_ELS_REQUEST64_DIR_READ;
7485
7486         gen->qosd = TRUE;
7487
7488         if (rnode->node_group) {
7489                 gen->hlm = TRUE;
7490                 gen->remote_n_port_id = rnode->fc_id & 0x00ffffff;
7491         }
7492
7493         gen->cmd_type = SLI4_CMD_GEN_REQUEST64_WQE;
7494
7495         gen->cq_id = cq_id;
7496
7497         return 0;
7498 }
7499
7500 /**
7501  * @ingroup sli_fc
7502  * @brief Write a SEND_FRAME work queue entry
7503  *
7504  * @param sli4 SLI context.
7505  * @param buf Destination buffer for the WQE.
7506  * @param size Buffer size, in bytes.
7507  * @param sof Start of frame value
7508  * @param eof End of frame value
7509  * @param hdr Pointer to FC header data
7510  * @param payload DMA memory for the payload.
7511  * @param req_len Length of payload.
7512  * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
7513  * @param xri XRI for this exchange.
7514  * @param req_tag IO tag value.
7515  *
7516  * @return Returns 0 on success, or a non-zero value on failure.
7517  */
7518 int32_t
7519 sli_send_frame_wqe(sli4_t *sli4, void *buf, size_t size, uint8_t sof, uint8_t eof, uint32_t *hdr,
7520                    ocs_dma_t *payload, uint32_t req_len, uint8_t timeout,
7521                    uint16_t xri, uint16_t req_tag)
7522 {
7523         sli4_send_frame_wqe_t *sf = buf;
7524
7525         ocs_memset(buf, 0, size);
7526
7527         sf->dbde = TRUE;
7528         sf->bde.buffer_length = req_len;
7529         sf->bde.u.data.buffer_address_low = ocs_addr32_lo(payload->phys);
7530         sf->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
7531
7532         /* Copy FC header */
7533         sf->fc_header_0_1[0] = hdr[0];
7534         sf->fc_header_0_1[1] = hdr[1];
7535         sf->fc_header_2_5[0] = hdr[2];
7536         sf->fc_header_2_5[1] = hdr[3];
7537         sf->fc_header_2_5[2] = hdr[4];
7538         sf->fc_header_2_5[3] = hdr[5];
7539
7540         sf->frame_length = req_len;
7541
7542         sf->xri_tag = xri;
7543         sf->pu = 0;
7544         sf->context_tag = 0;
7545
7546         sf->ct = 0;
7547         sf->command = SLI4_WQE_SEND_FRAME;
7548         sf->class = SLI4_ELS_REQUEST64_CLASS_3;
7549         sf->timer = timeout;
7550
7551         sf->request_tag = req_tag;
7552         sf->eof = eof;
7553         sf->sof = sof;
7554
7555         sf->qosd = 0;
7556         sf->lenloc = 1;
7557         sf->xc = 0;
7558
7559         sf->xbl = 1;
7560
7561         sf->cmd_type = SLI4_CMD_SEND_FRAME_WQE;
7562         sf->cq_id = 0xffff;
7563
7564         return 0;
7565 }
7566
7567 /**
7568  * @ingroup sli_fc
7569  * @brief Write a XMIT_SEQUENCE64 work queue entry.
7570  *
7571  * This WQE is used to send FC-CT response frames.
7572  *
7573  * @note This API implements a restricted use for this WQE, a TODO: would
7574  * include passing in sequence initiative, and full SGL's
7575  *
7576  * @param sli4 SLI context.
7577  * @param buf Destination buffer for the WQE.
7578  * @param size Buffer size, in bytes.
7579  * @param payload DMA memory for the request.
7580  * @param payload_len Length of request.
7581  * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
7582  * @param ox_id originator exchange ID
7583  * @param xri XRI for this exchange.
7584  * @param tag IO tag value.
7585  * @param rnode Destination of request (that is, the remote node).
7586  * @param r_ctl R_CTL value for sequence.
7587  * @param type TYPE value for sequence.
7588  * @param df_ctl DF_CTL value for sequence.
7589  *
7590  * @return Returns 0 on success, or a non-zero value on failure.
7591  */
7592 int32_t
7593 sli_xmit_sequence64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload,
7594                       uint32_t payload_len, uint8_t timeout, uint16_t ox_id,
7595                       uint16_t xri, uint16_t tag, ocs_remote_node_t *rnode,
7596                       uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
7597 {
7598         sli4_xmit_sequence64_wqe_t      *xmit = buf;
7599
7600         ocs_memset(buf, 0, size);
7601
7602         if ((payload == NULL) || (payload->virt == NULL)) {
7603                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7604                             payload, payload ? payload->virt : NULL);
7605                 return -1;
7606         }
7607
7608         if (sli4->config.sgl_pre_registered) {
7609                 xmit->dbde = TRUE;
7610         } else {
7611                 xmit->xbl = TRUE;
7612         }
7613
7614         xmit->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7615         xmit->bde.buffer_length = payload_len;
7616         xmit->bde.u.data.buffer_address_low  = ocs_addr32_lo(payload->phys);
7617         xmit->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
7618         xmit->sequence_payload_len = payload_len;
7619
7620         xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff;
7621
7622         xmit->relative_offset = 0;
7623
7624         xmit->si = 0;                   /* sequence initiative - this matches what is seen from
7625                                          * FC switches in response to FCGS commands */
7626         xmit->ft = 0;                   /* force transmit */
7627         xmit->xo = 0;                   /* exchange responder */
7628         xmit->ls = 1;                   /* last in seqence */
7629         xmit->df_ctl = df_ctl;
7630         xmit->type = type;
7631         xmit->r_ctl = r_ctl;
7632
7633         xmit->xri_tag = xri;
7634         xmit->context_tag = rnode->indicator;
7635
7636         xmit->dif = 0;
7637         xmit->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7638         xmit->bs = 0;
7639
7640         xmit->command = SLI4_WQE_XMIT_SEQUENCE64;
7641         xmit->class = SLI4_ELS_REQUEST64_CLASS_3;
7642         xmit->pu = 0;
7643         xmit->timer = timeout;
7644
7645         xmit->abort_tag = 0;
7646         xmit->request_tag = tag;
7647         xmit->remote_xid = ox_id;
7648
7649         xmit->iod = SLI4_ELS_REQUEST64_DIR_READ;
7650
7651         if (rnode->node_group) {
7652                 xmit->hlm = TRUE;
7653                 xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff;
7654         }
7655
7656         xmit->cmd_type = SLI4_CMD_XMIT_SEQUENCE64_WQE;
7657
7658         xmit->len_loc = 2;
7659
7660         xmit->cq_id = 0xFFFF;
7661
7662         return 0;
7663 }
7664
7665 /**
7666  * @ingroup sli_fc
7667  * @brief Write a REQUEUE_XRI_WQE work queue entry.
7668  *
7669  * @param sli4 SLI context.
7670  * @param buf Destination buffer for the WQE.
7671  * @param size Buffer size, in bytes.
7672  * @param xri XRI for this exchange.
7673  * @param tag IO tag value.
7674  * @param cq_id The id of the completion queue where the WQE response is sent.
7675  *
7676  * @return Returns 0 on success, or a non-zero value on failure.
7677  */
7678 int32_t
7679 sli_requeue_xri_wqe(sli4_t *sli4, void *buf, size_t size, uint16_t xri, uint16_t tag, uint16_t cq_id)
7680 {
7681         sli4_requeue_xri_wqe_t  *requeue = buf;
7682
7683         ocs_memset(buf, 0, size);
7684
7685         requeue->command = SLI4_WQE_REQUEUE_XRI;
7686         requeue->xri_tag = xri;
7687         requeue->request_tag = tag;
7688         requeue->xc = 1;
7689         requeue->qosd = 1;
7690         requeue->cq_id = cq_id;
7691         requeue->cmd_type = SLI4_CMD_REQUEUE_XRI_WQE;
7692         return 0;
7693 }
7694
7695 int32_t
7696 sli_xmit_bcast64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload,
7697                 uint32_t payload_len, uint8_t timeout, uint16_t xri, uint16_t tag,
7698                 uint16_t cq_id, ocs_remote_node_t *rnode,
7699                 uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
7700 {
7701         sli4_xmit_bcast64_wqe_t *bcast = buf;
7702
7703         /* Command requires a temporary RPI (i.e. unused remote node) */
7704         if (rnode->attached) {
7705                 ocs_log_test(sli4->os, "remote node %d in use\n", rnode->indicator);
7706                 return -1;
7707         }
7708
7709         ocs_memset(buf, 0, size);
7710
7711         bcast->dbde = TRUE;
7712         bcast->sequence_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
7713         bcast->sequence_payload.buffer_length = payload_len;
7714         bcast->sequence_payload.u.data.buffer_address_low  = ocs_addr32_lo(payload->phys);
7715         bcast->sequence_payload.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
7716
7717         bcast->sequence_payload_length = payload_len;
7718
7719         bcast->df_ctl = df_ctl;
7720         bcast->type = type;
7721         bcast->r_ctl = r_ctl;
7722
7723         bcast->xri_tag = xri;
7724
7725         bcast->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
7726         bcast->context_tag = rnode->sport->indicator;
7727
7728         bcast->class = SLI4_ELS_REQUEST64_CLASS_3;
7729
7730         bcast->command = SLI4_WQE_XMIT_BCAST64;
7731
7732         bcast->timer = timeout;
7733
7734         bcast->request_tag = tag;
7735
7736         bcast->temporary_rpi = rnode->indicator;
7737
7738         bcast->len_loc = 0x1;
7739
7740         bcast->iod = SLI4_ELS_REQUEST64_DIR_WRITE;
7741
7742         bcast->cmd_type = SLI4_CMD_XMIT_BCAST64_WQE;
7743
7744         bcast->cq_id = cq_id;
7745
7746         return 0;
7747 }
7748
7749 /**
7750  * @ingroup sli_fc
7751  * @brief Write an XMIT_BLS_RSP64_WQE work queue entry.
7752  *
7753  * @param sli4 SLI context.
7754  * @param buf Destination buffer for the WQE.
7755  * @param size Buffer size, in bytes.
7756  * @param payload Contents of the BLS payload to be sent.
7757  * @param xri XRI for this exchange.
7758  * @param tag IO tag value.
7759  * @param cq_id The id of the completion queue where the WQE response is sent.
7760  * @param rnode Destination of request (that is, the remote node).
7761  * @param s_id Source ID to use in the response. If UINT32_MAX, use SLI Port's ID.
7762  *
7763  * @return Returns 0 on success, or a non-zero value on failure.
7764  */
7765 int32_t
7766 sli_xmit_bls_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, sli_bls_payload_t *payload,
7767                        uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode, uint32_t s_id)
7768 {
7769         sli4_xmit_bls_rsp_wqe_t *bls = buf;
7770
7771         /*
7772          * Callers can either specify RPI or S_ID, but not both
7773          */
7774         if (rnode->attached && (s_id != UINT32_MAX)) {
7775                 ocs_log_test(sli4->os, "S_ID specified for attached remote node %d\n",
7776                              rnode->indicator);
7777                 return -1;
7778         }
7779
7780         ocs_memset(buf, 0, size);
7781
7782         if (SLI_BLS_ACC == payload->type) {
7783                 bls->payload_word0 = (payload->u.acc.seq_id_last << 16) |
7784                         (payload->u.acc.seq_id_validity << 24);
7785                 bls->high_seq_cnt = payload->u.acc.high_seq_cnt;
7786                 bls->low_seq_cnt = payload->u.acc.low_seq_cnt;
7787         } else if (SLI_BLS_RJT == payload->type) {
7788                 bls->payload_word0 = *((uint32_t *)&payload->u.rjt);
7789                 bls->ar = TRUE;
7790         } else {
7791                 ocs_log_test(sli4->os, "bad BLS type %#x\n",
7792                                 payload->type);
7793                 return -1;
7794         }
7795
7796         bls->ox_id = payload->ox_id;
7797         bls->rx_id = payload->rx_id;
7798
7799         if (rnode->attached) {
7800                 bls->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7801                 bls->context_tag = rnode->indicator;
7802         } else {
7803                 bls->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
7804                 bls->context_tag = rnode->sport->indicator;
7805
7806                 if (UINT32_MAX != s_id) {
7807                         bls->local_n_port_id = s_id & 0x00ffffff;
7808                 } else {
7809                         bls->local_n_port_id = rnode->sport->fc_id & 0x00ffffff;
7810                 }
7811                 bls->remote_id = rnode->fc_id & 0x00ffffff;
7812
7813                 bls->temporary_rpi = rnode->indicator;
7814         }
7815
7816         bls->xri_tag = xri;
7817
7818         bls->class = SLI4_ELS_REQUEST64_CLASS_3;
7819
7820         bls->command = SLI4_WQE_XMIT_BLS_RSP;
7821
7822         bls->request_tag = tag;
7823
7824         bls->qosd = TRUE;
7825
7826         if (rnode->node_group) {
7827                 bls->hlm = TRUE;
7828                 bls->remote_id = rnode->fc_id & 0x00ffffff;
7829         }
7830
7831         bls->cq_id = cq_id;
7832
7833         bls->cmd_type = SLI4_CMD_XMIT_BLS_RSP64_WQE;
7834
7835         return 0;
7836 }
7837
7838 /**
7839  * @ingroup sli_fc
7840  * @brief Write a XMIT_ELS_RSP64_WQE work queue entry.
7841  *
7842  * @param sli4 SLI context.
7843  * @param buf Destination buffer for the WQE.
7844  * @param size Buffer size, in bytes.
7845  * @param rsp DMA memory for the ELS response.
7846  * @param rsp_len Length of ELS response, in bytes.
7847  * @param xri XRI for this exchange.
7848  * @param tag IO tag value.
7849  * @param cq_id The id of the completion queue where the WQE response is sent.
7850  * @param ox_id OX_ID of the exchange containing the request.
7851  * @param rnode Destination of the ELS response (that is, the remote node).
7852  * @param flags Optional attributes, including:
7853  *  - SLI4_IO_CONTINUATION - IO is already active.
7854  * @param s_id S_ID used for special responses.
7855  *
7856  * @return Returns 0 on success, or a non-zero value on failure.
7857  */
7858 int32_t
7859 sli_xmit_els_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *rsp,
7860                        uint32_t rsp_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
7861                        uint16_t ox_id, ocs_remote_node_t *rnode, uint32_t flags, uint32_t s_id)
7862 {
7863         sli4_xmit_els_rsp64_wqe_t       *els = buf;
7864
7865         ocs_memset(buf, 0, size);
7866
7867         if (sli4->config.sgl_pre_registered) {
7868                 els->dbde = TRUE;
7869         } else {
7870                 els->xbl = TRUE;
7871         }
7872
7873         els->els_response_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
7874         els->els_response_payload.buffer_length = rsp_len;
7875         els->els_response_payload.u.data.buffer_address_low  = ocs_addr32_lo(rsp->phys);
7876         els->els_response_payload.u.data.buffer_address_high = ocs_addr32_hi(rsp->phys);
7877
7878         els->els_response_payload_length = rsp_len;
7879
7880         els->xri_tag = xri;
7881
7882         els->class = SLI4_ELS_REQUEST64_CLASS_3;
7883
7884         els->command = SLI4_WQE_ELS_RSP64;
7885
7886         els->request_tag = tag;
7887
7888         els->ox_id = ox_id;
7889
7890         els->iod = SLI4_ELS_REQUEST64_DIR_WRITE;
7891
7892         els->qosd = TRUE;
7893
7894         if (flags & SLI4_IO_CONTINUATION) {
7895                 els->xc = TRUE;
7896         }
7897
7898         if (rnode->attached) {
7899                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7900                 els->context_tag = rnode->indicator;
7901         } else {
7902                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
7903                 els->context_tag = rnode->sport->indicator;
7904                 els->remote_id = rnode->fc_id & 0x00ffffff;
7905                 els->temporary_rpi = rnode->indicator;
7906                 if (UINT32_MAX != s_id) {
7907                         els->sp = TRUE;
7908                         els->s_id = s_id & 0x00ffffff;
7909                 }
7910         }
7911
7912         if (rnode->node_group) {
7913                 els->hlm = TRUE;
7914                 els->remote_id = rnode->fc_id & 0x00ffffff;
7915         }
7916
7917         els->cmd_type = SLI4_ELS_REQUEST64_CMD_GEN;
7918
7919         els->cq_id = cq_id;
7920
7921         return 0;
7922 }
7923
7924 /**
7925  * @ingroup sli_fc
7926  * @brief Process an asynchronous Link State event entry.
7927  *
7928  * @par Description
7929  * Parses Asynchronous Completion Queue Entry (ACQE),
7930  * creates an abstracted event, and calls registered callback functions.
7931  *
7932  * @param sli4 SLI context.
7933  * @param acqe Pointer to the ACQE.
7934  *
7935  * @return Returns 0 on success, or a non-zero value on failure.
7936  */
7937 int32_t
7938 sli_fc_process_link_state(sli4_t *sli4, void *acqe)
7939 {
7940         sli4_link_state_t       *link_state = acqe;
7941         sli4_link_event_t       event = { 0 };
7942         int32_t                 rc = 0;
7943
7944         if (!sli4->link) {
7945                 /* bail if there is no callback */
7946                 return 0;
7947         }
7948
7949         if (SLI4_LINK_TYPE_ETHERNET == link_state->link_type) {
7950                 event.topology = SLI_LINK_TOPO_NPORT;
7951                 event.medium   = SLI_LINK_MEDIUM_ETHERNET;
7952         } else {
7953                 /* TODO is this supported for anything other than FCoE? */
7954                 ocs_log_test(sli4->os, "unsupported link type %#x\n",
7955                                 link_state->link_type);
7956                 event.topology = SLI_LINK_TOPO_MAX;
7957                 event.medium   = SLI_LINK_MEDIUM_MAX;
7958                 rc = -1;
7959         }
7960
7961         switch (link_state->port_link_status) {
7962         case SLI4_PORT_LINK_STATUS_PHYSICAL_DOWN:
7963         case SLI4_PORT_LINK_STATUS_LOGICAL_DOWN:
7964                 event.status = SLI_LINK_STATUS_DOWN;
7965                 break;
7966         case SLI4_PORT_LINK_STATUS_PHYSICAL_UP:
7967         case SLI4_PORT_LINK_STATUS_LOGICAL_UP:
7968                 event.status = SLI_LINK_STATUS_UP;
7969                 break;
7970         default:
7971                 ocs_log_test(sli4->os, "unsupported link status %#x\n",
7972                                 link_state->port_link_status);
7973                 event.status = SLI_LINK_STATUS_MAX;
7974                 rc = -1;
7975         }
7976
7977         switch (link_state->port_speed) {
7978         case 0:
7979                 event.speed = 0;
7980                 break;
7981         case 1:
7982                 event.speed = 10;
7983                 break;
7984         case 2:
7985                 event.speed = 100;
7986                 break;
7987         case 3:
7988                 event.speed = 1000;
7989                 break;
7990         case 4:
7991                 event.speed = 10000;
7992                 break;
7993         case 5:
7994                 event.speed = 20000;
7995                 break;
7996         case 6:
7997                 event.speed = 25000;
7998                 break;
7999         case 7:
8000                 event.speed = 40000;
8001                 break;
8002         case 8:
8003                 event.speed = 100000;
8004                 break;
8005         default:
8006                 ocs_log_test(sli4->os, "unsupported port_speed %#x\n",
8007                                 link_state->port_speed);
8008                 rc = -1;
8009         }
8010
8011         sli4->link(sli4->link_arg, (void *)&event);
8012
8013         return rc;
8014 }
8015
8016 /**
8017  * @ingroup sli_fc
8018  * @brief Process an asynchronous Link Attention event entry.
8019  *
8020  * @par Description
8021  * Parses Asynchronous Completion Queue Entry (ACQE),
8022  * creates an abstracted event, and calls the registered callback functions.
8023  *
8024  * @param sli4 SLI context.
8025  * @param acqe Pointer to the ACQE.
8026  *
8027  * @todo XXX all events return LINK_UP.
8028  *
8029  * @return Returns 0 on success, or a non-zero value on failure.
8030  */
8031 int32_t
8032 sli_fc_process_link_attention(sli4_t *sli4, void *acqe)
8033 {
8034         sli4_link_attention_t   *link_attn = acqe;
8035         sli4_link_event_t       event = { 0 };
8036
8037         ocs_log_debug(sli4->os, "link_number=%d attn_type=%#x topology=%#x port_speed=%#x "
8038                         "port_fault=%#x shared_link_status=%#x logical_link_speed=%#x "
8039                         "event_tag=%#x\n", link_attn->link_number, link_attn->attn_type,
8040                         link_attn->topology, link_attn->port_speed, link_attn->port_fault,
8041                         link_attn->shared_link_status, link_attn->logical_link_speed,
8042                         link_attn->event_tag);
8043
8044         if (!sli4->link) {
8045                 return 0;
8046         }
8047
8048         event.medium   = SLI_LINK_MEDIUM_FC;
8049
8050         switch (link_attn->attn_type) {
8051         case SLI4_LINK_ATTN_TYPE_LINK_UP:
8052                 event.status = SLI_LINK_STATUS_UP;
8053                 break;
8054         case SLI4_LINK_ATTN_TYPE_LINK_DOWN:
8055                 event.status = SLI_LINK_STATUS_DOWN;
8056                 break;
8057         case SLI4_LINK_ATTN_TYPE_NO_HARD_ALPA:
8058                 ocs_log_debug(sli4->os, "attn_type: no hard alpa\n");
8059                 event.status = SLI_LINK_STATUS_NO_ALPA;
8060                 break;
8061         default:
8062                 ocs_log_test(sli4->os, "attn_type: unknown\n");
8063                 break;
8064         }
8065
8066         switch (link_attn->event_type) {
8067         case SLI4_FC_EVENT_LINK_ATTENTION:
8068                 break;
8069         case SLI4_FC_EVENT_SHARED_LINK_ATTENTION:
8070                 ocs_log_debug(sli4->os, "event_type: FC shared link event \n");
8071                 break;
8072         default:
8073                 ocs_log_test(sli4->os, "event_type: unknown\n");
8074                 break;
8075         }
8076
8077         switch (link_attn->topology) {
8078         case SLI4_LINK_ATTN_P2P:
8079                 event.topology = SLI_LINK_TOPO_NPORT;
8080                 break;
8081         case SLI4_LINK_ATTN_FC_AL:
8082                 event.topology = SLI_LINK_TOPO_LOOP;
8083                 break;
8084         case SLI4_LINK_ATTN_INTERNAL_LOOPBACK:
8085                 ocs_log_debug(sli4->os, "topology Internal loopback\n");
8086                 event.topology = SLI_LINK_TOPO_LOOPBACK_INTERNAL;
8087                 break;
8088         case SLI4_LINK_ATTN_SERDES_LOOPBACK:
8089                 ocs_log_debug(sli4->os, "topology serdes loopback\n");
8090                 event.topology = SLI_LINK_TOPO_LOOPBACK_EXTERNAL;
8091                 break;
8092         default:
8093                 ocs_log_test(sli4->os, "topology: unknown\n");
8094                 break;
8095         }
8096
8097         event.speed    = link_attn->port_speed * 1000;
8098
8099         sli4->link(sli4->link_arg, (void *)&event);
8100
8101         return 0;
8102 }
8103
8104 /**
8105  * @ingroup sli_fc
8106  * @brief Parse an FC/FCoE work queue CQ entry.
8107  *
8108  * @param sli4 SLI context.
8109  * @param cq CQ to process.
8110  * @param cqe Pointer to the CQ entry.
8111  * @param etype CQ event type.
8112  * @param r_id Resource ID associated with this completion message (such as the IO tag).
8113  *
8114  * @return Returns 0 on success, or a non-zero value on failure.
8115  */
8116 int32_t
8117 sli_fc_cqe_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
8118                 uint16_t *r_id)
8119 {
8120         uint8_t         code = cqe[SLI4_CQE_CODE_OFFSET];
8121         int32_t         rc = -1;
8122
8123         switch (code) {
8124         case SLI4_CQE_CODE_WORK_REQUEST_COMPLETION:
8125         {
8126                 sli4_fc_wcqe_t *wcqe = (void *)cqe;
8127
8128                 *etype = SLI_QENTRY_WQ;
8129                 *r_id = wcqe->request_tag;
8130                 rc = wcqe->status;
8131
8132                 /* Flag errors except for FCP_RSP_FAILURE */
8133                 if (rc && (rc != SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE)) {
8134                         ocs_log_test(sli4->os, "WCQE: status=%#x hw_status=%#x tag=%#x w1=%#x w2=%#x xb=%d\n",
8135                                 wcqe->status, wcqe->hw_status,
8136                                 wcqe->request_tag, wcqe->wqe_specific_1,
8137                                 wcqe->wqe_specific_2, wcqe->xb);
8138                         ocs_log_test(sli4->os, "      %08X %08X %08X %08X\n", ((uint32_t*) cqe)[0], ((uint32_t*) cqe)[1],
8139                                 ((uint32_t*) cqe)[2], ((uint32_t*) cqe)[3]);
8140                 }
8141
8142                 /* TODO: need to pass additional status back out of here as well
8143                  * as status (could overload rc as status/addlstatus are only 8 bits each)
8144                  */
8145
8146                 break;
8147         }
8148         case SLI4_CQE_CODE_RQ_ASYNC:
8149         {
8150                 sli4_fc_async_rcqe_t *rcqe = (void *)cqe;
8151
8152                 *etype = SLI_QENTRY_RQ;
8153                 *r_id = rcqe->rq_id;
8154                 rc = rcqe->status;
8155                 break;
8156         }
8157         case SLI4_CQE_CODE_RQ_ASYNC_V1:
8158         {
8159                 sli4_fc_async_rcqe_v1_t *rcqe = (void *)cqe;
8160
8161                 *etype = SLI_QENTRY_RQ;
8162                 *r_id = rcqe->rq_id;
8163                 rc = rcqe->status;
8164                 break;
8165         }
8166         case SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD:
8167         {
8168                 sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe;
8169
8170                 *etype = SLI_QENTRY_OPT_WRITE_CMD;
8171                 *r_id = optcqe->rq_id;
8172                 rc = optcqe->status;
8173                 break;
8174         }
8175         case SLI4_CQE_CODE_OPTIMIZED_WRITE_DATA:
8176         {
8177                 sli4_fc_optimized_write_data_cqe_t *dcqe = (void *)cqe;
8178
8179                 *etype = SLI_QENTRY_OPT_WRITE_DATA;
8180                 *r_id = dcqe->xri;
8181                 rc = dcqe->status;
8182
8183                 /* Flag errors */
8184                 if (rc != SLI4_FC_WCQE_STATUS_SUCCESS) {
8185                         ocs_log_test(sli4->os, "Optimized DATA CQE: status=%#x hw_status=%#x xri=%#x dpl=%#x w3=%#x xb=%d\n",
8186                                 dcqe->status, dcqe->hw_status,
8187                                 dcqe->xri, dcqe->total_data_placed,
8188                                 ((uint32_t*) cqe)[3], dcqe->xb);
8189                 }
8190                 break;
8191         }
8192         case SLI4_CQE_CODE_RQ_COALESCING:
8193         {
8194                 sli4_fc_coalescing_rcqe_t *rcqe = (void *)cqe;
8195
8196                 *etype = SLI_QENTRY_RQ;
8197                 *r_id = rcqe->rq_id;
8198                 rc = rcqe->status;
8199                 break;
8200         }
8201         case SLI4_CQE_CODE_XRI_ABORTED:
8202         {
8203                 sli4_fc_xri_aborted_cqe_t *xa = (void *)cqe;
8204
8205                 *etype = SLI_QENTRY_XABT;
8206                 *r_id = xa->xri;
8207                 rc = 0;
8208                 break;
8209         }
8210         case SLI4_CQE_CODE_RELEASE_WQE: {
8211                 sli4_fc_wqec_t *wqec = (void*) cqe;
8212
8213                 *etype = SLI_QENTRY_WQ_RELEASE;
8214                 *r_id = wqec->wq_id;
8215                 rc = 0;
8216                 break;
8217         }
8218         default:
8219                 ocs_log_test(sli4->os, "CQE completion code %d not handled\n", code);
8220                 *etype = SLI_QENTRY_MAX;
8221                 *r_id = UINT16_MAX;
8222         }
8223
8224         return rc;
8225 }
8226
8227 /**
8228  * @ingroup sli_fc
8229  * @brief Return the ELS/CT response length.
8230  *
8231  * @param sli4 SLI context.
8232  * @param cqe Pointer to the CQ entry.
8233  *
8234  * @return Returns the length, in bytes.
8235  */
8236 uint32_t
8237 sli_fc_response_length(sli4_t *sli4, uint8_t *cqe)
8238 {
8239         sli4_fc_wcqe_t *wcqe = (void *)cqe;
8240
8241         return wcqe->wqe_specific_1;
8242 }
8243
8244 /**
8245  * @ingroup sli_fc
8246  * @brief Return the FCP IO length.
8247  *
8248  * @param sli4 SLI context.
8249  * @param cqe Pointer to the CQ entry.
8250  *
8251  * @return Returns the length, in bytes.
8252  */
8253 uint32_t
8254 sli_fc_io_length(sli4_t *sli4, uint8_t *cqe)
8255 {
8256         sli4_fc_wcqe_t *wcqe = (void *)cqe;
8257
8258         return wcqe->wqe_specific_1;
8259 }
8260
8261 /**
8262  * @ingroup sli_fc
8263  * @brief Retrieve the D_ID from the completion.
8264  *
8265  * @param sli4 SLI context.
8266  * @param cqe Pointer to the CQ entry.
8267  * @param d_id Pointer where the D_ID is written.
8268  *
8269  * @return Returns 0 on success, or a non-zero value on failure.
8270  */
8271 int32_t
8272 sli_fc_els_did(sli4_t *sli4, uint8_t *cqe, uint32_t *d_id)
8273 {
8274         sli4_fc_wcqe_t *wcqe = (void *)cqe;
8275
8276         *d_id = 0;
8277
8278         if (wcqe->status) {
8279                 return -1;
8280         } else {
8281                 *d_id = wcqe->wqe_specific_2 & 0x00ffffff;
8282                 return 0;
8283         }
8284 }
8285
8286 uint32_t
8287 sli_fc_ext_status(sli4_t *sli4, uint8_t *cqe)
8288 {
8289         sli4_fc_wcqe_t *wcqe = (void *)cqe;
8290         uint32_t        mask;
8291
8292         switch (wcqe->status) {
8293         case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE:
8294                 mask = UINT32_MAX;
8295                 break;
8296         case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
8297         case SLI4_FC_WCQE_STATUS_CMD_REJECT:
8298                 mask = 0xff;
8299                 break;
8300         case SLI4_FC_WCQE_STATUS_NPORT_RJT:
8301         case SLI4_FC_WCQE_STATUS_FABRIC_RJT:
8302         case SLI4_FC_WCQE_STATUS_NPORT_BSY:
8303         case SLI4_FC_WCQE_STATUS_FABRIC_BSY:
8304         case SLI4_FC_WCQE_STATUS_LS_RJT:
8305                 mask = UINT32_MAX;
8306                 break;
8307         case SLI4_FC_WCQE_STATUS_DI_ERROR:
8308                 mask = UINT32_MAX;
8309                 break;
8310         default:
8311                 mask = 0;
8312         }
8313
8314         return wcqe->wqe_specific_2 & mask;
8315 }
8316
8317 /**
8318  * @ingroup sli_fc
8319  * @brief Retrieve the RQ index from the completion.
8320  *
8321  * @param sli4 SLI context.
8322  * @param cqe Pointer to the CQ entry.
8323  * @param rq_id Pointer where the rq_id is written.
8324  * @param index Pointer where the index is written.
8325  *
8326  * @return Returns 0 on success, or a non-zero value on failure.
8327  */
8328 int32_t
8329 sli_fc_rqe_rqid_and_index(sli4_t *sli4, uint8_t *cqe, uint16_t *rq_id, uint32_t *index)
8330 {
8331         sli4_fc_async_rcqe_t    *rcqe = (void *)cqe;
8332         sli4_fc_async_rcqe_v1_t *rcqe_v1 = (void *)cqe;
8333         int32_t rc = -1;
8334         uint8_t code = 0;
8335
8336         *rq_id = 0;
8337         *index = UINT32_MAX;
8338
8339         code = cqe[SLI4_CQE_CODE_OFFSET];
8340
8341         if (code == SLI4_CQE_CODE_RQ_ASYNC) {
8342                 *rq_id = rcqe->rq_id;
8343                 if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe->status) {
8344                         *index = rcqe->rq_element_index;
8345                         rc = 0;
8346                 } else {
8347                         *index = rcqe->rq_element_index;
8348                         rc = rcqe->status;
8349                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
8350                                 rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id,
8351                                 rcqe->rq_element_index, rcqe->payload_data_placement_length, rcqe->sof_byte,
8352                                 rcqe->eof_byte, rcqe->header_data_placement_length);
8353                 }
8354         } else if (code == SLI4_CQE_CODE_RQ_ASYNC_V1) {
8355                 *rq_id = rcqe_v1->rq_id;
8356                 if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe_v1->status) {
8357                         *index = rcqe_v1->rq_element_index;
8358                         rc = 0;
8359                 } else {
8360                         *index = rcqe_v1->rq_element_index;
8361                         rc = rcqe_v1->status;
8362                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
8363                                 rcqe_v1->status, sli_fc_get_status_string(rcqe_v1->status),
8364                                 rcqe_v1->rq_id, rcqe_v1->rq_element_index,
8365                                 rcqe_v1->payload_data_placement_length, rcqe_v1->sof_byte,
8366                                 rcqe_v1->eof_byte, rcqe_v1->header_data_placement_length);
8367                 }
8368         } else if (code == SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD) {
8369                 sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe;
8370
8371                 *rq_id = optcqe->rq_id;
8372                 if (SLI4_FC_ASYNC_RQ_SUCCESS == optcqe->status) {
8373                         *index = optcqe->rq_element_index;
8374                         rc = 0;
8375                 } else {
8376                         *index = optcqe->rq_element_index;
8377                         rc = optcqe->status;
8378                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x hdpl=%x oox=%d agxr=%d xri=0x%x rpi=0x%x\n",
8379                                 optcqe->status, sli_fc_get_status_string(optcqe->status), optcqe->rq_id,
8380                                 optcqe->rq_element_index, optcqe->payload_data_placement_length,
8381                                 optcqe->header_data_placement_length, optcqe->oox, optcqe->agxr, optcqe->xri,
8382                                 optcqe->rpi);
8383                 }
8384         } else if (code == SLI4_CQE_CODE_RQ_COALESCING) {
8385                 sli4_fc_coalescing_rcqe_t       *rcqe = (void *)cqe;
8386
8387                 *rq_id = rcqe->rq_id;
8388                 if (SLI4_FC_COALESCE_RQ_SUCCESS == rcqe->status) {
8389                         *index = rcqe->rq_element_index;
8390                         rc = 0;
8391                 } else {
8392                         *index = UINT32_MAX;
8393                         rc = rcqe->status;
8394
8395                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x rq_id=%#x sdpl=%x\n",
8396                                 rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id,
8397                                 rcqe->rq_element_index, rcqe->rq_id, rcqe->sequence_reporting_placement_length);
8398                 }
8399         } else {
8400                 *index = UINT32_MAX;
8401
8402                 rc = rcqe->status;
8403
8404                 ocs_log_debug(sli4->os, "status=%02x rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
8405                         rcqe->status, rcqe->rq_id, rcqe->rq_element_index, rcqe->payload_data_placement_length,
8406                         rcqe->sof_byte, rcqe->eof_byte, rcqe->header_data_placement_length);
8407         }
8408
8409         return rc;
8410 }
8411
8412 /**
8413  * @ingroup sli_fc
8414  * @brief Process an asynchronous FCoE event entry.
8415  *
8416  * @par Description
8417  * Parses Asynchronous Completion Queue Entry (ACQE),
8418  * creates an abstracted event, and calls the registered callback functions.
8419  *
8420  * @param sli4 SLI context.
8421  * @param acqe Pointer to the ACQE.
8422  *
8423  * @return Returns 0 on success, or a non-zero value on failure.
8424  */
8425 int32_t
8426 sli_fc_process_fcoe(sli4_t *sli4, void *acqe)
8427 {
8428         sli4_fcoe_fip_t *fcoe = acqe;
8429         sli4_fip_event_t event = { 0 };
8430         uint32_t        mask = UINT32_MAX;
8431
8432         ocs_log_debug(sli4->os, "ACQE FCoE FIP type=%02x count=%d tag=%#x\n",
8433                         fcoe->event_type,
8434                         fcoe->fcf_count,
8435                         fcoe->event_tag);
8436
8437         if (!sli4->fip) {
8438                 return 0;
8439         }
8440
8441         event.type = fcoe->event_type;
8442         event.index = UINT32_MAX;
8443
8444         switch (fcoe->event_type) {
8445         case SLI4_FCOE_FIP_FCF_DISCOVERED:
8446                 ocs_log_debug(sli4->os, "FCF Discovered index=%d\n", fcoe->event_information);
8447                 break;
8448         case SLI4_FCOE_FIP_FCF_TABLE_FULL:
8449                 ocs_log_debug(sli4->os, "FCF Table Full\n");
8450                 mask = 0;
8451                 break;
8452         case SLI4_FCOE_FIP_FCF_DEAD:
8453                 ocs_log_debug(sli4->os, "FCF Dead/Gone index=%d\n", fcoe->event_information);
8454                 break;
8455         case SLI4_FCOE_FIP_FCF_CLEAR_VLINK:
8456                 mask = UINT16_MAX;
8457                 ocs_log_debug(sli4->os, "Clear VLINK Received VPI=%#x\n", fcoe->event_information & mask);
8458                 break;
8459         case SLI4_FCOE_FIP_FCF_MODIFIED:
8460                 ocs_log_debug(sli4->os, "FCF Modified\n");
8461                 break;
8462         default:
8463                 ocs_log_test(sli4->os, "bad FCoE type %#x", fcoe->event_type);
8464                 mask = 0;
8465         }
8466
8467         if (mask != 0) {
8468                 event.index = fcoe->event_information & mask;
8469         }
8470
8471         sli4->fip(sli4->fip_arg, &event);
8472
8473         return 0;
8474 }
8475
8476 /**
8477  * @ingroup sli_fc
8478  * @brief Allocate a receive queue.
8479  *
8480  * @par Description
8481  * Allocates DMA memory and configures the requested queue type.
8482  *
8483  * @param sli4 SLI context.
8484  * @param q Pointer to the queue object for the header.
8485  * @param n_entries Number of entries to allocate.
8486  * @param buffer_size buffer size for the queue.
8487  * @param cq Associated CQ.
8488  * @param ulp The ULP to bind
8489  * @param is_hdr Used to validate the rq_id and set the type of queue
8490  *
8491  * @return Returns 0 on success, or -1 on failure.
8492  */
8493 int32_t
8494 sli_fc_rq_alloc(sli4_t *sli4, sli4_queue_t *q,
8495                 uint32_t n_entries, uint32_t buffer_size,
8496                 sli4_queue_t *cq, uint16_t ulp, uint8_t is_hdr)
8497 {
8498         int32_t (*rq_create)(sli4_t *, void *, size_t, ocs_dma_t *, uint16_t, uint16_t, uint16_t);
8499
8500         if ((sli4 == NULL) || (q == NULL)) {
8501                 void *os = sli4 != NULL ? sli4->os : NULL;
8502
8503                 ocs_log_err(os, "bad parameter sli4=%p q=%p\n", sli4, q);
8504                 return -1;
8505         }
8506
8507         if (__sli_queue_init(sli4, q, SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE,
8508                                 n_entries, SLI_PAGE_SIZE)) {
8509                 return -1;
8510         }
8511
8512         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
8513                 rq_create = sli_cmd_fcoe_rq_create;
8514         } else {
8515                 rq_create = sli_cmd_fcoe_rq_create_v1;
8516         }
8517
8518         if (rq_create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma,
8519                       cq->id, ulp, buffer_size)) {
8520                 if (__sli_create_queue(sli4, q)) {
8521                         ocs_dma_free(sli4->os, &q->dma);
8522                         return -1;
8523                 }
8524                 if (is_hdr && q->id & 1) {
8525                         ocs_log_test(sli4->os, "bad header RQ_ID %d\n", q->id);
8526                         ocs_dma_free(sli4->os, &q->dma);
8527                         return -1;
8528                 } else if (!is_hdr  && (q->id & 1) == 0) {
8529                         ocs_log_test(sli4->os, "bad data RQ_ID %d\n", q->id);
8530                         ocs_dma_free(sli4->os, &q->dma);
8531                         return -1;
8532                 }
8533         } else {
8534                 return -1;
8535         }
8536         q->u.flag.is_hdr = is_hdr;
8537         if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
8538                 q->u.flag.rq_batch = TRUE;
8539         }
8540         return 0;
8541 }
8542
8543 /**
8544  * @ingroup sli_fc
8545  * @brief Allocate a receive queue set.
8546  *
8547  * @param sli4 SLI context.
8548  * @param num_rq_pairs to create
8549  * @param qs Pointers to the queue objects for both header and data.
8550  *      Length of this arrays should be 2 * num_rq_pairs
8551  * @param base_cq_id. Assumes base_cq_id : (base_cq_id + num_rq_pairs) cqs as allotted.
8552  * @param n_entries number of entries in each RQ queue.
8553  * @param header_buffer_size
8554  * @param payload_buffer_size
8555  * @param ulp The ULP to bind
8556  *
8557  * @return Returns 0 on success, or -1 on failure.
8558  */
8559 int32_t
8560 sli_fc_rq_set_alloc(sli4_t *sli4, uint32_t num_rq_pairs,
8561                     sli4_queue_t *qs[], uint32_t base_cq_id,
8562                     uint32_t n_entries, uint32_t header_buffer_size,
8563                     uint32_t payload_buffer_size,  uint16_t ulp)
8564 {
8565         uint32_t i, p, offset = 0;
8566         uint32_t payload_size, total_page_count = 0;
8567         uintptr_t addr;
8568         ocs_dma_t dma;
8569         sli4_res_common_create_queue_set_t *rsp = NULL;
8570         sli4_req_fcoe_rq_create_v2_t    *req = NULL;
8571
8572         ocs_memset(&dma, 0, sizeof(dma));
8573
8574         for (i = 0; i < (num_rq_pairs * 2); i++) {
8575                 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE,
8576                                         n_entries, SLI_PAGE_SIZE)) {
8577                         goto error;
8578                 }
8579         }
8580
8581         total_page_count = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE) * num_rq_pairs * 2;
8582
8583         /* Payload length must accommodate both request and response */
8584         payload_size = max((sizeof(sli4_req_fcoe_rq_create_v1_t) + (8 * total_page_count)),
8585                          sizeof(sli4_res_common_create_queue_set_t));
8586
8587         if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
8588                 ocs_log_err(sli4->os, "DMA allocation failed\n");
8589                 goto error;
8590         }
8591         ocs_memset(dma.virt, 0, payload_size);
8592
8593         if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
8594                         payload_size, &dma) == -1) {
8595                 goto error;
8596         }
8597         req = (sli4_req_fcoe_rq_create_v2_t *)((uint8_t *)dma.virt);
8598
8599         /* Fill Header fields */
8600         req->hdr.opcode    = SLI4_OPC_FCOE_RQ_CREATE;
8601         req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
8602         req->hdr.version   = 2;
8603         req->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v2_t) - sizeof(sli4_req_hdr_t)
8604                                         + (8 * total_page_count);
8605
8606         /* Fill Payload fields */
8607         req->dnb           = TRUE;
8608         req->num_pages     = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE);
8609         req->rqe_count     = qs[0]->dma.size / SLI4_FCOE_RQE_SIZE;
8610         req->rqe_size      = SLI4_FCOE_RQE_SIZE_8;
8611         req->page_size     = SLI4_FCOE_RQ_PAGE_SIZE_4096;
8612         req->rq_count      = num_rq_pairs * 2;
8613         req->base_cq_id    = base_cq_id;
8614         req->hdr_buffer_size     = header_buffer_size;
8615         req->payload_buffer_size = payload_buffer_size;
8616
8617         for (i = 0; i < (num_rq_pairs * 2); i++) {
8618                 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += SLI_PAGE_SIZE) {
8619                         req->page_physical_address[offset].low  = ocs_addr32_lo(addr);
8620                         req->page_physical_address[offset].high = ocs_addr32_hi(addr);
8621                         offset++;
8622                 }
8623         }
8624
8625         if (sli_bmbx_command(sli4)){
8626                 ocs_log_crit(sli4->os, "bootstrap mailbox write faild RQSet\n");
8627                 goto error;
8628         }
8629
8630         rsp = (void *)((uint8_t *)dma.virt);
8631         if (rsp->hdr.status) {
8632                 ocs_log_err(sli4->os, "bad create RQSet status=%#x addl=%#x\n",
8633                         rsp->hdr.status, rsp->hdr.additional_status);
8634                 goto error;
8635         } else {
8636                 for (i = 0; i < (num_rq_pairs * 2); i++) {
8637                         qs[i]->id = i + rsp->q_id;
8638                         if ((qs[i]->id & 1) == 0) {
8639                                 qs[i]->u.flag.is_hdr = TRUE;
8640                         } else {
8641                                 qs[i]->u.flag.is_hdr = FALSE;
8642                         }
8643                         qs[i]->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
8644                         qs[i]->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
8645                 }
8646         }
8647
8648         ocs_dma_free(sli4->os, &dma);
8649
8650         return 0;
8651
8652 error:
8653         for (i = 0; i < (num_rq_pairs * 2); i++) {
8654                 if (qs[i]->dma.size) {
8655                         ocs_dma_free(sli4->os, &qs[i]->dma);
8656                 }
8657         }
8658
8659         if (dma.size) {
8660                 ocs_dma_free(sli4->os, &dma);
8661         }
8662
8663         return -1;
8664 }
8665
8666 /**
8667  * @ingroup sli_fc
8668  * @brief Get the RPI resource requirements.
8669  *
8670  * @param sli4 SLI context.
8671  * @param n_rpi Number of RPIs desired.
8672  *
8673  * @return Returns the number of bytes needed. This value may be zero.
8674  */
8675 uint32_t
8676 sli_fc_get_rpi_requirements(sli4_t *sli4, uint32_t n_rpi)
8677 {
8678         uint32_t        bytes = 0;
8679
8680         /* Check if header templates needed */
8681         if (sli4->config.hdr_template_req) {
8682                 /* round up to a page */
8683                 bytes = SLI_ROUND_PAGE(n_rpi * SLI4_FCOE_HDR_TEMPLATE_SIZE);
8684         }
8685
8686         return bytes;
8687 }
8688
8689 /**
8690  * @ingroup sli_fc
8691  * @brief Return a text string corresponding to a CQE status value
8692  *
8693  * @param status Status value
8694  *
8695  * @return Returns corresponding string, otherwise "unknown"
8696  */
8697 const char *
8698 sli_fc_get_status_string(uint32_t status)
8699 {
8700         static struct {
8701                 uint32_t code;
8702                 const char *label;
8703         } lookup[] = {
8704                 {SLI4_FC_WCQE_STATUS_SUCCESS,                   "SUCCESS"},
8705                 {SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE,           "FCP_RSP_FAILURE"},
8706                 {SLI4_FC_WCQE_STATUS_REMOTE_STOP,               "REMOTE_STOP"},
8707                 {SLI4_FC_WCQE_STATUS_LOCAL_REJECT,              "LOCAL_REJECT"},
8708                 {SLI4_FC_WCQE_STATUS_NPORT_RJT,                 "NPORT_RJT"},
8709                 {SLI4_FC_WCQE_STATUS_FABRIC_RJT,                "FABRIC_RJT"},
8710                 {SLI4_FC_WCQE_STATUS_NPORT_BSY,                 "NPORT_BSY"},
8711                 {SLI4_FC_WCQE_STATUS_FABRIC_BSY,                "FABRIC_BSY"},
8712                 {SLI4_FC_WCQE_STATUS_LS_RJT,                    "LS_RJT"},
8713                 {SLI4_FC_WCQE_STATUS_CMD_REJECT,                "CMD_REJECT"},
8714                 {SLI4_FC_WCQE_STATUS_FCP_TGT_LENCHECK,          "FCP_TGT_LENCHECK"},
8715                 {SLI4_FC_WCQE_STATUS_RQ_BUF_LEN_EXCEEDED,       "BUF_LEN_EXCEEDED"},
8716                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_BUF_NEEDED,      "RQ_INSUFF_BUF_NEEDED"},
8717                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_FRM_DISC,        "RQ_INSUFF_FRM_DESC"},
8718                 {SLI4_FC_WCQE_STATUS_RQ_DMA_FAILURE,            "RQ_DMA_FAILURE"},
8719                 {SLI4_FC_WCQE_STATUS_FCP_RSP_TRUNCATE,          "FCP_RSP_TRUNCATE"},
8720                 {SLI4_FC_WCQE_STATUS_DI_ERROR,                  "DI_ERROR"},
8721                 {SLI4_FC_WCQE_STATUS_BA_RJT,                    "BA_RJT"},
8722                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_NEEDED,      "RQ_INSUFF_XRI_NEEDED"},
8723                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_DISC,        "INSUFF_XRI_DISC"},
8724                 {SLI4_FC_WCQE_STATUS_RX_ERROR_DETECT,           "RX_ERROR_DETECT"},
8725                 {SLI4_FC_WCQE_STATUS_RX_ABORT_REQUEST,          "RX_ABORT_REQUEST"},
8726                 };
8727         uint32_t i;
8728
8729         for (i = 0; i < ARRAY_SIZE(lookup); i++) {
8730                 if (status == lookup[i].code) {
8731                         return lookup[i].label;
8732                 }
8733         }
8734         return "unknown";
8735 }