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