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