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