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