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