1331766Sken/*-
2331766Sken * Copyright (c) 2017 Broadcom. All rights reserved.
3331766Sken * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4331766Sken *
5331766Sken * Redistribution and use in source and binary forms, with or without
6331766Sken * modification, are permitted provided that the following conditions are met:
7331766Sken *
8331766Sken * 1. Redistributions of source code must retain the above copyright notice,
9331766Sken *    this list of conditions and the following disclaimer.
10331766Sken *
11331766Sken * 2. Redistributions in binary form must reproduce the above copyright notice,
12331766Sken *    this list of conditions and the following disclaimer in the documentation
13331766Sken *    and/or other materials provided with the distribution.
14331766Sken *
15331766Sken * 3. Neither the name of the copyright holder nor the names of its contributors
16331766Sken *    may be used to endorse or promote products derived from this software
17331766Sken *    without specific prior written permission.
18331766Sken *
19331766Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20331766Sken * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21331766Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22331766Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23331766Sken * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24331766Sken * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25331766Sken * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26331766Sken * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27331766Sken * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28331766Sken * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29331766Sken * POSSIBILITY OF SUCH DAMAGE.
30331766Sken *
31331766Sken * $FreeBSD: stable/11/sys/dev/ocs_fc/sli4.c 332040 2018-04-04 18:06:52Z ken $
32331766Sken */
33331766Sken
34331766Sken/**
35331766Sken * @defgroup sli SLI-4 Base APIs
36331766Sken */
37331766Sken
38331766Sken/**
39331766Sken * @file
40331766Sken * All common (i.e. transport-independent) SLI-4 functions are implemented
41331766Sken * in this file.
42331766Sken */
43331766Sken
44331766Sken#include "sli4.h"
45331766Sken
46331766Sken#if defined(OCS_INCLUDE_DEBUG)
47331766Sken#include "ocs_utils.h"
48331766Sken#endif
49331766Sken
50331766Sken#define SLI4_BMBX_DELAY_US 1000 /* 1 ms */
51331766Sken#define SLI4_INIT_PORT_DELAY_US 10000 /* 10 ms */
52331766Sken
53331766Skenstatic int32_t sli_fw_init(sli4_t *);
54331766Skenstatic int32_t sli_fw_term(sli4_t *);
55331766Skenstatic int32_t sli_sliport_control(sli4_t *sli4, uint32_t endian);
56331766Skenstatic int32_t sli_cmd_fw_deinitialize(sli4_t *, void *, size_t);
57331766Skenstatic int32_t sli_cmd_fw_initialize(sli4_t *, void *, size_t);
58331766Skenstatic int32_t sli_queue_doorbell(sli4_t *, sli4_queue_t *);
59331766Skenstatic uint8_t sli_queue_entry_is_valid(sli4_queue_t *, uint8_t *, uint8_t);
60331766Sken
61331766Skenconst uint8_t sli4_fw_initialize[] = {
62331766Sken	0xff, 0x12, 0x34, 0xff,
63331766Sken	0xff, 0x56, 0x78, 0xff,
64331766Sken};
65331766Sken
66331766Skenconst uint8_t sli4_fw_deinitialize[] = {
67331766Sken	0xff, 0xaa, 0xbb, 0xff,
68331766Sken	0xff, 0xcc, 0xdd, 0xff,
69331766Sken};
70331766Sken
71331766Skentypedef struct {
72331766Sken	uint32_t rev_id;
73331766Sken	uint32_t family;	/* generation */
74331766Sken	sli4_asic_type_e type;
75331766Sken	sli4_asic_rev_e rev;
76331766Sken} sli4_asic_entry_t;
77331766Sken
78331766Skensli4_asic_entry_t sli4_asic_table[] = {
79331766Sken	{	0x00,	1,	SLI4_ASIC_TYPE_BE3,	SLI4_ASIC_REV_A0},
80331766Sken	{	0x01,	1,	SLI4_ASIC_TYPE_BE3,	SLI4_ASIC_REV_A1},
81331766Sken	{	0x02,	1,	SLI4_ASIC_TYPE_BE3,	SLI4_ASIC_REV_A2},
82331766Sken	{	0x00,	4,	SLI4_ASIC_TYPE_SKYHAWK,	SLI4_ASIC_REV_A0},
83331766Sken	{	0x00,	2,	SLI4_ASIC_TYPE_SKYHAWK,	SLI4_ASIC_REV_A0},
84331766Sken	{	0x10,	1,	SLI4_ASIC_TYPE_BE3,	SLI4_ASIC_REV_B0},
85331766Sken	{	0x10,	0x04,	SLI4_ASIC_TYPE_SKYHAWK,	SLI4_ASIC_REV_B0},
86331766Sken	{	0x11,	0x04,	SLI4_ASIC_TYPE_SKYHAWK,	SLI4_ASIC_REV_B1},
87331766Sken	{	0x0,	0x0a,	SLI4_ASIC_TYPE_LANCER,	SLI4_ASIC_REV_A0},
88331766Sken	{	0x10,	0x0b,	SLI4_ASIC_TYPE_LANCER,	SLI4_ASIC_REV_B0},
89331766Sken	{	0x30,	0x0b,	SLI4_ASIC_TYPE_LANCER,	SLI4_ASIC_REV_D0},
90331766Sken	{	0x3,	0x0b,	SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3},
91331766Sken	{	0x0,	0x0c,	SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A0},
92331766Sken	{	0x1,	0x0c,	SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A1},
93331766Sken	{	0x3,	0x0c,	SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3},
94331766Sken
95331766Sken	{	0x00,	0x05,	SLI4_ASIC_TYPE_CORSAIR,	SLI4_ASIC_REV_A0},
96331766Sken};
97331766Sken
98331766Sken/*
99331766Sken * @brief Convert queue type enum (SLI_QTYPE_*) into a string.
100331766Sken */
101331766Skenconst char *SLI_QNAME[] = {
102331766Sken	"Event Queue",
103331766Sken	"Completion Queue",
104331766Sken	"Mailbox Queue",
105331766Sken	"Work Queue",
106331766Sken	"Receive Queue",
107331766Sken	"Undefined"
108331766Sken};
109331766Sken
110331766Sken/**
111331766Sken * @brief Define the mapping of registers to their BAR and offset.
112331766Sken *
113331766Sken * @par Description
114331766Sken * Although SLI-4 specification defines a common set of registers, their locations
115331766Sken * (both BAR and offset) depend on the interface type. This array maps a register
116331766Sken * enum to an array of BAR/offset pairs indexed by the interface type. For
117331766Sken * example, to access the bootstrap mailbox register on an interface type 0
118331766Sken * device, code can refer to the offset using regmap[SLI4_REG_BMBX][0].offset.
119331766Sken *
120331766Sken * @b Note: A value of UINT32_MAX for either the register set (rset) or offset (off)
121331766Sken * indicates an invalid mapping.
122331766Sken */
123331766Skenconst sli4_reg_t regmap[SLI4_REG_MAX][SLI4_MAX_IF_TYPES] = {
124331766Sken	/* SLI4_REG_BMBX */
125331766Sken	{
126331766Sken		{ 2, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG },
127331766Sken	},
128331766Sken	/* SLI4_REG_EQCQ_DOORBELL */
129331766Sken	{
130331766Sken		{ 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
131331766Sken		{ 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
132331766Sken	},
133331766Sken	/* SLI4_REG_FCOE_RQ_DOORBELL */
134331766Sken	{
135331766Sken		{ 2, SLI4_RQ_DOORBELL_REG }, { 0, SLI4_RQ_DOORBELL_REG },
136331766Sken		{ 0, SLI4_RQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
137331766Sken	},
138331766Sken	/* SLI4_REG_IO_WQ_DOORBELL */
139331766Sken	{
140331766Sken		{ 2, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
141331766Sken	},
142331766Sken	/* SLI4_REG_MQ_DOORBELL */
143331766Sken	{
144331766Sken		{ 2, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
145331766Sken		{ 0, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
146331766Sken	},
147331766Sken	/* SLI4_REG_PHYSDEV_CONTROL */
148331766Sken	{
149331766Sken		{ UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_PHSDEV_CONTROL_REG_23 }, { 0, SLI4_PHSDEV_CONTROL_REG_23 },
150331766Sken	},
151331766Sken	/* SLI4_REG_SLIPORT_CONTROL */
152331766Sken	{
153331766Sken		{ UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_SLIPORT_CONTROL_REG }, { UINT32_MAX, UINT32_MAX },
154331766Sken	},
155331766Sken	/* SLI4_REG_SLIPORT_ERROR1 */
156331766Sken	{
157331766Sken		{ UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_SLIPORT_ERROR1 }, { UINT32_MAX, UINT32_MAX },
158331766Sken	},
159331766Sken	/* SLI4_REG_SLIPORT_ERROR2 */
160331766Sken	{
161331766Sken		{ UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_SLIPORT_ERROR2 }, { UINT32_MAX, UINT32_MAX },
162331766Sken	},
163331766Sken	/* SLI4_REG_SLIPORT_SEMAPHORE */
164331766Sken	{
165331766Sken		{ 1, SLI4_PORT_SEMAPHORE_REG_0 },  { 0, SLI4_PORT_SEMAPHORE_REG_1 },
166331766Sken		{ 0, SLI4_PORT_SEMAPHORE_REG_23 }, { 0, SLI4_PORT_SEMAPHORE_REG_23 },
167331766Sken	},
168331766Sken	/* SLI4_REG_SLIPORT_STATUS */
169331766Sken	{
170331766Sken		{ UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_PORT_STATUS_REG_23 }, { 0, SLI4_PORT_STATUS_REG_23 },
171331766Sken	},
172331766Sken	/* SLI4_REG_UERR_MASK_HI */
173331766Sken	{
174331766Sken		{ 0, SLI4_UERR_MASK_HIGH_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
175331766Sken	},
176331766Sken	/* SLI4_REG_UERR_MASK_LO */
177331766Sken	{
178331766Sken		{ 0, SLI4_UERR_MASK_LOW_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
179331766Sken	},
180331766Sken	/* SLI4_REG_UERR_STATUS_HI */
181331766Sken	{
182331766Sken		{ 0, SLI4_UERR_STATUS_HIGH_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
183331766Sken	},
184331766Sken	/* SLI4_REG_UERR_STATUS_LO */
185331766Sken	{
186331766Sken		{ 0, SLI4_UERR_STATUS_LOW_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
187331766Sken	},
188331766Sken	/* SLI4_REG_SW_UE_CSR1 */
189331766Sken	{
190331766Sken		{ 1, SLI4_SW_UE_CSR1}, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
191331766Sken	},
192331766Sken	/* SLI4_REG_SW_UE_CSR2 */
193331766Sken	{
194331766Sken		{ 1, SLI4_SW_UE_CSR2}, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
195331766Sken	},
196331766Sken};
197331766Sken
198331766Sken/**
199331766Sken * @brief Read the given SLI register.
200331766Sken *
201331766Sken * @param sli Pointer to the SLI context.
202331766Sken * @param reg Register name enum.
203331766Sken *
204331766Sken * @return Returns the register value.
205331766Sken */
206331766Skenuint32_t
207331766Skensli_reg_read(sli4_t *sli, sli4_regname_e reg)
208331766Sken{
209331766Sken	const sli4_reg_t	*r = &(regmap[reg][sli->if_type]);
210331766Sken
211331766Sken	if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
212331766Sken		ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
213331766Sken		return UINT32_MAX;
214331766Sken	}
215331766Sken
216331766Sken	return ocs_reg_read32(sli->os, r->rset, r->off);
217331766Sken}
218331766Sken
219331766Sken/**
220331766Sken * @brief Write the value to the given SLI register.
221331766Sken *
222331766Sken * @param sli Pointer to the SLI context.
223331766Sken * @param reg Register name enum.
224331766Sken * @param val Value to write.
225331766Sken *
226331766Sken * @return None.
227331766Sken */
228331766Skenvoid
229331766Skensli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
230331766Sken{
231331766Sken	const sli4_reg_t	*r = &(regmap[reg][sli->if_type]);
232331766Sken
233331766Sken	if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
234331766Sken		ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
235331766Sken		return;
236331766Sken	}
237331766Sken
238331766Sken	ocs_reg_write32(sli->os, r->rset, r->off, val);
239331766Sken}
240331766Sken
241331766Sken/**
242331766Sken * @brief Check if the SLI_INTF register is valid.
243331766Sken *
244331766Sken * @param val 32-bit SLI_INTF register value.
245331766Sken *
246331766Sken * @return Returns 0 on success, or a non-zero value on failure.
247331766Sken */
248331766Skenstatic uint8_t
249331766Skensli_intf_valid_check(uint32_t val)
250331766Sken{
251331766Sken	return ((val >> SLI4_INTF_VALID_SHIFT) & SLI4_INTF_VALID_MASK) != SLI4_INTF_VALID;
252331766Sken}
253331766Sken
254331766Sken/**
255331766Sken * @brief Retrieve the SLI revision level.
256331766Sken *
257331766Sken * @param val 32-bit SLI_INTF register value.
258331766Sken *
259331766Sken * @return Returns the SLI revision level.
260331766Sken */
261331766Skenstatic uint8_t
262331766Skensli_intf_sli_revision(uint32_t val)
263331766Sken{
264331766Sken	return ((val >> SLI4_INTF_SLI_REVISION_SHIFT) & SLI4_INTF_SLI_REVISION_MASK);
265331766Sken}
266331766Sken
267331766Skenstatic uint8_t
268331766Skensli_intf_sli_family(uint32_t val)
269331766Sken{
270331766Sken	return ((val >> SLI4_INTF_SLI_FAMILY_SHIFT) & SLI4_INTF_SLI_FAMILY_MASK);
271331766Sken}
272331766Sken
273331766Sken/**
274331766Sken * @brief Retrieve the SLI interface type.
275331766Sken *
276331766Sken * @param val 32-bit SLI_INTF register value.
277331766Sken *
278331766Sken * @return Returns the SLI interface type.
279331766Sken */
280331766Skenstatic uint8_t
281331766Skensli_intf_if_type(uint32_t val)
282331766Sken{
283331766Sken	return ((val >> SLI4_INTF_IF_TYPE_SHIFT) & SLI4_INTF_IF_TYPE_MASK);
284331766Sken}
285331766Sken
286331766Sken/**
287331766Sken * @brief Retrieve PCI revision ID.
288331766Sken *
289331766Sken * @param val 32-bit PCI CLASS_REVISION register value.
290331766Sken *
291331766Sken * @return Returns the PCI revision ID.
292331766Sken */
293331766Skenstatic uint8_t
294331766Skensli_pci_rev_id(uint32_t val)
295331766Sken{
296331766Sken	return ((val >> SLI4_PCI_REV_ID_SHIFT) & SLI4_PCI_REV_ID_MASK);
297331766Sken}
298331766Sken
299331766Sken/**
300331766Sken * @brief retrieve SLI ASIC generation
301331766Sken *
302331766Sken * @param val 32-bit SLI_ASIC_ID register value
303331766Sken *
304331766Sken * @return SLI ASIC generation
305331766Sken */
306331766Skenstatic uint8_t
307331766Skensli_asic_gen(uint32_t val)
308331766Sken{
309331766Sken	return ((val >> SLI4_ASIC_GEN_SHIFT) & SLI4_ASIC_GEN_MASK);
310331766Sken}
311331766Sken
312331766Sken/**
313331766Sken * @brief Wait for the bootstrap mailbox to report "ready".
314331766Sken *
315331766Sken * @param sli4 SLI context pointer.
316331766Sken * @param msec Number of milliseconds to wait.
317331766Sken *
318331766Sken * @return Returns 0 if BMBX is ready, or non-zero otherwise (i.e. time out occurred).
319331766Sken */
320331766Skenstatic int32_t
321331766Skensli_bmbx_wait(sli4_t *sli4, uint32_t msec)
322331766Sken{
323331766Sken	uint32_t	val = 0;
324331766Sken
325331766Sken	do {
326331766Sken		ocs_udelay(SLI4_BMBX_DELAY_US);
327331766Sken		val = sli_reg_read(sli4, SLI4_REG_BMBX);
328331766Sken		msec--;
329331766Sken	} while(msec && !(val & SLI4_BMBX_RDY));
330331766Sken
331331766Sken	return(!(val & SLI4_BMBX_RDY));
332331766Sken}
333331766Sken
334331766Sken/**
335331766Sken * @brief Write bootstrap mailbox.
336331766Sken *
337331766Sken * @param sli4 SLI context pointer.
338331766Sken *
339331766Sken * @return Returns 0 if command succeeded, or non-zero otherwise.
340331766Sken */
341331766Skenstatic int32_t
342331766Skensli_bmbx_write(sli4_t *sli4)
343331766Sken{
344331766Sken	uint32_t	val = 0;
345331766Sken
346331766Sken	/* write buffer location to bootstrap mailbox register */
347331766Sken	ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_PREWRITE);
348331766Sken	val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys);
349331766Sken	sli_reg_write(sli4, SLI4_REG_BMBX, val);
350331766Sken
351331766Sken	if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
352331766Sken		ocs_log_crit(sli4->os, "BMBX WRITE_HI failed\n");
353331766Sken		return -1;
354331766Sken	}
355331766Sken	val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys);
356331766Sken	sli_reg_write(sli4, SLI4_REG_BMBX, val);
357331766Sken
358331766Sken	/* wait for SLI Port to set ready bit */
359331766Sken	return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC/*XXX*/);
360331766Sken}
361331766Sken
362331766Sken#if defined(OCS_INCLUDE_DEBUG)
363331766Sken/**
364331766Sken * @ingroup sli
365331766Sken * @brief Dump BMBX mailbox command.
366331766Sken *
367331766Sken * @par Description
368331766Sken * Convenience function for dumping BMBX mailbox commands. Takes
369331766Sken * into account which mailbox command is given since SLI_CONFIG
370331766Sken * commands are special.
371331766Sken *
372331766Sken * @b Note: This function takes advantage of
373331766Sken * the one-command-at-a-time nature of the BMBX to be able to
374331766Sken * display non-embedded SLI_CONFIG commands. This will not work
375331766Sken * for mailbox commands on the MQ. Luckily, all current non-emb
376331766Sken * mailbox commands go through the BMBX.
377331766Sken *
378331766Sken * @param sli4 SLI context pointer.
379331766Sken * @param mbx Pointer to mailbox command to dump.
380331766Sken * @param prefix Prefix for dump label.
381331766Sken *
382331766Sken * @return None.
383331766Sken */
384331766Skenstatic void
385331766Skensli_dump_bmbx_command(sli4_t *sli4, void *mbx, const char *prefix)
386331766Sken{
387331766Sken	uint32_t size = 0;
388331766Sken	char label[64];
389331766Sken	uint32_t i;
390331766Sken	/* Mailbox diagnostic logging */
391331766Sken	sli4_mbox_command_header_t *hdr = (sli4_mbox_command_header_t *)mbx;
392331766Sken
393331766Sken	if (!ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP)) {
394331766Sken		return;
395331766Sken	}
396331766Sken
397331766Sken	if (hdr->command == SLI4_MBOX_COMMAND_SLI_CONFIG) {
398331766Sken		sli4_cmd_sli_config_t *sli_config = (sli4_cmd_sli_config_t *)hdr;
399331766Sken		sli4_req_hdr_t	*sli_config_hdr;
400331766Sken		if (sli_config->emb) {
401331766Sken			ocs_snprintf(label, sizeof(label), "%s (emb)", prefix);
402331766Sken
403331766Sken			/*  if embedded, dump entire command */
404331766Sken			sli_config_hdr = (sli4_req_hdr_t *)sli_config->payload.embed;
405331766Sken			size = sizeof(*sli_config) - sizeof(sli_config->payload) +
406331766Sken				sli_config_hdr->request_length + (4*sizeof(uint32_t));
407331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
408331766Sken				   (uint8_t *)sli4->bmbx.virt, size);
409331766Sken		} else {
410331766Sken			sli4_sli_config_pmd_t *pmd;
411331766Sken			ocs_snprintf(label, sizeof(label), "%s (non-emb hdr)", prefix);
412331766Sken
413331766Sken			/* if non-embedded, break up into two parts: SLI_CONFIG hdr
414331766Sken			   and the payload(s) */
415331766Sken			size = sizeof(*sli_config) - sizeof(sli_config->payload) + (12 * sli_config->pmd_count);
416331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
417331766Sken				   (uint8_t *)sli4->bmbx.virt, size);
418331766Sken
419331766Sken			/* as sanity check, make sure first PMD matches what was saved */
420331766Sken			pmd = &sli_config->payload.mem;
421331766Sken			if ((pmd->address_high == ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys)) &&
422331766Sken			    (pmd->address_low == ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys))) {
423331766Sken				for (i = 0; i < sli_config->pmd_count; i++, pmd++) {
424331766Sken					sli_config_hdr = sli4->bmbx_non_emb_pmd->virt;
425331766Sken					ocs_snprintf(label, sizeof(label), "%s (non-emb pay[%d])",
426331766Sken						     prefix, i);
427331766Sken					ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
428331766Sken						   (uint8_t *)sli4->bmbx_non_emb_pmd->virt,
429331766Sken						   sli_config_hdr->request_length + (4*sizeof(uint32_t)));
430331766Sken				}
431331766Sken			} else {
432331766Sken				ocs_log_debug(sli4->os, "pmd addr does not match pmd:%x %x (%x %x)\n",
433331766Sken					pmd->address_high, pmd->address_low,
434331766Sken					ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys),
435331766Sken					ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys));
436331766Sken			}
437331766Sken
438331766Sken		}
439331766Sken	} else {
440331766Sken		/* not an SLI_CONFIG command, just display first 64 bytes, like we do
441331766Sken		   for MQEs */
442331766Sken		size = 64;
443331766Sken		ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, prefix,
444331766Sken			   (uint8_t *)mbx, size);
445331766Sken	}
446331766Sken}
447331766Sken#endif
448331766Sken
449331766Sken/**
450331766Sken * @ingroup sli
451331766Sken * @brief Submit a command to the bootstrap mailbox and check the status.
452331766Sken *
453331766Sken * @param sli4 SLI context pointer.
454331766Sken *
455331766Sken * @return Returns 0 on success, or a non-zero value on failure.
456331766Sken */
457331766Skenint32_t
458331766Skensli_bmbx_command(sli4_t *sli4)
459331766Sken{
460331766Sken	void *cqe = (uint8_t *)sli4->bmbx.virt + SLI4_BMBX_SIZE;
461331766Sken
462331766Sken#if defined(OCS_INCLUDE_DEBUG)
463331766Sken	sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmd");
464331766Sken#endif
465331766Sken
466331766Sken	if (sli_fw_error_status(sli4) > 0) {
467331766Sken		ocs_log_crit(sli4->os, "Chip is in an error state - Mailbox "
468331766Sken			"command rejected status=%#x error1=%#x error2=%#x\n",
469331766Sken			sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
470331766Sken			sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
471331766Sken			sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
472331766Sken		return -1;
473331766Sken	}
474331766Sken
475331766Sken	if (sli_bmbx_write(sli4)) {
476331766Sken		ocs_log_crit(sli4->os, "bootstrap mailbox write fail phys=%p reg=%#x\n",
477331766Sken			(void*)sli4->bmbx.phys,
478331766Sken			sli_reg_read(sli4, SLI4_REG_BMBX));
479331766Sken		return -1;
480331766Sken	}
481331766Sken
482331766Sken	/* check completion queue entry status */
483331766Sken	ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_POSTREAD);
484331766Sken	if (((sli4_mcqe_t *)cqe)->val) {
485331766Sken#if defined(OCS_INCLUDE_DEBUG)
486331766Sken		sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmpl");
487331766Sken        ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "bmbx cqe", cqe, sizeof(sli4_mcqe_t));
488331766Sken#endif
489331766Sken		return sli_cqe_mq(cqe);
490331766Sken	} else {
491331766Sken		ocs_log_err(sli4->os, "invalid or wrong type\n");
492331766Sken		return -1;
493331766Sken	}
494331766Sken}
495331766Sken
496331766Sken/****************************************************************************
497331766Sken * Messages
498331766Sken */
499331766Sken
500331766Sken/**
501331766Sken * @ingroup sli
502331766Sken * @brief Write a CONFIG_LINK command to the provided buffer.
503331766Sken *
504331766Sken * @param sli4 SLI context pointer.
505331766Sken * @param buf Virtual pointer to the destination buffer.
506331766Sken * @param size Buffer size, in bytes.
507331766Sken *
508331766Sken * @return Returns the number of bytes written.
509331766Sken */
510331766Skenint32_t
511331766Skensli_cmd_config_link(sli4_t *sli4, void *buf, size_t size)
512331766Sken{
513331766Sken	sli4_cmd_config_link_t	*config_link = buf;
514331766Sken
515331766Sken	ocs_memset(buf, 0, size);
516331766Sken
517331766Sken	config_link->hdr.command = SLI4_MBOX_COMMAND_CONFIG_LINK;
518331766Sken
519331766Sken	/* Port interprets zero in a field as "use default value" */
520331766Sken
521331766Sken	return sizeof(sli4_cmd_config_link_t);
522331766Sken}
523331766Sken
524331766Sken/**
525331766Sken * @ingroup sli
526331766Sken * @brief Write a DOWN_LINK command to the provided buffer.
527331766Sken *
528331766Sken * @param sli4 SLI context pointer.
529331766Sken * @param buf Virtual pointer to the destination buffer.
530331766Sken * @param size Buffer size, in bytes.
531331766Sken *
532331766Sken * @return Returns the number of bytes written.
533331766Sken */
534331766Skenint32_t
535331766Skensli_cmd_down_link(sli4_t *sli4, void *buf, size_t size)
536331766Sken{
537331766Sken	sli4_mbox_command_header_t	*hdr = buf;
538331766Sken
539331766Sken	ocs_memset(buf, 0, size);
540331766Sken
541331766Sken	hdr->command = SLI4_MBOX_COMMAND_DOWN_LINK;
542331766Sken
543331766Sken	/* Port interprets zero in a field as "use default value" */
544331766Sken
545331766Sken	return sizeof(sli4_mbox_command_header_t);
546331766Sken}
547331766Sken
548331766Sken/**
549331766Sken * @ingroup sli
550331766Sken * @brief Write a DUMP Type 4 command to the provided buffer.
551331766Sken *
552331766Sken * @param sli4 SLI context pointer.
553331766Sken * @param buf Virtual pointer to the destination buffer.
554331766Sken * @param size Buffer size, in bytes.
555331766Sken * @param wki The well known item ID.
556331766Sken *
557331766Sken * @return Returns the number of bytes written.
558331766Sken */
559331766Skenint32_t
560331766Skensli_cmd_dump_type4(sli4_t *sli4, void *buf, size_t size, uint16_t wki)
561331766Sken{
562331766Sken	sli4_cmd_dump4_t	*cmd = buf;
563331766Sken
564331766Sken	ocs_memset(buf, 0, size);
565331766Sken
566331766Sken	cmd->hdr.command = SLI4_MBOX_COMMAND_DUMP;
567331766Sken	cmd->type = 4;
568331766Sken	cmd->wki_selection = wki;
569331766Sken	return sizeof(sli4_cmd_dump4_t);
570331766Sken}
571331766Sken
572331766Sken/**
573331766Sken * @ingroup sli
574331766Sken * @brief Write a COMMON_READ_TRANSCEIVER_DATA command.
575331766Sken *
576331766Sken * @param sli4 SLI context.
577331766Sken * @param buf Destination buffer for the command.
578331766Sken * @param size Buffer size, in bytes.
579331766Sken * @param page_num The page of SFP data to retrieve (0xa0 or 0xa2).
580331766Sken * @param dma DMA structure from which the data will be copied.
581331766Sken *
582331766Sken * @note This creates a Version 0 message.
583331766Sken *
584331766Sken * @return Returns the number of bytes written.
585331766Sken */
586331766Skenint32_t
587331766Skensli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size, uint32_t page_num,
588331766Sken				     ocs_dma_t *dma)
589331766Sken{
590331766Sken	sli4_req_common_read_transceiver_data_t *req = NULL;
591331766Sken	uint32_t	sli_config_off = 0;
592331766Sken	uint32_t	payload_size;
593331766Sken
594331766Sken	if (dma == NULL) {
595331766Sken		/* Payload length must accommodate both request and response */
596331766Sken		payload_size = max(sizeof(sli4_req_common_read_transceiver_data_t),
597331766Sken				   sizeof(sli4_res_common_read_transceiver_data_t));
598331766Sken	} else {
599331766Sken		payload_size = dma->size;
600331766Sken	}
601331766Sken
602331766Sken	if (sli4->port_type == SLI4_PORT_TYPE_FC) {
603331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, dma);
604331766Sken	}
605331766Sken
606331766Sken	if (dma == NULL) {
607331766Sken		req = (sli4_req_common_read_transceiver_data_t *)((uint8_t *)buf + sli_config_off);
608331766Sken	} else {
609331766Sken		req = (sli4_req_common_read_transceiver_data_t *)dma->virt;
610331766Sken		ocs_memset(req, 0, dma->size);
611331766Sken	}
612331766Sken
613331766Sken	req->hdr.opcode = SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA;
614331766Sken	req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
615331766Sken	req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
616331766Sken
617331766Sken	req->page_number = page_num;
618331766Sken	req->port = sli4->physical_port;
619331766Sken
620331766Sken	return(sli_config_off + sizeof(sli4_req_common_read_transceiver_data_t));
621331766Sken}
622331766Sken
623331766Sken/**
624331766Sken * @ingroup sli
625331766Sken * @brief Write a READ_LINK_STAT command to the provided buffer.
626331766Sken *
627331766Sken * @param sli4 SLI context pointer.
628331766Sken * @param buf Virtual pointer to the destination buffer.
629331766Sken * @param size Buffer size, in bytes.
630331766Sken * @param req_ext_counters If TRUE, then the extended counters will be requested.
631331766Sken * @param clear_overflow_flags If TRUE, then overflow flags will be cleared.
632331766Sken * @param clear_all_counters If TRUE, the counters will be cleared.
633331766Sken *
634331766Sken * @return Returns the number of bytes written.
635331766Sken */
636331766Skenint32_t
637331766Skensli_cmd_read_link_stats(sli4_t *sli4, void *buf, size_t size,
638331766Sken			uint8_t req_ext_counters,
639331766Sken			uint8_t clear_overflow_flags,
640331766Sken			uint8_t clear_all_counters)
641331766Sken{
642331766Sken	sli4_cmd_read_link_stats_t	*cmd = buf;
643331766Sken
644331766Sken	ocs_memset(buf, 0, size);
645331766Sken
646331766Sken	cmd->hdr.command = SLI4_MBOX_COMMAND_READ_LNK_STAT;
647331766Sken	cmd->rec = req_ext_counters;
648331766Sken	cmd->clrc = clear_all_counters;
649331766Sken	cmd->clof = clear_overflow_flags;
650331766Sken	return sizeof(sli4_cmd_read_link_stats_t);
651331766Sken}
652331766Sken
653331766Sken/**
654331766Sken * @ingroup sli
655331766Sken * @brief Write a READ_STATUS command to the provided buffer.
656331766Sken *
657331766Sken * @param sli4 SLI context pointer.
658331766Sken * @param buf Virtual pointer to the destination buffer.
659331766Sken * @param size Buffer size, in bytes.
660331766Sken * @param clear_counters If TRUE, the counters will be cleared.
661331766Sken *
662331766Sken * @return Returns the number of bytes written.
663331766Sken */
664331766Skenint32_t
665331766Skensli_cmd_read_status(sli4_t *sli4, void *buf, size_t size,
666331766Sken			uint8_t clear_counters)
667331766Sken{
668331766Sken	sli4_cmd_read_status_t	*cmd = buf;
669331766Sken
670331766Sken	ocs_memset(buf, 0, size);
671331766Sken
672331766Sken	cmd->hdr.command = SLI4_MBOX_COMMAND_READ_STATUS;
673331766Sken	cmd->cc = clear_counters;
674331766Sken	return sizeof(sli4_cmd_read_status_t);
675331766Sken}
676331766Sken
677331766Sken/**
678331766Sken * @brief Write a FW_DEINITIALIZE command to the provided buffer.
679331766Sken *
680331766Sken * @param sli4 SLI context pointer.
681331766Sken * @param buf Virtual pointer to the destination buffer.
682331766Sken * @param size Buffer size, in bytes.
683331766Sken *
684331766Sken * @return Returns the number of bytes written.
685331766Sken */
686331766Skenstatic int32_t
687331766Skensli_cmd_fw_deinitialize(sli4_t *sli4, void *buf, size_t size)
688331766Sken{
689331766Sken
690331766Sken	ocs_memset(buf, 0, size);
691331766Sken	ocs_memcpy(buf, sli4_fw_deinitialize, sizeof(sli4_fw_deinitialize));
692331766Sken
693331766Sken	return sizeof(sli4_fw_deinitialize);
694331766Sken}
695331766Sken
696331766Sken/**
697331766Sken * @brief Write a FW_INITIALIZE command to the provided buffer.
698331766Sken *
699331766Sken * @param sli4 SLI context pointer.
700331766Sken * @param buf Virtual pointer to the destination buffer.
701331766Sken * @param size Buffer size, in bytes.
702331766Sken *
703331766Sken * @return Returns the number of bytes written.
704331766Sken */
705331766Skenstatic int32_t
706331766Skensli_cmd_fw_initialize(sli4_t *sli4, void *buf, size_t size)
707331766Sken{
708331766Sken
709331766Sken	ocs_memset(buf, 0, size);
710331766Sken	ocs_memcpy(buf, sli4_fw_initialize, sizeof(sli4_fw_initialize));
711331766Sken
712331766Sken	return sizeof(sli4_fw_initialize);
713331766Sken}
714331766Sken
715331766Sken/**
716331766Sken * @ingroup sli
717331766Sken * @brief Write an INIT_LINK command to the provided buffer.
718331766Sken *
719331766Sken * @param sli4 SLI context pointer.
720331766Sken * @param buf Virtual pointer to the destination buffer.
721331766Sken * @param size Buffer size, in bytes.
722331766Sken * @param speed Link speed.
723331766Sken * @param reset_alpa For native FC, this is the selective reset AL_PA
724331766Sken *
725331766Sken * @return Returns the number of bytes written.
726331766Sken */
727331766Skenint32_t
728331766Skensli_cmd_init_link(sli4_t *sli4, void *buf, size_t size, uint32_t speed, uint8_t reset_alpa)
729331766Sken{
730331766Sken	sli4_cmd_init_link_t	*init_link = buf;
731331766Sken
732331766Sken	ocs_memset(buf, 0, size);
733331766Sken
734331766Sken	init_link->hdr.command = SLI4_MBOX_COMMAND_INIT_LINK;
735331766Sken
736331766Sken	/* Most fields only have meaning for FC links */
737331766Sken	if (sli4->config.topology != SLI4_READ_CFG_TOPO_FCOE) {
738331766Sken		init_link->selective_reset_al_pa = reset_alpa;
739331766Sken		init_link->link_flags.loopback = FALSE;
740331766Sken
741331766Sken		init_link->link_speed_selection_code = speed;
742331766Sken		switch (speed) {
743331766Sken		case FC_LINK_SPEED_1G:
744331766Sken		case FC_LINK_SPEED_2G:
745331766Sken		case FC_LINK_SPEED_4G:
746331766Sken		case FC_LINK_SPEED_8G:
747331766Sken		case FC_LINK_SPEED_16G:
748331766Sken		case FC_LINK_SPEED_32G:
749331766Sken			init_link->link_flags.fixed_speed = TRUE;
750331766Sken			break;
751331766Sken		case FC_LINK_SPEED_10G:
752331766Sken			ocs_log_test(sli4->os, "unsupported FC speed %d\n", speed);
753331766Sken			return 0;
754331766Sken		}
755331766Sken
756331766Sken		switch (sli4->config.topology) {
757331766Sken		case SLI4_READ_CFG_TOPO_FC:
758331766Sken			/* Attempt P2P but failover to FC-AL */
759331766Sken			init_link->link_flags.enable_topology_failover = TRUE;
760331766Sken
761331766Sken			if (sli_get_asic_type(sli4) == SLI4_ASIC_TYPE_LANCER)
762331766Sken				init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_FAIL_OVER;
763331766Sken			else
764331766Sken				init_link->link_flags.topology = SLI4_INIT_LINK_F_P2P_FAIL_OVER;
765331766Sken
766331766Sken			break;
767331766Sken		case SLI4_READ_CFG_TOPO_FC_AL:
768331766Sken			init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_ONLY;
769331766Sken			if ((init_link->link_speed_selection_code == FC_LINK_SPEED_16G) ||
770331766Sken			    (init_link->link_speed_selection_code == FC_LINK_SPEED_32G)) {
771331766Sken				ocs_log_test(sli4->os, "unsupported FC-AL speed %d\n", speed);
772331766Sken				return 0;
773331766Sken			}
774331766Sken			break;
775331766Sken		case SLI4_READ_CFG_TOPO_FC_DA:
776331766Sken			init_link->link_flags.topology = FC_TOPOLOGY_P2P;
777331766Sken			break;
778331766Sken		default:
779331766Sken			ocs_log_test(sli4->os, "unsupported topology %#x\n", sli4->config.topology);
780331766Sken			return 0;
781331766Sken		}
782331766Sken
783331766Sken		init_link->link_flags.unfair = FALSE;
784331766Sken		init_link->link_flags.skip_lirp_lilp = FALSE;
785331766Sken		init_link->link_flags.gen_loop_validity_check = FALSE;
786331766Sken		init_link->link_flags.skip_lisa = FALSE;
787331766Sken		init_link->link_flags.select_hightest_al_pa = FALSE;
788331766Sken	}
789331766Sken
790331766Sken	return sizeof(sli4_cmd_init_link_t);
791331766Sken}
792331766Sken
793331766Sken/**
794331766Sken * @ingroup sli
795331766Sken * @brief Write an INIT_VFI command to the provided buffer.
796331766Sken *
797331766Sken * @param sli4 SLI context pointer.
798331766Sken * @param buf Virtual pointer to the destination buffer.
799331766Sken * @param size Buffer size, in bytes.
800331766Sken * @param vfi VFI
801331766Sken * @param fcfi FCFI
802331766Sken * @param vpi VPI (Set to -1 if unused.)
803331766Sken *
804331766Sken * @return Returns the number of bytes written.
805331766Sken */
806331766Skenint32_t
807331766Skensli_cmd_init_vfi(sli4_t *sli4, void *buf, size_t size, uint16_t vfi,
808331766Sken		uint16_t fcfi, uint16_t vpi)
809331766Sken{
810331766Sken	sli4_cmd_init_vfi_t	*init_vfi = buf;
811331766Sken
812331766Sken	ocs_memset(buf, 0, size);
813331766Sken
814331766Sken	init_vfi->hdr.command = SLI4_MBOX_COMMAND_INIT_VFI;
815331766Sken
816331766Sken	init_vfi->vfi = vfi;
817331766Sken	init_vfi->fcfi = fcfi;
818331766Sken
819331766Sken	/*
820331766Sken	 * If the VPI is valid, initialize it at the same time as
821331766Sken	 * the VFI
822331766Sken	 */
823331766Sken	if (0xffff != vpi) {
824331766Sken		init_vfi->vp  = TRUE;
825331766Sken		init_vfi->vpi = vpi;
826331766Sken	}
827331766Sken
828331766Sken	return sizeof(sli4_cmd_init_vfi_t);
829331766Sken}
830331766Sken
831331766Sken/**
832331766Sken * @ingroup sli
833331766Sken * @brief Write an INIT_VPI command to the provided buffer.
834331766Sken *
835331766Sken * @param sli4 SLI context pointer.
836331766Sken * @param buf Virtual pointer to the destination buffer.
837331766Sken * @param size Buffer size, in bytes.
838331766Sken * @param vpi VPI allocated.
839331766Sken * @param vfi VFI associated with this VPI.
840331766Sken *
841331766Sken * @return Returns the number of bytes written.
842331766Sken */
843331766Skenint32_t
844331766Skensli_cmd_init_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t vpi, uint16_t vfi)
845331766Sken{
846331766Sken	sli4_cmd_init_vpi_t	*init_vpi = buf;
847331766Sken
848331766Sken	ocs_memset(buf, 0, size);
849331766Sken
850331766Sken	init_vpi->hdr.command = SLI4_MBOX_COMMAND_INIT_VPI;
851331766Sken	init_vpi->vpi = vpi;
852331766Sken	init_vpi->vfi = vfi;
853331766Sken
854331766Sken	return sizeof(sli4_cmd_init_vpi_t);
855331766Sken}
856331766Sken
857331766Sken/**
858331766Sken * @ingroup sli
859331766Sken * @brief Write a POST_XRI command to the provided buffer.
860331766Sken *
861331766Sken * @param sli4 SLI context pointer.
862331766Sken * @param buf Virtual pointer to the destination buffer.
863331766Sken * @param size Buffer size, in bytes.
864331766Sken * @param xri_base Starting XRI value for range of XRI given to SLI Port.
865331766Sken * @param xri_count Number of XRIs provided to the SLI Port.
866331766Sken *
867331766Sken * @return Returns the number of bytes written.
868331766Sken */
869331766Skenint32_t
870331766Skensli_cmd_post_xri(sli4_t *sli4, void *buf, size_t size,  uint16_t xri_base, uint16_t xri_count)
871331766Sken{
872331766Sken	sli4_cmd_post_xri_t	*post_xri = buf;
873331766Sken
874331766Sken	ocs_memset(buf, 0, size);
875331766Sken
876331766Sken	post_xri->hdr.command = SLI4_MBOX_COMMAND_POST_XRI;
877331766Sken	post_xri->xri_base = xri_base;
878331766Sken	post_xri->xri_count = xri_count;
879331766Sken
880331766Sken	if (sli4->config.auto_xfer_rdy == 0) {
881331766Sken		post_xri->enx = TRUE;
882331766Sken		post_xri->val = TRUE;
883331766Sken	}
884331766Sken
885331766Sken	return sizeof(sli4_cmd_post_xri_t);
886331766Sken}
887331766Sken
888331766Sken/**
889331766Sken * @ingroup sli
890331766Sken * @brief Write a RELEASE_XRI command to the provided buffer.
891331766Sken *
892331766Sken * @param sli4 SLI context pointer.
893331766Sken * @param buf Virtual pointer to the destination buffer.
894331766Sken * @param size Buffer size, in bytes.
895331766Sken * @param num_xri The number of XRIs to be released.
896331766Sken *
897331766Sken * @return Returns the number of bytes written.
898331766Sken */
899331766Skenint32_t
900331766Skensli_cmd_release_xri(sli4_t *sli4, void *buf, size_t size,  uint8_t num_xri)
901331766Sken{
902331766Sken	sli4_cmd_release_xri_t	*release_xri = buf;
903331766Sken
904331766Sken	ocs_memset(buf, 0, size);
905331766Sken
906331766Sken	release_xri->hdr.command = SLI4_MBOX_COMMAND_RELEASE_XRI;
907331766Sken	release_xri->xri_count = num_xri;
908331766Sken
909331766Sken	return sizeof(sli4_cmd_release_xri_t);
910331766Sken}
911331766Sken
912331766Sken/**
913331766Sken * @brief Write a READ_CONFIG command to the provided buffer.
914331766Sken *
915331766Sken * @param sli4 SLI context pointer.
916331766Sken * @param buf Virtual pointer to the destination buffer.
917331766Sken * @param size Buffer size, in bytes
918331766Sken *
919331766Sken * @return Returns the number of bytes written.
920331766Sken */
921331766Skenstatic int32_t
922331766Skensli_cmd_read_config(sli4_t *sli4, void *buf, size_t size)
923331766Sken{
924331766Sken	sli4_cmd_read_config_t	*read_config = buf;
925331766Sken
926331766Sken	ocs_memset(buf, 0, size);
927331766Sken
928331766Sken	read_config->hdr.command = SLI4_MBOX_COMMAND_READ_CONFIG;
929331766Sken
930331766Sken	return sizeof(sli4_cmd_read_config_t);
931331766Sken}
932331766Sken
933331766Sken/**
934331766Sken * @brief Write a READ_NVPARMS command to the provided buffer.
935331766Sken *
936331766Sken * @param sli4 SLI context pointer.
937331766Sken * @param buf Virtual pointer to the destination buffer.
938331766Sken * @param size Buffer size, in bytes.
939331766Sken *
940331766Sken * @return Returns the number of bytes written.
941331766Sken */
942331766Skenint32_t
943331766Skensli_cmd_read_nvparms(sli4_t *sli4, void *buf, size_t size)
944331766Sken{
945331766Sken	sli4_cmd_read_nvparms_t	*read_nvparms = buf;
946331766Sken
947331766Sken	ocs_memset(buf, 0, size);
948331766Sken
949331766Sken	read_nvparms->hdr.command = SLI4_MBOX_COMMAND_READ_NVPARMS;
950331766Sken
951331766Sken	return sizeof(sli4_cmd_read_nvparms_t);
952331766Sken}
953331766Sken
954331766Sken/**
955331766Sken * @brief Write a WRITE_NVPARMS command to the provided buffer.
956331766Sken *
957331766Sken * @param sli4 SLI context pointer.
958331766Sken * @param buf Virtual pointer to the destination buffer.
959331766Sken * @param size Buffer size, in bytes.
960331766Sken * @param wwpn WWPN to write - pointer to array of 8 uint8_t.
961331766Sken * @param wwnn WWNN to write - pointer to array of 8 uint8_t.
962331766Sken * @param hard_alpa Hard ALPA to write.
963331766Sken * @param preferred_d_id  Preferred D_ID to write.
964331766Sken *
965331766Sken * @return Returns the number of bytes written.
966331766Sken */
967331766Skenint32_t
968331766Skensli_cmd_write_nvparms(sli4_t *sli4, void *buf, size_t size, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
969331766Sken		uint32_t preferred_d_id)
970331766Sken{
971331766Sken	sli4_cmd_write_nvparms_t	*write_nvparms = buf;
972331766Sken
973331766Sken	ocs_memset(buf, 0, size);
974331766Sken
975331766Sken	write_nvparms->hdr.command = SLI4_MBOX_COMMAND_WRITE_NVPARMS;
976331766Sken	ocs_memcpy(write_nvparms->wwpn, wwpn, 8);
977331766Sken	ocs_memcpy(write_nvparms->wwnn, wwnn, 8);
978331766Sken	write_nvparms->hard_alpa = hard_alpa;
979331766Sken	write_nvparms->preferred_d_id = preferred_d_id;
980331766Sken
981331766Sken	return sizeof(sli4_cmd_write_nvparms_t);
982331766Sken}
983331766Sken
984331766Sken/**
985331766Sken * @brief Write a READ_REV command to the provided buffer.
986331766Sken *
987331766Sken * @param sli4 SLI context pointer.
988331766Sken * @param buf Virtual pointer to the destination buffer.
989331766Sken * @param size Buffer size, in bytes.
990331766Sken * @param vpd Pointer to the buffer.
991331766Sken *
992331766Sken * @return Returns the number of bytes written.
993331766Sken */
994331766Skenstatic int32_t
995331766Skensli_cmd_read_rev(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *vpd)
996331766Sken{
997331766Sken	sli4_cmd_read_rev_t	*read_rev = buf;
998331766Sken
999331766Sken	ocs_memset(buf, 0, size);
1000331766Sken
1001331766Sken	read_rev->hdr.command = SLI4_MBOX_COMMAND_READ_REV;
1002331766Sken
1003331766Sken	if (vpd && vpd->size) {
1004331766Sken		read_rev->vpd = TRUE;
1005331766Sken
1006331766Sken		read_rev->available_length = vpd->size;
1007331766Sken
1008331766Sken		read_rev->physical_address_low  = ocs_addr32_lo(vpd->phys);
1009331766Sken		read_rev->physical_address_high = ocs_addr32_hi(vpd->phys);
1010331766Sken	}
1011331766Sken
1012331766Sken	return sizeof(sli4_cmd_read_rev_t);
1013331766Sken}
1014331766Sken
1015331766Sken/**
1016331766Sken * @ingroup sli
1017331766Sken * @brief Write a READ_SPARM64 command to the provided buffer.
1018331766Sken *
1019331766Sken * @param sli4 SLI context pointer.
1020331766Sken * @param buf Virtual pointer to the destination buffer.
1021331766Sken * @param size Buffer size, in bytes.
1022331766Sken * @param dma DMA buffer for the service parameters.
1023331766Sken * @param vpi VPI used to determine the WWN.
1024331766Sken *
1025331766Sken * @return Returns the number of bytes written.
1026331766Sken */
1027331766Skenint32_t
1028331766Skensli_cmd_read_sparm64(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
1029331766Sken		uint16_t vpi)
1030331766Sken{
1031331766Sken	sli4_cmd_read_sparm64_t	*read_sparm64 = buf;
1032331766Sken
1033331766Sken	ocs_memset(buf, 0, size);
1034331766Sken
1035331766Sken	if (SLI4_READ_SPARM64_VPI_SPECIAL == vpi) {
1036331766Sken		ocs_log_test(sli4->os, "special VPI not supported!!!\n");
1037331766Sken		return -1;
1038331766Sken	}
1039331766Sken
1040331766Sken	if (!dma || !dma->phys) {
1041331766Sken		ocs_log_test(sli4->os, "bad DMA buffer\n");
1042331766Sken		return -1;
1043331766Sken	}
1044331766Sken
1045331766Sken	read_sparm64->hdr.command = SLI4_MBOX_COMMAND_READ_SPARM64;
1046331766Sken
1047331766Sken	read_sparm64->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
1048331766Sken	read_sparm64->bde_64.buffer_length = dma->size;
1049331766Sken	read_sparm64->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
1050331766Sken	read_sparm64->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
1051331766Sken
1052331766Sken	read_sparm64->vpi = vpi;
1053331766Sken
1054331766Sken	return sizeof(sli4_cmd_read_sparm64_t);
1055331766Sken}
1056331766Sken
1057331766Sken/**
1058331766Sken * @ingroup sli
1059331766Sken * @brief Write a READ_TOPOLOGY command to the provided buffer.
1060331766Sken *
1061331766Sken * @param sli4 SLI context pointer.
1062331766Sken * @param buf Virtual pointer to the destination buffer.
1063331766Sken * @param size Buffer size, in bytes.
1064331766Sken * @param dma DMA buffer for loop map (optional).
1065331766Sken *
1066331766Sken * @return Returns the number of bytes written.
1067331766Sken */
1068331766Skenint32_t
1069331766Skensli_cmd_read_topology(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
1070331766Sken{
1071331766Sken	sli4_cmd_read_topology_t *read_topo = buf;
1072331766Sken
1073331766Sken	ocs_memset(buf, 0, size);
1074331766Sken
1075331766Sken	read_topo->hdr.command = SLI4_MBOX_COMMAND_READ_TOPOLOGY;
1076331766Sken
1077331766Sken	if (dma && dma->size) {
1078331766Sken		if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) {
1079331766Sken			ocs_log_test(sli4->os, "loop map buffer too small %jd\n",
1080331766Sken					dma->size);
1081331766Sken			return 0;
1082331766Sken		}
1083331766Sken
1084331766Sken		ocs_memset(dma->virt, 0, dma->size);
1085331766Sken
1086331766Sken		read_topo->bde_loop_map.bde_type = SLI4_BDE_TYPE_BDE_64;
1087331766Sken		read_topo->bde_loop_map.buffer_length = dma->size;
1088331766Sken		read_topo->bde_loop_map.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
1089331766Sken		read_topo->bde_loop_map.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
1090331766Sken	}
1091331766Sken
1092331766Sken	return sizeof(sli4_cmd_read_topology_t);
1093331766Sken}
1094331766Sken
1095331766Sken/**
1096331766Sken * @ingroup sli
1097331766Sken * @brief Write a REG_FCFI command to the provided buffer.
1098331766Sken *
1099331766Sken * @param sli4 SLI context pointer.
1100331766Sken * @param buf Virtual pointer to the destination buffer.
1101331766Sken * @param size Buffer size, in bytes.
1102331766Sken * @param index FCF index returned by READ_FCF_TABLE.
1103331766Sken * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
1104331766Sken * @param vlan_id VLAN ID tag.
1105331766Sken *
1106331766Sken * @return Returns the number of bytes written.
1107331766Sken */
1108331766Skenint32_t
1109331766Skensli_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)
1110331766Sken{
1111331766Sken	sli4_cmd_reg_fcfi_t	*reg_fcfi = buf;
1112331766Sken	uint32_t		i;
1113331766Sken
1114331766Sken	ocs_memset(buf, 0, size);
1115331766Sken
1116331766Sken	reg_fcfi->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI;
1117331766Sken
1118331766Sken	reg_fcfi->fcf_index = index;
1119331766Sken
1120331766Sken	for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
1121331766Sken		switch(i) {
1122331766Sken		case 0:	reg_fcfi->rq_id_0 = rq_cfg[0].rq_id; break;
1123331766Sken		case 1:	reg_fcfi->rq_id_1 = rq_cfg[1].rq_id; break;
1124331766Sken		case 2:	reg_fcfi->rq_id_2 = rq_cfg[2].rq_id; break;
1125331766Sken		case 3:	reg_fcfi->rq_id_3 = rq_cfg[3].rq_id; break;
1126331766Sken		}
1127331766Sken		reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
1128331766Sken		reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
1129331766Sken		reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
1130331766Sken		reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match;
1131331766Sken	}
1132331766Sken
1133331766Sken	if (vlan_id) {
1134331766Sken		reg_fcfi->vv = TRUE;
1135331766Sken		reg_fcfi->vlan_tag = vlan_id;
1136331766Sken	}
1137331766Sken
1138331766Sken	return sizeof(sli4_cmd_reg_fcfi_t);
1139331766Sken}
1140331766Sken
1141331766Sken/**
1142331766Sken * @brief Write REG_FCFI_MRQ to provided command buffer
1143331766Sken *
1144331766Sken * @param sli4 SLI context pointer.
1145331766Sken * @param buf Virtual pointer to the destination buffer.
1146331766Sken * @param size Buffer size, in bytes.
1147331766Sken * @param fcf_index FCF index returned by READ_FCF_TABLE.
1148331766Sken * @param vlan_id VLAN ID tag.
1149331766Sken * @param rr_quant Round robin quanta if RQ selection policy is 2
1150331766Sken * @param rq_selection_policy RQ selection policy
1151331766Sken * @param num_rqs Array of count of RQs per filter
1152331766Sken * @param rq_ids Array of RQ ids per filter
1153331766Sken * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
1154331766Sken *
1155331766Sken * @return returns 0 for success, a negative error code value for failure.
1156331766Sken */
1157331766Skenint32_t
1158331766Skensli_cmd_reg_fcfi_mrq(sli4_t *sli4, void *buf, size_t size, uint8_t mode,
1159331766Sken		     uint16_t fcf_index, uint16_t vlan_id, uint8_t rq_selection_policy,
1160331766Sken		     uint8_t mrq_bit_mask, uint16_t num_mrqs,
1161331766Sken		     sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG])
1162331766Sken{
1163331766Sken	sli4_cmd_reg_fcfi_mrq_t	*reg_fcfi_mrq = buf;
1164331766Sken	uint32_t i;
1165331766Sken
1166331766Sken	ocs_memset(buf, 0, size);
1167331766Sken
1168331766Sken	reg_fcfi_mrq->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI_MRQ;
1169331766Sken	if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) {
1170331766Sken		reg_fcfi_mrq->fcf_index = fcf_index;
1171331766Sken		if (vlan_id) {
1172331766Sken			reg_fcfi_mrq->vv = TRUE;
1173331766Sken			reg_fcfi_mrq->vlan_tag = vlan_id;
1174331766Sken		}
1175331766Sken		goto done;
1176331766Sken	}
1177331766Sken
1178331766Sken	reg_fcfi_mrq->mode = mode;
1179331766Sken	for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
1180331766Sken		reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
1181331766Sken		reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
1182331766Sken		reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
1183331766Sken		reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match;
1184331766Sken
1185331766Sken		switch(i) {
1186331766Sken		case 3:	reg_fcfi_mrq->rq_id_3 = rq_cfg[i].rq_id; break;
1187331766Sken		case 2:	reg_fcfi_mrq->rq_id_2 = rq_cfg[i].rq_id; break;
1188331766Sken		case 1:	reg_fcfi_mrq->rq_id_1 = rq_cfg[i].rq_id; break;
1189331766Sken		case 0:	reg_fcfi_mrq->rq_id_0 = rq_cfg[i].rq_id; break;
1190331766Sken		}
1191331766Sken	}
1192331766Sken
1193331766Sken	reg_fcfi_mrq->rq_selection_policy = rq_selection_policy;
1194331766Sken	reg_fcfi_mrq->mrq_filter_bitmask = mrq_bit_mask;
1195331766Sken	reg_fcfi_mrq->num_mrq_pairs = num_mrqs;
1196331766Skendone:
1197331766Sken	return sizeof(sli4_cmd_reg_fcfi_mrq_t);
1198331766Sken}
1199331766Sken
1200331766Sken/**
1201331766Sken * @ingroup sli
1202331766Sken * @brief Write a REG_RPI command to the provided buffer.
1203331766Sken *
1204331766Sken * @param sli4 SLI context pointer.
1205331766Sken * @param buf Virtual pointer to the destination buffer.
1206331766Sken * @param size Buffer size, in bytes.
1207331766Sken * @param nport_id Remote F/N_Port_ID.
1208331766Sken * @param rpi Previously-allocated Remote Port Indicator.
1209331766Sken * @param vpi Previously-allocated Virtual Port Indicator.
1210331766Sken * @param dma DMA buffer that contains the remote port's service parameters.
1211331766Sken * @param update Boolean indicating an update to an existing RPI (TRUE)
1212331766Sken * or a new registration (FALSE).
1213331766Sken *
1214331766Sken * @return Returns the number of bytes written.
1215331766Sken */
1216331766Skenint32_t
1217331766Skensli_cmd_reg_rpi(sli4_t *sli4, void *buf, size_t size, uint32_t nport_id, uint16_t rpi,
1218331766Sken			uint16_t vpi, ocs_dma_t *dma, uint8_t update,  uint8_t enable_t10_pi)
1219331766Sken{
1220331766Sken	sli4_cmd_reg_rpi_t *reg_rpi = buf;
1221331766Sken
1222331766Sken	ocs_memset(buf, 0, size);
1223331766Sken
1224331766Sken	reg_rpi->hdr.command = SLI4_MBOX_COMMAND_REG_RPI;
1225331766Sken
1226331766Sken	reg_rpi->rpi = rpi;
1227331766Sken	reg_rpi->remote_n_port_id = nport_id;
1228331766Sken	reg_rpi->upd = update;
1229331766Sken	reg_rpi->etow = enable_t10_pi;
1230331766Sken
1231331766Sken	reg_rpi->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
1232331766Sken	reg_rpi->bde_64.buffer_length = SLI4_REG_RPI_BUF_LEN;
1233331766Sken	reg_rpi->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
1234331766Sken	reg_rpi->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
1235331766Sken
1236331766Sken	reg_rpi->vpi = vpi;
1237331766Sken
1238331766Sken	return sizeof(sli4_cmd_reg_rpi_t);
1239331766Sken}
1240331766Sken
1241331766Sken/**
1242331766Sken * @ingroup sli
1243331766Sken * @brief Write a REG_VFI command to the provided buffer.
1244331766Sken *
1245331766Sken * @param sli4 SLI context pointer.
1246331766Sken * @param buf Virtual pointer to the destination buffer.
1247331766Sken * @param size Buffer size, in bytes.
1248331766Sken * @param domain Pointer to the domain object.
1249331766Sken *
1250331766Sken * @return Returns the number of bytes written.
1251331766Sken */
1252331766Skenint32_t
1253331766Skensli_cmd_reg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain)
1254331766Sken{
1255331766Sken	sli4_cmd_reg_vfi_t	*reg_vfi = buf;
1256331766Sken
1257331766Sken	if (!sli4 || !buf || !domain) {
1258331766Sken		return 0;
1259331766Sken	}
1260331766Sken
1261331766Sken	ocs_memset(buf, 0, size);
1262331766Sken
1263331766Sken	reg_vfi->hdr.command = SLI4_MBOX_COMMAND_REG_VFI;
1264331766Sken
1265331766Sken	reg_vfi->vfi = domain->indicator;
1266331766Sken
1267331766Sken	reg_vfi->fcfi = domain->fcf_indicator;
1268331766Sken
1269331766Sken	/* TODO contents of domain->dma only valid if topo == FABRIC */
1270331766Sken	reg_vfi->sparm.bde_type = SLI4_BDE_TYPE_BDE_64;
1271331766Sken	reg_vfi->sparm.buffer_length = 0x70;
1272331766Sken	reg_vfi->sparm.u.data.buffer_address_low  = ocs_addr32_lo(domain->dma.phys);
1273331766Sken	reg_vfi->sparm.u.data.buffer_address_high = ocs_addr32_hi(domain->dma.phys);
1274331766Sken
1275331766Sken	reg_vfi->e_d_tov = sli4->config.e_d_tov;
1276331766Sken	reg_vfi->r_a_tov = sli4->config.r_a_tov;
1277331766Sken
1278331766Sken	reg_vfi->vp = TRUE;
1279331766Sken	reg_vfi->vpi = domain->sport->indicator;
1280331766Sken	ocs_memcpy(reg_vfi->wwpn, &domain->sport->sli_wwpn, sizeof(reg_vfi->wwpn));
1281331766Sken	reg_vfi->local_n_port_id = domain->sport->fc_id;
1282331766Sken
1283331766Sken	return sizeof(sli4_cmd_reg_vfi_t);
1284331766Sken}
1285331766Sken
1286331766Sken/**
1287331766Sken * @ingroup sli
1288331766Sken * @brief Write a REG_VPI command to the provided buffer.
1289331766Sken *
1290331766Sken * @param sli4 SLI context pointer.
1291331766Sken * @param buf Virtual pointer to the destination buffer.
1292331766Sken * @param size Buffer size, in bytes.
1293331766Sken * @param sport Point to SLI Port object.
1294331766Sken * @param update Boolean indicating whether to update the existing VPI (true)
1295331766Sken * or create a new VPI (false).
1296331766Sken *
1297331766Sken * @return Returns the number of bytes written.
1298331766Sken */
1299331766Skenint32_t
1300331766Skensli_cmd_reg_vpi(sli4_t *sli4, void *buf, size_t size, ocs_sli_port_t *sport, uint8_t update)
1301331766Sken{
1302331766Sken	sli4_cmd_reg_vpi_t	*reg_vpi = buf;
1303331766Sken
1304331766Sken	if (!sli4 || !buf || !sport) {
1305331766Sken		return 0;
1306331766Sken	}
1307331766Sken
1308331766Sken	ocs_memset(buf, 0, size);
1309331766Sken
1310331766Sken	reg_vpi->hdr.command = SLI4_MBOX_COMMAND_REG_VPI;
1311331766Sken
1312331766Sken	reg_vpi->local_n_port_id = sport->fc_id;
1313331766Sken	reg_vpi->upd = update != 0;
1314331766Sken	ocs_memcpy(reg_vpi->wwpn, &sport->sli_wwpn, sizeof(reg_vpi->wwpn));
1315331766Sken	reg_vpi->vpi = sport->indicator;
1316331766Sken	reg_vpi->vfi = sport->domain->indicator;
1317331766Sken
1318331766Sken	return sizeof(sli4_cmd_reg_vpi_t);
1319331766Sken}
1320331766Sken
1321331766Sken/**
1322331766Sken * @brief Write a REQUEST_FEATURES command to the provided buffer.
1323331766Sken *
1324331766Sken * @param sli4 SLI context pointer.
1325331766Sken * @param buf Virtual pointer to the destination buffer.
1326331766Sken * @param size Buffer size, in bytes.
1327331766Sken * @param mask Features to request.
1328331766Sken * @param query Use feature query mode (does not change FW).
1329331766Sken *
1330331766Sken * @return Returns the number of bytes written.
1331331766Sken */
1332331766Skenstatic int32_t
1333331766Skensli_cmd_request_features(sli4_t *sli4, void *buf, size_t size, sli4_features_t mask, uint8_t query)
1334331766Sken{
1335331766Sken	sli4_cmd_request_features_t *features = buf;
1336331766Sken
1337331766Sken	ocs_memset(buf, 0, size);
1338331766Sken
1339331766Sken	features->hdr.command = SLI4_MBOX_COMMAND_REQUEST_FEATURES;
1340331766Sken
1341331766Sken	if (query) {
1342331766Sken		features->qry = TRUE;
1343331766Sken	}
1344331766Sken	features->command.dword = mask.dword;
1345331766Sken
1346331766Sken	return sizeof(sli4_cmd_request_features_t);
1347331766Sken}
1348331766Sken
1349331766Sken/**
1350331766Sken * @ingroup sli
1351331766Sken * @brief Write a SLI_CONFIG command to the provided buffer.
1352331766Sken *
1353331766Sken * @param sli4 SLI context pointer.
1354331766Sken * @param buf Virtual pointer to the destination buffer.
1355331766Sken * @param size Buffer size, in bytes.
1356331766Sken * @param length Length in bytes of attached command.
1357331766Sken * @param dma DMA buffer for non-embedded commands.
1358331766Sken *
1359331766Sken * @return Returns the number of bytes written.
1360331766Sken */
1361331766Skenint32_t
1362331766Skensli_cmd_sli_config(sli4_t *sli4, void *buf, size_t size, uint32_t length, ocs_dma_t *dma)
1363331766Sken{
1364331766Sken	sli4_cmd_sli_config_t	*sli_config = NULL;
1365331766Sken
1366331766Sken	if ((length > sizeof(sli_config->payload.embed)) && (dma == NULL)) {
1367331766Sken		ocs_log_test(sli4->os, "length(%d) > payload(%ld)\n",
1368331766Sken				length, sizeof(sli_config->payload.embed));
1369331766Sken		return -1;
1370331766Sken	}
1371331766Sken
1372331766Sken	sli_config = buf;
1373331766Sken
1374331766Sken	ocs_memset(buf, 0, size);
1375331766Sken
1376331766Sken	sli_config->hdr.command = SLI4_MBOX_COMMAND_SLI_CONFIG;
1377331766Sken	if (NULL == dma) {
1378331766Sken		sli_config->emb = TRUE;
1379331766Sken		sli_config->payload_length = length;
1380331766Sken	} else {
1381331766Sken		sli_config->emb = FALSE;
1382331766Sken
1383331766Sken		sli_config->pmd_count = 1;
1384331766Sken
1385331766Sken		sli_config->payload.mem.address_low = ocs_addr32_lo(dma->phys);
1386331766Sken		sli_config->payload.mem.address_high = ocs_addr32_hi(dma->phys);
1387331766Sken		sli_config->payload.mem.length = dma->size;
1388331766Sken		sli_config->payload_length = dma->size;
1389331766Sken#if defined(OCS_INCLUDE_DEBUG)
1390331766Sken		/* save pointer to DMA for BMBX dumping purposes */
1391331766Sken		sli4->bmbx_non_emb_pmd = dma;
1392331766Sken#endif
1393331766Sken
1394331766Sken	}
1395331766Sken
1396331766Sken	return offsetof(sli4_cmd_sli_config_t, payload.embed);
1397331766Sken}
1398331766Sken
1399331766Sken/**
1400331766Sken * @brief Initialize SLI Port control register.
1401331766Sken *
1402331766Sken * @param sli4 SLI context pointer.
1403331766Sken * @param endian Endian value to write.
1404331766Sken *
1405331766Sken * @return Returns 0 on success, or a negative error code value on failure.
1406331766Sken */
1407331766Sken
1408331766Skenstatic int32_t
1409331766Skensli_sliport_control(sli4_t *sli4, uint32_t endian)
1410331766Sken{
1411331766Sken	uint32_t iter;
1412331766Sken	int32_t rc;
1413331766Sken
1414331766Sken	rc = -1;
1415331766Sken
1416331766Sken	/* Initialize port, endian */
1417331766Sken	sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, endian | SLI4_SLIPORT_CONTROL_IP);
1418331766Sken
1419331766Sken	for (iter = 0; iter < 3000; iter ++) {
1420331766Sken		ocs_udelay(SLI4_INIT_PORT_DELAY_US);
1421331766Sken		if (sli_fw_ready(sli4) == 1) {
1422331766Sken			rc = 0;
1423331766Sken			break;
1424331766Sken		}
1425331766Sken	}
1426331766Sken
1427331766Sken	if (rc != 0) {
1428331766Sken		ocs_log_crit(sli4->os, "port failed to become ready after initialization\n");
1429331766Sken	}
1430331766Sken
1431331766Sken	return rc;
1432331766Sken}
1433331766Sken
1434331766Sken/**
1435331766Sken * @ingroup sli
1436331766Sken * @brief Write a UNREG_FCFI command to the provided buffer.
1437331766Sken *
1438331766Sken * @param sli4 SLI context pointer.
1439331766Sken * @param buf Virtual pointer to the destination buffer.
1440331766Sken * @param size Buffer size, in bytes.
1441331766Sken * @param indicator Indicator value.
1442331766Sken *
1443331766Sken * @return Returns the number of bytes written.
1444331766Sken */
1445331766Skenint32_t
1446331766Skensli_cmd_unreg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator)
1447331766Sken{
1448331766Sken	sli4_cmd_unreg_fcfi_t	*unreg_fcfi = buf;
1449331766Sken
1450331766Sken	if (!sli4 || !buf) {
1451331766Sken		return 0;
1452331766Sken	}
1453331766Sken
1454331766Sken	ocs_memset(buf, 0, size);
1455331766Sken
1456331766Sken	unreg_fcfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_FCFI;
1457331766Sken
1458331766Sken	unreg_fcfi->fcfi = indicator;
1459331766Sken
1460331766Sken	return sizeof(sli4_cmd_unreg_fcfi_t);
1461331766Sken}
1462331766Sken
1463331766Sken/**
1464331766Sken * @ingroup sli
1465331766Sken * @brief Write an UNREG_RPI command to the provided buffer.
1466331766Sken *
1467331766Sken * @param sli4 SLI context pointer.
1468331766Sken * @param buf Virtual pointer to the destination buffer.
1469331766Sken * @param size Buffer size, in bytes.
1470331766Sken * @param indicator Indicator value.
1471331766Sken * @param which Type of unregister, such as node, port, domain, or FCF.
1472331766Sken * @param fc_id FC address.
1473331766Sken *
1474331766Sken * @return Returns the number of bytes written.
1475331766Sken */
1476331766Skenint32_t
1477331766Skensli_cmd_unreg_rpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, sli4_resource_e which,
1478331766Sken		uint32_t fc_id)
1479331766Sken{
1480331766Sken	sli4_cmd_unreg_rpi_t	*unreg_rpi = buf;
1481331766Sken	uint8_t		index_indicator = 0;
1482331766Sken
1483331766Sken	if (!sli4 || !buf) {
1484331766Sken		return 0;
1485331766Sken	}
1486331766Sken
1487331766Sken	ocs_memset(buf, 0, size);
1488331766Sken
1489331766Sken	unreg_rpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_RPI;
1490331766Sken
1491331766Sken	switch (which) {
1492331766Sken	case SLI_RSRC_FCOE_RPI:
1493331766Sken		index_indicator = SLI4_UNREG_RPI_II_RPI;
1494331766Sken		if (fc_id != UINT32_MAX) {
1495331766Sken			unreg_rpi->dp = TRUE;
1496331766Sken			unreg_rpi->destination_n_port_id = fc_id & 0x00ffffff;
1497331766Sken		}
1498331766Sken		break;
1499331766Sken	case SLI_RSRC_FCOE_VPI:
1500331766Sken		index_indicator = SLI4_UNREG_RPI_II_VPI;
1501331766Sken		break;
1502331766Sken	case SLI_RSRC_FCOE_VFI:
1503331766Sken		index_indicator = SLI4_UNREG_RPI_II_VFI;
1504331766Sken		break;
1505331766Sken	case SLI_RSRC_FCOE_FCFI:
1506331766Sken		index_indicator = SLI4_UNREG_RPI_II_FCFI;
1507331766Sken		break;
1508331766Sken	default:
1509331766Sken		ocs_log_test(sli4->os, "unknown type %#x\n", which);
1510331766Sken		return 0;
1511331766Sken	}
1512331766Sken
1513331766Sken	unreg_rpi->ii = index_indicator;
1514331766Sken	unreg_rpi->index = indicator;
1515331766Sken
1516331766Sken	return sizeof(sli4_cmd_unreg_rpi_t);
1517331766Sken}
1518331766Sken
1519331766Sken/**
1520331766Sken * @ingroup sli
1521331766Sken * @brief Write an UNREG_VFI command to the provided buffer.
1522331766Sken *
1523331766Sken * @param sli4 SLI context pointer.
1524331766Sken * @param buf Virtual pointer to the destination buffer.
1525331766Sken * @param size Buffer size, in bytes.
1526331766Sken * @param domain Pointer to the domain object
1527331766Sken * @param which Type of unregister, such as domain, FCFI, or everything.
1528331766Sken *
1529331766Sken * @return Returns the number of bytes written.
1530331766Sken */
1531331766Skenint32_t
1532331766Skensli_cmd_unreg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain, uint32_t which)
1533331766Sken{
1534331766Sken	sli4_cmd_unreg_vfi_t	*unreg_vfi = buf;
1535331766Sken
1536331766Sken	if (!sli4 || !buf || !domain) {
1537331766Sken		return 0;
1538331766Sken	}
1539331766Sken
1540331766Sken	ocs_memset(buf, 0, size);
1541331766Sken
1542331766Sken	unreg_vfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VFI;
1543331766Sken	switch (which) {
1544331766Sken	case SLI4_UNREG_TYPE_DOMAIN:
1545331766Sken		unreg_vfi->index = domain->indicator;
1546331766Sken		break;
1547331766Sken	case SLI4_UNREG_TYPE_FCF:
1548331766Sken		unreg_vfi->index = domain->fcf_indicator;
1549331766Sken		break;
1550331766Sken	case SLI4_UNREG_TYPE_ALL:
1551331766Sken		unreg_vfi->index = UINT16_MAX;
1552331766Sken		break;
1553331766Sken	default:
1554331766Sken		return 0;
1555331766Sken	}
1556331766Sken
1557331766Sken	if (SLI4_UNREG_TYPE_DOMAIN != which) {
1558331766Sken		unreg_vfi->ii = SLI4_UNREG_VFI_II_FCFI;
1559331766Sken	}
1560331766Sken
1561331766Sken	return sizeof(sli4_cmd_unreg_vfi_t);
1562331766Sken}
1563331766Sken
1564331766Sken/**
1565331766Sken * @ingroup sli
1566331766Sken * @brief Write an UNREG_VPI command to the provided buffer.
1567331766Sken *
1568331766Sken * @param sli4 SLI context pointer.
1569331766Sken * @param buf Virtual pointer to the destination buffer.
1570331766Sken * @param size Buffer size, in bytes.
1571331766Sken * @param indicator Indicator value.
1572331766Sken * @param which Type of unregister: port, domain, FCFI, everything
1573331766Sken *
1574331766Sken * @return Returns the number of bytes written.
1575331766Sken */
1576331766Skenint32_t
1577331766Skensli_cmd_unreg_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, uint32_t which)
1578331766Sken{
1579331766Sken	sli4_cmd_unreg_vpi_t	*unreg_vpi = buf;
1580331766Sken
1581331766Sken	if (!sli4 || !buf) {
1582331766Sken		return 0;
1583331766Sken	}
1584331766Sken
1585331766Sken	ocs_memset(buf, 0, size);
1586331766Sken
1587331766Sken	unreg_vpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VPI;
1588331766Sken	unreg_vpi->index = indicator;
1589331766Sken	switch (which) {
1590331766Sken	case SLI4_UNREG_TYPE_PORT:
1591331766Sken		unreg_vpi->ii = SLI4_UNREG_VPI_II_VPI;
1592331766Sken		break;
1593331766Sken	case SLI4_UNREG_TYPE_DOMAIN:
1594331766Sken		unreg_vpi->ii = SLI4_UNREG_VPI_II_VFI;
1595331766Sken		break;
1596331766Sken	case SLI4_UNREG_TYPE_FCF:
1597331766Sken		unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
1598331766Sken		break;
1599331766Sken	case SLI4_UNREG_TYPE_ALL:
1600331766Sken		unreg_vpi->index = UINT16_MAX;	/* override indicator */
1601331766Sken		unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
1602331766Sken		break;
1603331766Sken	default:
1604331766Sken		return 0;
1605331766Sken	}
1606331766Sken
1607331766Sken	return sizeof(sli4_cmd_unreg_vpi_t);
1608331766Sken}
1609331766Sken
1610331766Sken
1611331766Sken/**
1612331766Sken * @ingroup sli
1613331766Sken * @brief Write an CONFIG_AUTO_XFER_RDY command to the provided buffer.
1614331766Sken *
1615331766Sken * @param sli4 SLI context pointer.
1616331766Sken * @param buf Virtual pointer to the destination buffer.
1617331766Sken * @param size Buffer size, in bytes.
1618331766Sken * @param max_burst_len if the write FCP_DL is less than this size,
1619331766Sken * then the SLI port will generate the auto XFER_RDY.
1620331766Sken *
1621331766Sken * @return Returns the number of bytes written.
1622331766Sken */
1623331766Skenint32_t
1624331766Skensli_cmd_config_auto_xfer_rdy(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len)
1625331766Sken{
1626331766Sken	sli4_cmd_config_auto_xfer_rdy_t	*req = buf;
1627331766Sken
1628331766Sken	if (!sli4 || !buf) {
1629331766Sken		return 0;
1630331766Sken	}
1631331766Sken
1632331766Sken	ocs_memset(buf, 0, size);
1633331766Sken
1634331766Sken	req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY;
1635331766Sken	req->max_burst_len = max_burst_len;
1636331766Sken
1637331766Sken	return sizeof(sli4_cmd_config_auto_xfer_rdy_t);
1638331766Sken}
1639331766Sken
1640331766Sken/**
1641331766Sken * @ingroup sli
1642331766Sken * @brief Write an CONFIG_AUTO_XFER_RDY_HP command to the provided buffer.
1643331766Sken *
1644331766Sken * @param sli4 SLI context pointer.
1645331766Sken * @param buf Virtual pointer to the destination buffer.
1646331766Sken * @param size Buffer size, in bytes.
1647331766Sken * @param max_burst_len if the write FCP_DL is less than this size,
1648331766Sken * @param esoc enable start offset computation,
1649331766Sken * @param block_size block size,
1650331766Sken * then the SLI port will generate the auto XFER_RDY.
1651331766Sken *
1652331766Sken * @return Returns the number of bytes written.
1653331766Sken */
1654331766Skenint32_t
1655331766Skensli_cmd_config_auto_xfer_rdy_hp(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len,
1656331766Sken                                                uint32_t esoc, uint32_t block_size )
1657331766Sken{
1658331766Sken        sli4_cmd_config_auto_xfer_rdy_hp_t      *req = buf;
1659331766Sken
1660331766Sken        if (!sli4 || !buf) {
1661331766Sken                return 0;
1662331766Sken        }
1663331766Sken
1664331766Sken        ocs_memset(buf, 0, size);
1665331766Sken
1666331766Sken        req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY_HP;
1667331766Sken        req->max_burst_len = max_burst_len;
1668331766Sken        req->esoc = esoc;
1669331766Sken        req->block_size = block_size;
1670331766Sken        return sizeof(sli4_cmd_config_auto_xfer_rdy_hp_t);
1671331766Sken}
1672331766Sken
1673331766Sken/**
1674331766Sken * @brief Write a COMMON_FUNCTION_RESET command.
1675331766Sken *
1676331766Sken * @param sli4 SLI context.
1677331766Sken * @param buf Destination buffer for the command.
1678331766Sken * @param size Buffer size, in bytes.
1679331766Sken *
1680331766Sken * @return Returns the number of bytes written.
1681331766Sken */
1682331766Skenstatic int32_t
1683331766Skensli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size)
1684331766Sken{
1685331766Sken	sli4_req_common_function_reset_t *reset = NULL;
1686331766Sken	uint32_t	sli_config_off = 0;
1687331766Sken
1688331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1689331766Sken		uint32_t payload_size;
1690331766Sken
1691331766Sken		/* Payload length must accommodate both request and response */
1692331766Sken		payload_size = max(sizeof(sli4_req_common_function_reset_t),
1693331766Sken				sizeof(sli4_res_common_function_reset_t));
1694331766Sken
1695331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
1696331766Sken				NULL);
1697331766Sken	}
1698331766Sken	reset = (sli4_req_common_function_reset_t *)((uint8_t *)buf + sli_config_off);
1699331766Sken
1700331766Sken	reset->hdr.opcode = SLI4_OPC_COMMON_FUNCTION_RESET;
1701331766Sken	reset->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1702331766Sken
1703331766Sken	return(sli_config_off + sizeof(sli4_req_common_function_reset_t));
1704331766Sken}
1705331766Sken
1706331766Sken/**
1707331766Sken * @brief Write a COMMON_CREATE_CQ command.
1708331766Sken *
1709331766Sken * @param sli4 SLI context.
1710331766Sken * @param buf Destination buffer for the command.
1711331766Sken * @param size Buffer size, in bytes.
1712331766Sken * @param qmem DMA memory for the queue.
1713331766Sken * @param eq_id Associated EQ_ID
1714331766Sken * @param ignored This parameter carries the ULP which is only used for WQ and RQs
1715331766Sken *
1716331766Sken * @note This creates a Version 0 message.
1717331766Sken *
1718331766Sken * @return Returns the number of bytes written.
1719331766Sken */
1720331766Skenstatic int32_t
1721331766Skensli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size,
1722331766Sken		ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored)
1723331766Sken{
1724331766Sken	sli4_req_common_create_cq_v0_t	*cqv0 = NULL;
1725331766Sken	sli4_req_common_create_cq_v2_t	*cqv2 = NULL;
1726331766Sken	uint32_t	sli_config_off = 0;
1727331766Sken	uint32_t	p;
1728331766Sken	uintptr_t	addr;
1729331766Sken	uint32_t	if_type = sli4->if_type;
1730331766Sken	uint32_t	page_bytes = 0;
1731331766Sken	uint32_t	num_pages = 0;
1732331766Sken	uint32_t 	cmd_size = 0;
1733331766Sken	uint32_t	page_size = 0;
1734331766Sken	uint32_t	n_cqe = 0;
1735331766Sken
1736331766Sken	/* First calculate number of pages and the mailbox cmd length */
1737331766Sken	switch (if_type)
1738331766Sken	{
1739331766Sken	case SLI4_IF_TYPE_BE3_SKH_PF:
1740331766Sken		page_bytes = SLI_PAGE_SIZE;
1741331766Sken		num_pages = sli_page_count(qmem->size, page_bytes);
1742331766Sken		cmd_size = sizeof(sli4_req_common_create_cq_v0_t) + (8 * num_pages);
1743331766Sken		break;
1744331766Sken	case SLI4_IF_TYPE_LANCER_FC_ETH:
1745331766Sken		n_cqe = qmem->size / SLI4_CQE_BYTES;
1746331766Sken		switch (n_cqe) {
1747331766Sken		case 256:
1748331766Sken		case 512:
1749331766Sken		case 1024:
1750331766Sken		case 2048:
1751331766Sken			page_size = 1;
1752331766Sken			break;
1753331766Sken		case 4096:
1754331766Sken			page_size = 2;
1755331766Sken			break;
1756331766Sken		default:
1757331766Sken			return 0;
1758331766Sken		}
1759331766Sken		page_bytes = page_size * SLI_PAGE_SIZE;
1760331766Sken		num_pages = sli_page_count(qmem->size, page_bytes);
1761331766Sken		cmd_size = sizeof(sli4_req_common_create_cq_v2_t) + (8 * num_pages);
1762331766Sken		break;
1763331766Sken	default:
1764331766Sken		ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", if_type);
1765331766Sken		return -1;
1766331766Sken	}
1767331766Sken
1768331766Sken
1769331766Sken	/* now that we have the mailbox command size, we can set SLI_CONFIG fields */
1770331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1771331766Sken		uint32_t payload_size;
1772331766Sken
1773331766Sken		/* Payload length must accommodate both request and response */
1774331766Sken		payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_t));
1775331766Sken
1776331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
1777331766Sken				NULL);
1778331766Sken	}
1779331766Sken
1780331766Sken	switch (if_type)
1781331766Sken	{
1782331766Sken	case SLI4_IF_TYPE_BE3_SKH_PF:
1783331766Sken		cqv0 = (sli4_req_common_create_cq_v0_t *)((uint8_t *)buf + sli_config_off);
1784331766Sken		cqv0->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
1785331766Sken		cqv0->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1786331766Sken		cqv0->hdr.version = 0;
1787331766Sken		cqv0->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
1788331766Sken
1789331766Sken		/* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
1790331766Sken		cqv0->num_pages = num_pages;
1791331766Sken		switch (cqv0->num_pages) {
1792331766Sken		case 1:
1793331766Sken			cqv0->cqecnt = SLI4_CQ_CNT_256;
1794331766Sken			break;
1795331766Sken		case 2:
1796331766Sken			cqv0->cqecnt = SLI4_CQ_CNT_512;
1797331766Sken			break;
1798331766Sken		case 4:
1799331766Sken			cqv0->cqecnt = SLI4_CQ_CNT_1024;
1800331766Sken			break;
1801331766Sken		default:
1802331766Sken			ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv0->num_pages);
1803331766Sken			return -1;
1804331766Sken		}
1805331766Sken		cqv0->evt = TRUE;
1806331766Sken		cqv0->valid = TRUE;
1807331766Sken		/* TODO cq->nodelay = ???; */
1808331766Sken		/* TODO cq->clswm = ???; */
1809331766Sken		cqv0->arm = FALSE;
1810331766Sken		cqv0->eq_id = eq_id;
1811331766Sken
1812331766Sken		for (p = 0, addr = qmem->phys;
1813331766Sken				p < cqv0->num_pages;
1814331766Sken				p++, addr += page_bytes) {
1815331766Sken			cqv0->page_physical_address[p].low = ocs_addr32_lo(addr);
1816331766Sken			cqv0->page_physical_address[p].high = ocs_addr32_hi(addr);
1817331766Sken		}
1818331766Sken
1819331766Sken		break;
1820331766Sken	case SLI4_IF_TYPE_LANCER_FC_ETH:
1821331766Sken	{
1822331766Sken		cqv2 = (sli4_req_common_create_cq_v2_t *)((uint8_t *)buf + sli_config_off);
1823331766Sken		cqv2->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
1824331766Sken		cqv2->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1825331766Sken		cqv2->hdr.version = 2;
1826331766Sken		cqv2->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
1827331766Sken
1828331766Sken		cqv2->page_size = page_size;
1829331766Sken
1830331766Sken		/* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.3) */
1831331766Sken		cqv2->num_pages = num_pages;
1832331766Sken		if (!cqv2->num_pages || (cqv2->num_pages > SLI4_COMMON_CREATE_CQ_V2_MAX_PAGES)) {
1833331766Sken			return 0;
1834331766Sken		}
1835331766Sken
1836331766Sken		switch (cqv2->num_pages) {
1837331766Sken		case 1:
1838331766Sken			cqv2->cqecnt = SLI4_CQ_CNT_256;
1839331766Sken			break;
1840331766Sken		case 2:
1841331766Sken			cqv2->cqecnt = SLI4_CQ_CNT_512;
1842331766Sken			break;
1843331766Sken		case 4:
1844331766Sken			cqv2->cqecnt = SLI4_CQ_CNT_1024;
1845331766Sken			break;
1846331766Sken		case 8:
1847331766Sken			cqv2->cqecnt = SLI4_CQ_CNT_LARGE;
1848331766Sken			cqv2->cqe_count = n_cqe;
1849331766Sken			break;
1850331766Sken		default:
1851331766Sken			ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv2->num_pages);
1852331766Sken			return -1;
1853331766Sken		}
1854331766Sken
1855331766Sken		cqv2->evt = TRUE;
1856331766Sken		cqv2->valid = TRUE;
1857331766Sken		/* TODO cq->nodelay = ???; */
1858331766Sken		/* TODO cq->clswm = ???; */
1859331766Sken		cqv2->arm = FALSE;
1860331766Sken		cqv2->eq_id = eq_id;
1861331766Sken
1862331766Sken		for (p = 0, addr = qmem->phys;
1863331766Sken				p < cqv2->num_pages;
1864331766Sken				p++, addr += page_bytes) {
1865331766Sken			cqv2->page_physical_address[p].low = ocs_addr32_lo(addr);
1866331766Sken			cqv2->page_physical_address[p].high = ocs_addr32_hi(addr);
1867331766Sken		}
1868331766Sken	}
1869331766Sken		break;
1870331766Sken	default:
1871331766Sken		ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", if_type);
1872331766Sken		return -1;
1873331766Sken	}
1874331766Sken
1875331766Sken	return (sli_config_off + cmd_size);
1876331766Sken}
1877331766Sken
1878331766Sken/**
1879331766Sken * @brief Write a COMMON_DESTROY_CQ command.
1880331766Sken *
1881331766Sken * @param sli4 SLI context.
1882331766Sken * @param buf Destination buffer for the command.
1883331766Sken * @param size Buffer size, in bytes.
1884331766Sken * @param cq_id CQ ID
1885331766Sken *
1886331766Sken * @note This creates a Version 0 message.
1887331766Sken *
1888331766Sken * @return Returns the number of bytes written.
1889331766Sken */
1890331766Skenstatic int32_t
1891331766Skensli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint16_t cq_id)
1892331766Sken{
1893331766Sken	sli4_req_common_destroy_cq_t	*cq = NULL;
1894331766Sken	uint32_t	sli_config_off = 0;
1895331766Sken
1896331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1897331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
1898331766Sken				/* Payload length must accommodate both request and response */
1899331766Sken				max(sizeof(sli4_req_common_destroy_cq_t),
1900331766Sken					sizeof(sli4_res_hdr_t)),
1901331766Sken				NULL);
1902331766Sken	}
1903331766Sken	cq = (sli4_req_common_destroy_cq_t *)((uint8_t *)buf + sli_config_off);
1904331766Sken
1905331766Sken	cq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_CQ;
1906331766Sken	cq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1907331766Sken	cq->hdr.request_length = sizeof(sli4_req_common_destroy_cq_t) -
1908331766Sken					sizeof(sli4_req_hdr_t);
1909331766Sken	cq->cq_id = cq_id;
1910331766Sken
1911331766Sken	return(sli_config_off + sizeof(sli4_req_common_destroy_cq_t));
1912331766Sken}
1913331766Sken
1914331766Sken/**
1915331766Sken * @brief Write a COMMON_MODIFY_EQ_DELAY command.
1916331766Sken *
1917331766Sken * @param sli4 SLI context.
1918331766Sken * @param buf Destination buffer for the command.
1919331766Sken * @param size Buffer size, in bytes.
1920331766Sken * @param q Queue object array.
1921331766Sken * @param num_q Queue object array count.
1922331766Sken * @param shift Phase shift for staggering interrupts.
1923331766Sken * @param delay_mult Delay multiplier for limiting interrupt frequency.
1924331766Sken *
1925331766Sken * @return Returns the number of bytes written.
1926331766Sken */
1927331766Skenstatic int32_t
1928331766Skensli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift,
1929331766Sken				uint32_t delay_mult)
1930331766Sken{
1931331766Sken	sli4_req_common_modify_eq_delay_t *modify_delay = NULL;
1932331766Sken	uint32_t	sli_config_off = 0;
1933331766Sken	int i;
1934331766Sken
1935331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1936331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
1937331766Sken				/* Payload length must accommodate both request and response */
1938331766Sken				max(sizeof(sli4_req_common_modify_eq_delay_t), sizeof(sli4_res_hdr_t)),
1939331766Sken				NULL);
1940331766Sken	}
1941331766Sken
1942331766Sken	modify_delay = (sli4_req_common_modify_eq_delay_t *)((uint8_t *)buf + sli_config_off);
1943331766Sken
1944331766Sken	modify_delay->hdr.opcode = SLI4_OPC_COMMON_MODIFY_EQ_DELAY;
1945331766Sken	modify_delay->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
1946331766Sken	modify_delay->hdr.request_length = sizeof(sli4_req_common_modify_eq_delay_t) -
1947331766Sken					sizeof(sli4_req_hdr_t);
1948331766Sken
1949331766Sken	modify_delay->num_eq = num_q;
1950331766Sken
1951331766Sken	for (i = 0; i<num_q; i++) {
1952331766Sken		modify_delay->eq_delay_record[i].eq_id = q[i].id;
1953331766Sken		modify_delay->eq_delay_record[i].phase = shift;
1954331766Sken		modify_delay->eq_delay_record[i].delay_multiplier = delay_mult;
1955331766Sken	}
1956331766Sken
1957331766Sken	return(sli_config_off + sizeof(sli4_req_common_modify_eq_delay_t));
1958331766Sken}
1959331766Sken
1960331766Sken/**
1961331766Sken * @brief Write a COMMON_CREATE_EQ command.
1962331766Sken *
1963331766Sken * @param sli4 SLI context.
1964331766Sken * @param buf Destination buffer for the command.
1965331766Sken * @param size Buffer size, in bytes.
1966331766Sken * @param qmem DMA memory for the queue.
1967331766Sken * @param ignored1 Ignored (used for consistency among queue creation functions).
1968331766Sken * @param ignored2 Ignored (used for consistency among queue creation functions).
1969331766Sken *
1970331766Sken * @note Other queue creation routines use the last parameter to pass in
1971331766Sken * the associated Q_ID and ULP. EQ doesn't have an associated queue or ULP,
1972331766Sken * so these parameters are ignored
1973331766Sken *
1974331766Sken * @note This creates a Version 0 message
1975331766Sken *
1976331766Sken * @return Returns the number of bytes written.
1977331766Sken */
1978331766Skenstatic int32_t
1979331766Skensli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
1980331766Sken		uint16_t ignored1, uint16_t ignored2)
1981331766Sken{
1982331766Sken	sli4_req_common_create_eq_t	*eq = NULL;
1983331766Sken	uint32_t	sli_config_off = 0;
1984331766Sken	uint32_t	p;
1985331766Sken	uintptr_t	addr;
1986331766Sken
1987331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
1988331766Sken		uint32_t payload_size;
1989331766Sken
1990331766Sken		/* Payload length must accommodate both request and response */
1991331766Sken		payload_size = max(sizeof(sli4_req_common_create_eq_t),
1992331766Sken				sizeof(sli4_res_common_create_queue_t));
1993331766Sken
1994331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
1995331766Sken				NULL);
1996331766Sken	}
1997331766Sken	eq = (sli4_req_common_create_eq_t *)((uint8_t *)buf + sli_config_off);
1998331766Sken
1999331766Sken	eq->hdr.opcode = SLI4_OPC_COMMON_CREATE_EQ;
2000331766Sken	eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2001331766Sken	eq->hdr.request_length = sizeof(sli4_req_common_create_eq_t) -
2002331766Sken					sizeof(sli4_req_hdr_t);
2003331766Sken	/* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
2004331766Sken	eq->num_pages = qmem->size / SLI_PAGE_SIZE;
2005331766Sken	switch (eq->num_pages) {
2006331766Sken	case 1:
2007331766Sken		eq->eqesz = SLI4_EQE_SIZE_4;
2008331766Sken		eq->count = SLI4_EQ_CNT_1024;
2009331766Sken		break;
2010331766Sken	case 2:
2011331766Sken		eq->eqesz = SLI4_EQE_SIZE_4;
2012331766Sken		eq->count = SLI4_EQ_CNT_2048;
2013331766Sken		break;
2014331766Sken	case 4:
2015331766Sken		eq->eqesz = SLI4_EQE_SIZE_4;
2016331766Sken		eq->count = SLI4_EQ_CNT_4096;
2017331766Sken		break;
2018331766Sken	default:
2019331766Sken		ocs_log_test(sli4->os, "num_pages %d not valid\n", eq->num_pages);
2020331766Sken		return -1;
2021331766Sken	}
2022331766Sken	eq->valid = TRUE;
2023331766Sken	eq->arm = FALSE;
2024331766Sken	eq->delay_multiplier = 32;
2025331766Sken
2026331766Sken	for (p = 0, addr = qmem->phys;
2027331766Sken			p < eq->num_pages;
2028331766Sken			p++, addr += SLI_PAGE_SIZE) {
2029331766Sken		eq->page_address[p].low = ocs_addr32_lo(addr);
2030331766Sken		eq->page_address[p].high = ocs_addr32_hi(addr);
2031331766Sken	}
2032331766Sken
2033331766Sken	return(sli_config_off + sizeof(sli4_req_common_create_eq_t));
2034331766Sken}
2035331766Sken
2036331766Sken
2037331766Sken/**
2038331766Sken * @brief Write a COMMON_DESTROY_EQ command.
2039331766Sken *
2040331766Sken * @param sli4 SLI context.
2041331766Sken * @param buf Destination buffer for the command.
2042331766Sken * @param size Buffer size, in bytes.
2043331766Sken * @param eq_id Queue ID to destroy.
2044331766Sken *
2045331766Sken * @note Other queue creation routines use the last parameter to pass in
2046331766Sken * the associated Q_ID. EQ doesn't have an associated queue so this
2047331766Sken * parameter is ignored.
2048331766Sken *
2049331766Sken * @note This creates a Version 0 message.
2050331766Sken *
2051331766Sken * @return Returns the number of bytes written.
2052331766Sken */
2053331766Skenstatic int32_t
2054331766Skensli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint16_t eq_id)
2055331766Sken{
2056331766Sken	sli4_req_common_destroy_eq_t	*eq = NULL;
2057331766Sken	uint32_t	sli_config_off = 0;
2058331766Sken
2059331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2060331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2061331766Sken				/* Payload length must accommodate both request and response */
2062331766Sken				max(sizeof(sli4_req_common_destroy_eq_t),
2063331766Sken					sizeof(sli4_res_hdr_t)),
2064331766Sken				NULL);
2065331766Sken	}
2066331766Sken	eq = (sli4_req_common_destroy_eq_t *)((uint8_t *)buf + sli_config_off);
2067331766Sken
2068331766Sken	eq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_EQ;
2069331766Sken	eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2070331766Sken	eq->hdr.request_length = sizeof(sli4_req_common_destroy_eq_t) -
2071331766Sken					sizeof(sli4_req_hdr_t);
2072331766Sken
2073331766Sken	eq->eq_id = eq_id;
2074331766Sken
2075331766Sken	return(sli_config_off + sizeof(sli4_req_common_destroy_eq_t));
2076331766Sken}
2077331766Sken
2078331766Sken/**
2079331766Sken * @brief Write a LOWLEVEL_SET_WATCHDOG command.
2080331766Sken *
2081331766Sken * @param sli4 SLI context.
2082331766Sken * @param buf Destination buffer for the command.
2083331766Sken * @param size Buffer size, in bytes.
2084331766Sken * @param timeout watchdog timer timeout in seconds
2085331766Sken *
2086331766Sken * @return void
2087331766Sken */
2088331766Skenvoid
2089331766Skensli4_cmd_lowlevel_set_watchdog(sli4_t *sli4, void *buf, size_t size, uint16_t timeout)
2090331766Sken{
2091331766Sken
2092331766Sken	sli4_req_lowlevel_set_watchdog_t *req = NULL;
2093331766Sken	uint32_t	sli_config_off = 0;
2094331766Sken
2095331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2096331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2097331766Sken				/* Payload length must accommodate both request and response */
2098331766Sken				max(sizeof(sli4_req_lowlevel_set_watchdog_t),
2099331766Sken					sizeof(sli4_res_lowlevel_set_watchdog_t)),
2100331766Sken				NULL);
2101331766Sken	}
2102331766Sken	req = (sli4_req_lowlevel_set_watchdog_t *)((uint8_t *)buf + sli_config_off);
2103331766Sken
2104331766Sken	req->hdr.opcode = SLI4_OPC_LOWLEVEL_SET_WATCHDOG;
2105331766Sken	req->hdr.subsystem = SLI4_SUBSYSTEM_LOWLEVEL;
2106331766Sken	req->hdr.request_length = sizeof(sli4_req_lowlevel_set_watchdog_t) - sizeof(sli4_req_hdr_t);
2107331766Sken	req->watchdog_timeout = timeout;
2108331766Sken
2109331766Sken	return;
2110331766Sken}
2111331766Sken
2112331766Skenstatic int32_t
2113331766Skensli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
2114331766Sken{
2115331766Sken	sli4_req_hdr_t *hdr = NULL;
2116331766Sken	uint32_t	sli_config_off = 0;
2117331766Sken
2118331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2119331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2120331766Sken				sizeof(sli4_req_hdr_t),
2121331766Sken				dma);
2122331766Sken	}
2123331766Sken
2124331766Sken	if (dma == NULL) {
2125331766Sken		return 0;
2126331766Sken	}
2127331766Sken
2128331766Sken	ocs_memset(dma->virt, 0, dma->size);
2129331766Sken
2130331766Sken	hdr = dma->virt;
2131331766Sken
2132331766Sken	hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ATTRIBUTES;
2133331766Sken	hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
2134331766Sken	hdr->request_length = dma->size;
2135331766Sken
2136331766Sken	return(sli_config_off + sizeof(sli4_req_hdr_t));
2137331766Sken}
2138331766Sken
2139331766Sken/**
2140331766Sken * @brief Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command.
2141331766Sken *
2142331766Sken * @param sli4 SLI context.
2143331766Sken * @param buf Destination buffer for the command.
2144331766Sken * @param size Buffer size, in bytes.
2145331766Sken * @param dma DMA structure from which the data will be copied.
2146331766Sken *
2147331766Sken * @note This creates a Version 0 message.
2148331766Sken *
2149331766Sken * @return Returns the number of bytes written.
2150331766Sken */
2151331766Skenstatic int32_t
2152331766Skensli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
2153331766Sken{
2154331766Sken	sli4_req_hdr_t *hdr = NULL;
2155331766Sken	uint32_t	sli_config_off = 0;
2156331766Sken
2157331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2158331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, sizeof(sli4_req_hdr_t), dma);
2159331766Sken	}
2160331766Sken
2161331766Sken	if (dma == NULL) {
2162331766Sken		return 0;
2163331766Sken	}
2164331766Sken
2165331766Sken	ocs_memset(dma->virt, 0, dma->size);
2166331766Sken
2167331766Sken	hdr = dma->virt;
2168331766Sken
2169331766Sken	hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ADDL_ATTRIBUTES;
2170331766Sken	hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
2171331766Sken	hdr->request_length = dma->size;
2172331766Sken
2173331766Sken	return(sli_config_off + sizeof(sli4_req_hdr_t));
2174331766Sken}
2175331766Sken
2176331766Sken/**
2177331766Sken * @brief Write a COMMON_CREATE_MQ_EXT command.
2178331766Sken *
2179331766Sken * @param sli4 SLI context.
2180331766Sken * @param buf Destination buffer for the command.
2181331766Sken * @param size Buffer size, in bytes.
2182331766Sken * @param qmem DMA memory for the queue.
2183331766Sken * @param cq_id Associated CQ_ID.
2184331766Sken * @param ignored This parameter carries the ULP which is only used for WQ and RQs
2185331766Sken *
2186331766Sken * @note This creates a Version 0 message.
2187331766Sken *
2188331766Sken * @return Returns the number of bytes written.
2189331766Sken */
2190331766Skenstatic int32_t
2191331766Skensli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size,
2192331766Sken			     ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored)
2193331766Sken{
2194331766Sken	sli4_req_common_create_mq_ext_t	*mq = NULL;
2195331766Sken	uint32_t	sli_config_off = 0;
2196331766Sken	uint32_t	p;
2197331766Sken	uintptr_t	addr;
2198331766Sken
2199331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2200331766Sken		uint32_t payload_size;
2201331766Sken
2202331766Sken		/* Payload length must accommodate both request and response */
2203331766Sken		payload_size = max(sizeof(sli4_req_common_create_mq_ext_t),
2204331766Sken				sizeof(sli4_res_common_create_queue_t));
2205331766Sken
2206331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
2207331766Sken				NULL);
2208331766Sken	}
2209331766Sken	mq = (sli4_req_common_create_mq_ext_t *)((uint8_t *)buf + sli_config_off);
2210331766Sken
2211331766Sken	mq->hdr.opcode = SLI4_OPC_COMMON_CREATE_MQ_EXT;
2212331766Sken	mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2213331766Sken	mq->hdr.request_length = sizeof(sli4_req_common_create_mq_ext_t) -
2214331766Sken					sizeof(sli4_req_hdr_t);
2215331766Sken	/* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */
2216331766Sken	mq->num_pages = qmem->size / SLI_PAGE_SIZE;
2217331766Sken	switch (mq->num_pages) {
2218331766Sken	case 1:
2219331766Sken		mq->ring_size = SLI4_MQE_SIZE_16;
2220331766Sken		break;
2221331766Sken	case 2:
2222331766Sken		mq->ring_size = SLI4_MQE_SIZE_32;
2223331766Sken		break;
2224331766Sken	case 4:
2225331766Sken		mq->ring_size = SLI4_MQE_SIZE_64;
2226331766Sken		break;
2227331766Sken	case 8:
2228331766Sken		mq->ring_size = SLI4_MQE_SIZE_128;
2229331766Sken		break;
2230331766Sken	default:
2231331766Sken		ocs_log_test(sli4->os, "num_pages %d not valid\n", mq->num_pages);
2232331766Sken		return -1;
2233331766Sken	}
2234331766Sken
2235331766Sken	/* TODO break this down by sli4->config.topology */
2236331766Sken	mq->async_event_bitmap = SLI4_ASYNC_EVT_FC_FCOE;
2237331766Sken
2238331766Sken	if (sli4->config.mq_create_version) {
2239331766Sken		mq->cq_id_v1 = cq_id;
2240331766Sken		mq->hdr.version = 1;
2241331766Sken	}
2242331766Sken	else {
2243331766Sken		mq->cq_id_v0 = cq_id;
2244331766Sken	}
2245331766Sken	mq->val = TRUE;
2246331766Sken
2247331766Sken	for (p = 0, addr = qmem->phys;
2248331766Sken			p < mq->num_pages;
2249331766Sken			p++, addr += SLI_PAGE_SIZE) {
2250331766Sken		mq->page_physical_address[p].low = ocs_addr32_lo(addr);
2251331766Sken		mq->page_physical_address[p].high = ocs_addr32_hi(addr);
2252331766Sken	}
2253331766Sken
2254331766Sken	return(sli_config_off + sizeof(sli4_req_common_create_mq_ext_t));
2255331766Sken}
2256331766Sken
2257331766Sken/**
2258331766Sken * @brief Write a COMMON_DESTROY_MQ command.
2259331766Sken *
2260331766Sken * @param sli4 SLI context.
2261331766Sken * @param buf Destination buffer for the command.
2262331766Sken * @param size Buffer size, in bytes.
2263331766Sken * @param mq_id MQ ID
2264331766Sken *
2265331766Sken * @note This creates a Version 0 message.
2266331766Sken *
2267331766Sken * @return Returns the number of bytes written.
2268331766Sken */
2269331766Skenstatic int32_t
2270331766Skensli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint16_t mq_id)
2271331766Sken{
2272331766Sken	sli4_req_common_destroy_mq_t	*mq = NULL;
2273331766Sken	uint32_t	sli_config_off = 0;
2274331766Sken
2275331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2276331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2277331766Sken				/* Payload length must accommodate both request and response */
2278331766Sken				max(sizeof(sli4_req_common_destroy_mq_t),
2279331766Sken					sizeof(sli4_res_hdr_t)),
2280331766Sken				NULL);
2281331766Sken	}
2282331766Sken	mq = (sli4_req_common_destroy_mq_t *)((uint8_t *)buf + sli_config_off);
2283331766Sken
2284331766Sken	mq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_MQ;
2285331766Sken	mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2286331766Sken	mq->hdr.request_length = sizeof(sli4_req_common_destroy_mq_t) -
2287331766Sken					sizeof(sli4_req_hdr_t);
2288331766Sken
2289331766Sken	mq->mq_id = mq_id;
2290331766Sken
2291331766Sken	return(sli_config_off + sizeof(sli4_req_common_destroy_mq_t));
2292331766Sken}
2293331766Sken
2294331766Sken/**
2295331766Sken * @ingroup sli
2296331766Sken * @brief Write a COMMON_NOP command
2297331766Sken *
2298331766Sken * @param sli4 SLI context.
2299331766Sken * @param buf Destination buffer for the command.
2300331766Sken * @param size Buffer size, in bytes.
2301331766Sken * @param context NOP context value (passed to response, except on FC/FCoE).
2302331766Sken *
2303331766Sken * @return Returns the number of bytes written.
2304331766Sken */
2305331766Skenint32_t
2306331766Skensli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t context)
2307331766Sken{
2308331766Sken	sli4_req_common_nop_t *nop = NULL;
2309331766Sken	uint32_t	sli_config_off = 0;
2310331766Sken
2311331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2312331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2313331766Sken				/* Payload length must accommodate both request and response */
2314331766Sken				max(sizeof(sli4_req_common_nop_t), sizeof(sli4_res_common_nop_t)),
2315331766Sken				NULL);
2316331766Sken	}
2317331766Sken
2318331766Sken	nop = (sli4_req_common_nop_t *)((uint8_t *)buf + sli_config_off);
2319331766Sken
2320331766Sken	nop->hdr.opcode = SLI4_OPC_COMMON_NOP;
2321331766Sken	nop->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2322331766Sken	nop->hdr.request_length = 8;
2323331766Sken
2324331766Sken	ocs_memcpy(&nop->context, &context, sizeof(context));
2325331766Sken
2326331766Sken	return(sli_config_off + sizeof(sli4_req_common_nop_t));
2327331766Sken}
2328331766Sken
2329331766Sken/**
2330331766Sken * @ingroup sli
2331331766Sken * @brief Write a COMMON_GET_RESOURCE_EXTENT_INFO command.
2332331766Sken *
2333331766Sken * @param sli4 SLI context.
2334331766Sken * @param buf Destination buffer for the command.
2335331766Sken * @param size Buffer size, in bytes.
2336331766Sken * @param rtype Resource type (for example, XRI, VFI, VPI, and RPI).
2337331766Sken *
2338331766Sken * @return Returns the number of bytes written.
2339331766Sken */
2340331766Skenint32_t
2341331766Skensli_cmd_common_get_resource_extent_info(sli4_t *sli4, void *buf, size_t size, uint16_t rtype)
2342331766Sken{
2343331766Sken	sli4_req_common_get_resource_extent_info_t *extent = NULL;
2344331766Sken	uint32_t	sli_config_off = 0;
2345331766Sken
2346331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2347331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2348331766Sken				sizeof(sli4_req_common_get_resource_extent_info_t),
2349331766Sken				NULL);
2350331766Sken	}
2351331766Sken
2352331766Sken	extent = (sli4_req_common_get_resource_extent_info_t *)((uint8_t *)buf + sli_config_off);
2353331766Sken
2354331766Sken	extent->hdr.opcode = SLI4_OPC_COMMON_GET_RESOURCE_EXTENT_INFO;
2355331766Sken	extent->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2356331766Sken	extent->hdr.request_length = 4;
2357331766Sken
2358331766Sken	extent->resource_type = rtype;
2359331766Sken
2360331766Sken	return(sli_config_off + sizeof(sli4_req_common_get_resource_extent_info_t));
2361331766Sken}
2362331766Sken
2363331766Sken/**
2364331766Sken * @ingroup sli
2365331766Sken * @brief Write a COMMON_GET_SLI4_PARAMETERS command.
2366331766Sken *
2367331766Sken * @param sli4 SLI context.
2368331766Sken * @param buf Destination buffer for the command.
2369331766Sken * @param size Buffer size, in bytes.
2370331766Sken *
2371331766Sken * @return Returns the number of bytes written.
2372331766Sken */
2373331766Skenint32_t
2374331766Skensli_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size)
2375331766Sken{
2376331766Sken	sli4_req_hdr_t	*hdr = NULL;
2377331766Sken	uint32_t	sli_config_off = 0;
2378331766Sken
2379331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2380331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2381331766Sken				sizeof(sli4_res_common_get_sli4_parameters_t),
2382331766Sken				NULL);
2383331766Sken	}
2384331766Sken
2385331766Sken	hdr = (sli4_req_hdr_t *)((uint8_t *)buf + sli_config_off);
2386331766Sken
2387331766Sken	hdr->opcode = SLI4_OPC_COMMON_GET_SLI4_PARAMETERS;
2388331766Sken	hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
2389331766Sken	hdr->request_length = 0x50;
2390331766Sken
2391331766Sken	return(sli_config_off + sizeof(sli4_req_hdr_t));
2392331766Sken}
2393331766Sken
2394331766Sken/**
2395331766Sken * @brief Write a COMMON_QUERY_FW_CONFIG command to the provided buffer.
2396331766Sken *
2397331766Sken * @param sli4 SLI context pointer.
2398331766Sken * @param buf Virtual pointer to destination buffer.
2399331766Sken * @param size Buffer size in bytes.
2400331766Sken *
2401331766Sken * @return Returns the number of bytes written
2402331766Sken */
2403331766Skenstatic int32_t
2404331766Skensli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size)
2405331766Sken{
2406331766Sken	sli4_req_common_query_fw_config_t   *fw_config;
2407331766Sken	uint32_t	sli_config_off = 0;
2408331766Sken	uint32_t payload_size;
2409331766Sken
2410331766Sken	/* Payload length must accommodate both request and response */
2411331766Sken	payload_size = max(sizeof(sli4_req_common_query_fw_config_t),
2412331766Sken			   sizeof(sli4_res_common_query_fw_config_t));
2413331766Sken
2414331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2415331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2416331766Sken				payload_size,
2417331766Sken				NULL);
2418331766Sken	}
2419331766Sken
2420331766Sken	fw_config = (sli4_req_common_query_fw_config_t*)((uint8_t*)buf + sli_config_off);
2421331766Sken	fw_config->hdr.opcode	      = SLI4_OPC_COMMON_QUERY_FW_CONFIG;
2422331766Sken	fw_config->hdr.subsystem      = SLI4_SUBSYSTEM_COMMON;
2423331766Sken	fw_config->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2424331766Sken	return sli_config_off + sizeof(sli4_req_common_query_fw_config_t);
2425331766Sken}
2426331766Sken
2427331766Sken/**
2428331766Sken * @brief Write a COMMON_GET_PORT_NAME command to the provided buffer.
2429331766Sken *
2430331766Sken * @param sli4 SLI context pointer.
2431331766Sken * @param buf Virtual pointer to destination buffer.
2432331766Sken * @param size Buffer size in bytes.
2433331766Sken *
2434331766Sken * @note Function supports both version 0 and 1 forms of this command via
2435331766Sken * the IF_TYPE.
2436331766Sken *
2437331766Sken * @return Returns the number of bytes written.
2438331766Sken */
2439331766Skenstatic int32_t
2440331766Skensli_cmd_common_get_port_name(sli4_t *sli4, void *buf, size_t size)
2441331766Sken{
2442331766Sken	sli4_req_common_get_port_name_t	*port_name;
2443331766Sken	uint32_t	sli_config_off = 0;
2444331766Sken	uint32_t	payload_size;
2445331766Sken	uint8_t		version = 0;
2446331766Sken	uint8_t		pt = 0;
2447331766Sken
2448331766Sken	/* Select command version according to IF_TYPE */
2449331766Sken	switch (sli4->if_type) {
2450331766Sken	case SLI4_IF_TYPE_BE3_SKH_PF:
2451331766Sken	case SLI4_IF_TYPE_BE3_SKH_VF:
2452331766Sken		version = 0;
2453331766Sken		break;
2454331766Sken	case SLI4_IF_TYPE_LANCER_FC_ETH:
2455331766Sken	case SLI4_IF_TYPE_LANCER_RDMA:
2456331766Sken		version = 1;
2457331766Sken		break;
2458331766Sken	default:
2459331766Sken		ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", sli4->if_type);
2460331766Sken		return 0;
2461331766Sken	}
2462331766Sken
2463331766Sken	/* Payload length must accommodate both request and response */
2464331766Sken	payload_size = max(sizeof(sli4_req_common_get_port_name_t),
2465331766Sken			   sizeof(sli4_res_common_get_port_name_t));
2466331766Sken
2467331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2468331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2469331766Sken				payload_size,
2470331766Sken				NULL);
2471331766Sken
2472331766Sken		pt = 1;
2473331766Sken	}
2474331766Sken
2475331766Sken	port_name = (sli4_req_common_get_port_name_t *)((uint8_t *)buf + sli_config_off);
2476331766Sken
2477331766Sken	port_name->hdr.opcode		= SLI4_OPC_COMMON_GET_PORT_NAME;
2478331766Sken	port_name->hdr.subsystem	= SLI4_SUBSYSTEM_COMMON;
2479331766Sken	port_name->hdr.request_length	= sizeof(sli4_req_hdr_t) + (version * sizeof(uint32_t));
2480331766Sken	port_name->hdr.version		= version;
2481331766Sken
2482331766Sken	/* Set the port type value (ethernet=0, FC=1) for V1 commands */
2483331766Sken	if (version == 1) {
2484331766Sken		port_name->pt = pt;
2485331766Sken	}
2486331766Sken
2487331766Sken	return sli_config_off + port_name->hdr.request_length;
2488331766Sken}
2489331766Sken
2490331766Sken
2491331766Sken/**
2492331766Sken * @ingroup sli
2493331766Sken * @brief Write a COMMON_WRITE_OBJECT command.
2494331766Sken *
2495331766Sken * @param sli4 SLI context.
2496331766Sken * @param buf Destination buffer for the command.
2497331766Sken * @param size Buffer size, in bytes.
2498331766Sken * @param noc True if the object should be written but not committed to flash.
2499331766Sken * @param eof True if this is the last write for this object.
2500331766Sken * @param desired_write_length Number of bytes of data to write to the object.
2501331766Sken * @param offset Offset, in bytes, from the start of the object.
2502331766Sken * @param object_name Name of the object to write.
2503331766Sken * @param dma DMA structure from which the data will be copied.
2504331766Sken *
2505331766Sken * @return Returns the number of bytes written.
2506331766Sken */
2507331766Skenint32_t
2508331766Skensli_cmd_common_write_object(sli4_t *sli4, void *buf, size_t size,
2509331766Sken		uint16_t noc, uint16_t eof, uint32_t desired_write_length,
2510331766Sken		uint32_t offset,
2511331766Sken		char *object_name,
2512331766Sken		ocs_dma_t *dma)
2513331766Sken{
2514331766Sken	sli4_req_common_write_object_t *wr_obj = NULL;
2515331766Sken	uint32_t	sli_config_off = 0;
2516331766Sken	sli4_bde_t *host_buffer;
2517331766Sken
2518331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2519331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2520331766Sken				sizeof (sli4_req_common_write_object_t) + sizeof (sli4_bde_t),
2521331766Sken				NULL);
2522331766Sken	}
2523331766Sken
2524331766Sken	wr_obj = (sli4_req_common_write_object_t *)((uint8_t *)buf + sli_config_off);
2525331766Sken
2526331766Sken	wr_obj->hdr.opcode = SLI4_OPC_COMMON_WRITE_OBJECT;
2527331766Sken	wr_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2528331766Sken	wr_obj->hdr.request_length = sizeof(*wr_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
2529331766Sken	wr_obj->hdr.timeout = 0;
2530331766Sken	wr_obj->hdr.version = 0;
2531331766Sken
2532331766Sken	wr_obj->noc = noc;
2533331766Sken	wr_obj->eof = eof;
2534331766Sken	wr_obj->desired_write_length = desired_write_length;
2535331766Sken	wr_obj->write_offset = offset;
2536331766Sken	ocs_strncpy(wr_obj->object_name, object_name, sizeof(wr_obj->object_name));
2537331766Sken	wr_obj->host_buffer_descriptor_count = 1;
2538331766Sken
2539331766Sken	host_buffer = (sli4_bde_t *)wr_obj->host_buffer_descriptor;
2540331766Sken
2541331766Sken	/* Setup to transfer xfer_size bytes to device */
2542331766Sken	host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
2543331766Sken	host_buffer->buffer_length = desired_write_length;
2544331766Sken	host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
2545331766Sken	host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
2546331766Sken
2547331766Sken
2548331766Sken	return(sli_config_off + sizeof(sli4_req_common_write_object_t) + sizeof (sli4_bde_t));
2549331766Sken}
2550331766Sken
2551331766Sken
2552331766Sken/**
2553331766Sken * @ingroup sli
2554331766Sken * @brief Write a COMMON_DELETE_OBJECT command.
2555331766Sken *
2556331766Sken * @param sli4 SLI context.
2557331766Sken * @param buf Destination buffer for the command.
2558331766Sken * @param size Buffer size, in bytes.
2559331766Sken * @param object_name Name of the object to write.
2560331766Sken *
2561331766Sken * @return Returns the number of bytes written.
2562331766Sken */
2563331766Skenint32_t
2564331766Skensli_cmd_common_delete_object(sli4_t *sli4, void *buf, size_t size,
2565331766Sken		char *object_name)
2566331766Sken{
2567331766Sken	sli4_req_common_delete_object_t *del_obj = NULL;
2568331766Sken	uint32_t	sli_config_off = 0;
2569331766Sken
2570331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2571331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2572331766Sken				sizeof (sli4_req_common_delete_object_t),
2573331766Sken				NULL);
2574331766Sken	}
2575331766Sken
2576331766Sken	del_obj = (sli4_req_common_delete_object_t *)((uint8_t *)buf + sli_config_off);
2577331766Sken
2578331766Sken	del_obj->hdr.opcode = SLI4_OPC_COMMON_DELETE_OBJECT;
2579331766Sken	del_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2580331766Sken	del_obj->hdr.request_length = sizeof(*del_obj);
2581331766Sken	del_obj->hdr.timeout = 0;
2582331766Sken	del_obj->hdr.version = 0;
2583331766Sken
2584331766Sken	ocs_strncpy(del_obj->object_name, object_name, sizeof(del_obj->object_name));
2585331766Sken	return(sli_config_off + sizeof(sli4_req_common_delete_object_t));
2586331766Sken}
2587331766Sken
2588331766Sken/**
2589331766Sken * @ingroup sli
2590331766Sken * @brief Write a COMMON_READ_OBJECT command.
2591331766Sken *
2592331766Sken * @param sli4 SLI context.
2593331766Sken * @param buf Destination buffer for the command.
2594331766Sken * @param size Buffer size, in bytes.
2595331766Sken * @param desired_read_length Number of bytes of data to read from the object.
2596331766Sken * @param offset Offset, in bytes, from the start of the object.
2597331766Sken * @param object_name Name of the object to read.
2598331766Sken * @param dma DMA structure from which the data will be copied.
2599331766Sken *
2600331766Sken * @return Returns the number of bytes written.
2601331766Sken */
2602331766Skenint32_t
2603331766Skensli_cmd_common_read_object(sli4_t *sli4, void *buf, size_t size,
2604331766Sken		uint32_t desired_read_length,
2605331766Sken		uint32_t offset,
2606331766Sken		char *object_name,
2607331766Sken		ocs_dma_t *dma)
2608331766Sken{
2609331766Sken	sli4_req_common_read_object_t *rd_obj = NULL;
2610331766Sken	uint32_t	sli_config_off = 0;
2611331766Sken	sli4_bde_t *host_buffer;
2612331766Sken
2613331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2614331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2615331766Sken				sizeof (sli4_req_common_read_object_t) + sizeof (sli4_bde_t),
2616331766Sken				NULL);
2617331766Sken	}
2618331766Sken
2619331766Sken	rd_obj = (sli4_req_common_read_object_t *)((uint8_t *)buf + sli_config_off);
2620331766Sken
2621331766Sken	rd_obj->hdr.opcode = SLI4_OPC_COMMON_READ_OBJECT;
2622331766Sken	rd_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2623331766Sken	rd_obj->hdr.request_length = sizeof(*rd_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
2624331766Sken	rd_obj->hdr.timeout = 0;
2625331766Sken	rd_obj->hdr.version = 0;
2626331766Sken
2627331766Sken	rd_obj->desired_read_length = desired_read_length;
2628331766Sken	rd_obj->read_offset = offset;
2629331766Sken	ocs_strncpy(rd_obj->object_name, object_name, sizeof(rd_obj->object_name));
2630331766Sken	rd_obj->host_buffer_descriptor_count = 1;
2631331766Sken
2632331766Sken	host_buffer = (sli4_bde_t *)rd_obj->host_buffer_descriptor;
2633331766Sken
2634331766Sken	/* Setup to transfer xfer_size bytes to device */
2635331766Sken	host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
2636331766Sken	host_buffer->buffer_length = desired_read_length;
2637331766Sken	if (dma != NULL) {
2638331766Sken		host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
2639331766Sken		host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
2640331766Sken	} else {
2641331766Sken		host_buffer->u.data.buffer_address_low = 0;
2642331766Sken		host_buffer->u.data.buffer_address_high = 0;
2643331766Sken	}
2644331766Sken
2645331766Sken
2646331766Sken	return(sli_config_off + sizeof(sli4_req_common_read_object_t) + sizeof (sli4_bde_t));
2647331766Sken}
2648331766Sken
2649331766Sken/**
2650331766Sken * @ingroup sli
2651331766Sken * @brief Write a DMTF_EXEC_CLP_CMD command.
2652331766Sken *
2653331766Sken * @param sli4 SLI context.
2654331766Sken * @param buf Destination buffer for the command.
2655331766Sken * @param size Buffer size, in bytes.
2656331766Sken * @param cmd DMA structure that describes the buffer for the command.
2657331766Sken * @param resp DMA structure that describes the buffer for the response.
2658331766Sken *
2659331766Sken * @return Returns the number of bytes written.
2660331766Sken */
2661331766Skenint32_t
2662331766Skensli_cmd_dmtf_exec_clp_cmd(sli4_t *sli4, void *buf, size_t size,
2663331766Sken		ocs_dma_t *cmd,
2664331766Sken		ocs_dma_t *resp)
2665331766Sken{
2666331766Sken	sli4_req_dmtf_exec_clp_cmd_t *clp_cmd = NULL;
2667331766Sken	uint32_t	sli_config_off = 0;
2668331766Sken
2669331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2670331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2671331766Sken				sizeof (sli4_req_dmtf_exec_clp_cmd_t),
2672331766Sken				NULL);
2673331766Sken	}
2674331766Sken
2675331766Sken	clp_cmd = (sli4_req_dmtf_exec_clp_cmd_t*)((uint8_t *)buf + sli_config_off);
2676331766Sken
2677331766Sken	clp_cmd->hdr.opcode = SLI4_OPC_DMTF_EXEC_CLP_CMD;
2678331766Sken	clp_cmd->hdr.subsystem = SLI4_SUBSYSTEM_DMTF;
2679331766Sken	clp_cmd->hdr.request_length = sizeof(sli4_req_dmtf_exec_clp_cmd_t) -
2680331766Sken					sizeof(sli4_req_hdr_t);
2681331766Sken	clp_cmd->hdr.timeout = 0;
2682331766Sken	clp_cmd->hdr.version = 0;
2683331766Sken	clp_cmd->cmd_buf_length = cmd->size;
2684331766Sken	clp_cmd->cmd_buf_addr_low = ocs_addr32_lo(cmd->phys);
2685331766Sken	clp_cmd->cmd_buf_addr_high = ocs_addr32_hi(cmd->phys);
2686331766Sken	clp_cmd->resp_buf_length = resp->size;
2687331766Sken	clp_cmd->resp_buf_addr_low = ocs_addr32_lo(resp->phys);
2688331766Sken	clp_cmd->resp_buf_addr_high = ocs_addr32_hi(resp->phys);
2689331766Sken
2690331766Sken	return(sli_config_off + sizeof(sli4_req_dmtf_exec_clp_cmd_t));
2691331766Sken}
2692331766Sken
2693331766Sken/**
2694331766Sken * @ingroup sli
2695331766Sken * @brief Write a COMMON_SET_DUMP_LOCATION command.
2696331766Sken *
2697331766Sken * @param sli4 SLI context.
2698331766Sken * @param buf Destination buffer for the command.
2699331766Sken * @param size Buffer size, in bytes.
2700331766Sken * @param query Zero to set dump location, non-zero to query dump size
2701331766Sken * @param is_buffer_list Set to one if the buffer is a set of buffer descriptors or
2702331766Sken *                       set to 0 if the buffer is a contiguous dump area.
2703331766Sken * @param buffer DMA structure to which the dump will be copied.
2704331766Sken *
2705331766Sken * @return Returns the number of bytes written.
2706331766Sken */
2707331766Skenint32_t
2708331766Skensli_cmd_common_set_dump_location(sli4_t *sli4, void *buf, size_t size,
2709331766Sken				 uint8_t query, uint8_t is_buffer_list,
2710331766Sken				 ocs_dma_t *buffer, uint8_t fdb)
2711331766Sken{
2712331766Sken	sli4_req_common_set_dump_location_t *set_dump_loc = NULL;
2713331766Sken	uint32_t	sli_config_off = 0;
2714331766Sken
2715331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2716331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2717331766Sken				sizeof (sli4_req_common_set_dump_location_t),
2718331766Sken				NULL);
2719331766Sken	}
2720331766Sken
2721331766Sken	set_dump_loc = (sli4_req_common_set_dump_location_t *)((uint8_t *)buf + sli_config_off);
2722331766Sken
2723331766Sken	set_dump_loc->hdr.opcode = SLI4_OPC_COMMON_SET_DUMP_LOCATION;
2724331766Sken	set_dump_loc->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2725331766Sken	set_dump_loc->hdr.request_length = sizeof(sli4_req_common_set_dump_location_t) - sizeof(sli4_req_hdr_t);
2726331766Sken	set_dump_loc->hdr.timeout = 0;
2727331766Sken	set_dump_loc->hdr.version = 0;
2728331766Sken
2729331766Sken	set_dump_loc->blp = is_buffer_list;
2730331766Sken	set_dump_loc->qry = query;
2731331766Sken	set_dump_loc->fdb = fdb;
2732331766Sken
2733331766Sken	if (buffer) {
2734331766Sken		set_dump_loc->buf_addr_low = ocs_addr32_lo(buffer->phys);
2735331766Sken		set_dump_loc->buf_addr_high = ocs_addr32_hi(buffer->phys);
2736331766Sken		set_dump_loc->buffer_length = buffer->len;
2737331766Sken	} else {
2738331766Sken		set_dump_loc->buf_addr_low = 0;
2739331766Sken		set_dump_loc->buf_addr_high = 0;
2740331766Sken		set_dump_loc->buffer_length = 0;
2741331766Sken	}
2742331766Sken
2743331766Sken	return(sli_config_off + sizeof(sli4_req_common_set_dump_location_t));
2744331766Sken}
2745331766Sken
2746331766Sken
2747331766Sken/**
2748331766Sken * @ingroup sli
2749331766Sken * @brief Write a COMMON_SET_FEATURES command.
2750331766Sken *
2751331766Sken * @param sli4 SLI context.
2752331766Sken * @param buf Destination buffer for the command.
2753331766Sken * @param size Buffer size, in bytes.
2754331766Sken * @param feature Feature to set.
2755331766Sken * @param param_len Length of the parameter (must be a multiple of 4 bytes).
2756331766Sken * @param parameter Pointer to the parameter value.
2757331766Sken *
2758331766Sken * @return Returns the number of bytes written.
2759331766Sken */
2760331766Skenint32_t
2761331766Skensli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size,
2762331766Sken			    uint32_t feature,
2763331766Sken			    uint32_t param_len,
2764331766Sken			    void* parameter)
2765331766Sken{
2766331766Sken	sli4_req_common_set_features_t *cmd = NULL;
2767331766Sken	uint32_t	sli_config_off = 0;
2768331766Sken
2769331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2770331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2771331766Sken				sizeof (sli4_req_common_set_features_t),
2772331766Sken				NULL);
2773331766Sken	}
2774331766Sken
2775331766Sken	cmd = (sli4_req_common_set_features_t *)((uint8_t *)buf + sli_config_off);
2776331766Sken
2777331766Sken	cmd->hdr.opcode = SLI4_OPC_COMMON_SET_FEATURES;
2778331766Sken	cmd->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2779331766Sken	cmd->hdr.request_length = sizeof(sli4_req_common_set_features_t) - sizeof(sli4_req_hdr_t);
2780331766Sken	cmd->hdr.timeout = 0;
2781331766Sken	cmd->hdr.version = 0;
2782331766Sken
2783331766Sken	cmd->feature = feature;
2784331766Sken	cmd->param_len = param_len;
2785331766Sken	ocs_memcpy(cmd->params, parameter, param_len);
2786331766Sken
2787331766Sken	return(sli_config_off + sizeof(sli4_req_common_set_features_t));
2788331766Sken}
2789331766Sken
2790331766Sken/**
2791331766Sken * @ingroup sli
2792331766Sken * @brief Write a COMMON_COMMON_GET_PROFILE_CONFIG command.
2793331766Sken *
2794331766Sken * @param sli4 SLI context.
2795331766Sken * @param buf Destination buffer for the command.
2796331766Sken * @param size Buffer size in bytes.
2797331766Sken * @param dma DMA capable memory used to retrieve profile.
2798331766Sken *
2799331766Sken * @return Returns the number of bytes written.
2800331766Sken */
2801331766Skenint32_t
2802331766Skensli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
2803331766Sken{
2804331766Sken        sli4_req_common_get_profile_config_t *req = NULL;
2805331766Sken	uint32_t	sli_config_off = 0;
2806331766Sken	uint32_t	payload_size;
2807331766Sken
2808331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2809331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size,
2810331766Sken				sizeof (sli4_req_common_get_profile_config_t),
2811331766Sken				dma);
2812331766Sken	}
2813331766Sken
2814331766Sken	if (dma != NULL) {
2815331766Sken		req = dma->virt;
2816331766Sken		ocs_memset(req, 0, dma->size);
2817331766Sken		payload_size = dma->size;
2818331766Sken	} else {
2819331766Sken		req = (sli4_req_common_get_profile_config_t *)((uint8_t *)buf + sli_config_off);
2820331766Sken		payload_size = sizeof(sli4_req_common_get_profile_config_t);
2821331766Sken	}
2822331766Sken
2823331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_CONFIG;
2824331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2825331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2826331766Sken        req->hdr.version = 1;
2827331766Sken
2828331766Sken        return(sli_config_off + sizeof(sli4_req_common_get_profile_config_t));
2829331766Sken}
2830331766Sken
2831331766Sken/**
2832331766Sken * @ingroup sli
2833331766Sken * @brief Write a COMMON_COMMON_SET_PROFILE_CONFIG command.
2834331766Sken *
2835331766Sken * @param sli4 SLI context.
2836331766Sken * @param buf Destination buffer for the command.
2837331766Sken * @param size Buffer size, in bytes.
2838331766Sken * @param dma DMA capable memory containing profile.
2839331766Sken * @param profile_id Profile ID to configure.
2840331766Sken * @param descriptor_count Number of descriptors in DMA buffer.
2841331766Sken * @param isap Implicit Set Active Profile value to use.
2842331766Sken *
2843331766Sken * @return Returns the number of bytes written.
2844331766Sken */
2845331766Skenint32_t
2846331766Skensli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
2847331766Sken		uint8_t profile_id, uint32_t descriptor_count, uint8_t isap)
2848331766Sken{
2849331766Sken        sli4_req_common_set_profile_config_t *req = NULL;
2850331766Sken        uint32_t cmd_off = 0;
2851331766Sken        uint32_t payload_size;
2852331766Sken
2853331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2854331766Sken		cmd_off = sli_cmd_sli_config(sli4, buf, size,
2855331766Sken						    sizeof (sli4_req_common_set_profile_config_t),
2856331766Sken						    dma);
2857331766Sken	}
2858331766Sken
2859331766Sken	if (dma != NULL) {
2860331766Sken		req = dma->virt;
2861331766Sken		ocs_memset(req, 0, dma->size);
2862331766Sken		payload_size = dma->size;
2863331766Sken	} else {
2864331766Sken		req = (sli4_req_common_set_profile_config_t *)((uint8_t *)buf + cmd_off);
2865331766Sken		payload_size = sizeof(sli4_req_common_set_profile_config_t);
2866331766Sken	}
2867331766Sken
2868331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_SET_PROFILE_CONFIG;
2869331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2870331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2871331766Sken        req->hdr.version = 1;
2872331766Sken        req->profile_id = profile_id;
2873331766Sken        req->desc_count = descriptor_count;
2874331766Sken        req->isap = isap;
2875331766Sken
2876331766Sken        return(cmd_off + sizeof(sli4_req_common_set_profile_config_t));
2877331766Sken}
2878331766Sken
2879331766Sken/**
2880331766Sken * @ingroup sli
2881331766Sken * @brief Write a COMMON_COMMON_GET_PROFILE_LIST command.
2882331766Sken *
2883331766Sken * @param sli4 SLI context.
2884331766Sken * @param buf Destination buffer for the command.
2885331766Sken * @param size Buffer size in bytes.
2886331766Sken * @param start_profile_index First profile index to return.
2887331766Sken * @param dma Buffer into which the list will be written.
2888331766Sken *
2889331766Sken * @return Returns the number of bytes written.
2890331766Sken */
2891331766Skenint32_t
2892331766Skensli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size,
2893331766Sken                                   uint32_t start_profile_index, ocs_dma_t *dma)
2894331766Sken{
2895331766Sken        sli4_req_common_get_profile_list_t *req = NULL;
2896331766Sken        uint32_t cmd_off = 0;
2897331766Sken        uint32_t payload_size;
2898331766Sken
2899331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2900331766Sken		cmd_off = sli_cmd_sli_config(sli4, buf, size,
2901331766Sken					     sizeof (sli4_req_common_get_profile_list_t),
2902331766Sken					     dma);
2903331766Sken	}
2904331766Sken
2905331766Sken	if (dma != NULL) {
2906331766Sken		req = dma->virt;
2907331766Sken		ocs_memset(req, 0, dma->size);
2908331766Sken		payload_size = dma->size;
2909331766Sken	} else {
2910331766Sken		req = (sli4_req_common_get_profile_list_t *)((uint8_t *)buf + cmd_off);
2911331766Sken		payload_size = sizeof(sli4_req_common_get_profile_list_t);
2912331766Sken	}
2913331766Sken
2914331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_LIST;
2915331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2916331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2917331766Sken        req->hdr.version = 0;
2918331766Sken
2919331766Sken        req->start_profile_index = start_profile_index;
2920331766Sken
2921331766Sken        return(cmd_off + sizeof(sli4_req_common_get_profile_list_t));
2922331766Sken}
2923331766Sken
2924331766Sken/**
2925331766Sken * @ingroup sli
2926331766Sken * @brief Write a COMMON_COMMON_GET_ACTIVE_PROFILE command.
2927331766Sken *
2928331766Sken * @param sli4 SLI context.
2929331766Sken * @param buf Destination buffer for the command.
2930331766Sken * @param size Buffer size in bytes.
2931331766Sken *
2932331766Sken * @return Returns the number of bytes written.
2933331766Sken */
2934331766Skenint32_t
2935331766Skensli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size)
2936331766Sken{
2937331766Sken        sli4_req_common_get_active_profile_t *req = NULL;
2938331766Sken        uint32_t cmd_off = 0;
2939331766Sken        uint32_t payload_size;
2940331766Sken
2941331766Sken        /* Payload length must accommodate both request and response */
2942331766Sken        payload_size = max(sizeof(sli4_req_common_get_active_profile_t),
2943331766Sken                           sizeof(sli4_res_common_get_active_profile_t));
2944331766Sken
2945331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2946331766Sken		cmd_off = sli_cmd_sli_config(sli4, buf, size,
2947331766Sken				payload_size,
2948331766Sken				NULL);
2949331766Sken	}
2950331766Sken
2951331766Sken        req = (sli4_req_common_get_active_profile_t *)
2952331766Sken                ((uint8_t*)buf + cmd_off);
2953331766Sken
2954331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_GET_ACTIVE_PROFILE;
2955331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2956331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2957331766Sken        req->hdr.version = 0;
2958331766Sken
2959331766Sken        return(cmd_off + sizeof(sli4_req_common_get_active_profile_t));
2960331766Sken}
2961331766Sken
2962331766Sken/**
2963331766Sken * @ingroup sli
2964331766Sken * @brief Write a COMMON_COMMON_SET_ACTIVE_PROFILE command.
2965331766Sken *
2966331766Sken * @param sli4 SLI context.
2967331766Sken * @param buf Destination buffer for the command.
2968331766Sken * @param size Buffer size in bytes.
2969331766Sken * @param fd If non-zero, set profile to factory default.
2970331766Sken * @param active_profile_id ID of new active profile.
2971331766Sken *
2972331766Sken * @return Returns the number of bytes written.
2973331766Sken */
2974331766Skenint32_t
2975331766Skensli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size,
2976331766Sken                                  uint32_t fd, uint32_t active_profile_id)
2977331766Sken{
2978331766Sken        sli4_req_common_set_active_profile_t *req = NULL;
2979331766Sken        uint32_t cmd_off = 0;
2980331766Sken        uint32_t payload_size;
2981331766Sken
2982331766Sken        /* Payload length must accommodate both request and response */
2983331766Sken        payload_size = max(sizeof(sli4_req_common_set_active_profile_t),
2984331766Sken                           sizeof(sli4_res_common_set_active_profile_t));
2985331766Sken
2986331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
2987331766Sken		cmd_off = sli_cmd_sli_config(sli4, buf, size,
2988331766Sken				payload_size,
2989331766Sken				NULL);
2990331766Sken	}
2991331766Sken
2992331766Sken        req = (sli4_req_common_set_active_profile_t *)
2993331766Sken                ((uint8_t*)buf + cmd_off);
2994331766Sken
2995331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_SET_ACTIVE_PROFILE;
2996331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
2997331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
2998331766Sken        req->hdr.version = 0;
2999331766Sken        req->fd = fd;
3000331766Sken        req->active_profile_id = active_profile_id;
3001331766Sken
3002331766Sken        return(cmd_off + sizeof(sli4_req_common_set_active_profile_t));
3003331766Sken}
3004331766Sken
3005331766Sken/**
3006331766Sken * @ingroup sli
3007331766Sken * @brief Write a COMMON_GET_RECONFIG_LINK_INFO command.
3008331766Sken *
3009331766Sken * @param sli4 SLI context.
3010331766Sken * @param buf Destination buffer for the command.
3011331766Sken * @param size Buffer size in bytes.
3012331766Sken * @param dma Buffer to store the supported link configuration modes from the physical device.
3013331766Sken *
3014331766Sken * @return Returns the number of bytes written.
3015331766Sken */
3016331766Skenint32_t
3017331766Skensli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
3018331766Sken{
3019331766Sken        sli4_req_common_get_reconfig_link_info_t *req = NULL;
3020331766Sken        uint32_t cmd_off = 0;
3021331766Sken        uint32_t payload_size;
3022331766Sken
3023331766Sken        /* Payload length must accommodate both request and response */
3024331766Sken        payload_size = max(sizeof(sli4_req_common_get_reconfig_link_info_t),
3025331766Sken                           sizeof(sli4_res_common_get_reconfig_link_info_t));
3026331766Sken
3027331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3028331766Sken		cmd_off = sli_cmd_sli_config(sli4, buf, size,
3029331766Sken				payload_size,
3030331766Sken				dma);
3031331766Sken	}
3032331766Sken
3033331766Sken	if (dma != NULL) {
3034331766Sken		req = dma->virt;
3035331766Sken		ocs_memset(req, 0, dma->size);
3036331766Sken		payload_size = dma->size;
3037331766Sken	} else {
3038331766Sken		req = (sli4_req_common_get_reconfig_link_info_t *)((uint8_t *)buf + cmd_off);
3039331766Sken		payload_size = sizeof(sli4_req_common_get_reconfig_link_info_t);
3040331766Sken	}
3041331766Sken
3042331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_GET_RECONFIG_LINK_INFO;
3043331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
3044331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
3045331766Sken        req->hdr.version = 0;
3046331766Sken
3047331766Sken        return(cmd_off + sizeof(sli4_req_common_get_reconfig_link_info_t));
3048331766Sken}
3049331766Sken
3050331766Sken/**
3051331766Sken * @ingroup sli
3052331766Sken * @brief Write a COMMON_SET_RECONFIG_LINK_ID command.
3053331766Sken *
3054331766Sken * @param sli4 SLI context.
3055331766Sken * @param buf destination buffer for the command.
3056331766Sken * @param size buffer size in bytes.
3057331766Sken * @param fd If non-zero, set link config to factory default.
3058331766Sken * @param active_link_config_id ID of new active profile.
3059331766Sken * @param dma Buffer to assign the link configuration mode that is to become active from the physical device.
3060331766Sken *
3061331766Sken * @return Returns the number of bytes written.
3062331766Sken */
3063331766Skenint32_t
3064331766Skensli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
3065331766Sken                                  uint32_t fd, uint32_t active_link_config_id)
3066331766Sken{
3067331766Sken        sli4_req_common_set_reconfig_link_id_t *req = NULL;
3068331766Sken        uint32_t cmd_off = 0;
3069331766Sken        uint32_t payload_size;
3070331766Sken
3071331766Sken        /* Payload length must accommodate both request and response */
3072331766Sken        payload_size = max(sizeof(sli4_req_common_set_reconfig_link_id_t),
3073331766Sken                           sizeof(sli4_res_common_set_reconfig_link_id_t));
3074331766Sken
3075331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3076331766Sken		cmd_off = sli_cmd_sli_config(sli4, buf, size,
3077331766Sken				payload_size,
3078331766Sken				NULL);
3079331766Sken	}
3080331766Sken
3081331766Sken		if (dma != NULL) {
3082331766Sken		req = dma->virt;
3083331766Sken		ocs_memset(req, 0, dma->size);
3084331766Sken		payload_size = dma->size;
3085331766Sken	} else {
3086331766Sken		req = (sli4_req_common_set_reconfig_link_id_t *)((uint8_t *)buf + cmd_off);
3087331766Sken		payload_size = sizeof(sli4_req_common_set_reconfig_link_id_t);
3088331766Sken	}
3089331766Sken
3090331766Sken        req->hdr.opcode = SLI4_OPC_COMMON_SET_RECONFIG_LINK_ID;
3091331766Sken        req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
3092331766Sken        req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
3093331766Sken        req->hdr.version = 0;
3094331766Sken        req->fd = fd;
3095331766Sken        req->next_link_config_id = active_link_config_id;
3096331766Sken
3097331766Sken        return(cmd_off + sizeof(sli4_req_common_set_reconfig_link_id_t));
3098331766Sken}
3099331766Sken
3100331766Sken
3101331766Sken/**
3102331766Sken * @ingroup sli
3103331766Sken * @brief Check the mailbox/queue completion entry.
3104331766Sken *
3105331766Sken * @param buf Pointer to the MCQE.
3106331766Sken *
3107331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3108331766Sken */
3109331766Skenint32_t
3110331766Skensli_cqe_mq(void *buf)
3111331766Sken{
3112331766Sken	sli4_mcqe_t	*mcqe = buf;
3113331766Sken
3114331766Sken	/*
3115331766Sken	 * Firmware can split mbx completions into two MCQEs: first with only
3116331766Sken	 * the "consumed" bit set and a second with the "complete" bit set.
3117331766Sken	 * Thus, ignore MCQE unless "complete" is set.
3118331766Sken	 */
3119331766Sken	if (!mcqe->cmp) {
3120331766Sken		return -2;
3121331766Sken	}
3122331766Sken
3123331766Sken	if (mcqe->completion_status) {
3124331766Sken		ocs_log_debug(NULL, "bad status (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
3125331766Sken				mcqe->completion_status,
3126331766Sken				mcqe->extended_status,
3127331766Sken				mcqe->con,
3128331766Sken				mcqe->cmp,
3129331766Sken				mcqe->ae,
3130331766Sken				mcqe->val);
3131331766Sken	}
3132331766Sken
3133331766Sken	return mcqe->completion_status;
3134331766Sken}
3135331766Sken
3136331766Sken/**
3137331766Sken * @ingroup sli
3138331766Sken * @brief Check the asynchronous event completion entry.
3139331766Sken *
3140331766Sken * @param sli4 SLI context.
3141331766Sken * @param buf Pointer to the ACQE.
3142331766Sken *
3143331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3144331766Sken */
3145331766Skenint32_t
3146331766Skensli_cqe_async(sli4_t *sli4, void *buf)
3147331766Sken{
3148331766Sken	sli4_acqe_t	*acqe = buf;
3149331766Sken	int32_t		rc = -1;
3150331766Sken
3151331766Sken	if (!sli4 || !buf) {
3152331766Sken		ocs_log_err(NULL, "bad parameter sli4=%p buf=%p\n", sli4, buf);
3153331766Sken		return -1;
3154331766Sken	}
3155331766Sken
3156331766Sken	switch (acqe->event_code) {
3157331766Sken	case SLI4_ACQE_EVENT_CODE_LINK_STATE:
3158331766Sken		rc = sli_fc_process_link_state(sli4, buf);
3159331766Sken		break;
3160331766Sken	case SLI4_ACQE_EVENT_CODE_FCOE_FIP:
3161331766Sken		rc = sli_fc_process_fcoe(sli4, buf);
3162331766Sken		break;
3163331766Sken	case SLI4_ACQE_EVENT_CODE_GRP_5:
3164331766Sken		/*TODO*/ocs_log_debug(sli4->os, "ACQE GRP5\n");
3165331766Sken		break;
3166331766Sken	case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT:
3167331766Sken        ocs_log_debug(sli4->os,"ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n",
3168331766Sken		acqe->event_type, acqe->event_data[0], acqe->event_data[1]);
3169331766Sken#if defined(OCS_INCLUDE_DEBUG)
3170331766Sken		ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "acq", acqe, sizeof(*acqe));
3171331766Sken#endif
3172331766Sken		break;
3173331766Sken	case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT:
3174331766Sken		rc = sli_fc_process_link_attention(sli4, buf);
3175331766Sken		break;
3176331766Sken	default:
3177331766Sken		/*TODO*/ocs_log_test(sli4->os, "ACQE unknown=%#x\n", acqe->event_code);
3178331766Sken	}
3179331766Sken
3180331766Sken	return rc;
3181331766Sken}
3182331766Sken
3183331766Sken/**
3184331766Sken * @brief Check the SLI_CONFIG response.
3185331766Sken *
3186331766Sken * @par Description
3187331766Sken * Function checks the SLI_CONFIG response and the payload status.
3188331766Sken *
3189331766Sken * @param buf Pointer to SLI_CONFIG response.
3190331766Sken *
3191331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3192331766Sken */
3193331766Skenstatic int32_t
3194331766Skensli_res_sli_config(void *buf)
3195331766Sken{
3196331766Sken	sli4_cmd_sli_config_t	*sli_config = buf;
3197331766Sken
3198331766Sken	if (!buf || (SLI4_MBOX_COMMAND_SLI_CONFIG != sli_config->hdr.command)) {
3199331766Sken		ocs_log_err(NULL, "bad parameter buf=%p cmd=%#x\n", buf,
3200331766Sken				buf ? sli_config->hdr.command : -1);
3201331766Sken		return -1;
3202331766Sken	}
3203331766Sken
3204331766Sken	if (sli_config->hdr.status) {
3205331766Sken		return sli_config->hdr.status;
3206331766Sken	}
3207331766Sken
3208331766Sken	if (sli_config->emb) {
3209331766Sken		return sli_config->payload.embed[4];
3210331766Sken	} else {
3211331766Sken		ocs_log_test(NULL, "external buffers not supported\n");
3212331766Sken		return -1;
3213331766Sken	}
3214331766Sken}
3215331766Sken
3216331766Sken/**
3217331766Sken * @brief Issue a COMMON_FUNCTION_RESET command.
3218331766Sken *
3219331766Sken * @param sli4 SLI context.
3220331766Sken *
3221331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3222331766Sken */
3223331766Skenstatic int32_t
3224331766Skensli_common_function_reset(sli4_t *sli4)
3225331766Sken{
3226331766Sken
3227331766Sken	if (sli_cmd_common_function_reset(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3228331766Sken		if (sli_bmbx_command(sli4)) {
3229331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COM_FUNC_RESET)\n");
3230331766Sken			return -1;
3231331766Sken		}
3232331766Sken		if (sli_res_sli_config(sli4->bmbx.virt)) {
3233331766Sken			ocs_log_err(sli4->os, "bad status COM_FUNC_RESET\n");
3234331766Sken			return -1;
3235331766Sken		}
3236331766Sken	} else {
3237331766Sken		ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
3238331766Sken		return -1;
3239331766Sken	}
3240331766Sken
3241331766Sken	return 0;
3242331766Sken}
3243331766Sken
3244331766Sken
3245331766Sken/**
3246331766Sken * @brief check to see if the FW is ready.
3247331766Sken *
3248331766Sken * @par Description
3249331766Sken * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
3250331766Sken *
3251331766Sken * @param sli4 SLI context.
3252331766Sken * @param timeout_ms Time, in milliseconds, to wait for the port to be ready
3253331766Sken *  before failing.
3254331766Sken *
3255331766Sken * @return Returns TRUE for ready, or FALSE otherwise.
3256331766Sken */
3257331766Skenstatic int32_t
3258331766Skensli_wait_for_fw_ready(sli4_t *sli4, uint32_t timeout_ms)
3259331766Sken{
3260331766Sken	uint32_t	iter = timeout_ms / (SLI4_INIT_PORT_DELAY_US / 1000);
3261331766Sken	uint32_t	ready = FALSE;
3262331766Sken
3263331766Sken	do {
3264331766Sken		iter--;
3265331766Sken		ocs_udelay(SLI4_INIT_PORT_DELAY_US);
3266331766Sken		if (sli_fw_ready(sli4) == 1) {
3267331766Sken			ready = TRUE;
3268331766Sken		}
3269331766Sken	} while (!ready && (iter > 0));
3270331766Sken
3271331766Sken	return ready;
3272331766Sken}
3273331766Sken
3274331766Sken/**
3275331766Sken * @brief Initialize the firmware.
3276331766Sken *
3277331766Sken * @par Description
3278331766Sken * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
3279331766Sken *
3280331766Sken * @param sli4 SLI context.
3281331766Sken *
3282331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3283331766Sken */
3284331766Skenstatic int32_t
3285331766Skensli_fw_init(sli4_t *sli4)
3286331766Sken{
3287331766Sken	uint32_t ready;
3288331766Sken	uint32_t endian;
3289331766Sken
3290331766Sken	/*
3291331766Sken	 * Is firmware ready for operation?
3292331766Sken	 */
3293331766Sken	ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
3294331766Sken	if (!ready) {
3295331766Sken		ocs_log_crit(sli4->os, "FW status is NOT ready\n");
3296331766Sken		return -1;
3297331766Sken	}
3298331766Sken
3299331766Sken	/*
3300331766Sken	 * Reset port to a known state
3301331766Sken	 */
3302331766Sken	switch (sli4->if_type) {
3303331766Sken	case SLI4_IF_TYPE_BE3_SKH_PF:
3304331766Sken	case SLI4_IF_TYPE_BE3_SKH_VF:
3305331766Sken		/* No SLIPORT_CONTROL register so use command sequence instead */
3306331766Sken		if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
3307331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
3308331766Sken			return -1;
3309331766Sken		}
3310331766Sken
3311331766Sken		if (sli_cmd_fw_initialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3312331766Sken			if (sli_bmbx_command(sli4)) {
3313331766Sken				ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_INIT)\n");
3314331766Sken				return -1;
3315331766Sken			}
3316331766Sken		} else {
3317331766Sken			ocs_log_crit(sli4->os, "bad FW_INIT write\n");
3318331766Sken			return -1;
3319331766Sken		}
3320331766Sken
3321331766Sken		if (sli_common_function_reset(sli4)) {
3322331766Sken			ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
3323331766Sken			return -1;
3324331766Sken		}
3325331766Sken		break;
3326331766Sken	case SLI4_IF_TYPE_LANCER_FC_ETH:
3327331766Sken#if BYTE_ORDER == LITTLE_ENDIAN
3328331766Sken		endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
3329331766Sken#else
3330331766Sken		endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
3331331766Sken#endif
3332331766Sken
3333331766Sken		if (sli_sliport_control(sli4, endian))
3334331766Sken			return -1;
3335331766Sken		break;
3336331766Sken	default:
3337331766Sken		ocs_log_test(sli4->os, "if_type %d not supported\n", sli4->if_type);
3338331766Sken		return -1;
3339331766Sken	}
3340331766Sken
3341331766Sken	return 0;
3342331766Sken}
3343331766Sken
3344331766Sken/**
3345331766Sken * @brief Terminate the firmware.
3346331766Sken *
3347331766Sken * @param sli4 SLI context.
3348331766Sken *
3349331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3350331766Sken */
3351331766Skenstatic int32_t
3352331766Skensli_fw_term(sli4_t *sli4)
3353331766Sken{
3354331766Sken	uint32_t endian;
3355331766Sken
3356331766Sken	if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF ||
3357331766Sken	    sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF) {
3358331766Sken		/* No SLIPORT_CONTROL register so use command sequence instead */
3359331766Sken		if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
3360331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
3361331766Sken			return -1;
3362331766Sken		}
3363331766Sken
3364331766Sken		if (sli_common_function_reset(sli4)) {
3365331766Sken			ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
3366331766Sken			return -1;
3367331766Sken		}
3368331766Sken
3369331766Sken		if (sli_cmd_fw_deinitialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3370331766Sken			if (sli_bmbx_command(sli4)) {
3371331766Sken				ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_DEINIT)\n");
3372331766Sken				return -1;
3373331766Sken			}
3374331766Sken		} else {
3375331766Sken			ocs_log_test(sli4->os, "bad FW_DEINIT write\n");
3376331766Sken			return -1;
3377331766Sken		}
3378331766Sken	} else {
3379331766Sken#if BYTE_ORDER == LITTLE_ENDIAN
3380331766Sken		endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
3381331766Sken#else
3382331766Sken		endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
3383331766Sken#endif
3384331766Sken		/* type 2 etc. use SLIPORT_CONTROL to initialize port */
3385331766Sken		sli_sliport_control(sli4, endian);
3386331766Sken	}
3387331766Sken	return 0;
3388331766Sken}
3389331766Sken
3390331766Sken/**
3391331766Sken * @brief Write the doorbell register associated with the queue object.
3392331766Sken *
3393331766Sken * @param sli4 SLI context.
3394331766Sken * @param q Queue object.
3395331766Sken *
3396331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3397331766Sken */
3398331766Skenstatic int32_t
3399331766Skensli_queue_doorbell(sli4_t *sli4, sli4_queue_t *q)
3400331766Sken{
3401331766Sken	uint32_t	val = 0;
3402331766Sken
3403331766Sken	switch (q->type) {
3404331766Sken	case SLI_QTYPE_EQ:
3405331766Sken		val = sli_eq_doorbell(q->n_posted, q->id, FALSE);
3406331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3407331766Sken		break;
3408331766Sken	case SLI_QTYPE_CQ:
3409331766Sken		val = sli_cq_doorbell(q->n_posted, q->id, FALSE);
3410331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3411331766Sken		break;
3412331766Sken	case SLI_QTYPE_MQ:
3413331766Sken		val = SLI4_MQ_DOORBELL(q->n_posted, q->id);
3414331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3415331766Sken		break;
3416331766Sken	case SLI_QTYPE_RQ:
3417331766Sken	{
3418331766Sken		uint32_t	n_posted = q->n_posted;
3419331766Sken		/*
3420331766Sken		 * FC/FCoE has different rules for Receive Queues. The host
3421331766Sken		 * should only update the doorbell of the RQ-pair containing
3422331766Sken		 * the headers since the header / payload RQs are treated
3423331766Sken		 * as a matched unit.
3424331766Sken		 */
3425331766Sken		if (SLI4_PORT_TYPE_FC == sli4->port_type) {
3426331766Sken			/*
3427331766Sken			 * In RQ-pair, an RQ either contains the FC header
3428331766Sken			 * (i.e. is_hdr == TRUE) or the payload.
3429331766Sken			 *
3430331766Sken			 * Don't ring doorbell for payload RQ
3431331766Sken			 */
3432331766Sken			if (!q->u.flag.is_hdr) {
3433331766Sken				break;
3434331766Sken			}
3435331766Sken			/*
3436331766Sken			 * Some RQ cannot be incremented one entry at a time. Instead,
3437331766Sken			 * the driver collects a number of entries and updates the
3438331766Sken			 * RQ in batches.
3439331766Sken			 */
3440331766Sken			if (q->u.flag.rq_batch) {
3441331766Sken				if (((q->index + q->n_posted) % SLI4_QUEUE_RQ_BATCH)) {
3442331766Sken					break;
3443331766Sken				}
3444331766Sken				n_posted = SLI4_QUEUE_RQ_BATCH;
3445331766Sken			}
3446331766Sken		}
3447331766Sken
3448331766Sken		val = SLI4_RQ_DOORBELL(n_posted, q->id);
3449331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3450331766Sken		break;
3451331766Sken	}
3452331766Sken	case SLI_QTYPE_WQ:
3453331766Sken		val = SLI4_WQ_DOORBELL(q->n_posted, q->index, q->id);
3454331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
3455331766Sken		break;
3456331766Sken	default:
3457331766Sken		ocs_log_test(sli4->os, "bad queue type %d\n", q->type);
3458331766Sken		return -1;
3459331766Sken	}
3460331766Sken
3461331766Sken	return 0;
3462331766Sken}
3463331766Sken
3464331766Skenstatic int32_t
3465331766Skensli_request_features(sli4_t *sli4, sli4_features_t *features, uint8_t query)
3466331766Sken{
3467331766Sken
3468331766Sken	if (sli_cmd_request_features(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
3469331766Sken				*features, query)) {
3470331766Sken		sli4_cmd_request_features_t *req_features = sli4->bmbx.virt;
3471331766Sken
3472331766Sken		if (sli_bmbx_command(sli4)) {
3473331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (REQUEST_FEATURES)\n");
3474331766Sken			return -1;
3475331766Sken		}
3476331766Sken		if (req_features->hdr.status) {
3477331766Sken			ocs_log_err(sli4->os, "REQUEST_FEATURES bad status %#x\n",
3478331766Sken					req_features->hdr.status);
3479331766Sken			return -1;
3480331766Sken		}
3481331766Sken		features->dword = req_features->response.dword;
3482331766Sken	} else {
3483331766Sken		ocs_log_err(sli4->os, "bad REQUEST_FEATURES write\n");
3484331766Sken		return -1;
3485331766Sken	}
3486331766Sken
3487331766Sken	return 0;
3488331766Sken}
3489331766Sken
3490331766Sken/**
3491331766Sken * @brief Calculate max queue entries.
3492331766Sken *
3493331766Sken * @param sli4 SLI context.
3494331766Sken *
3495331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3496331766Sken */
3497331766Skenvoid
3498331766Skensli_calc_max_qentries(sli4_t *sli4)
3499331766Sken{
3500331766Sken	sli4_qtype_e q;
3501331766Sken	uint32_t alloc_size, qentries, qentry_size;
3502331766Sken
3503331766Sken	for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
3504331766Sken		sli4->config.max_qentries[q] = sli_convert_mask_to_count(sli4->config.count_method[q],
3505331766Sken									 sli4->config.count_mask[q]);
3506331766Sken	}
3507331766Sken
3508331766Sken	/* single, continguous DMA allocations will be called for each queue
3509331766Sken	 * of size (max_qentries * queue entry size); since these can be large,
3510331766Sken	 * check against the OS max DMA allocation size
3511331766Sken	 */
3512331766Sken	for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
3513331766Sken		qentries = sli4->config.max_qentries[q];
3514331766Sken		qentry_size = sli_get_queue_entry_size(sli4, q);
3515331766Sken		alloc_size = qentries * qentry_size;
3516331766Sken		if (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
3517331766Sken			while (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
3518331766Sken				/* cut the qentries in hwf until alloc_size <= max DMA alloc size */
3519331766Sken				qentries >>= 1;
3520331766Sken				alloc_size = qentries * qentry_size;
3521331766Sken			}
3522331766Sken			ocs_log_debug(sli4->os, "[%s]: max_qentries from %d to %d (max dma %d)\n",
3523331766Sken				SLI_QNAME[q], sli4->config.max_qentries[q],
3524331766Sken				qentries, ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE));
3525331766Sken			sli4->config.max_qentries[q] = qentries;
3526331766Sken		}
3527331766Sken	}
3528331766Sken}
3529331766Sken
3530331766Sken/**
3531331766Sken * @brief Issue a FW_CONFIG mailbox command and store the results.
3532331766Sken *
3533331766Sken * @param sli4 SLI context.
3534331766Sken *
3535331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3536331766Sken */
3537331766Skenstatic int32_t
3538331766Skensli_query_fw_config(sli4_t *sli4)
3539331766Sken{
3540331766Sken	/*
3541331766Sken	 * Read the device configuration
3542331766Sken	 *
3543331766Sken	 * Note: Only ulp0 fields contain values
3544331766Sken	 */
3545331766Sken	if (sli_cmd_common_query_fw_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3546331766Sken		sli4_res_common_query_fw_config_t   *fw_config =
3547331766Sken			(sli4_res_common_query_fw_config_t *)
3548331766Sken			(((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
3549331766Sken
3550331766Sken		if (sli_bmbx_command(sli4)) {
3551331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (QUERY_FW_CONFIG)\n");
3552331766Sken			return -1;
3553331766Sken		}
3554331766Sken		if (fw_config->hdr.status) {
3555331766Sken			ocs_log_err(sli4->os, "COMMON_QUERY_FW_CONFIG bad status %#x\n",
3556331766Sken				fw_config->hdr.status);
3557331766Sken			return -1;
3558331766Sken		}
3559331766Sken
3560331766Sken		sli4->physical_port = fw_config->physical_port;
3561331766Sken		sli4->config.dual_ulp_capable = ((fw_config->function_mode & SLI4_FUNCTION_MODE_DUA_MODE) == 0 ? 0 : 1);
3562331766Sken		sli4->config.is_ulp_fc[0] = ((fw_config->ulp0_mode &
3563331766Sken					      (SLI4_ULP_MODE_FCOE_INI |
3564331766Sken					       SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
3565331766Sken		sli4->config.is_ulp_fc[1] = ((fw_config->ulp1_mode &
3566331766Sken					      (SLI4_ULP_MODE_FCOE_INI |
3567331766Sken					       SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
3568331766Sken
3569331766Sken		if (sli4->config.dual_ulp_capable) {
3570331766Sken			/*
3571331766Sken			 * Lancer will not support this, so we use the values
3572331766Sken			 * from the READ_CONFIG.
3573331766Sken			 */
3574331766Sken			if (sli4->config.is_ulp_fc[0] &&
3575331766Sken			    sli4->config.is_ulp_fc[1]) {
3576331766Sken				sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total + fw_config->ulp1_toe_wq_total;
3577331766Sken				sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total + fw_config->ulp1_toe_defrq_total;
3578331766Sken			} else if (sli4->config.is_ulp_fc[0]) {
3579331766Sken				sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total;
3580331766Sken				sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total;
3581331766Sken			} else {
3582331766Sken				sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp1_toe_wq_total;
3583331766Sken				sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp1_toe_defrq_total;
3584331766Sken			}
3585331766Sken		}
3586331766Sken	} else {
3587331766Sken		ocs_log_err(sli4->os, "bad QUERY_FW_CONFIG write\n");
3588331766Sken		return -1;
3589331766Sken	}
3590331766Sken	return 0;
3591331766Sken}
3592331766Sken
3593331766Sken
3594331766Skenstatic int32_t
3595331766Skensli_get_config(sli4_t *sli4)
3596331766Sken{
3597331766Sken	ocs_dma_t	get_cntl_addl_data;
3598331766Sken
3599331766Sken	/*
3600331766Sken	 * Read the device configuration
3601331766Sken	 */
3602331766Sken	if (sli_cmd_read_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3603331766Sken		sli4_res_read_config_t	*read_config = sli4->bmbx.virt;
3604331766Sken		uint32_t	i;
3605331766Sken		uint32_t	total;
3606331766Sken
3607331766Sken		if (sli_bmbx_command(sli4)) {
3608331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n");
3609331766Sken			return -1;
3610331766Sken		}
3611331766Sken		if (read_config->hdr.status) {
3612331766Sken			ocs_log_err(sli4->os, "READ_CONFIG bad status %#x\n",
3613331766Sken					read_config->hdr.status);
3614331766Sken			return -1;
3615331766Sken		}
3616331766Sken
3617331766Sken		sli4->config.has_extents = read_config->ext;
3618331766Sken		if (FALSE == sli4->config.has_extents) {
3619331766Sken			uint32_t	i = 0;
3620331766Sken			uint32_t	*base = sli4->config.extent[0].base;
3621331766Sken
3622331766Sken			if (!base) {
3623331766Sken				if (NULL == (base = ocs_malloc(sli4->os, SLI_RSRC_MAX * sizeof(uint32_t),
3624331766Sken								OCS_M_ZERO | OCS_M_NOWAIT))) {
3625331766Sken					ocs_log_err(sli4->os, "memory allocation failed for sli4_resource_t\n");
3626331766Sken					return -1;
3627331766Sken				}
3628331766Sken			}
3629331766Sken
3630331766Sken			for (i = 0; i < SLI_RSRC_MAX; i++) {
3631331766Sken				sli4->config.extent[i].number = 1;
3632331766Sken				sli4->config.extent[i].n_alloc = 0;
3633331766Sken				sli4->config.extent[i].base = &base[i];
3634331766Sken			}
3635331766Sken
3636331766Sken			sli4->config.extent[SLI_RSRC_FCOE_VFI].base[0] = read_config->vfi_base;
3637331766Sken			sli4->config.extent[SLI_RSRC_FCOE_VFI].size = read_config->vfi_count;
3638331766Sken
3639331766Sken			sli4->config.extent[SLI_RSRC_FCOE_VPI].base[0] = read_config->vpi_base;
3640331766Sken			sli4->config.extent[SLI_RSRC_FCOE_VPI].size = read_config->vpi_count;
3641331766Sken
3642331766Sken			sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0] = read_config->rpi_base;
3643331766Sken			sli4->config.extent[SLI_RSRC_FCOE_RPI].size = read_config->rpi_count;
3644331766Sken
3645331766Sken			sli4->config.extent[SLI_RSRC_FCOE_XRI].base[0] = read_config->xri_base;
3646331766Sken			sli4->config.extent[SLI_RSRC_FCOE_XRI].size = read_config->xri_count;
3647331766Sken
3648331766Sken			sli4->config.extent[SLI_RSRC_FCOE_FCFI].base[0] = 0;
3649331766Sken			sli4->config.extent[SLI_RSRC_FCOE_FCFI].size = read_config->fcfi_count;
3650331766Sken		} else {
3651331766Sken			/* TODO extents*/
3652331766Sken			;
3653331766Sken		}
3654331766Sken
3655331766Sken		for (i = 0; i < SLI_RSRC_MAX; i++) {
3656331766Sken			total = sli4->config.extent[i].number * sli4->config.extent[i].size;
3657331766Sken			sli4->config.extent[i].use_map = ocs_bitmap_alloc(total);
3658331766Sken			if (NULL == sli4->config.extent[i].use_map) {
3659331766Sken				ocs_log_err(sli4->os, "bitmap memory allocation failed "
3660331766Sken						"resource %d\n", i);
3661331766Sken				return -1;
3662331766Sken			}
3663331766Sken			sli4->config.extent[i].map_size = total;
3664331766Sken		}
3665331766Sken
3666331766Sken		sli4->config.topology = read_config->topology;
3667331766Sken		switch (sli4->config.topology) {
3668331766Sken		case SLI4_READ_CFG_TOPO_FCOE:
3669331766Sken			ocs_log_debug(sli4->os, "FCoE\n");
3670331766Sken			break;
3671331766Sken		case SLI4_READ_CFG_TOPO_FC:
3672331766Sken			ocs_log_debug(sli4->os, "FC (unknown)\n");
3673331766Sken			break;
3674331766Sken		case SLI4_READ_CFG_TOPO_FC_DA:
3675331766Sken			ocs_log_debug(sli4->os, "FC (direct attach)\n");
3676331766Sken			break;
3677331766Sken		case SLI4_READ_CFG_TOPO_FC_AL:
3678331766Sken			ocs_log_debug(sli4->os, "FC (arbitrated loop)\n");
3679331766Sken			break;
3680331766Sken		default:
3681331766Sken			ocs_log_test(sli4->os, "bad topology %#x\n", sli4->config.topology);
3682331766Sken		}
3683331766Sken
3684331766Sken		sli4->config.e_d_tov = read_config->e_d_tov;
3685331766Sken		sli4->config.r_a_tov = read_config->r_a_tov;
3686331766Sken
3687331766Sken		sli4->config.link_module_type = read_config->lmt;
3688331766Sken
3689331766Sken		sli4->config.max_qcount[SLI_QTYPE_EQ] = read_config->eq_count;
3690331766Sken		sli4->config.max_qcount[SLI_QTYPE_CQ] = read_config->cq_count;
3691331766Sken		sli4->config.max_qcount[SLI_QTYPE_WQ] = read_config->wq_count;
3692331766Sken		sli4->config.max_qcount[SLI_QTYPE_RQ] = read_config->rq_count;
3693331766Sken
3694331766Sken		/*
3695331766Sken		 * READ_CONFIG doesn't give the max number of MQ. Applications
3696331766Sken		 * will typically want 1, but we may need another at some future
3697331766Sken		 * date. Dummy up a "max" MQ count here.
3698331766Sken		 */
3699331766Sken		sli4->config.max_qcount[SLI_QTYPE_MQ] = SLI_USER_MQ_COUNT;
3700331766Sken	} else {
3701331766Sken		ocs_log_err(sli4->os, "bad READ_CONFIG write\n");
3702331766Sken		return -1;
3703331766Sken	}
3704331766Sken
3705331766Sken	if (sli_cmd_common_get_sli4_parameters(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3706331766Sken		sli4_res_common_get_sli4_parameters_t	*parms = (sli4_res_common_get_sli4_parameters_t *)
3707331766Sken			(((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
3708331766Sken
3709331766Sken		if (sli_bmbx_command(sli4)) {
3710331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_SLI4_PARAMETERS)\n");
3711331766Sken			return -1;
3712331766Sken		} else if (parms->hdr.status) {
3713331766Sken			ocs_log_err(sli4->os, "COMMON_GET_SLI4_PARAMETERS bad status %#x att'l %#x\n",
3714331766Sken					parms->hdr.status, parms->hdr.additional_status);
3715331766Sken			return -1;
3716331766Sken		}
3717331766Sken
3718331766Sken		sli4->config.auto_reg = parms->areg;
3719331766Sken		sli4->config.auto_xfer_rdy = parms->agxf;
3720331766Sken		sli4->config.hdr_template_req = parms->hdrr;
3721331766Sken		sli4->config.t10_dif_inline_capable = parms->timm;
3722331766Sken		sli4->config.t10_dif_separate_capable = parms->tsmm;
3723331766Sken
3724331766Sken		sli4->config.mq_create_version = parms->mqv;
3725331766Sken		sli4->config.cq_create_version = parms->cqv;
3726331766Sken		sli4->config.rq_min_buf_size = parms->min_rq_buffer_size;
3727331766Sken		sli4->config.rq_max_buf_size = parms->max_rq_buffer_size;
3728331766Sken
3729331766Sken		sli4->config.qpage_count[SLI_QTYPE_EQ] = parms->eq_page_cnt;
3730331766Sken		sli4->config.qpage_count[SLI_QTYPE_CQ] = parms->cq_page_cnt;
3731331766Sken		sli4->config.qpage_count[SLI_QTYPE_MQ] = parms->mq_page_cnt;
3732331766Sken		sli4->config.qpage_count[SLI_QTYPE_WQ] = parms->wq_page_cnt;
3733331766Sken		sli4->config.qpage_count[SLI_QTYPE_RQ] = parms->rq_page_cnt;
3734331766Sken
3735331766Sken		/* save count methods and masks for each queue type */
3736331766Sken		sli4->config.count_mask[SLI_QTYPE_EQ] = parms->eqe_count_mask;
3737331766Sken		sli4->config.count_method[SLI_QTYPE_EQ] = parms->eqe_count_method;
3738331766Sken		sli4->config.count_mask[SLI_QTYPE_CQ] = parms->cqe_count_mask;
3739331766Sken		sli4->config.count_method[SLI_QTYPE_CQ] = parms->cqe_count_method;
3740331766Sken		sli4->config.count_mask[SLI_QTYPE_MQ] = parms->mqe_count_mask;
3741331766Sken		sli4->config.count_method[SLI_QTYPE_MQ] = parms->mqe_count_method;
3742331766Sken		sli4->config.count_mask[SLI_QTYPE_WQ] = parms->wqe_count_mask;
3743331766Sken		sli4->config.count_method[SLI_QTYPE_WQ] = parms->wqe_count_method;
3744331766Sken		sli4->config.count_mask[SLI_QTYPE_RQ] = parms->rqe_count_mask;
3745331766Sken		sli4->config.count_method[SLI_QTYPE_RQ] = parms->rqe_count_method;
3746331766Sken
3747331766Sken		/* now calculate max queue entries */
3748331766Sken		sli_calc_max_qentries(sli4);
3749331766Sken
3750331766Sken		sli4->config.max_sgl_pages = parms->sgl_page_cnt;	/* max # of pages */
3751331766Sken		sli4->config.sgl_page_sizes = parms->sgl_page_sizes;	/* bit map of available sizes */
3752331766Sken		/* ignore HLM here. Use value from REQUEST_FEATURES */
3753331766Sken
3754331766Sken		sli4->config.sge_supported_length = parms->sge_supported_length;
3755331766Sken		if (sli4->config.sge_supported_length > OCS_MAX_SGE_SIZE)
3756331766Sken			sli4->config.sge_supported_length = OCS_MAX_SGE_SIZE;
3757331766Sken
3758331766Sken		sli4->config.sgl_pre_registration_required = parms->sglr;
3759331766Sken		/* default to using pre-registered SGL's */
3760331766Sken		sli4->config.sgl_pre_registered = TRUE;
3761331766Sken
3762331766Sken		sli4->config.perf_hint = parms->phon;
3763331766Sken		sli4->config.perf_wq_id_association = parms->phwq;
3764331766Sken
3765331766Sken		sli4->config.rq_batch = parms->rq_db_window;
3766331766Sken
3767331766Sken		/* save the fields for skyhawk SGL chaining */
3768331766Sken		sli4->config.sgl_chaining_params.chaining_capable =
3769331766Sken			(parms->sglc == 1);
3770331766Sken		sli4->config.sgl_chaining_params.frag_num_field_offset =
3771331766Sken			parms->frag_num_field_offset;
3772331766Sken		sli4->config.sgl_chaining_params.frag_num_field_mask =
3773331766Sken			(1ull << parms->frag_num_field_size) - 1;
3774331766Sken		sli4->config.sgl_chaining_params.sgl_index_field_offset =
3775331766Sken			parms->sgl_index_field_offset;
3776331766Sken		sli4->config.sgl_chaining_params.sgl_index_field_mask =
3777331766Sken			(1ull << parms->sgl_index_field_size) - 1;
3778331766Sken		sli4->config.sgl_chaining_params.chain_sge_initial_value_lo =
3779331766Sken			parms->chain_sge_initial_value_lo;
3780331766Sken		sli4->config.sgl_chaining_params.chain_sge_initial_value_hi =
3781331766Sken			parms->chain_sge_initial_value_hi;
3782331766Sken
3783331766Sken		/* Use the highest available WQE size. */
3784331766Sken		if (parms->wqe_sizes & SLI4_128BYTE_WQE_SUPPORT) {
3785331766Sken			sli4->config.wqe_size = SLI4_WQE_EXT_BYTES;
3786331766Sken		} else {
3787331766Sken			sli4->config.wqe_size = SLI4_WQE_BYTES;
3788331766Sken		}
3789331766Sken	}
3790331766Sken
3791331766Sken	if (sli_query_fw_config(sli4)) {
3792331766Sken		ocs_log_err(sli4->os, "Error sending QUERY_FW_CONFIG\n");
3793331766Sken		return -1;
3794331766Sken	}
3795331766Sken
3796331766Sken	sli4->config.port_number = 0;
3797331766Sken
3798331766Sken	/*
3799331766Sken	 * Issue COMMON_GET_CNTL_ATTRIBUTES to get port_number. Temporarily
3800331766Sken	 * uses VPD DMA buffer as the response won't fit in the embedded
3801331766Sken	 * buffer.
3802331766Sken	 */
3803331766Sken	if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
3804331766Sken		sli4_res_common_get_cntl_attributes_t *attr = sli4->vpd.data.virt;
3805331766Sken
3806331766Sken		if (sli_bmbx_command(sli4)) {
3807331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ATTRIBUTES)\n");
3808331766Sken			return -1;
3809331766Sken		} else if (attr->hdr.status) {
3810331766Sken			ocs_log_err(sli4->os, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x att'l %#x\n",
3811331766Sken					attr->hdr.status, attr->hdr.additional_status);
3812331766Sken			return -1;
3813331766Sken		}
3814331766Sken
3815331766Sken		sli4->config.port_number = attr->port_number;
3816331766Sken
3817331766Sken		ocs_memcpy(sli4->config.bios_version_string, attr->bios_version_string,
3818331766Sken				sizeof(sli4->config.bios_version_string));
3819331766Sken	} else {
3820331766Sken		ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ATTRIBUTES write\n");
3821331766Sken		return -1;
3822331766Sken	}
3823331766Sken
3824331766Sken	if (ocs_dma_alloc(sli4->os, &get_cntl_addl_data, sizeof(sli4_res_common_get_cntl_addl_attributes_t),
3825331766Sken			  OCS_MIN_DMA_ALIGNMENT)) {
3826331766Sken		ocs_log_err(sli4->os, "Failed to allocate memory for GET_CNTL_ADDL_ATTR data\n");
3827331766Sken	} else {
3828331766Sken		if (sli_cmd_common_get_cntl_addl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
3829331766Sken							    &get_cntl_addl_data)) {
3830331766Sken			sli4_res_common_get_cntl_addl_attributes_t *attr = get_cntl_addl_data.virt;
3831331766Sken
3832331766Sken			if (sli_bmbx_command(sli4)) {
3833331766Sken				ocs_log_crit(sli4->os,
3834331766Sken					     "bootstrap mailbox write fail (COMMON_GET_CNTL_ADDL_ATTRIBUTES)\n");
3835331766Sken				ocs_dma_free(sli4->os, &get_cntl_addl_data);
3836331766Sken				return -1;
3837331766Sken			}
3838331766Sken			if (attr->hdr.status) {
3839331766Sken				ocs_log_err(sli4->os, "COMMON_GET_CNTL_ADDL_ATTRIBUTES bad status %#x\n",
3840331766Sken					    attr->hdr.status);
3841331766Sken				ocs_dma_free(sli4->os, &get_cntl_addl_data);
3842331766Sken				return -1;
3843331766Sken			}
3844331766Sken
3845331766Sken			ocs_memcpy(sli4->config.ipl_name, attr->ipl_file_name, sizeof(sli4->config.ipl_name));
3846331766Sken
3847331766Sken			ocs_log_debug(sli4->os, "IPL:%s \n", (char*)sli4->config.ipl_name);
3848331766Sken		} else {
3849331766Sken			ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ADDL_ATTRIBUTES write\n");
3850331766Sken			ocs_dma_free(sli4->os, &get_cntl_addl_data);
3851331766Sken			return -1;
3852331766Sken		}
3853331766Sken
3854331766Sken		ocs_dma_free(sli4->os, &get_cntl_addl_data);
3855331766Sken	}
3856331766Sken
3857331766Sken	if (sli_cmd_common_get_port_name(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3858331766Sken		sli4_res_common_get_port_name_t	*port_name = (sli4_res_common_get_port_name_t *)(((uint8_t *)sli4->bmbx.virt) +
3859331766Sken			offsetof(sli4_cmd_sli_config_t, payload.embed));
3860331766Sken
3861331766Sken		if (sli_bmbx_command(sli4)) {
3862331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_PORT_NAME)\n");
3863331766Sken			return -1;
3864331766Sken		}
3865331766Sken
3866331766Sken		sli4->config.port_name[0] = port_name->port_name[sli4->config.port_number];
3867331766Sken	}
3868331766Sken	sli4->config.port_name[1] = '\0';
3869331766Sken
3870331766Sken	if (sli_cmd_read_rev(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
3871331766Sken		sli4_cmd_read_rev_t	*read_rev = sli4->bmbx.virt;
3872331766Sken
3873331766Sken		if (sli_bmbx_command(sli4)) {
3874331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_REV)\n");
3875331766Sken			return -1;
3876331766Sken		}
3877331766Sken		if (read_rev->hdr.status) {
3878331766Sken			ocs_log_err(sli4->os, "READ_REV bad status %#x\n",
3879331766Sken					read_rev->hdr.status);
3880331766Sken			return -1;
3881331766Sken		}
3882331766Sken
3883331766Sken		sli4->config.fw_rev[0] = read_rev->first_fw_id;
3884331766Sken		ocs_memcpy(sli4->config.fw_name[0],read_rev->first_fw_name, sizeof(sli4->config.fw_name[0]));
3885331766Sken
3886331766Sken		sli4->config.fw_rev[1] = read_rev->second_fw_id;
3887331766Sken		ocs_memcpy(sli4->config.fw_name[1],read_rev->second_fw_name, sizeof(sli4->config.fw_name[1]));
3888331766Sken
3889331766Sken		sli4->config.hw_rev[0] = read_rev->first_hw_revision;
3890331766Sken		sli4->config.hw_rev[1] = read_rev->second_hw_revision;
3891331766Sken		sli4->config.hw_rev[2] = read_rev->third_hw_revision;
3892331766Sken
3893331766Sken		ocs_log_debug(sli4->os, "FW1:%s (%08x) / FW2:%s (%08x)\n",
3894331766Sken				read_rev->first_fw_name, read_rev->first_fw_id,
3895331766Sken				read_rev->second_fw_name, read_rev->second_fw_id);
3896331766Sken
3897331766Sken		ocs_log_debug(sli4->os, "HW1: %08x / HW2: %08x\n", read_rev->first_hw_revision,
3898331766Sken				read_rev->second_hw_revision);
3899331766Sken
3900331766Sken		/* Check that all VPD data was returned */
3901331766Sken		if (read_rev->returned_vpd_length != read_rev->actual_vpd_length) {
3902331766Sken			ocs_log_test(sli4->os, "VPD length: available=%d returned=%d actual=%d\n",
3903331766Sken					read_rev->available_length,
3904331766Sken					read_rev->returned_vpd_length,
3905331766Sken					read_rev->actual_vpd_length);
3906331766Sken		}
3907331766Sken		sli4->vpd.length = read_rev->returned_vpd_length;
3908331766Sken	} else {
3909331766Sken		ocs_log_err(sli4->os, "bad READ_REV write\n");
3910331766Sken		return -1;
3911331766Sken	}
3912331766Sken
3913331766Sken	if (sli_cmd_read_nvparms(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
3914331766Sken		sli4_cmd_read_nvparms_t	*read_nvparms = sli4->bmbx.virt;
3915331766Sken
3916331766Sken		if (sli_bmbx_command(sli4)) {
3917331766Sken			ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_NVPARMS)\n");
3918331766Sken			return -1;
3919331766Sken		}
3920331766Sken		if (read_nvparms->hdr.status) {
3921331766Sken			ocs_log_err(sli4->os, "READ_NVPARMS bad status %#x\n",
3922331766Sken					read_nvparms->hdr.status);
3923331766Sken			return -1;
3924331766Sken		}
3925331766Sken
3926331766Sken		ocs_memcpy(sli4->config.wwpn, read_nvparms->wwpn, sizeof(sli4->config.wwpn));
3927331766Sken		ocs_memcpy(sli4->config.wwnn, read_nvparms->wwnn, sizeof(sli4->config.wwnn));
3928331766Sken
3929331766Sken		ocs_log_debug(sli4->os, "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
3930331766Sken				sli4->config.wwpn[0],
3931331766Sken				sli4->config.wwpn[1],
3932331766Sken				sli4->config.wwpn[2],
3933331766Sken				sli4->config.wwpn[3],
3934331766Sken				sli4->config.wwpn[4],
3935331766Sken				sli4->config.wwpn[5],
3936331766Sken				sli4->config.wwpn[6],
3937331766Sken				sli4->config.wwpn[7]);
3938331766Sken		ocs_log_debug(sli4->os, "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
3939331766Sken				sli4->config.wwnn[0],
3940331766Sken				sli4->config.wwnn[1],
3941331766Sken				sli4->config.wwnn[2],
3942331766Sken				sli4->config.wwnn[3],
3943331766Sken				sli4->config.wwnn[4],
3944331766Sken				sli4->config.wwnn[5],
3945331766Sken				sli4->config.wwnn[6],
3946331766Sken				sli4->config.wwnn[7]);
3947331766Sken	} else {
3948331766Sken		ocs_log_err(sli4->os, "bad READ_NVPARMS write\n");
3949331766Sken		return -1;
3950331766Sken	}
3951331766Sken
3952331766Sken	return 0;
3953331766Sken}
3954331766Sken
3955331766Sken/****************************************************************************
3956331766Sken * Public functions
3957331766Sken */
3958331766Sken
3959331766Sken/**
3960331766Sken * @ingroup sli
3961331766Sken * @brief Set up the SLI context.
3962331766Sken *
3963331766Sken * @param sli4 SLI context.
3964331766Sken * @param os Device abstraction.
3965331766Sken * @param port_type Protocol type of port (for example, FC and NIC).
3966331766Sken *
3967331766Sken * @return Returns 0 on success, or a non-zero value on failure.
3968331766Sken */
3969331766Skenint32_t
3970331766Skensli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type)
3971331766Sken{
3972331766Sken	uint32_t sli_intf = UINT32_MAX;
3973331766Sken	uint32_t pci_class_rev = 0;
3974331766Sken	uint32_t rev_id = 0;
3975331766Sken	uint32_t family = 0;
3976331766Sken	uint32_t i;
3977331766Sken	sli4_asic_entry_t *asic;
3978331766Sken
3979331766Sken	ocs_memset(sli4, 0, sizeof(sli4_t));
3980331766Sken
3981331766Sken	sli4->os = os;
3982331766Sken	sli4->port_type = port_type;
3983331766Sken
3984331766Sken	/*
3985331766Sken	 * Read the SLI_INTF register to discover the register layout
3986331766Sken	 * and other capability information
3987331766Sken	 */
3988331766Sken	sli_intf = ocs_config_read32(os, SLI4_INTF_REG);
3989331766Sken
3990331766Sken	if (sli_intf_valid_check(sli_intf)) {
3991331766Sken		ocs_log_err(os, "SLI_INTF is not valid\n");
3992331766Sken		return -1;
3993331766Sken	}
3994331766Sken
3995331766Sken	/* driver only support SLI-4 */
3996331766Sken	sli4->sli_rev = sli_intf_sli_revision(sli_intf);
3997331766Sken	if (4 != sli4->sli_rev) {
3998331766Sken		ocs_log_err(os, "Unsupported SLI revision (intf=%#x)\n",
3999331766Sken				sli_intf);
4000331766Sken		return -1;
4001331766Sken	}
4002331766Sken
4003331766Sken	sli4->sli_family = sli_intf_sli_family(sli_intf);
4004331766Sken
4005331766Sken	sli4->if_type = sli_intf_if_type(sli_intf);
4006331766Sken
4007331766Sken	if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) {
4008331766Sken		ocs_log_debug(os, "status=%#x error1=%#x error2=%#x\n",
4009331766Sken				sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
4010331766Sken				sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
4011331766Sken				sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
4012331766Sken	}
4013331766Sken
4014331766Sken	/*
4015331766Sken	 * set the ASIC type and revision
4016331766Sken	 */
4017331766Sken	pci_class_rev = ocs_config_read32(os, SLI4_PCI_CLASS_REVISION);
4018331766Sken	rev_id = sli_pci_rev_id(pci_class_rev);
4019331766Sken	family = sli4->sli_family;
4020331766Sken	if (family == SLI4_FAMILY_CHECK_ASIC_TYPE) {
4021331766Sken		uint32_t asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG);
4022331766Sken		family = sli_asic_gen(asic_id);
4023331766Sken	}
4024331766Sken
4025331766Sken	for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table); i++, asic++) {
4026331766Sken		if ((rev_id == asic->rev_id) && (family == asic->family)) {
4027331766Sken			sli4->asic_type = asic->type;
4028331766Sken			sli4->asic_rev = asic->rev;
4029331766Sken			break;
4030331766Sken		}
4031331766Sken	}
4032331766Sken	/* Fail if no matching asic type/rev was found */
4033331766Sken	if( (sli4->asic_type == 0) || (sli4->asic_rev == 0)) {
4034331766Sken		ocs_log_err(os, "no matching asic family/rev found: %02x/%02x\n", family, rev_id);
4035331766Sken		return -1;
4036331766Sken	}
4037331766Sken
4038331766Sken	/*
4039331766Sken	 * The bootstrap mailbox is equivalent to a MQ with a single 256 byte
4040331766Sken	 * entry, a CQ with a single 16 byte entry, and no event queue.
4041331766Sken	 * Alignment must be 16 bytes as the low order address bits in the
4042331766Sken	 * address register are also control / status.
4043331766Sken	 */
4044331766Sken	if (ocs_dma_alloc(sli4->os, &sli4->bmbx, SLI4_BMBX_SIZE +
4045331766Sken				sizeof(sli4_mcqe_t), 16)) {
4046331766Sken		ocs_log_err(os, "bootstrap mailbox allocation failed\n");
4047331766Sken		return -1;
4048331766Sken	}
4049331766Sken
4050331766Sken	if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) {
4051331766Sken		ocs_log_err(os, "bad alignment for bootstrap mailbox\n");
4052331766Sken		return -1;
4053331766Sken	}
4054331766Sken
4055331766Sken	ocs_log_debug(os, "bmbx v=%p p=0x%x %08x s=%zd\n", sli4->bmbx.virt,
4056331766Sken		ocs_addr32_hi(sli4->bmbx.phys),
4057331766Sken		ocs_addr32_lo(sli4->bmbx.phys),
4058331766Sken		sli4->bmbx.size);
4059331766Sken
4060331766Sken	/* TODO 4096 is arbitrary. What should this value actually be? */
4061331766Sken	if (ocs_dma_alloc(sli4->os, &sli4->vpd.data, 4096/*TODO*/, 4096)) {
4062331766Sken		/* Note that failure isn't fatal in this specific case */
4063331766Sken		sli4->vpd.data.size = 0;
4064331766Sken		ocs_log_test(os, "VPD buffer allocation failed\n");
4065331766Sken	}
4066331766Sken
4067331766Sken	if (sli_fw_init(sli4)) {
4068331766Sken		ocs_log_err(sli4->os, "FW initialization failed\n");
4069331766Sken		return -1;
4070331766Sken	}
4071331766Sken
4072331766Sken	/*
4073331766Sken	 * Set one of fcpi(initiator), fcpt(target), fcpc(combined) to true
4074331766Sken	 * in addition to any other desired features
4075331766Sken	 */
4076331766Sken	sli4->config.features.flag.iaab = TRUE;
4077331766Sken	sli4->config.features.flag.npiv = TRUE;
4078331766Sken	sli4->config.features.flag.dif = TRUE;
4079331766Sken	sli4->config.features.flag.vf = TRUE;
4080331766Sken	sli4->config.features.flag.fcpc = TRUE;
4081331766Sken	sli4->config.features.flag.iaar = TRUE;
4082331766Sken	sli4->config.features.flag.hlm = TRUE;
4083331766Sken	sli4->config.features.flag.perfh = TRUE;
4084331766Sken	sli4->config.features.flag.rxseq = TRUE;
4085331766Sken	sli4->config.features.flag.rxri = TRUE;
4086331766Sken	sli4->config.features.flag.mrqp = TRUE;
4087331766Sken
4088331766Sken	/* use performance hints if available */
4089331766Sken	if (sli4->config.perf_hint) {
4090331766Sken		sli4->config.features.flag.perfh = TRUE;
4091331766Sken	}
4092331766Sken
4093331766Sken	if (sli_request_features(sli4, &sli4->config.features, TRUE)) {
4094331766Sken		return -1;
4095331766Sken	}
4096331766Sken
4097331766Sken	if (sli_get_config(sli4)) {
4098331766Sken		return -1;
4099331766Sken	}
4100331766Sken
4101331766Sken	return 0;
4102331766Sken}
4103331766Sken
4104331766Skenint32_t
4105331766Skensli_init(sli4_t *sli4)
4106331766Sken{
4107331766Sken
4108331766Sken	if (sli4->config.has_extents) {
4109331766Sken		/* TODO COMMON_ALLOC_RESOURCE_EXTENTS */;
4110331766Sken		ocs_log_test(sli4->os, "XXX need to implement extent allocation\n");
4111331766Sken		return -1;
4112331766Sken	}
4113331766Sken
4114331766Sken	sli4->config.features.flag.hlm = sli4->config.high_login_mode;
4115331766Sken	sli4->config.features.flag.rxseq = FALSE;
4116331766Sken	sli4->config.features.flag.rxri  = FALSE;
4117331766Sken
4118331766Sken	if (sli_request_features(sli4, &sli4->config.features, FALSE)) {
4119331766Sken		return -1;
4120331766Sken	}
4121331766Sken
4122331766Sken	return 0;
4123331766Sken}
4124331766Sken
4125331766Skenint32_t
4126331766Skensli_reset(sli4_t *sli4)
4127331766Sken{
4128331766Sken	uint32_t	i;
4129331766Sken
4130331766Sken	if (sli_fw_init(sli4)) {
4131331766Sken		ocs_log_crit(sli4->os, "FW initialization failed\n");
4132331766Sken		return -1;
4133331766Sken	}
4134331766Sken
4135331766Sken	if (sli4->config.extent[0].base) {
4136331766Sken		ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
4137331766Sken		sli4->config.extent[0].base = NULL;
4138331766Sken	}
4139331766Sken
4140331766Sken	for (i = 0; i < SLI_RSRC_MAX; i++) {
4141331766Sken		if (sli4->config.extent[i].use_map) {
4142331766Sken			ocs_bitmap_free(sli4->config.extent[i].use_map);
4143331766Sken			sli4->config.extent[i].use_map = NULL;
4144331766Sken		}
4145331766Sken		sli4->config.extent[i].base = NULL;
4146331766Sken	}
4147331766Sken
4148331766Sken	if (sli_get_config(sli4)) {
4149331766Sken		return -1;
4150331766Sken	}
4151331766Sken
4152331766Sken	return 0;
4153331766Sken}
4154331766Sken
4155331766Sken/**
4156331766Sken * @ingroup sli
4157331766Sken * @brief Issue a Firmware Reset.
4158331766Sken *
4159331766Sken * @par Description
4160331766Sken * Issues a Firmware Reset to the chip.  This reset affects the entire chip,
4161331766Sken * so all PCI function on the same PCI bus and device are affected.
4162331766Sken * @n @n This type of reset can be used to activate newly downloaded firmware.
4163331766Sken * @n @n The driver should be considered to be in an unknown state after this
4164331766Sken * reset and should be reloaded.
4165331766Sken *
4166331766Sken * @param sli4 SLI context.
4167331766Sken *
4168331766Sken * @return Returns 0 on success, or -1 otherwise.
4169331766Sken */
4170331766Sken
4171331766Skenint32_t
4172331766Skensli_fw_reset(sli4_t *sli4)
4173331766Sken{
4174331766Sken	uint32_t val;
4175331766Sken	uint32_t ready;
4176331766Sken
4177331766Sken	/*
4178331766Sken	 * Firmware must be ready before issuing the reset.
4179331766Sken	 */
4180331766Sken	ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
4181331766Sken	if (!ready) {
4182331766Sken		ocs_log_crit(sli4->os, "FW status is NOT ready\n");
4183331766Sken		return -1;
4184331766Sken	}
4185331766Sken	switch(sli4->if_type) {
4186331766Sken	case SLI4_IF_TYPE_BE3_SKH_PF:
4187331766Sken		/* BE3 / Skyhawk use PCICFG_SOFT_RESET_CSR */
4188331766Sken		val = ocs_config_read32(sli4->os, SLI4_PCI_SOFT_RESET_CSR);
4189331766Sken		val |= SLI4_PCI_SOFT_RESET_MASK;
4190331766Sken		ocs_config_write32(sli4->os, SLI4_PCI_SOFT_RESET_CSR, val);
4191331766Sken		break;
4192331766Sken	case SLI4_IF_TYPE_LANCER_FC_ETH:
4193331766Sken		/* Lancer uses PHYDEV_CONTROL */
4194331766Sken
4195331766Sken		val = SLI4_PHYDEV_CONTROL_FRST;
4196331766Sken		sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, val);
4197331766Sken		break;
4198331766Sken	default:
4199331766Sken		ocs_log_test(sli4->os, "Unexpected iftype %d\n", sli4->if_type);
4200331766Sken		return -1;
4201331766Sken		break;
4202331766Sken	}
4203331766Sken
4204331766Sken	/* wait for the FW to become ready after the reset */
4205331766Sken	ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
4206331766Sken	if (!ready) {
4207331766Sken		ocs_log_crit(sli4->os, "Failed to become ready after firmware reset\n");
4208331766Sken		return -1;
4209331766Sken	}
4210331766Sken	return 0;
4211331766Sken}
4212331766Sken
4213331766Sken/**
4214331766Sken * @ingroup sli
4215331766Sken * @brief Tear down a SLI context.
4216331766Sken *
4217331766Sken * @param sli4 SLI context.
4218331766Sken *
4219331766Sken * @return Returns 0 on success, or non-zero otherwise.
4220331766Sken */
4221331766Skenint32_t
4222331766Skensli_teardown(sli4_t *sli4)
4223331766Sken{
4224331766Sken	uint32_t i;
4225331766Sken
4226331766Sken	if (sli4->config.extent[0].base) {
4227331766Sken		ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
4228331766Sken		sli4->config.extent[0].base = NULL;
4229331766Sken	}
4230331766Sken
4231331766Sken	for (i = 0; i < SLI_RSRC_MAX; i++) {
4232331766Sken		if (sli4->config.has_extents) {
4233331766Sken			/* TODO COMMON_DEALLOC_RESOURCE_EXTENTS */;
4234331766Sken		}
4235331766Sken
4236331766Sken		sli4->config.extent[i].base = NULL;
4237331766Sken
4238331766Sken		ocs_bitmap_free(sli4->config.extent[i].use_map);
4239331766Sken		sli4->config.extent[i].use_map = NULL;
4240331766Sken	}
4241331766Sken
4242331766Sken	if (sli_fw_term(sli4)) {
4243331766Sken		ocs_log_err(sli4->os, "FW deinitialization failed\n");
4244331766Sken	}
4245331766Sken
4246331766Sken	ocs_dma_free(sli4->os, &sli4->vpd.data);
4247331766Sken	ocs_dma_free(sli4->os, &sli4->bmbx);
4248331766Sken
4249331766Sken	return 0;
4250331766Sken}
4251331766Sken
4252331766Sken/**
4253331766Sken * @ingroup sli
4254331766Sken * @brief Register a callback for the given event.
4255331766Sken *
4256331766Sken * @param sli4 SLI context.
4257331766Sken * @param which Event of interest.
4258331766Sken * @param func Function to call when the event occurs.
4259331766Sken * @param arg Argument passed to the callback function.
4260331766Sken *
4261331766Sken * @return Returns 0 on success, or non-zero otherwise.
4262331766Sken */
4263331766Skenint32_t
4264331766Skensli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg)
4265331766Sken{
4266331766Sken
4267331766Sken	if (!sli4 || !func || (which >= SLI4_CB_MAX)) {
4268331766Sken		ocs_log_err(NULL, "bad parameter sli4=%p which=%#x func=%p\n",
4269331766Sken			    sli4, which, func);
4270331766Sken		return -1;
4271331766Sken	}
4272331766Sken
4273331766Sken	switch (which) {
4274331766Sken	case SLI4_CB_LINK:
4275331766Sken		sli4->link = func;
4276331766Sken		sli4->link_arg = arg;
4277331766Sken		break;
4278331766Sken	case SLI4_CB_FIP:
4279331766Sken		sli4->fip = func;
4280331766Sken		sli4->fip_arg = arg;
4281331766Sken		break;
4282331766Sken	default:
4283331766Sken		ocs_log_test(sli4->os, "unknown callback %#x\n", which);
4284331766Sken		return -1;
4285331766Sken	}
4286331766Sken
4287331766Sken	return 0;
4288331766Sken}
4289331766Sken
4290331766Sken/**
4291331766Sken * @ingroup sli
4292331766Sken * @brief Initialize a queue object.
4293331766Sken *
4294331766Sken * @par Description
4295331766Sken * This initializes the sli4_queue_t object members, including the underlying
4296331766Sken * DMA memory.
4297331766Sken *
4298331766Sken * @param sli4 SLI context.
4299331766Sken * @param q Pointer to queue object.
4300331766Sken * @param qtype Type of queue to create.
4301331766Sken * @param size Size of each entry.
4302331766Sken * @param n_entries Number of entries to allocate.
4303331766Sken * @param align Starting memory address alignment.
4304331766Sken *
4305331766Sken * @note Checks if using the existing DMA memory (if any) is possible. If not,
4306331766Sken * it frees the existing memory and re-allocates.
4307331766Sken *
4308331766Sken * @return Returns 0 on success, or non-zero otherwise.
4309331766Sken */
4310331766Skenint32_t
4311331766Sken__sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype,
4312331766Sken		size_t size, uint32_t n_entries, uint32_t align)
4313331766Sken{
4314331766Sken
4315331766Sken	if ((q->dma.virt == NULL) || (size != q->size) || (n_entries != q->length)) {
4316331766Sken		if (q->dma.size) {
4317331766Sken			ocs_dma_free(sli4->os, &q->dma);
4318331766Sken		}
4319331766Sken
4320331766Sken		ocs_memset(q, 0, sizeof(sli4_queue_t));
4321331766Sken
4322331766Sken		if (ocs_dma_alloc(sli4->os, &q->dma, size * n_entries, align)) {
4323331766Sken			ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
4324331766Sken			return -1;
4325331766Sken		}
4326331766Sken
4327331766Sken		ocs_memset(q->dma.virt, 0, size * n_entries);
4328331766Sken
4329331766Sken		ocs_lock_init(sli4->os, &q->lock, "%s lock[%d:%p]",
4330331766Sken			SLI_QNAME[qtype], ocs_instance(sli4->os), &q->lock);
4331331766Sken
4332331766Sken		q->type = qtype;
4333331766Sken		q->size = size;
4334331766Sken		q->length = n_entries;
4335331766Sken
4336331766Sken		/* Limit to hwf the queue size per interrupt */
4337331766Sken		q->proc_limit = n_entries / 2;
4338331766Sken
4339331766Sken		switch(q->type) {
4340331766Sken		case SLI_QTYPE_EQ:
4341331766Sken			q->posted_limit = q->length / 2;
4342331766Sken			break;
4343331766Sken		default:
4344331766Sken			if ((sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) ||
4345331766Sken			    (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF)) {
4346331766Sken				/* For Skyhawk, ring the doorbell more often */
4347331766Sken				q->posted_limit = 8;
4348331766Sken			} else {
4349331766Sken				q->posted_limit = 64;
4350331766Sken			}
4351331766Sken			break;
4352331766Sken		}
4353331766Sken	}
4354331766Sken
4355331766Sken	return 0;
4356331766Sken}
4357331766Sken
4358331766Sken/**
4359331766Sken * @ingroup sli
4360331766Sken * @brief Issue the command to create a queue.
4361331766Sken *
4362331766Sken * @param sli4 SLI context.
4363331766Sken * @param q Pointer to queue object.
4364331766Sken *
4365331766Sken * @return Returns 0 on success, or non-zero otherwise.
4366331766Sken */
4367331766Skenint32_t
4368331766Sken__sli_create_queue(sli4_t *sli4, sli4_queue_t *q)
4369331766Sken{
4370331766Sken	sli4_res_common_create_queue_t *res_q = NULL;
4371331766Sken
4372331766Sken	if (sli_bmbx_command(sli4)){
4373331766Sken		ocs_log_crit(sli4->os, "bootstrap mailbox write fail %s\n",
4374331766Sken				SLI_QNAME[q->type]);
4375331766Sken		ocs_dma_free(sli4->os, &q->dma);
4376331766Sken		return -1;
4377331766Sken	}
4378331766Sken	if (sli_res_sli_config(sli4->bmbx.virt)) {
4379331766Sken		ocs_log_err(sli4->os, "bad status create %s\n", SLI_QNAME[q->type]);
4380331766Sken		ocs_dma_free(sli4->os, &q->dma);
4381331766Sken		return -1;
4382331766Sken	}
4383331766Sken	res_q = (void *)((uint8_t *)sli4->bmbx.virt +
4384331766Sken			offsetof(sli4_cmd_sli_config_t, payload));
4385331766Sken
4386331766Sken	if (res_q->hdr.status) {
4387331766Sken		ocs_log_err(sli4->os, "bad create %s status=%#x addl=%#x\n",
4388331766Sken				SLI_QNAME[q->type],
4389331766Sken				res_q->hdr.status, res_q->hdr.additional_status);
4390331766Sken		ocs_dma_free(sli4->os, &q->dma);
4391331766Sken		return -1;
4392331766Sken	} else {
4393331766Sken		q->id = res_q->q_id;
4394331766Sken		q->doorbell_offset = res_q->db_offset;
4395331766Sken		q->doorbell_rset = res_q->db_rs;
4396331766Sken
4397331766Sken		switch (q->type) {
4398331766Sken		case SLI_QTYPE_EQ:
4399331766Sken			/* No doorbell information in response for EQs */
4400331766Sken			q->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
4401331766Sken			q->doorbell_rset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
4402331766Sken			break;
4403331766Sken		case SLI_QTYPE_CQ:
4404331766Sken			/* No doorbell information in response for CQs */
4405331766Sken			q->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
4406331766Sken			q->doorbell_rset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
4407331766Sken			break;
4408331766Sken		case SLI_QTYPE_MQ:
4409331766Sken			/* No doorbell information in response for MQs */
4410331766Sken			q->doorbell_offset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].off;
4411331766Sken			q->doorbell_rset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].rset;
4412331766Sken			break;
4413331766Sken		case SLI_QTYPE_RQ:
4414331766Sken			/* set the doorbell for non-skyhawks */
4415331766Sken			if (!sli4->config.dual_ulp_capable) {
4416331766Sken				q->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
4417331766Sken				q->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
4418331766Sken			}
4419331766Sken			break;
4420331766Sken		case SLI_QTYPE_WQ:
4421331766Sken			/* set the doorbell for non-skyhawks */
4422331766Sken			if (!sli4->config.dual_ulp_capable) {
4423331766Sken				q->doorbell_offset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].off;
4424331766Sken				q->doorbell_rset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].rset;
4425331766Sken			}
4426331766Sken			break;
4427331766Sken		default:
4428331766Sken			break;
4429331766Sken		}
4430331766Sken	}
4431331766Sken
4432331766Sken	return 0;
4433331766Sken}
4434331766Sken
4435331766Sken/**
4436331766Sken * @ingroup sli
4437331766Sken * @brief Get queue entry size.
4438331766Sken *
4439331766Sken * Get queue entry size given queue type.
4440331766Sken *
4441331766Sken * @param sli4 SLI context
4442331766Sken * @param qtype Type for which the entry size is returned.
4443331766Sken *
4444331766Sken * @return Returns > 0 on success (queue entry size), or a negative value on failure.
4445331766Sken */
4446331766Skenint32_t
4447331766Skensli_get_queue_entry_size(sli4_t *sli4, uint32_t qtype)
4448331766Sken{
4449331766Sken	uint32_t	size = 0;
4450331766Sken
4451331766Sken	if (!sli4) {
4452331766Sken		ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
4453331766Sken		return -1;
4454331766Sken	}
4455331766Sken
4456331766Sken	switch (qtype) {
4457331766Sken	case SLI_QTYPE_EQ:
4458331766Sken		size = sizeof(uint32_t);
4459331766Sken		break;
4460331766Sken	case SLI_QTYPE_CQ:
4461331766Sken		size = 16;
4462331766Sken		break;
4463331766Sken	case SLI_QTYPE_MQ:
4464331766Sken		size = 256;
4465331766Sken		break;
4466331766Sken	case SLI_QTYPE_WQ:
4467331766Sken		if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4468331766Sken			size = sli4->config.wqe_size;
4469331766Sken		} else {
4470331766Sken			/* TODO */
4471331766Sken			ocs_log_test(sli4->os, "unsupported queue entry size\n");
4472331766Sken			return -1;
4473331766Sken		}
4474331766Sken		break;
4475331766Sken	case SLI_QTYPE_RQ:
4476331766Sken		size = SLI4_FCOE_RQE_SIZE;
4477331766Sken		break;
4478331766Sken	default:
4479331766Sken		ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
4480331766Sken		return -1;
4481331766Sken	}
4482331766Sken	return size;
4483331766Sken}
4484331766Sken
4485331766Sken/**
4486331766Sken * @ingroup sli
4487331766Sken * @brief Modify the delay timer for all the EQs
4488331766Sken *
4489331766Sken * @param sli4 SLI context.
4490331766Sken * @param eq Array of EQs.
4491331766Sken * @param num_eq Count of EQs.
4492331766Sken * @param shift Phase shift for staggering interrupts.
4493331766Sken * @param delay_mult Delay multiplier for limiting interrupt frequency.
4494331766Sken *
4495331766Sken * @return Returns 0 on success, or -1 otherwise.
4496331766Sken */
4497331766Skenint32_t
4498331766Skensli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult)
4499331766Sken{
4500331766Sken
4501331766Sken	sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, eq, num_eq, shift, delay_mult);
4502331766Sken
4503331766Sken	if (sli_bmbx_command(sli4)) {
4504331766Sken		ocs_log_crit(sli4->os, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n");
4505331766Sken		return -1;
4506331766Sken	}
4507331766Sken	if (sli_res_sli_config(sli4->bmbx.virt)) {
4508331766Sken		ocs_log_err(sli4->os, "bad status MODIFY EQ DELAY\n");
4509331766Sken		return -1;
4510331766Sken	}
4511331766Sken
4512331766Sken	return 0;
4513331766Sken}
4514331766Sken
4515331766Sken/**
4516331766Sken * @ingroup sli
4517331766Sken * @brief Allocate a queue.
4518331766Sken *
4519331766Sken * @par Description
4520331766Sken * Allocates DMA memory and configures the requested queue type.
4521331766Sken *
4522331766Sken * @param sli4 SLI context.
4523331766Sken * @param qtype Type of queue to create.
4524331766Sken * @param q Pointer to the queue object.
4525331766Sken * @param n_entries Number of entries to allocate.
4526331766Sken * @param assoc Associated queue (that is, the EQ for a CQ, the CQ for a MQ, and so on).
4527331766Sken * @param ulp The ULP to bind, which is only used for WQ and RQs
4528331766Sken *
4529331766Sken * @return Returns 0 on success, or -1 otherwise.
4530331766Sken */
4531331766Skenint32_t
4532331766Skensli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries,
4533331766Sken		sli4_queue_t *assoc, uint16_t ulp)
4534331766Sken{
4535331766Sken	int32_t		size;
4536331766Sken	uint32_t	align = 0;
4537331766Sken	sli4_create_q_fn_t create = NULL;
4538331766Sken
4539331766Sken	if (!sli4 || !q) {
4540331766Sken		ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
4541331766Sken		return -1;
4542331766Sken	}
4543331766Sken
4544331766Sken	/* get queue size */
4545331766Sken	size = sli_get_queue_entry_size(sli4, qtype);
4546331766Sken	if (size < 0)
4547331766Sken		return -1;
4548331766Sken	align = SLI_PAGE_SIZE;
4549331766Sken
4550331766Sken	switch (qtype) {
4551331766Sken	case SLI_QTYPE_EQ:
4552331766Sken		create = sli_cmd_common_create_eq;
4553331766Sken		break;
4554331766Sken	case SLI_QTYPE_CQ:
4555331766Sken		create = sli_cmd_common_create_cq;
4556331766Sken		break;
4557331766Sken	case SLI_QTYPE_MQ:
4558331766Sken		/* Validate the number of entries */
4559331766Sken		switch (n_entries) {
4560331766Sken		case 16:
4561331766Sken		case 32:
4562331766Sken		case 64:
4563331766Sken		case 128:
4564331766Sken			break;
4565331766Sken		default:
4566331766Sken			ocs_log_test(sli4->os, "illegal n_entries value %d for MQ\n", n_entries);
4567331766Sken			return -1;
4568331766Sken		}
4569331766Sken		assoc->u.flag.is_mq = TRUE;
4570331766Sken		create = sli_cmd_common_create_mq_ext;
4571331766Sken		break;
4572331766Sken	case SLI_QTYPE_WQ:
4573331766Sken		if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4574331766Sken			if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
4575331766Sken				create = sli_cmd_fcoe_wq_create;
4576331766Sken			} else {
4577331766Sken				create = sli_cmd_fcoe_wq_create_v1;
4578331766Sken			}
4579331766Sken		} else {
4580331766Sken			/* TODO */
4581331766Sken			ocs_log_test(sli4->os, "unsupported WQ create\n");
4582331766Sken			return -1;
4583331766Sken		}
4584331766Sken		break;
4585331766Sken	default:
4586331766Sken		ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
4587331766Sken		return -1;
4588331766Sken	}
4589331766Sken
4590331766Sken
4591331766Sken	if (__sli_queue_init(sli4, q, qtype, size, n_entries, align)) {
4592331766Sken		ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
4593331766Sken		return -1;
4594331766Sken	}
4595331766Sken
4596331766Sken	if (create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma, assoc ? assoc->id : 0, ulp)) {
4597331766Sken
4598331766Sken		if (__sli_create_queue(sli4, q)) {
4599331766Sken			ocs_log_err(sli4->os, "create %s failed\n", SLI_QNAME[qtype]);
4600331766Sken			return -1;
4601331766Sken		}
4602331766Sken		q->ulp = ulp;
4603331766Sken	} else {
4604331766Sken		ocs_log_err(sli4->os, "cannot create %s\n", SLI_QNAME[qtype]);
4605331766Sken		return -1;
4606331766Sken	}
4607331766Sken
4608331766Sken	return 0;
4609331766Sken}
4610331766Sken
4611331766Sken
4612331766Sken/**
4613331766Sken * @ingroup sli
4614331766Sken * @brief Allocate a c queue set.
4615331766Sken *
4616331766Sken * @param sli4 SLI context.
4617331766Sken * @param num_cqs to create
4618331766Sken * @param qs Pointers to the queue objects.
4619331766Sken * @param n_entries Number of entries to allocate per CQ.
4620331766Sken * @param eqs Associated event queues
4621331766Sken *
4622331766Sken * @return Returns 0 on success, or -1 otherwise.
4623331766Sken */
4624331766Skenint32_t
4625331766Skensli_cq_alloc_set(sli4_t *sli4, sli4_queue_t *qs[], uint32_t num_cqs,
4626331766Sken		 uint32_t n_entries, sli4_queue_t *eqs[])
4627331766Sken{
4628331766Sken	uint32_t i, offset = 0,  page_bytes = 0, payload_size, cmd_size = 0;
4629331766Sken	uint32_t p = 0, page_size = 0, n_cqe = 0, num_pages_cq;
4630331766Sken	uintptr_t addr;
4631331766Sken	ocs_dma_t dma;
4632331766Sken	sli4_req_common_create_cq_set_v0_t  *req = NULL;
4633331766Sken	sli4_res_common_create_queue_set_t *res = NULL;
4634331766Sken
4635331766Sken	if (!sli4) {
4636331766Sken		ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
4637331766Sken		return -1;
4638331766Sken	}
4639331766Sken
4640331766Sken	/* Align the queue DMA memory */
4641331766Sken	for (i = 0; i < num_cqs; i++) {
4642331766Sken		if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_CQ, SLI4_CQE_BYTES,
4643331766Sken			n_entries, SLI_PAGE_SIZE)) {
4644331766Sken			ocs_log_err(sli4->os, "Queue init failed.\n");
4645331766Sken			goto error;
4646331766Sken		}
4647331766Sken	}
4648331766Sken
4649331766Sken	n_cqe = qs[0]->dma.size / SLI4_CQE_BYTES;
4650331766Sken	switch (n_cqe) {
4651331766Sken	case 256:
4652331766Sken	case 512:
4653331766Sken	case 1024:
4654331766Sken	case 2048:
4655331766Sken		page_size = 1;
4656331766Sken		break;
4657331766Sken	case 4096:
4658331766Sken		page_size = 2;
4659331766Sken		break;
4660331766Sken	default:
4661331766Sken		return -1;
4662331766Sken	}
4663331766Sken
4664331766Sken	page_bytes = page_size * SLI_PAGE_SIZE;
4665331766Sken	num_pages_cq = sli_page_count(qs[0]->dma.size, page_bytes);
4666331766Sken	cmd_size = sizeof(sli4_req_common_create_cq_set_v0_t) + (8 * num_pages_cq * num_cqs);
4667331766Sken	payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_set_t));
4668331766Sken
4669331766Sken	if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
4670331766Sken		ocs_log_err(sli4->os, "DMA allocation failed\n");
4671331766Sken		goto error;
4672331766Sken	}
4673331766Sken	ocs_memset(dma.virt, 0, payload_size);
4674331766Sken
4675331766Sken	if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
4676331766Sken			payload_size, &dma) == -1) {
4677331766Sken		goto error;
4678331766Sken	}
4679331766Sken
4680331766Sken	/* Fill the request structure */
4681331766Sken
4682331766Sken	req = (sli4_req_common_create_cq_set_v0_t *)((uint8_t *)dma.virt);
4683331766Sken	req->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ_SET;
4684331766Sken	req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
4685331766Sken	req->hdr.version = 0;
4686331766Sken	req->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
4687331766Sken	req->page_size = page_size;
4688331766Sken
4689331766Sken	req->num_pages = num_pages_cq;
4690331766Sken	switch (req->num_pages) {
4691331766Sken	case 1:
4692331766Sken		req->cqecnt = SLI4_CQ_CNT_256;
4693331766Sken		break;
4694331766Sken	case 2:
4695331766Sken		req->cqecnt = SLI4_CQ_CNT_512;
4696331766Sken		break;
4697331766Sken	case 4:
4698331766Sken		req->cqecnt = SLI4_CQ_CNT_1024;
4699331766Sken		break;
4700331766Sken	case 8:
4701331766Sken		req->cqecnt = SLI4_CQ_CNT_LARGE;
4702331766Sken		req->cqe_count = n_cqe;
4703331766Sken		break;
4704331766Sken	default:
4705331766Sken		ocs_log_test(sli4->os, "num_pages %d not valid\n", req->num_pages);
4706331766Sken		goto error;
4707331766Sken	}
4708331766Sken
4709331766Sken	req->evt = TRUE;
4710331766Sken	req->valid = TRUE;
4711331766Sken	req->arm = FALSE;
4712331766Sken	req->num_cq_req = num_cqs;
4713331766Sken
4714331766Sken	/* Fill page addresses of all the CQs. */
4715331766Sken	for (i = 0; i < num_cqs; i++) {
4716331766Sken		req->eq_id[i] = eqs[i]->id;
4717331766Sken		for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += page_bytes) {
4718331766Sken			req->page_physical_address[offset].low = ocs_addr32_lo(addr);
4719331766Sken			req->page_physical_address[offset].high = ocs_addr32_hi(addr);
4720331766Sken			offset++;
4721331766Sken		}
4722331766Sken	}
4723331766Sken
4724331766Sken	if (sli_bmbx_command(sli4)) {
4725331766Sken		ocs_log_crit(sli4->os, "bootstrap mailbox write fail CQSet\n");
4726331766Sken		goto error;
4727331766Sken	}
4728331766Sken
4729331766Sken	res = (void *)((uint8_t *)dma.virt);
4730331766Sken	if (res->hdr.status) {
4731331766Sken		ocs_log_err(sli4->os, "bad create CQSet status=%#x addl=%#x\n",
4732331766Sken			res->hdr.status, res->hdr.additional_status);
4733331766Sken		goto error;
4734331766Sken	} else {
4735331766Sken		/* Check if we got all requested CQs. */
4736331766Sken		if (res->num_q_allocated != num_cqs) {
4737331766Sken			ocs_log_crit(sli4->os, "Requested count CQs doesnt match.\n");
4738331766Sken			goto error;
4739331766Sken		}
4740331766Sken
4741331766Sken		/* Fill the resp cq ids. */
4742331766Sken		for (i = 0; i < num_cqs; i++) {
4743331766Sken			qs[i]->id = res->q_id + i;
4744331766Sken			qs[i]->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
4745331766Sken			qs[i]->doorbell_rset   = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
4746331766Sken		}
4747331766Sken	}
4748331766Sken
4749331766Sken	ocs_dma_free(sli4->os, &dma);
4750331766Sken
4751331766Sken	return 0;
4752331766Sken
4753331766Skenerror:
4754331766Sken	for (i = 0; i < num_cqs; i++) {
4755331766Sken		if (qs[i]->dma.size) {
4756331766Sken			ocs_dma_free(sli4->os, &qs[i]->dma);
4757331766Sken		}
4758331766Sken	}
4759331766Sken
4760331766Sken	if (dma.size) {
4761331766Sken		ocs_dma_free(sli4->os, &dma);
4762331766Sken	}
4763331766Sken
4764331766Sken	return -1;
4765331766Sken}
4766331766Sken
4767331766Sken
4768331766Sken
4769331766Sken/**
4770331766Sken * @ingroup sli
4771331766Sken * @brief Free a queue.
4772331766Sken *
4773331766Sken * @par Description
4774331766Sken * Frees DMA memory and de-registers the requested queue.
4775331766Sken *
4776331766Sken * @param sli4 SLI context.
4777331766Sken * @param q Pointer to the queue object.
4778331766Sken * @param destroy_queues Non-zero if the mailbox commands should be sent to destroy the queues.
4779331766Sken * @param free_memory Non-zero if the DMA memory associated with the queue should be freed.
4780331766Sken *
4781331766Sken * @return Returns 0 on success, or -1 otherwise.
4782331766Sken */
4783331766Skenint32_t
4784331766Skensli_queue_free(sli4_t *sli4, sli4_queue_t *q, uint32_t destroy_queues, uint32_t free_memory)
4785331766Sken{
4786331766Sken	sli4_destroy_q_fn_t destroy = NULL;
4787331766Sken	int32_t		rc = -1;
4788331766Sken
4789331766Sken	if (!sli4 || !q) {
4790331766Sken		ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
4791331766Sken		return -1;
4792331766Sken	}
4793331766Sken
4794331766Sken	if (destroy_queues) {
4795331766Sken		switch (q->type) {
4796331766Sken		case SLI_QTYPE_EQ:
4797331766Sken			destroy = sli_cmd_common_destroy_eq;
4798331766Sken			break;
4799331766Sken		case SLI_QTYPE_CQ:
4800331766Sken			destroy = sli_cmd_common_destroy_cq;
4801331766Sken			break;
4802331766Sken		case SLI_QTYPE_MQ:
4803331766Sken			destroy = sli_cmd_common_destroy_mq;
4804331766Sken			break;
4805331766Sken		case SLI_QTYPE_WQ:
4806331766Sken			if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4807331766Sken				destroy = sli_cmd_fcoe_wq_destroy;
4808331766Sken			} else {
4809331766Sken				/* TODO */
4810331766Sken				ocs_log_test(sli4->os, "unsupported WQ destroy\n");
4811331766Sken				return -1;
4812331766Sken			}
4813331766Sken			break;
4814331766Sken		case SLI_QTYPE_RQ:
4815331766Sken			if (SLI4_PORT_TYPE_FC == sli4->port_type) {
4816331766Sken				destroy = sli_cmd_fcoe_rq_destroy;
4817331766Sken			} else {
4818331766Sken				/* TODO */
4819331766Sken				ocs_log_test(sli4->os, "unsupported RQ destroy\n");
4820331766Sken				return -1;
4821331766Sken			}
4822331766Sken			break;
4823331766Sken		default:
4824331766Sken			ocs_log_test(sli4->os, "bad queue type %d\n",
4825331766Sken					q->type);
4826331766Sken			return -1;
4827331766Sken		}
4828331766Sken
4829331766Sken		/*
4830331766Sken		 * Destroying queues makes BE3 sad (version 0 interface type). Rely
4831331766Sken		 * on COMMON_FUNCTION_RESET to free host allocated queue resources
4832331766Sken		 * inside the SLI Port.
4833331766Sken		 */
4834331766Sken		if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
4835331766Sken			destroy = NULL;
4836331766Sken		}
4837331766Sken
4838331766Sken		/* Destroy the queue if the operation is defined */
4839331766Sken		if (destroy && destroy(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, q->id)) {
4840331766Sken			sli4_res_hdr_t	*res = NULL;
4841331766Sken
4842331766Sken			if (sli_bmbx_command(sli4)){
4843331766Sken				ocs_log_crit(sli4->os, "bootstrap mailbox write fail destroy %s\n",
4844331766Sken						SLI_QNAME[q->type]);
4845331766Sken			} else if (sli_res_sli_config(sli4->bmbx.virt)) {
4846331766Sken				ocs_log_err(sli4->os, "bad status destroy %s\n", SLI_QNAME[q->type]);
4847331766Sken			} else {
4848331766Sken				res = (void *)((uint8_t *)sli4->bmbx.virt +
4849331766Sken						offsetof(sli4_cmd_sli_config_t, payload));
4850331766Sken
4851331766Sken				if (res->status) {
4852331766Sken					ocs_log_err(sli4->os, "bad destroy %s status=%#x addl=%#x\n",
4853331766Sken							SLI_QNAME[q->type],
4854331766Sken							res->status, res->additional_status);
4855331766Sken				} else {
4856331766Sken					rc = 0;
4857331766Sken				}
4858331766Sken			}
4859331766Sken		}
4860331766Sken	}
4861331766Sken
4862331766Sken	if (free_memory) {
4863331766Sken		ocs_lock_free(&q->lock);
4864331766Sken
4865331766Sken		if (ocs_dma_free(sli4->os, &q->dma)) {
4866331766Sken			ocs_log_err(sli4->os, "%s queue ID %d free failed\n",
4867331766Sken				    SLI_QNAME[q->type], q->id);
4868331766Sken			rc = -1;
4869331766Sken		}
4870331766Sken	}
4871331766Sken
4872331766Sken	return rc;
4873331766Sken}
4874331766Sken
4875331766Skenint32_t
4876331766Skensli_queue_reset(sli4_t *sli4, sli4_queue_t *q)
4877331766Sken{
4878331766Sken
4879331766Sken	ocs_lock(&q->lock);
4880331766Sken
4881331766Sken	q->index = 0;
4882331766Sken	q->n_posted = 0;
4883331766Sken
4884331766Sken	if (SLI_QTYPE_MQ == q->type) {
4885331766Sken		q->u.r_idx = 0;
4886331766Sken	}
4887331766Sken
4888331766Sken	if (q->dma.virt != NULL) {
4889331766Sken		ocs_memset(q->dma.virt, 0, (q->size * q->length));
4890331766Sken	}
4891331766Sken
4892331766Sken	ocs_unlock(&q->lock);
4893331766Sken
4894331766Sken	return 0;
4895331766Sken}
4896331766Sken
4897331766Sken/**
4898331766Sken * @ingroup sli
4899331766Sken * @brief Check if the given queue is empty.
4900331766Sken *
4901331766Sken * @par Description
4902331766Sken * If the valid bit of the current entry is unset, the queue is empty.
4903331766Sken *
4904331766Sken * @param sli4 SLI context.
4905331766Sken * @param q Pointer to the queue object.
4906331766Sken *
4907331766Sken * @return Returns TRUE if empty, or FALSE otherwise.
4908331766Sken */
4909331766Skenint32_t
4910331766Skensli_queue_is_empty(sli4_t *sli4, sli4_queue_t *q)
4911331766Sken{
4912331766Sken	int32_t		rc = TRUE;
4913331766Sken	uint8_t		*qe = q->dma.virt;
4914331766Sken
4915331766Sken	ocs_lock(&q->lock);
4916331766Sken
4917331766Sken	ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
4918331766Sken
4919331766Sken	qe += q->index * q->size;
4920331766Sken
4921331766Sken	rc = !sli_queue_entry_is_valid(q, qe, FALSE);
4922331766Sken
4923331766Sken	ocs_unlock(&q->lock);
4924331766Sken
4925331766Sken	return rc;
4926331766Sken}
4927331766Sken
4928331766Sken/**
4929331766Sken * @ingroup sli
4930331766Sken * @brief Arm an EQ.
4931331766Sken *
4932331766Sken * @param sli4 SLI context.
4933331766Sken * @param q Pointer to queue object.
4934331766Sken * @param arm If TRUE, arm the EQ.
4935331766Sken *
4936331766Sken * @return Returns 0 on success, or non-zero otherwise.
4937331766Sken */
4938331766Skenint32_t
4939331766Skensli_queue_eq_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
4940331766Sken{
4941331766Sken	uint32_t	val = 0;
4942331766Sken
4943331766Sken	ocs_lock(&q->lock);
4944331766Sken		val = sli_eq_doorbell(q->n_posted, q->id, arm);
4945331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
4946331766Sken		q->n_posted = 0;
4947331766Sken	ocs_unlock(&q->lock);
4948331766Sken
4949331766Sken	return 0;
4950331766Sken}
4951331766Sken
4952331766Sken/**
4953331766Sken * @ingroup sli
4954331766Sken * @brief Arm a queue.
4955331766Sken *
4956331766Sken * @param sli4 SLI context.
4957331766Sken * @param q Pointer to queue object.
4958331766Sken * @param arm If TRUE, arm the queue.
4959331766Sken *
4960331766Sken * @return Returns 0 on success, or non-zero otherwise.
4961331766Sken */
4962331766Skenint32_t
4963331766Skensli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
4964331766Sken{
4965331766Sken	uint32_t	val = 0;
4966331766Sken
4967331766Sken	ocs_lock(&q->lock);
4968331766Sken
4969331766Sken	switch (q->type) {
4970331766Sken	case SLI_QTYPE_EQ:
4971331766Sken		val = sli_eq_doorbell(q->n_posted, q->id, arm);
4972331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
4973331766Sken		q->n_posted = 0;
4974331766Sken		break;
4975331766Sken	case SLI_QTYPE_CQ:
4976331766Sken		val = sli_cq_doorbell(q->n_posted, q->id, arm);
4977331766Sken		ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
4978331766Sken		q->n_posted = 0;
4979331766Sken		break;
4980331766Sken	default:
4981331766Sken		ocs_log_test(sli4->os, "should only be used for EQ/CQ, not %s\n",
4982331766Sken			     SLI_QNAME[q->type]);
4983331766Sken	}
4984331766Sken
4985331766Sken	ocs_unlock(&q->lock);
4986331766Sken
4987331766Sken	return 0;
4988331766Sken}
4989331766Sken
4990331766Sken/**
4991331766Sken * @ingroup sli
4992331766Sken * @brief Write an entry to the queue object.
4993331766Sken *
4994331766Sken * Note: Assumes the q->lock will be locked and released by the caller.
4995331766Sken *
4996331766Sken * @param sli4 SLI context.
4997331766Sken * @param q Pointer to the queue object.
4998331766Sken * @param entry Pointer to the entry contents.
4999331766Sken *
5000331766Sken * @return Returns queue index on success, or negative error value otherwise.
5001331766Sken */
5002331766Skenint32_t
5003331766Sken_sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
5004331766Sken{
5005331766Sken	int32_t		rc = 0;
5006331766Sken	uint8_t		*qe = q->dma.virt;
5007331766Sken	uint32_t	qindex;
5008331766Sken
5009331766Sken	qindex = q->index;
5010331766Sken	qe += q->index * q->size;
5011331766Sken
5012331766Sken	if (entry) {
5013331766Sken		if ((SLI_QTYPE_WQ == q->type) && sli4->config.perf_wq_id_association) {
5014331766Sken			sli_set_wq_id_association(entry, q->id);
5015331766Sken		}
5016331766Sken#if defined(OCS_INCLUDE_DEBUG)
5017331766Sken		switch (q->type) {
5018331766Sken		case SLI_QTYPE_WQ: {
5019331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, "wqe", entry, q->size);
5020331766Sken			break;
5021331766Sken
5022331766Sken		}
5023331766Sken		case SLI_QTYPE_MQ:
5024331766Sken			/* Note: we don't really need to dump the whole
5025331766Sken			 * 256 bytes, just do 64 */
5026331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mqe outbound", entry, 64);
5027331766Sken			break;
5028331766Sken
5029331766Sken		default:
5030331766Sken			break;
5031331766Sken		}
5032331766Sken#endif
5033331766Sken		ocs_memcpy(qe, entry, q->size);
5034331766Sken		q->n_posted = 1;
5035331766Sken	}
5036331766Sken
5037331766Sken	ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
5038331766Sken
5039331766Sken	rc = sli_queue_doorbell(sli4, q);
5040331766Sken
5041331766Sken	q->index = (q->index + q->n_posted) & (q->length - 1);
5042331766Sken	q->n_posted = 0;
5043331766Sken
5044331766Sken	if (rc < 0) {
5045331766Sken		/* failure */
5046331766Sken		return rc;
5047331766Sken	} else if (rc > 0) {
5048331766Sken		/* failure, but we need to return a negative value on failure */
5049331766Sken		return -rc;
5050331766Sken	} else {
5051331766Sken		return qindex;
5052331766Sken	}
5053331766Sken}
5054331766Sken
5055331766Sken/**
5056331766Sken * @ingroup sli
5057331766Sken * @brief Write an entry to the queue object.
5058331766Sken *
5059331766Sken * Note: Assumes the q->lock will be locked and released by the caller.
5060331766Sken *
5061331766Sken * @param sli4 SLI context.
5062331766Sken * @param q Pointer to the queue object.
5063331766Sken * @param entry Pointer to the entry contents.
5064331766Sken *
5065331766Sken * @return Returns queue index on success, or negative error value otherwise.
5066331766Sken */
5067331766Skenint32_t
5068331766Skensli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
5069331766Sken{
5070331766Sken	int32_t rc;
5071331766Sken
5072331766Sken	ocs_lock(&q->lock);
5073331766Sken		rc = _sli_queue_write(sli4, q, entry);
5074331766Sken	ocs_unlock(&q->lock);
5075331766Sken
5076331766Sken	return rc;
5077331766Sken}
5078331766Sken
5079331766Sken/**
5080331766Sken * @brief Check if the current queue entry is valid.
5081331766Sken *
5082331766Sken * @param q Pointer to the queue object.
5083331766Sken * @param qe Pointer to the queue entry.
5084331766Sken * @param clear Boolean to clear valid bit.
5085331766Sken *
5086331766Sken * @return Returns TRUE if the entry is valid, or FALSE otherwise.
5087331766Sken */
5088331766Skenstatic uint8_t
5089331766Skensli_queue_entry_is_valid(sli4_queue_t *q, uint8_t *qe, uint8_t clear)
5090331766Sken{
5091331766Sken	uint8_t		valid = FALSE;
5092331766Sken
5093331766Sken	switch (q->type) {
5094331766Sken	case SLI_QTYPE_EQ:
5095331766Sken		valid = ((sli4_eqe_t *)qe)->vld;
5096331766Sken		if (valid && clear) {
5097331766Sken			((sli4_eqe_t *)qe)->vld = 0;
5098331766Sken		}
5099331766Sken		break;
5100331766Sken	case SLI_QTYPE_CQ:
5101331766Sken		/*
5102331766Sken		 * For both MCQE and WCQE/RCQE, the valid bit
5103331766Sken		 * is bit 31 of dword 3 (0 based)
5104331766Sken		 */
5105331766Sken		valid = (qe[15] & 0x80) != 0;
5106331766Sken		if (valid & clear) {
5107331766Sken			qe[15] &= ~0x80;
5108331766Sken		}
5109331766Sken		break;
5110331766Sken	case SLI_QTYPE_MQ:
5111331766Sken		valid = q->index != q->u.r_idx;
5112331766Sken		break;
5113331766Sken	case SLI_QTYPE_RQ:
5114331766Sken		valid = TRUE;
5115331766Sken		clear = FALSE;
5116331766Sken		break;
5117331766Sken	default:
5118331766Sken		ocs_log_test(NULL, "doesn't handle type=%#x\n", q->type);
5119331766Sken	}
5120331766Sken
5121331766Sken	if (clear) {
5122331766Sken		ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
5123331766Sken	}
5124331766Sken
5125331766Sken	return valid;
5126331766Sken}
5127331766Sken
5128331766Sken/**
5129331766Sken * @ingroup sli
5130331766Sken * @brief Read an entry from the queue object.
5131331766Sken *
5132331766Sken * @param sli4 SLI context.
5133331766Sken * @param q Pointer to the queue object.
5134331766Sken * @param entry Destination pointer for the queue entry contents.
5135331766Sken *
5136331766Sken * @return Returns 0 on success, or non-zero otherwise.
5137331766Sken */
5138331766Skenint32_t
5139331766Skensli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
5140331766Sken{
5141331766Sken	int32_t		rc = 0;
5142331766Sken	uint8_t		*qe = q->dma.virt;
5143331766Sken	uint32_t	*qindex = NULL;
5144331766Sken
5145331766Sken	if (SLI_QTYPE_MQ == q->type) {
5146331766Sken		qindex = &q->u.r_idx;
5147331766Sken	} else {
5148331766Sken		qindex = &q->index;
5149331766Sken	}
5150331766Sken
5151331766Sken	ocs_lock(&q->lock);
5152331766Sken
5153331766Sken	ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
5154331766Sken
5155331766Sken	qe += *qindex * q->size;
5156331766Sken
5157331766Sken	if (!sli_queue_entry_is_valid(q, qe, TRUE)) {
5158331766Sken		ocs_unlock(&q->lock);
5159331766Sken		return -1;
5160331766Sken	}
5161331766Sken
5162331766Sken	if (entry) {
5163331766Sken		ocs_memcpy(entry, qe, q->size);
5164331766Sken#if defined(OCS_INCLUDE_DEBUG)
5165331766Sken		switch(q->type) {
5166331766Sken		case SLI_QTYPE_CQ:
5167331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "cq", entry, q->size);
5168331766Sken			break;
5169331766Sken		case SLI_QTYPE_MQ:
5170331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mq Compl", entry, 64);
5171331766Sken			break;
5172331766Sken		case SLI_QTYPE_EQ:
5173331766Sken			ocs_dump32(OCS_DEBUG_ENABLE_EQ_DUMP, sli4->os, "eq Compl", entry, q->size);
5174331766Sken			break;
5175331766Sken		default:
5176331766Sken			break;
5177331766Sken		}
5178331766Sken#endif
5179331766Sken	}
5180331766Sken
5181331766Sken	switch (q->type) {
5182331766Sken		case SLI_QTYPE_EQ:
5183331766Sken		case SLI_QTYPE_CQ:
5184331766Sken		case SLI_QTYPE_MQ:
5185331766Sken			*qindex = (*qindex + 1) & (q->length - 1);
5186331766Sken			if (SLI_QTYPE_MQ != q->type) {
5187331766Sken				q->n_posted++;
5188331766Sken			}
5189331766Sken			break;
5190331766Sken		default:
5191331766Sken			/* reads don't update the index */
5192331766Sken			break;
5193331766Sken	}
5194331766Sken
5195331766Sken	ocs_unlock(&q->lock);
5196331766Sken
5197331766Sken	return rc;
5198331766Sken}
5199331766Sken
5200331766Skenint32_t
5201331766Skensli_queue_index(sli4_t *sli4, sli4_queue_t *q)
5202331766Sken{
5203331766Sken
5204331766Sken	if (q) {
5205331766Sken		return q->index;
5206331766Sken	} else {
5207331766Sken		return -1;
5208331766Sken	}
5209331766Sken}
5210331766Sken
5211331766Skenint32_t
5212331766Skensli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
5213331766Sken{
5214331766Sken	int32_t rc;
5215331766Sken
5216331766Sken	ocs_lock(&q->lock);
5217331766Sken		rc = _sli_queue_poke(sli4, q, index, entry);
5218331766Sken	ocs_unlock(&q->lock);
5219331766Sken
5220331766Sken	return rc;
5221331766Sken}
5222331766Sken
5223331766Skenint32_t
5224331766Sken_sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
5225331766Sken{
5226331766Sken	int32_t		rc = 0;
5227331766Sken	uint8_t		*qe = q->dma.virt;
5228331766Sken
5229331766Sken	if (index >= q->length) {
5230331766Sken		return -1;
5231331766Sken	}
5232331766Sken
5233331766Sken	qe += index * q->size;
5234331766Sken
5235331766Sken	if (entry) {
5236331766Sken		ocs_memcpy(qe, entry, q->size);
5237331766Sken	}
5238331766Sken
5239331766Sken	ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
5240331766Sken
5241331766Sken	return rc;
5242331766Sken}
5243331766Sken
5244331766Sken/**
5245331766Sken * @ingroup sli
5246331766Sken * @brief Allocate SLI Port resources.
5247331766Sken *
5248331766Sken * @par Description
5249331766Sken * Allocate port-related resources, such as VFI, RPI, XRI, and so on.
5250331766Sken * Resources are modeled using extents, regardless of whether the underlying
5251331766Sken * device implements resource extents. If the device does not implement
5252331766Sken * extents, the SLI layer models this as a single (albeit large) extent.
5253331766Sken *
5254331766Sken * @param sli4 SLI context.
5255331766Sken * @param rtype Resource type (for example, RPI or XRI)
5256331766Sken * @param rid Allocated resource ID.
5257331766Sken * @param index Index into the bitmap.
5258331766Sken *
5259331766Sken * @return Returns 0 on success, or a non-zero value on failure.
5260331766Sken */
5261331766Skenint32_t
5262331766Skensli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index)
5263331766Sken{
5264331766Sken	int32_t		rc = 0;
5265331766Sken	uint32_t	size;
5266331766Sken	uint32_t	extent_idx;
5267331766Sken	uint32_t	item_idx;
5268331766Sken	int		status;
5269331766Sken
5270331766Sken	*rid = UINT32_MAX;
5271331766Sken	*index = UINT32_MAX;
5272331766Sken
5273331766Sken	switch (rtype) {
5274331766Sken	case SLI_RSRC_FCOE_VFI:
5275331766Sken	case SLI_RSRC_FCOE_VPI:
5276331766Sken	case SLI_RSRC_FCOE_RPI:
5277331766Sken	case SLI_RSRC_FCOE_XRI:
5278331766Sken		status = ocs_bitmap_find(sli4->config.extent[rtype].use_map,
5279331766Sken				sli4->config.extent[rtype].map_size);
5280331766Sken		if (status < 0) {
5281331766Sken			ocs_log_err(sli4->os, "out of resource %d (alloc=%d)\n",
5282331766Sken					rtype, sli4->config.extent[rtype].n_alloc);
5283331766Sken			rc = -1;
5284331766Sken			break;
5285331766Sken		} else {
5286331766Sken			*index = status;
5287331766Sken		}
5288331766Sken
5289331766Sken		size = sli4->config.extent[rtype].size;
5290331766Sken
5291331766Sken		extent_idx = *index / size;
5292331766Sken		item_idx   = *index % size;
5293331766Sken
5294331766Sken		*rid = sli4->config.extent[rtype].base[extent_idx] + item_idx;
5295331766Sken
5296331766Sken		sli4->config.extent[rtype].n_alloc++;
5297331766Sken		break;
5298331766Sken	default:
5299331766Sken		rc = -1;
5300331766Sken	}
5301331766Sken
5302331766Sken	return rc;
5303331766Sken}
5304331766Sken
5305331766Sken/**
5306331766Sken * @ingroup sli
5307331766Sken * @brief Free the SLI Port resources.
5308331766Sken *
5309331766Sken * @par Description
5310331766Sken * Free port-related resources, such as VFI, RPI, XRI, and so. See discussion of
5311331766Sken * "extent" usage in sli_resource_alloc.
5312331766Sken *
5313331766Sken * @param sli4 SLI context.
5314331766Sken * @param rtype Resource type (for example, RPI or XRI).
5315331766Sken * @param rid Allocated resource ID.
5316331766Sken *
5317331766Sken * @return Returns 0 on success, or a non-zero value on failure.
5318331766Sken */
5319331766Skenint32_t
5320331766Skensli_resource_free(sli4_t *sli4, sli4_resource_e rtype, uint32_t rid)
5321331766Sken{
5322331766Sken	int32_t		rc = -1;
5323331766Sken	uint32_t	x;
5324331766Sken	uint32_t	size, *base;
5325331766Sken
5326331766Sken	switch (rtype) {
5327331766Sken	case SLI_RSRC_FCOE_VFI:
5328331766Sken	case SLI_RSRC_FCOE_VPI:
5329331766Sken	case SLI_RSRC_FCOE_RPI:
5330331766Sken	case SLI_RSRC_FCOE_XRI:
5331331766Sken		/*
5332331766Sken		 * Figure out which extent contains the resource ID. I.e. find
5333331766Sken		 * the extent such that
5334331766Sken		 *   extent->base <= resource ID < extent->base + extent->size
5335331766Sken		 */
5336331766Sken		base = sli4->config.extent[rtype].base;
5337331766Sken		size = sli4->config.extent[rtype].size;
5338331766Sken
5339331766Sken		/*
5340331766Sken		 * In the case of FW reset, this may be cleared but the force_free path will
5341331766Sken		 * still attempt to free the resource. Prevent a NULL pointer access.
5342331766Sken		 */
5343331766Sken		if (base != NULL) {
5344331766Sken			for (x = 0; x < sli4->config.extent[rtype].number; x++) {
5345331766Sken				if ((rid >= base[x]) && (rid < (base[x] + size))) {
5346331766Sken					rid -= base[x];
5347331766Sken					ocs_bitmap_clear(sli4->config.extent[rtype].use_map,
5348331766Sken							 (x * size) + rid);
5349331766Sken					rc = 0;
5350331766Sken					break;
5351331766Sken				}
5352331766Sken			}
5353331766Sken		}
5354331766Sken		break;
5355331766Sken	default:
5356331766Sken		;
5357331766Sken	}
5358331766Sken
5359331766Sken	return rc;
5360331766Sken}
5361331766Sken
5362331766Skenint32_t
5363331766Skensli_resource_reset(sli4_t *sli4, sli4_resource_e rtype)
5364331766Sken{
5365331766Sken	int32_t		rc = -1;
5366331766Sken	uint32_t	i;
5367331766Sken
5368331766Sken	switch (rtype) {
5369331766Sken	case SLI_RSRC_FCOE_VFI:
5370331766Sken	case SLI_RSRC_FCOE_VPI:
5371331766Sken	case SLI_RSRC_FCOE_RPI:
5372331766Sken	case SLI_RSRC_FCOE_XRI:
5373331766Sken		for (i = 0; i < sli4->config.extent[rtype].map_size; i++) {
5374331766Sken			ocs_bitmap_clear(sli4->config.extent[rtype].use_map, i);
5375331766Sken		}
5376331766Sken		rc = 0;
5377331766Sken		break;
5378331766Sken	default:
5379331766Sken		;
5380331766Sken	}
5381331766Sken
5382331766Sken	return rc;
5383331766Sken}
5384331766Sken
5385331766Sken/**
5386331766Sken * @ingroup sli
5387331766Sken * @brief Parse an EQ entry to retrieve the CQ_ID for this event.
5388331766Sken *
5389331766Sken * @param sli4 SLI context.
5390331766Sken * @param buf Pointer to the EQ entry.
5391331766Sken * @param cq_id CQ_ID for this entry (only valid on success).
5392331766Sken *
5393331766Sken * @return
5394331766Sken * - 0 if success.
5395331766Sken * - < 0 if error.
5396331766Sken * - > 0 if firmware detects EQ overflow.
5397331766Sken */
5398331766Skenint32_t
5399331766Skensli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id)
5400331766Sken{
5401331766Sken	sli4_eqe_t	*eqe = (void *)buf;
5402331766Sken	int32_t		rc = 0;
5403331766Sken
5404331766Sken	if (!sli4 || !buf || !cq_id) {
5405331766Sken		ocs_log_err(NULL, "bad parameters sli4=%p buf=%p cq_id=%p\n",
5406331766Sken				sli4, buf, cq_id);
5407331766Sken		return -1;
5408331766Sken	}
5409331766Sken
5410331766Sken	switch (eqe->major_code) {
5411331766Sken	case SLI4_MAJOR_CODE_STANDARD:
5412331766Sken		*cq_id = eqe->resource_id;
5413331766Sken		break;
5414331766Sken	case SLI4_MAJOR_CODE_SENTINEL:
5415331766Sken		ocs_log_debug(sli4->os, "sentinel EQE\n");
5416331766Sken		rc = 1;
5417331766Sken		break;
5418331766Sken	default:
5419331766Sken		ocs_log_test(sli4->os, "Unsupported EQE: major %x minor %x\n",
5420331766Sken				eqe->major_code, eqe->minor_code);
5421331766Sken		rc = -1;
5422331766Sken	}
5423331766Sken
5424331766Sken	return rc;
5425331766Sken}
5426331766Sken
5427331766Sken/**
5428331766Sken * @ingroup sli
5429331766Sken * @brief Parse a CQ entry to retrieve the event type and the associated queue.
5430331766Sken *
5431331766Sken * @param sli4 SLI context.
5432331766Sken * @param cq CQ to process.
5433331766Sken * @param cqe Pointer to the CQ entry.
5434331766Sken * @param etype CQ event type.
5435331766Sken * @param q_id Queue ID associated with this completion message
5436331766Sken * (that is, MQ_ID, RQ_ID, and so on).
5437331766Sken *
5438331766Sken * @return
5439331766Sken * - 0 if call completed correctly and CQE status is SUCCESS.
5440331766Sken * - -1 if call failed (no CQE status).
5441331766Sken * - Other value if call completed correctly and return value is a CQE status value.
5442331766Sken */
5443331766Skenint32_t
5444331766Skensli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
5445331766Sken		uint16_t *q_id)
5446331766Sken{
5447331766Sken	int32_t	rc = 0;
5448331766Sken
5449331766Sken	if (!sli4 || !cq || !cqe || !etype) {
5450331766Sken		ocs_log_err(NULL, "bad parameters sli4=%p cq=%p cqe=%p etype=%p q_id=%p\n",
5451331766Sken			    sli4, cq, cqe, etype, q_id);
5452331766Sken		return -1;
5453331766Sken	}
5454331766Sken
5455331766Sken	if (cq->u.flag.is_mq) {
5456331766Sken		sli4_mcqe_t	*mcqe = (void *)cqe;
5457331766Sken
5458331766Sken		if (mcqe->ae) {
5459331766Sken			*etype = SLI_QENTRY_ASYNC;
5460331766Sken		} else {
5461331766Sken			*etype = SLI_QENTRY_MQ;
5462331766Sken			rc = sli_cqe_mq(mcqe);
5463331766Sken		}
5464331766Sken		*q_id = -1;
5465331766Sken	} else if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5466331766Sken		rc = sli_fc_cqe_parse(sli4, cq, cqe, etype, q_id);
5467331766Sken	} else {
5468331766Sken		ocs_log_test(sli4->os, "implement CQE parsing type = %#x\n",
5469331766Sken			     sli4->port_type);
5470331766Sken		rc = -1;
5471331766Sken	}
5472331766Sken
5473331766Sken	return rc;
5474331766Sken}
5475331766Sken
5476331766Sken/**
5477331766Sken * @ingroup sli
5478331766Sken * @brief Cause chip to enter an unrecoverable error state.
5479331766Sken *
5480331766Sken * @par Description
5481331766Sken * Cause chip to enter an unrecoverable error state. This is
5482331766Sken * used when detecting unexpected FW behavior so FW can be
5483331766Sken * hwted from the driver as soon as error is detected.
5484331766Sken *
5485331766Sken * @param sli4 SLI context.
5486331766Sken * @param dump Generate dump as part of reset.
5487331766Sken *
5488331766Sken * @return Returns 0 if call completed correctly, or -1 if call failed (unsupported chip).
5489331766Sken */
5490331766Skenint32_t sli_raise_ue(sli4_t *sli4, uint8_t dump)
5491331766Sken{
5492331766Sken#define FDD 2
5493331766Sken	if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
5494331766Sken		switch(sli_get_asic_type(sli4)) {
5495331766Sken		case SLI4_ASIC_TYPE_BE3: {
5496331766Sken			sli_reg_write(sli4, SLI4_REG_SW_UE_CSR1, 0xffffffff);
5497331766Sken			sli_reg_write(sli4, SLI4_REG_SW_UE_CSR2, 0);
5498331766Sken			break;
5499331766Sken		}
5500331766Sken		case SLI4_ASIC_TYPE_SKYHAWK: {
5501331766Sken			uint32_t value;
5502331766Sken			value = ocs_config_read32(sli4->os, SLI4_SW_UE_REG);
5503331766Sken			ocs_config_write32(sli4->os, SLI4_SW_UE_REG, (value | (1U << 24)));
5504331766Sken			break;
5505331766Sken		}
5506331766Sken		default:
5507331766Sken			ocs_log_test(sli4->os, "invalid asic type %d\n", sli_get_asic_type(sli4));
5508331766Sken			return -1;
5509331766Sken		}
5510331766Sken	} else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) {
5511331766Sken		if (dump == FDD) {
5512331766Sken			sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, SLI4_SLIPORT_CONTROL_FDD | SLI4_SLIPORT_CONTROL_IP);
5513331766Sken		} else {
5514331766Sken			uint32_t value = SLI4_PHYDEV_CONTROL_FRST;
5515331766Sken			if (dump == 1) {
5516331766Sken				value |= SLI4_PHYDEV_CONTROL_DD;
5517331766Sken			}
5518331766Sken			sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, value);
5519331766Sken		}
5520331766Sken	} else {
5521331766Sken		ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
5522331766Sken		return -1;
5523331766Sken	}
5524331766Sken	return 0;
5525331766Sken}
5526331766Sken
5527331766Sken/**
5528331766Sken * @ingroup sli
5529331766Sken * @brief Read the SLIPORT_STATUS register to to check if a dump is present.
5530331766Sken *
5531331766Sken * @param sli4 SLI context.
5532331766Sken *
5533331766Sken * @return  Returns 1 if the chip is ready, or 0 if the chip is not ready, 2 if fdp is present.
5534331766Sken */
5535331766Skenint32_t sli_dump_is_ready(sli4_t *sli4)
5536331766Sken{
5537331766Sken	int32_t	rc = 0;
5538331766Sken	uint32_t port_val;
5539331766Sken	uint32_t bmbx_val;
5540331766Sken	uint32_t uerr_lo;
5541331766Sken	uint32_t uerr_hi;
5542331766Sken	uint32_t uerr_mask_lo;
5543331766Sken	uint32_t uerr_mask_hi;
5544331766Sken
5545331766Sken	if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
5546331766Sken		/* for iftype=0, dump ready when UE is encountered */
5547331766Sken		uerr_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
5548331766Sken		uerr_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
5549331766Sken		uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
5550331766Sken		uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
5551331766Sken		if ((uerr_lo & ~uerr_mask_lo) || (uerr_hi & ~uerr_mask_hi)) {
5552331766Sken			rc = 1;
5553331766Sken		}
5554331766Sken
5555331766Sken	} else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) {
5556331766Sken		/*
5557331766Sken		 * Ensure that the port is ready AND the mailbox is
5558331766Sken		 * ready before signaling that the dump is ready to go.
5559331766Sken		 */
5560331766Sken		port_val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5561331766Sken		bmbx_val = sli_reg_read(sli4, SLI4_REG_BMBX);
5562331766Sken
5563331766Sken		if ((bmbx_val & SLI4_BMBX_RDY) &&
5564331766Sken		    SLI4_PORT_STATUS_READY(port_val)) {
5565331766Sken		    	if(SLI4_PORT_STATUS_DUMP_PRESENT(port_val)) {
5566331766Sken				rc = 1;
5567331766Sken			}else if( SLI4_PORT_STATUS_FDP_PRESENT(port_val)) {
5568331766Sken				rc = 2;
5569331766Sken			}
5570331766Sken		}
5571331766Sken	} else {
5572331766Sken		ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
5573331766Sken		return -1;
5574331766Sken	}
5575331766Sken	return rc;
5576331766Sken}
5577331766Sken
5578331766Sken/**
5579331766Sken * @ingroup sli
5580331766Sken * @brief Read the SLIPORT_STATUS register to check if a dump is present.
5581331766Sken *
5582331766Sken * @param sli4 SLI context.
5583331766Sken *
5584331766Sken * @return
5585331766Sken * - 0 if call completed correctly and no dump is present.
5586331766Sken * - 1 if call completed and dump is present.
5587331766Sken * - -1 if call failed (unsupported chip).
5588331766Sken */
5589331766Skenint32_t sli_dump_is_present(sli4_t *sli4)
5590331766Sken{
5591331766Sken	uint32_t val;
5592331766Sken	uint32_t ready;
5593331766Sken
5594331766Sken	if (SLI4_IF_TYPE_LANCER_FC_ETH != sli_get_if_type(sli4)) {
5595331766Sken		ocs_log_test(sli4->os, "Function only supported for I/F type 2");
5596331766Sken		return -1;
5597331766Sken	}
5598331766Sken
5599331766Sken	/* If the chip is not ready, then there cannot be a dump */
5600331766Sken	ready = sli_wait_for_fw_ready(sli4, SLI4_INIT_PORT_DELAY_US);
5601331766Sken	if (!ready) {
5602331766Sken		return 0;
5603331766Sken	}
5604331766Sken
5605331766Sken	val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5606331766Sken	if (UINT32_MAX == val) {
5607331766Sken		ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
5608331766Sken		return -1;
5609331766Sken	} else {
5610331766Sken		return ((val & SLI4_PORT_STATUS_DIP) ? 1 : 0);
5611331766Sken	}
5612331766Sken}
5613331766Sken
5614331766Sken/**
5615331766Sken * @ingroup sli
5616331766Sken * @brief Read the SLIPORT_STATUS register to check if the reset required is set.
5617331766Sken *
5618331766Sken * @param sli4 SLI context.
5619331766Sken *
5620331766Sken * @return
5621331766Sken * - 0 if call completed correctly and reset is not required.
5622331766Sken * - 1 if call completed and reset is required.
5623331766Sken * - -1 if call failed.
5624331766Sken */
5625331766Skenint32_t sli_reset_required(sli4_t *sli4)
5626331766Sken{
5627331766Sken	uint32_t val;
5628331766Sken
5629331766Sken	if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
5630331766Sken		ocs_log_test(sli4->os, "reset required N/A for iftype 0\n");
5631331766Sken		return 0;
5632331766Sken	}
5633331766Sken
5634331766Sken	val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5635331766Sken	if (UINT32_MAX == val) {
5636331766Sken		ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
5637331766Sken		return -1;
5638331766Sken	} else {
5639331766Sken		return ((val & SLI4_PORT_STATUS_RN) ? 1 : 0);
5640331766Sken	}
5641331766Sken}
5642331766Sken
5643331766Sken/**
5644331766Sken * @ingroup sli
5645331766Sken * @brief Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if
5646331766Sken * the port status indicates that a FW error has occurred.
5647331766Sken *
5648331766Sken * @param sli4 SLI context.
5649331766Sken *
5650331766Sken * @return
5651331766Sken * - 0 if call completed correctly and no FW error occurred.
5652331766Sken * - > 0 which indicates that a FW error has occurred.
5653331766Sken * - -1 if call failed.
5654331766Sken */
5655331766Skenint32_t sli_fw_error_status(sli4_t *sli4)
5656331766Sken{
5657331766Sken	uint32_t sliport_semaphore;
5658331766Sken	int32_t rc = 0;
5659331766Sken
5660331766Sken	sliport_semaphore = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
5661331766Sken	if (UINT32_MAX == sliport_semaphore) {
5662331766Sken		ocs_log_err(sli4->os, "error reading SLIPORT_SEMAPHORE register\n");
5663331766Sken		return 1;
5664331766Sken	}
5665331766Sken	rc = (SLI4_PORT_SEMAPHORE_IN_ERR(sliport_semaphore) ? 1 : 0);
5666331766Sken
5667331766Sken	if (rc == 0) {
5668331766Sken		if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
5669331766Sken		    (SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type)) {
5670331766Sken			uint32_t uerr_mask_lo, uerr_mask_hi;
5671331766Sken			uint32_t uerr_status_lo, uerr_status_hi;
5672331766Sken
5673331766Sken			uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
5674331766Sken			uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
5675331766Sken			uerr_status_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
5676331766Sken			uerr_status_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
5677331766Sken			if ((uerr_mask_lo & uerr_status_lo) != 0 ||
5678331766Sken			    (uerr_mask_hi & uerr_status_hi) != 0) {
5679331766Sken				rc = 1;
5680331766Sken			}
5681331766Sken		} else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type)) {
5682331766Sken			uint32_t sliport_status;
5683331766Sken
5684331766Sken			sliport_status = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5685331766Sken			rc = (SLI4_PORT_STATUS_ERROR(sliport_status) ? 1 : 0);
5686331766Sken		}
5687331766Sken	}
5688331766Sken	return rc;
5689331766Sken}
5690331766Sken
5691331766Sken/**
5692331766Sken * @ingroup sli
5693331766Sken * @brief Determine if the chip FW is in a ready state
5694331766Sken *
5695331766Sken * @param sli4 SLI context.
5696331766Sken *
5697331766Sken * @return
5698331766Sken * - 0 if call completed correctly and FW is not ready.
5699331766Sken * - 1 if call completed correctly and FW is ready.
5700331766Sken * - -1 if call failed.
5701331766Sken */
5702331766Skenint32_t
5703331766Skensli_fw_ready(sli4_t *sli4)
5704331766Sken{
5705331766Sken	uint32_t val;
5706331766Sken	int32_t rc = -1;
5707331766Sken
5708331766Sken	/*
5709331766Sken	 * Is firmware ready for operation? Check needed depends on IF_TYPE
5710331766Sken	 */
5711331766Sken	if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
5712331766Sken	    SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type) {
5713331766Sken		val = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
5714331766Sken		rc = ((SLI4_PORT_SEMAPHORE_STATUS_POST_READY ==
5715331766Sken		       SLI4_PORT_SEMAPHORE_PORT(val)) &&
5716331766Sken		      (!SLI4_PORT_SEMAPHORE_IN_ERR(val)) ? 1 : 0);
5717331766Sken	} else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) {
5718331766Sken		val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
5719331766Sken		rc = (SLI4_PORT_STATUS_READY(val) ? 1 : 0);
5720331766Sken	}
5721331766Sken	return rc;
5722331766Sken}
5723331766Sken
5724331766Sken/**
5725331766Sken * @ingroup sli
5726331766Sken * @brief Determine if the link can be configured
5727331766Sken *
5728331766Sken * @param sli4 SLI context.
5729331766Sken *
5730331766Sken * @return
5731331766Sken * - 0 if link is not configurable.
5732331766Sken * - 1 if link is configurable.
5733331766Sken */
5734331766Skenint32_t sli_link_is_configurable(sli4_t *sli)
5735331766Sken{
5736331766Sken	int32_t rc = 0;
5737331766Sken	/*
5738331766Sken	 * Link config works on: Skyhawk and Lancer
5739331766Sken	 * Link config does not work on: LancerG6
5740331766Sken	 */
5741331766Sken
5742331766Sken	switch (sli_get_asic_type(sli)) {
5743331766Sken	case SLI4_ASIC_TYPE_SKYHAWK:
5744331766Sken	case SLI4_ASIC_TYPE_LANCER:
5745331766Sken	case SLI4_ASIC_TYPE_CORSAIR:
5746331766Sken		rc = 1;
5747331766Sken		break;
5748331766Sken	case SLI4_ASIC_TYPE_LANCERG6:
5749331766Sken	case SLI4_ASIC_TYPE_BE3:
5750331766Sken	default:
5751331766Sken		rc = 0;
5752331766Sken		break;
5753331766Sken	}
5754331766Sken
5755331766Sken	return rc;
5756331766Sken
5757331766Sken}
5758331766Sken
5759331766Sken/* vim: set noexpandtab textwidth=120: */
5760331766Sken
5761331766Sken/**
5762331766Sken * @ingroup sli_fc
5763331766Sken * @brief Write an FCOE_WQ_CREATE command.
5764331766Sken *
5765331766Sken * @param sli4 SLI context.
5766331766Sken * @param buf Destination buffer for the command.
5767331766Sken * @param size Buffer size, in bytes.
5768331766Sken * @param qmem DMA memory for the queue.
5769331766Sken * @param cq_id Associated CQ_ID.
5770331766Sken * @param ulp The ULP to bind
5771331766Sken *
5772331766Sken * @note This creates a Version 0 message.
5773331766Sken *
5774331766Sken * @return Returns the number of bytes written.
5775331766Sken */
5776331766Skenint32_t
5777331766Skensli_cmd_fcoe_wq_create(sli4_t *sli4, void *buf, size_t size,
5778331766Sken		       ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp)
5779331766Sken{
5780331766Sken	sli4_req_fcoe_wq_create_t	*wq = NULL;
5781331766Sken	uint32_t	sli_config_off = 0;
5782331766Sken	uint32_t	p;
5783331766Sken	uintptr_t	addr;
5784331766Sken
5785331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5786331766Sken		uint32_t payload_size;
5787331766Sken
5788331766Sken		/* Payload length must accommodate both request and response */
5789331766Sken		payload_size = max(sizeof(sli4_req_fcoe_wq_create_t),
5790331766Sken				sizeof(sli4_res_common_create_queue_t));
5791331766Sken
5792331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
5793331766Sken				NULL);
5794331766Sken	}
5795331766Sken	wq = (sli4_req_fcoe_wq_create_t *)((uint8_t *)buf + sli_config_off);
5796331766Sken
5797331766Sken	wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
5798331766Sken	wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
5799331766Sken	wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_t) -
5800331766Sken					sizeof(sli4_req_hdr_t);
5801331766Sken	/* valid values for number of pages: 1-4 (sec 4.5.1) */
5802331766Sken	wq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
5803331766Sken	if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V0_MAX_PAGES)) {
5804331766Sken		return 0;
5805331766Sken	}
5806331766Sken
5807331766Sken	wq->cq_id = cq_id;
5808331766Sken
5809331766Sken	if (sli4->config.dual_ulp_capable) {
5810331766Sken		wq->dua = 1;
5811331766Sken		wq->bqu = 1;
5812331766Sken		wq->ulp = ulp;
5813331766Sken	}
5814331766Sken
5815331766Sken	for (p = 0, addr = qmem->phys;
5816331766Sken			p < wq->num_pages;
5817331766Sken			p++, addr += SLI_PAGE_SIZE) {
5818331766Sken		wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
5819331766Sken		wq->page_physical_address[p].high = ocs_addr32_hi(addr);
5820331766Sken	}
5821331766Sken
5822331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_t));
5823331766Sken}
5824331766Sken
5825331766Sken/**
5826331766Sken * @ingroup sli_fc
5827331766Sken * @brief Write an FCOE_WQ_CREATE_V1 command.
5828331766Sken *
5829331766Sken * @param sli4 SLI context.
5830331766Sken * @param buf Destination buffer for the command.
5831331766Sken * @param size Buffer size, in bytes.
5832331766Sken * @param qmem DMA memory for the queue.
5833331766Sken * @param cq_id Associated CQ_ID.
5834331766Sken * @param ignored This parameter carries the ULP for WQ (ignored for V1)
5835331766Sken
5836331766Sken *
5837331766Sken * @return Returns the number of bytes written.
5838331766Sken */
5839331766Skenint32_t
5840331766Skensli_cmd_fcoe_wq_create_v1(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
5841331766Sken			  uint16_t cq_id, uint16_t ignored)
5842331766Sken{
5843331766Sken	sli4_req_fcoe_wq_create_v1_t	*wq = NULL;
5844331766Sken	uint32_t	sli_config_off = 0;
5845331766Sken	uint32_t	p;
5846331766Sken	uintptr_t	addr;
5847331766Sken	uint32_t	page_size = 0;
5848331766Sken	uint32_t	page_bytes = 0;
5849331766Sken	uint32_t	n_wqe = 0;
5850331766Sken
5851331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5852331766Sken		uint32_t payload_size;
5853331766Sken
5854331766Sken		/* Payload length must accommodate both request and response */
5855331766Sken		payload_size = max(sizeof(sli4_req_fcoe_wq_create_v1_t),
5856331766Sken				sizeof(sli4_res_common_create_queue_t));
5857331766Sken
5858331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
5859331766Sken				NULL);
5860331766Sken	}
5861331766Sken	wq = (sli4_req_fcoe_wq_create_v1_t *)((uint8_t *)buf + sli_config_off);
5862331766Sken
5863331766Sken	wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
5864331766Sken	wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
5865331766Sken	wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_v1_t) -
5866331766Sken					sizeof(sli4_req_hdr_t);
5867331766Sken	wq->hdr.version = 1;
5868331766Sken
5869331766Sken	n_wqe = qmem->size / sli4->config.wqe_size;
5870331766Sken
5871331766Sken	/* This heuristic to determine the page size is simplistic
5872331766Sken	 * but could be made more sophisticated
5873331766Sken	 */
5874331766Sken	switch (qmem->size) {
5875331766Sken	case 4096:
5876331766Sken	case 8192:
5877331766Sken	case 16384:
5878331766Sken	case 32768:
5879331766Sken		page_size = 1;
5880331766Sken		break;
5881331766Sken	case 65536:
5882331766Sken		page_size = 2;
5883331766Sken		break;
5884331766Sken	case 131072:
5885331766Sken		page_size = 4;
5886331766Sken		break;
5887331766Sken	case 262144:
5888331766Sken		page_size = 8;
5889331766Sken		break;
5890331766Sken	case 524288:
5891331766Sken		page_size = 10;
5892331766Sken		break;
5893331766Sken	default:
5894331766Sken		return 0;
5895331766Sken	}
5896331766Sken	page_bytes = page_size * SLI_PAGE_SIZE;
5897331766Sken
5898331766Sken	/* valid values for number of pages: 1-8 */
5899331766Sken	wq->num_pages = sli_page_count(qmem->size, page_bytes);
5900331766Sken	if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V1_MAX_PAGES)) {
5901331766Sken		return 0;
5902331766Sken	}
5903331766Sken
5904331766Sken	wq->cq_id = cq_id;
5905331766Sken
5906331766Sken	wq->page_size = page_size;
5907331766Sken
5908331766Sken	if (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) {
5909331766Sken		wq->wqe_size = SLI4_WQE_EXT_SIZE;
5910331766Sken	} else {
5911331766Sken		wq->wqe_size = SLI4_WQE_SIZE;
5912331766Sken	}
5913331766Sken
5914331766Sken	wq->wqe_count = n_wqe;
5915331766Sken
5916331766Sken	for (p = 0, addr = qmem->phys;
5917331766Sken			p < wq->num_pages;
5918331766Sken			p++, addr += page_bytes) {
5919331766Sken		wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
5920331766Sken		wq->page_physical_address[p].high = ocs_addr32_hi(addr);
5921331766Sken	}
5922331766Sken
5923331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_v1_t));
5924331766Sken}
5925331766Sken
5926331766Sken/**
5927331766Sken * @ingroup sli_fc
5928331766Sken * @brief Write an FCOE_WQ_DESTROY command.
5929331766Sken *
5930331766Sken * @param sli4 SLI context.
5931331766Sken * @param buf Destination buffer for the command.
5932331766Sken * @param size Buffer size, in bytes.
5933331766Sken * @param wq_id WQ_ID.
5934331766Sken *
5935331766Sken * @return Returns the number of bytes written.
5936331766Sken */
5937331766Skenint32_t
5938331766Skensli_cmd_fcoe_wq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t wq_id)
5939331766Sken{
5940331766Sken	sli4_req_fcoe_wq_destroy_t	*wq = NULL;
5941331766Sken	uint32_t	sli_config_off = 0;
5942331766Sken
5943331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5944331766Sken		uint32_t payload_size;
5945331766Sken
5946331766Sken		/* Payload length must accommodate both request and response */
5947331766Sken		payload_size = max(sizeof(sli4_req_fcoe_wq_destroy_t),
5948331766Sken				sizeof(sli4_res_hdr_t));
5949331766Sken
5950331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
5951331766Sken				NULL);
5952331766Sken	}
5953331766Sken	wq = (sli4_req_fcoe_wq_destroy_t *)((uint8_t *)buf + sli_config_off);
5954331766Sken
5955331766Sken	wq->hdr.opcode = SLI4_OPC_FCOE_WQ_DESTROY;
5956331766Sken	wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
5957331766Sken	wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_destroy_t) -
5958331766Sken					sizeof(sli4_req_hdr_t);
5959331766Sken
5960331766Sken	wq->wq_id = wq_id;
5961331766Sken
5962331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_wq_destroy_t));
5963331766Sken}
5964331766Sken
5965331766Sken/**
5966331766Sken * @ingroup sli_fc
5967331766Sken * @brief Write an FCOE_POST_SGL_PAGES command.
5968331766Sken *
5969331766Sken * @param sli4 SLI context.
5970331766Sken * @param buf Destination buffer for the command.
5971331766Sken * @param size Buffer size, in bytes.
5972331766Sken * @param xri starting XRI
5973331766Sken * @param xri_count XRI
5974331766Sken * @param page0 First SGL memory page.
5975331766Sken * @param page1 Second SGL memory page (optional).
5976331766Sken * @param dma DMA buffer for non-embedded mailbox command (options)
5977331766Sken *
5978331766Sken * if non-embedded mbx command is used, dma buffer must be at least (32 + xri_count*16) in length
5979331766Sken *
5980331766Sken * @return Returns the number of bytes written.
5981331766Sken */
5982331766Skenint32_t
5983331766Skensli_cmd_fcoe_post_sgl_pages(sli4_t *sli4, void *buf, size_t size,
5984331766Sken		uint16_t xri, uint32_t xri_count, ocs_dma_t *page0[], ocs_dma_t *page1[], ocs_dma_t *dma)
5985331766Sken{
5986331766Sken	sli4_req_fcoe_post_sgl_pages_t	*post = NULL;
5987331766Sken	uint32_t	sli_config_off = 0;
5988331766Sken	uint32_t	i;
5989331766Sken
5990331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
5991331766Sken		uint32_t payload_size;
5992331766Sken
5993331766Sken		/* Payload length must accommodate both request and response */
5994331766Sken		payload_size = max(sizeof(sli4_req_fcoe_post_sgl_pages_t),
5995331766Sken				sizeof(sli4_res_hdr_t));
5996331766Sken
5997331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
5998331766Sken				dma);
5999331766Sken	}
6000331766Sken	if (dma) {
6001331766Sken		post = dma->virt;
6002331766Sken		ocs_memset(post, 0, dma->size);
6003331766Sken	} else {
6004331766Sken		post = (sli4_req_fcoe_post_sgl_pages_t *)((uint8_t *)buf + sli_config_off);
6005331766Sken	}
6006331766Sken
6007331766Sken	post->hdr.opcode = SLI4_OPC_FCOE_POST_SGL_PAGES;
6008331766Sken	post->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6009331766Sken	/* payload size calculation
6010331766Sken	 *   4 = xri_start + xri_count
6011331766Sken	 *   xri_count = # of XRI's registered
6012331766Sken	 *   sizeof(uint64_t) = physical address size
6013331766Sken	 *   2 = # of physical addresses per page set
6014331766Sken	 */
6015331766Sken	post->hdr.request_length = 4 + (xri_count * (sizeof(uint64_t) * 2));
6016331766Sken
6017331766Sken	post->xri_start = xri;
6018331766Sken	post->xri_count = xri_count;
6019331766Sken
6020331766Sken	for (i = 0; i < xri_count; i++) {
6021331766Sken		post->page_set[i].page0_low  = ocs_addr32_lo(page0[i]->phys);
6022331766Sken		post->page_set[i].page0_high = ocs_addr32_hi(page0[i]->phys);
6023331766Sken	}
6024331766Sken
6025331766Sken	if (page1) {
6026331766Sken		for (i = 0; i < xri_count; i++) {
6027331766Sken			post->page_set[i].page1_low  = ocs_addr32_lo(page1[i]->phys);
6028331766Sken			post->page_set[i].page1_high = ocs_addr32_hi(page1[i]->phys);
6029331766Sken		}
6030331766Sken	}
6031331766Sken
6032331766Sken	return dma ? sli_config_off : (sli_config_off + sizeof(sli4_req_fcoe_post_sgl_pages_t));
6033331766Sken}
6034331766Sken
6035331766Sken/**
6036331766Sken * @ingroup sli_fc
6037331766Sken * @brief Write an FCOE_RQ_CREATE command.
6038331766Sken *
6039331766Sken * @param sli4 SLI context.
6040331766Sken * @param buf Destination buffer for the command.
6041331766Sken * @param size Buffer size, in bytes.
6042331766Sken * @param qmem DMA memory for the queue.
6043331766Sken * @param cq_id Associated CQ_ID.
6044331766Sken * @param ulp This parameter carries the ULP for the RQ
6045331766Sken * @param buffer_size Buffer size pointed to by each RQE.
6046331766Sken *
6047331766Sken * @note This creates a Version 0 message.
6048331766Sken *
6049331766Sken * @return Returns the number of bytes written.
6050331766Sken */
6051331766Skenint32_t
6052331766Skensli_cmd_fcoe_rq_create(sli4_t *sli4, void *buf, size_t size,
6053331766Sken		ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp, uint16_t buffer_size)
6054331766Sken{
6055331766Sken	sli4_req_fcoe_rq_create_t	*rq = NULL;
6056331766Sken	uint32_t	sli_config_off = 0;
6057331766Sken	uint32_t	p;
6058331766Sken	uintptr_t	addr;
6059331766Sken
6060331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6061331766Sken		uint32_t payload_size;
6062331766Sken
6063331766Sken		/* Payload length must accommodate both request and response */
6064331766Sken		payload_size = max(sizeof(sli4_req_fcoe_rq_create_t),
6065331766Sken				sizeof(sli4_res_common_create_queue_t));
6066331766Sken
6067331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6068331766Sken				NULL);
6069331766Sken	}
6070331766Sken	rq = (sli4_req_fcoe_rq_create_t *)((uint8_t *)buf + sli_config_off);
6071331766Sken
6072331766Sken	rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
6073331766Sken	rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6074331766Sken	rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_t) -
6075331766Sken					sizeof(sli4_req_hdr_t);
6076331766Sken	/* valid values for number of pages: 1-8 (sec 4.5.6) */
6077331766Sken	rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
6078331766Sken	if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V0_MAX_PAGES)) {
6079331766Sken		ocs_log_test(sli4->os, "num_pages %d not valid\n", rq->num_pages);
6080331766Sken		return 0;
6081331766Sken	}
6082331766Sken
6083331766Sken	/*
6084331766Sken	 * RQE count is the log base 2 of the total number of entries
6085331766Sken	 */
6086331766Sken	rq->rqe_count = ocs_lg2(qmem->size / SLI4_FCOE_RQE_SIZE);
6087331766Sken
6088331766Sken	if ((buffer_size < SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE) ||
6089331766Sken			(buffer_size > SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE)) {
6090331766Sken		ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
6091331766Sken				buffer_size,
6092331766Sken				SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE,
6093331766Sken				SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE);
6094331766Sken		return -1;
6095331766Sken	}
6096331766Sken	rq->buffer_size = buffer_size;
6097331766Sken
6098331766Sken	rq->cq_id = cq_id;
6099331766Sken
6100331766Sken	if (sli4->config.dual_ulp_capable) {
6101331766Sken		rq->dua = 1;
6102331766Sken		rq->bqu = 1;
6103331766Sken		rq->ulp = ulp;
6104331766Sken	}
6105331766Sken
6106331766Sken	for (p = 0, addr = qmem->phys;
6107331766Sken			p < rq->num_pages;
6108331766Sken			p++, addr += SLI_PAGE_SIZE) {
6109331766Sken		rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
6110331766Sken		rq->page_physical_address[p].high = ocs_addr32_hi(addr);
6111331766Sken	}
6112331766Sken
6113331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_t));
6114331766Sken}
6115331766Sken
6116331766Sken/**
6117331766Sken * @ingroup sli_fc
6118331766Sken * @brief Write an FCOE_RQ_CREATE_V1 command.
6119331766Sken *
6120331766Sken * @param sli4 SLI context.
6121331766Sken * @param buf Destination buffer for the command.
6122331766Sken * @param size Buffer size, in bytes.
6123331766Sken * @param qmem DMA memory for the queue.
6124331766Sken * @param cq_id Associated CQ_ID.
6125331766Sken * @param ulp This parameter carries the ULP for RQ (ignored for V1)
6126331766Sken * @param buffer_size Buffer size pointed to by each RQE.
6127331766Sken *
6128331766Sken * @note This creates a Version 0 message
6129331766Sken *
6130331766Sken * @return Returns the number of bytes written.
6131331766Sken */
6132331766Skenint32_t
6133331766Skensli_cmd_fcoe_rq_create_v1(sli4_t *sli4, void *buf, size_t size,
6134331766Sken			  ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp,
6135331766Sken			  uint16_t buffer_size)
6136331766Sken{
6137331766Sken	sli4_req_fcoe_rq_create_v1_t	*rq = NULL;
6138331766Sken	uint32_t	sli_config_off = 0;
6139331766Sken	uint32_t	p;
6140331766Sken	uintptr_t	addr;
6141331766Sken
6142331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6143331766Sken		uint32_t payload_size;
6144331766Sken
6145331766Sken		/* Payload length must accommodate both request and response */
6146331766Sken		payload_size = max(sizeof(sli4_req_fcoe_rq_create_v1_t),
6147331766Sken				sizeof(sli4_res_common_create_queue_t));
6148331766Sken
6149331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6150331766Sken				NULL);
6151331766Sken	}
6152331766Sken	rq = (sli4_req_fcoe_rq_create_v1_t *)((uint8_t *)buf + sli_config_off);
6153331766Sken
6154331766Sken	rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
6155331766Sken	rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6156331766Sken	rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v1_t) -
6157331766Sken					sizeof(sli4_req_hdr_t);
6158331766Sken	rq->hdr.version = 1;
6159331766Sken
6160331766Sken	/* Disable "no buffer warnings" to avoid Lancer bug */
6161331766Sken	rq->dnb = TRUE;
6162331766Sken
6163331766Sken	/* valid values for number of pages: 1-8 (sec 4.5.6) */
6164331766Sken	rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
6165331766Sken	if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES)) {
6166331766Sken		ocs_log_test(sli4->os, "num_pages %d not valid, max %d\n",
6167331766Sken                rq->num_pages, SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES);
6168331766Sken		return 0;
6169331766Sken	}
6170331766Sken
6171331766Sken	/*
6172331766Sken	 * RQE count is the total number of entries (note not lg2(# entries))
6173331766Sken	 */
6174331766Sken	rq->rqe_count = qmem->size / SLI4_FCOE_RQE_SIZE;
6175331766Sken
6176331766Sken	rq->rqe_size = SLI4_FCOE_RQE_SIZE_8;
6177331766Sken
6178331766Sken	rq->page_size = SLI4_FCOE_RQ_PAGE_SIZE_4096;
6179331766Sken
6180331766Sken	if ((buffer_size < sli4->config.rq_min_buf_size) ||
6181331766Sken	    (buffer_size > sli4->config.rq_max_buf_size)) {
6182331766Sken		ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
6183331766Sken				buffer_size,
6184331766Sken				sli4->config.rq_min_buf_size,
6185331766Sken				sli4->config.rq_max_buf_size);
6186331766Sken		return -1;
6187331766Sken	}
6188331766Sken	rq->buffer_size = buffer_size;
6189331766Sken
6190331766Sken	rq->cq_id = cq_id;
6191331766Sken
6192331766Sken	for (p = 0, addr = qmem->phys;
6193331766Sken			p < rq->num_pages;
6194331766Sken			p++, addr += SLI_PAGE_SIZE) {
6195331766Sken		rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
6196331766Sken		rq->page_physical_address[p].high = ocs_addr32_hi(addr);
6197331766Sken	}
6198331766Sken
6199331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_v1_t));
6200331766Sken}
6201331766Sken
6202331766Sken/**
6203331766Sken * @ingroup sli_fc
6204331766Sken * @brief Write an FCOE_RQ_DESTROY command.
6205331766Sken *
6206331766Sken * @param sli4 SLI context.
6207331766Sken * @param buf Destination buffer for the command.
6208331766Sken * @param size Buffer size, in bytes.
6209331766Sken * @param rq_id RQ_ID.
6210331766Sken *
6211331766Sken * @return Returns the number of bytes written.
6212331766Sken */
6213331766Skenint32_t
6214331766Skensli_cmd_fcoe_rq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t rq_id)
6215331766Sken{
6216331766Sken	sli4_req_fcoe_rq_destroy_t	*rq = NULL;
6217331766Sken	uint32_t	sli_config_off = 0;
6218331766Sken
6219331766Sken	if (SLI4_PORT_TYPE_FC == sli4->port_type) {
6220331766Sken		uint32_t payload_size;
6221331766Sken
6222331766Sken		/* Payload length must accommodate both request and response */
6223331766Sken		payload_size = max(sizeof(sli4_req_fcoe_rq_destroy_t),
6224331766Sken				sizeof(sli4_res_hdr_t));
6225331766Sken
6226331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
6227331766Sken				NULL);
6228331766Sken	}
6229331766Sken	rq = (sli4_req_fcoe_rq_destroy_t *)((uint8_t *)buf + sli_config_off);
6230331766Sken
6231331766Sken	rq->hdr.opcode = SLI4_OPC_FCOE_RQ_DESTROY;
6232331766Sken	rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6233331766Sken	rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_destroy_t) -
6234331766Sken					sizeof(sli4_req_hdr_t);
6235331766Sken
6236331766Sken	rq->rq_id = rq_id;
6237331766Sken
6238331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_rq_destroy_t));
6239331766Sken}
6240331766Sken
6241331766Sken/**
6242331766Sken * @ingroup sli_fc
6243331766Sken * @brief Write an FCOE_READ_FCF_TABLE command.
6244331766Sken *
6245331766Sken * @note
6246331766Sken * The response of this command exceeds the size of an embedded
6247331766Sken * command and requires an external buffer with DMA capability to hold the results.
6248331766Sken * The caller should allocate the ocs_dma_t structure / memory.
6249331766Sken *
6250331766Sken * @param sli4 SLI context.
6251331766Sken * @param buf Destination buffer for the command.
6252331766Sken * @param size Buffer size, in bytes.
6253331766Sken * @param dma Pointer to DMA memory structure. This is allocated by the caller.
6254331766Sken * @param index FCF table index to retrieve.
6255331766Sken *
6256331766Sken * @return Returns the number of bytes written.
6257331766Sken */
6258331766Skenint32_t
6259331766Skensli_cmd_fcoe_read_fcf_table(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, uint16_t index)
6260331766Sken{
6261331766Sken	sli4_req_fcoe_read_fcf_table_t *read_fcf = NULL;
6262331766Sken
6263331766Sken	if (SLI4_PORT_TYPE_FC != sli4->port_type) {
6264331766Sken		ocs_log_test(sli4->os, "FCOE_READ_FCF_TABLE only supported on FC\n");
6265331766Sken		return -1;
6266331766Sken	}
6267331766Sken
6268331766Sken	read_fcf = dma->virt;
6269331766Sken
6270331766Sken	ocs_memset(read_fcf, 0, sizeof(sli4_req_fcoe_read_fcf_table_t));
6271331766Sken
6272331766Sken	read_fcf->hdr.opcode = SLI4_OPC_FCOE_READ_FCF_TABLE;
6273331766Sken	read_fcf->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6274331766Sken	read_fcf->hdr.request_length = dma->size -
6275331766Sken		sizeof(sli4_req_fcoe_read_fcf_table_t);
6276331766Sken	read_fcf->fcf_index = index;
6277331766Sken
6278331766Sken	return sli_cmd_sli_config(sli4, buf, size, 0, dma);
6279331766Sken}
6280331766Sken
6281331766Sken/**
6282331766Sken * @ingroup sli_fc
6283331766Sken * @brief Write an FCOE_POST_HDR_TEMPLATES command.
6284331766Sken *
6285331766Sken * @param sli4 SLI context.
6286331766Sken * @param buf Destination buffer for the command.
6287331766Sken * @param size Buffer size, in bytes.
6288331766Sken * @param dma Pointer to DMA memory structure. This is allocated by the caller.
6289331766Sken * @param rpi Starting RPI index for the header templates.
6290331766Sken * @param payload_dma Pointer to DMA memory used to hold larger descriptor counts.
6291331766Sken *
6292331766Sken * @return Returns the number of bytes written.
6293331766Sken */
6294331766Skenint32_t
6295331766Skensli_cmd_fcoe_post_hdr_templates(sli4_t *sli4, void *buf, size_t size,
6296331766Sken		ocs_dma_t *dma, uint16_t rpi, ocs_dma_t *payload_dma)
6297331766Sken{
6298331766Sken	sli4_req_fcoe_post_hdr_templates_t *template = NULL;
6299331766Sken	uint32_t	sli_config_off = 0;
6300331766Sken	uintptr_t	phys = 0;
6301331766Sken	uint32_t	i = 0;
6302331766Sken	uint32_t	page_count;
6303331766Sken	uint32_t	payload_size;
6304331766Sken
6305331766Sken	page_count = sli_page_count(dma->size, SLI_PAGE_SIZE);
6306331766Sken
6307331766Sken	payload_size = sizeof(sli4_req_fcoe_post_hdr_templates_t) +
6308331766Sken				page_count * sizeof(sli4_physical_page_descriptor_t);
6309331766Sken
6310331766Sken	if (page_count > 16) {
6311331766Sken		/* We can't fit more than 16 descriptors into an embedded mailbox
6312331766Sken		   command, it has to be non-embedded */
6313331766Sken		if (ocs_dma_alloc(sli4->os, payload_dma, payload_size, 4)) {
6314331766Sken			ocs_log_err(sli4->os, "mailbox payload memory allocation fail\n");
6315331766Sken			return 0;
6316331766Sken		}
6317331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, payload_dma);
6318331766Sken		template = (sli4_req_fcoe_post_hdr_templates_t *)payload_dma->virt;
6319331766Sken	} else {
6320331766Sken		sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, NULL);
6321331766Sken		template = (sli4_req_fcoe_post_hdr_templates_t *)((uint8_t *)buf + sli_config_off);
6322331766Sken	}
6323331766Sken
6324331766Sken	if (UINT16_MAX == rpi) {
6325331766Sken		rpi = sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0];
6326331766Sken	}
6327331766Sken
6328331766Sken	template->hdr.opcode = SLI4_OPC_FCOE_POST_HDR_TEMPLATES;
6329331766Sken	template->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6330331766Sken	template->hdr.request_length = sizeof(sli4_req_fcoe_post_hdr_templates_t) -
6331331766Sken					sizeof(sli4_req_hdr_t);
6332331766Sken
6333331766Sken	template->rpi_offset = rpi;
6334331766Sken	template->page_count = page_count;
6335331766Sken	phys = dma->phys;
6336331766Sken	for (i = 0; i < template->page_count; i++) {
6337331766Sken		template->page_descriptor[i].low  = ocs_addr32_lo(phys);
6338331766Sken		template->page_descriptor[i].high = ocs_addr32_hi(phys);
6339331766Sken
6340331766Sken		phys += SLI_PAGE_SIZE;
6341331766Sken	}
6342331766Sken
6343331766Sken	return(sli_config_off + payload_size);
6344331766Sken}
6345331766Sken
6346331766Skenint32_t
6347331766Skensli_cmd_fcoe_rediscover_fcf(sli4_t *sli4, void *buf, size_t size, uint16_t index)
6348331766Sken{
6349331766Sken	sli4_req_fcoe_rediscover_fcf_t *redisc = NULL;
6350331766Sken	uint32_t	sli_config_off = 0;
6351331766Sken
6352331766Sken	sli_config_off = sli_cmd_sli_config(sli4, buf, size,
6353331766Sken			sizeof(sli4_req_fcoe_rediscover_fcf_t),
6354331766Sken			NULL);
6355331766Sken
6356331766Sken	redisc = (sli4_req_fcoe_rediscover_fcf_t *)((uint8_t *)buf + sli_config_off);
6357331766Sken
6358331766Sken	redisc->hdr.opcode = SLI4_OPC_FCOE_REDISCOVER_FCF;
6359331766Sken	redisc->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
6360331766Sken	redisc->hdr.request_length = sizeof(sli4_req_fcoe_rediscover_fcf_t) -
6361331766Sken					sizeof(sli4_req_hdr_t);
6362331766Sken
6363331766Sken	if (index == UINT16_MAX) {
6364331766Sken		redisc->fcf_count = 0;
6365331766Sken	} else {
6366331766Sken		redisc->fcf_count = 1;
6367331766Sken		redisc->fcf_index[0] = index;
6368331766Sken	}
6369331766Sken
6370331766Sken	return(sli_config_off + sizeof(sli4_req_fcoe_rediscover_fcf_t));
6371331766Sken}
6372331766Sken
6373331766Sken/**
6374331766Sken * @ingroup sli_fc
6375331766Sken * @brief Write an ABORT_WQE work queue entry.
6376331766Sken *
6377331766Sken * @param sli4 SLI context.
6378331766Sken * @param buf Destination buffer for the WQE.
6379331766Sken * @param size Buffer size, in bytes.
6380331766Sken * @param type Abort type, such as XRI, abort tag, and request tag.
6381331766Sken * @param send_abts Boolean to cause the hardware to automatically generate an ABTS.
6382331766Sken * @param ids ID of IOs to abort.
6383331766Sken * @param mask Mask applied to the ID values to abort.
6384331766Sken * @param tag Tag value associated with this abort.
6385331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
6386331766Sken * @param dnrx When set to 1, this field indicates that the SLI Port must not return the associated XRI to the SLI
6387331766Sken *             Port's optimized write XRI pool.
6388331766Sken *
6389331766Sken * @return Returns 0 on success, or a non-zero value on failure.
6390331766Sken */
6391331766Skenint32_t
6392331766Skensli_abort_wqe(sli4_t *sli4, void *buf, size_t size, sli4_abort_type_e type, uint32_t send_abts,
6393331766Sken	      uint32_t ids, uint32_t mask, uint16_t tag, uint16_t cq_id)
6394331766Sken{
6395331766Sken	sli4_abort_wqe_t	*abort = buf;
6396331766Sken
6397331766Sken	ocs_memset(buf, 0, size);
6398331766Sken
6399331766Sken	switch (type) {
6400331766Sken	case SLI_ABORT_XRI:
6401331766Sken		abort->criteria = SLI4_ABORT_CRITERIA_XRI_TAG;
6402331766Sken		if (mask) {
6403331766Sken			ocs_log_warn(sli4->os, "warning non-zero mask %#x when aborting XRI %#x\n", mask, ids);
6404331766Sken			mask = 0;
6405331766Sken		}
6406331766Sken		break;
6407331766Sken	case SLI_ABORT_ABORT_ID:
6408331766Sken		abort->criteria = SLI4_ABORT_CRITERIA_ABORT_TAG;
6409331766Sken		break;
6410331766Sken	case SLI_ABORT_REQUEST_ID:
6411331766Sken		abort->criteria = SLI4_ABORT_CRITERIA_REQUEST_TAG;
6412331766Sken		break;
6413331766Sken	default:
6414331766Sken		ocs_log_test(sli4->os, "unsupported type %#x\n", type);
6415331766Sken		return -1;
6416331766Sken	}
6417331766Sken
6418331766Sken	abort->ia = send_abts ? 0 : 1;
6419331766Sken
6420331766Sken	/* Suppress ABTS retries */
6421331766Sken	abort->ir = 1;
6422331766Sken
6423331766Sken	abort->t_mask = mask;
6424331766Sken	abort->t_tag  = ids;
6425331766Sken	abort->command = SLI4_WQE_ABORT;
6426331766Sken	abort->request_tag = tag;
6427331766Sken	abort->qosd = TRUE;
6428331766Sken	abort->cq_id = cq_id;
6429331766Sken	abort->cmd_type = SLI4_CMD_ABORT_WQE;
6430331766Sken
6431331766Sken	return 0;
6432331766Sken}
6433331766Sken
6434331766Sken/**
6435331766Sken * @ingroup sli_fc
6436331766Sken * @brief Write an ELS_REQUEST64_WQE work queue entry.
6437331766Sken *
6438331766Sken * @param sli4 SLI context.
6439331766Sken * @param buf Destination buffer for the WQE.
6440331766Sken * @param size Buffer size, in bytes.
6441331766Sken * @param sgl DMA memory for the ELS request.
6442331766Sken * @param req_type ELS request type.
6443331766Sken * @param req_len Length of ELS request in bytes.
6444331766Sken * @param max_rsp_len Max length of ELS response in bytes.
6445331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means 2 * R_A_TOV.
6446331766Sken * @param xri XRI for this exchange.
6447331766Sken * @param tag IO tag value.
6448331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
6449331766Sken * @param rnode Destination of ELS request (that is, the remote node).
6450331766Sken *
6451331766Sken * @return Returns 0 on success, or a non-zero value on failure.
6452331766Sken */
6453331766Skenint32_t
6454331766Skensli_els_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint8_t req_type,
6455331766Sken		      uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
6456331766Sken		      uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode)
6457331766Sken{
6458331766Sken	sli4_els_request64_wqe_t	*els = buf;
6459331766Sken	sli4_sge_t	*sge = sgl->virt;
6460331766Sken	uint8_t		is_fabric = FALSE;
6461331766Sken
6462331766Sken	ocs_memset(buf, 0, size);
6463331766Sken
6464331766Sken	if (sli4->config.sgl_pre_registered) {
6465331766Sken		els->xbl = FALSE;
6466331766Sken
6467331766Sken		els->dbde = TRUE;
6468331766Sken		els->els_request_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
6469331766Sken
6470331766Sken		els->els_request_payload.buffer_length = req_len;
6471331766Sken		els->els_request_payload.u.data.buffer_address_low  = sge[0].buffer_address_low;
6472331766Sken		els->els_request_payload.u.data.buffer_address_high = sge[0].buffer_address_high;
6473331766Sken	} else {
6474331766Sken		els->xbl = TRUE;
6475331766Sken
6476331766Sken		els->els_request_payload.bde_type = SLI4_BDE_TYPE_BLP;
6477331766Sken
6478331766Sken		els->els_request_payload.buffer_length = 2 * sizeof(sli4_sge_t);
6479331766Sken		els->els_request_payload.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6480331766Sken		els->els_request_payload.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6481331766Sken	}
6482331766Sken
6483331766Sken	els->els_request_payload_length = req_len;
6484331766Sken	els->max_response_payload_length = max_rsp_len;
6485331766Sken
6486331766Sken	els->xri_tag = xri;
6487331766Sken	els->timer = timeout;
6488331766Sken	els->class = SLI4_ELS_REQUEST64_CLASS_3;
6489331766Sken
6490331766Sken	els->command = SLI4_WQE_ELS_REQUEST64;
6491331766Sken
6492331766Sken	els->request_tag = tag;
6493331766Sken
6494331766Sken	if (rnode->node_group) {
6495331766Sken		els->hlm = TRUE;
6496331766Sken		els->remote_id = rnode->fc_id & 0x00ffffff;
6497331766Sken	}
6498331766Sken
6499331766Sken	els->iod = SLI4_ELS_REQUEST64_DIR_READ;
6500331766Sken
6501331766Sken	els->qosd = TRUE;
6502331766Sken
6503331766Sken	/* figure out the ELS_ID value from the request buffer */
6504331766Sken
6505331766Sken	switch (req_type) {
6506331766Sken	case FC_ELS_CMD_LOGO:
6507331766Sken		els->els_id = SLI4_ELS_REQUEST64_LOGO;
6508331766Sken		if (rnode->attached) {
6509331766Sken			els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6510331766Sken			els->context_tag = rnode->indicator;
6511331766Sken		} else {
6512331766Sken			els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6513331766Sken			els->context_tag = rnode->sport->indicator;
6514331766Sken		}
6515331766Sken		if (FC_ADDR_FABRIC == rnode->fc_id) {
6516331766Sken			is_fabric = TRUE;
6517331766Sken		}
6518331766Sken		break;
6519331766Sken	case FC_ELS_CMD_FDISC:
6520331766Sken		if (FC_ADDR_FABRIC == rnode->fc_id) {
6521331766Sken			is_fabric = TRUE;
6522331766Sken		}
6523331766Sken		if (0 == rnode->sport->fc_id) {
6524331766Sken			els->els_id = SLI4_ELS_REQUEST64_FDISC;
6525331766Sken			is_fabric = TRUE;
6526331766Sken		} else {
6527331766Sken			els->els_id = SLI4_ELS_REQUEST64_OTHER;
6528331766Sken		}
6529331766Sken		els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6530331766Sken		els->context_tag = rnode->sport->indicator;
6531331766Sken		els->sp = TRUE;
6532331766Sken		break;
6533331766Sken	case FC_ELS_CMD_FLOGI:
6534331766Sken		els->els_id = SLI4_ELS_REQUEST64_FLOGIN;
6535331766Sken		is_fabric = TRUE;
6536331766Sken		if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
6537331766Sken			if (!rnode->sport->domain) {
6538331766Sken				ocs_log_test(sli4->os, "invalid domain handle\n");
6539331766Sken				return -1;
6540331766Sken			}
6541331766Sken			/*
6542331766Sken			 * IF_TYPE 0 skips INIT_VFI/INIT_VPI and therefore must use the
6543331766Sken			 * FCFI here
6544331766Sken			 */
6545331766Sken			els->ct = SLI4_ELS_REQUEST64_CONTEXT_FCFI;
6546331766Sken			els->context_tag = rnode->sport->domain->fcf_indicator;
6547331766Sken			els->sp = TRUE;
6548331766Sken		} else {
6549331766Sken			els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6550331766Sken			els->context_tag = rnode->sport->indicator;
6551331766Sken
6552331766Sken			/*
6553331766Sken			 * Set SP here ... we haven't done a REG_VPI yet
6554331766Sken			 * TODO: need to maybe not set this when we have
6555331766Sken			 *       completed VFI/VPI registrations ...
6556331766Sken			 *
6557331766Sken			 * Use the FC_ID of the SPORT if it has been allocated, otherwise
6558331766Sken			 * use an S_ID of zero.
6559331766Sken			 */
6560331766Sken			els->sp = TRUE;
6561331766Sken			if (rnode->sport->fc_id != UINT32_MAX) {
6562331766Sken				els->sid = rnode->sport->fc_id;
6563331766Sken			}
6564331766Sken		}
6565331766Sken		break;
6566331766Sken	case FC_ELS_CMD_PLOGI:
6567331766Sken		els->els_id = SLI4_ELS_REQUEST64_PLOGI;
6568331766Sken		els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6569331766Sken		els->context_tag = rnode->sport->indicator;
6570331766Sken		break;
6571331766Sken	case FC_ELS_CMD_SCR:
6572331766Sken		els->els_id = SLI4_ELS_REQUEST64_OTHER;
6573331766Sken		els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6574331766Sken		els->context_tag = rnode->sport->indicator;
6575331766Sken		break;
6576331766Sken	default:
6577331766Sken		els->els_id = SLI4_ELS_REQUEST64_OTHER;
6578331766Sken		if (rnode->attached) {
6579331766Sken			els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6580331766Sken			els->context_tag = rnode->indicator;
6581331766Sken		} else {
6582331766Sken			els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
6583331766Sken			els->context_tag = rnode->sport->indicator;
6584331766Sken		}
6585331766Sken		break;
6586331766Sken	}
6587331766Sken
6588331766Sken	if (is_fabric) {
6589331766Sken		els->cmd_type = SLI4_ELS_REQUEST64_CMD_FABRIC;
6590331766Sken	} else {
6591331766Sken		els->cmd_type = SLI4_ELS_REQUEST64_CMD_NON_FABRIC;
6592331766Sken	}
6593331766Sken
6594331766Sken	els->cq_id = cq_id;
6595331766Sken
6596331766Sken	if (SLI4_ELS_REQUEST64_CONTEXT_RPI != els->ct) {
6597331766Sken		els->remote_id = rnode->fc_id;
6598331766Sken	}
6599331766Sken	if (SLI4_ELS_REQUEST64_CONTEXT_VPI == els->ct) {
6600331766Sken		els->temporary_rpi = rnode->indicator;
6601331766Sken	}
6602331766Sken
6603331766Sken	return 0;
6604331766Sken}
6605331766Sken
6606331766Sken
6607331766Sken/**
6608331766Sken * @ingroup sli_fc
6609331766Sken * @brief Write an FCP_ICMND64_WQE work queue entry.
6610331766Sken *
6611331766Sken * @param sli4 SLI context.
6612331766Sken * @param buf Destination buffer for the WQE.
6613331766Sken * @param size Buffer size, in bytes.
6614331766Sken * @param sgl DMA memory for the scatter gather list.
6615331766Sken * @param xri XRI for this exchange.
6616331766Sken * @param tag IO tag value.
6617331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
6618331766Sken * @param rpi remote node indicator (RPI)
6619331766Sken * @param rnode Destination request (that is, the remote node).
6620331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
6621331766Sken *
6622331766Sken * @return Returns 0 on success, or a non-zero value on failure.
6623331766Sken */
6624331766Skenint32_t
6625331766Skensli_fcp_icmnd64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl,
6626331766Sken		    uint16_t xri, uint16_t tag, uint16_t cq_id,
6627331766Sken		    uint32_t rpi, ocs_remote_node_t *rnode, uint8_t timeout)
6628331766Sken{
6629331766Sken	sli4_fcp_icmnd64_wqe_t *icmnd = buf;
6630331766Sken	sli4_sge_t	*sge = NULL;
6631331766Sken
6632331766Sken	ocs_memset(buf, 0, size);
6633331766Sken
6634331766Sken	if (!sgl || !sgl->virt) {
6635331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6636331766Sken			    sgl, sgl ? sgl->virt : NULL);
6637331766Sken		return -1;
6638331766Sken	}
6639331766Sken	sge = sgl->virt;
6640331766Sken
6641331766Sken	if (sli4->config.sgl_pre_registered) {
6642331766Sken		icmnd->xbl = FALSE;
6643331766Sken
6644331766Sken		icmnd->dbde = TRUE;
6645331766Sken		icmnd->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6646331766Sken
6647331766Sken		icmnd->bde.buffer_length = sge[0].buffer_length;
6648331766Sken		icmnd->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6649331766Sken		icmnd->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6650331766Sken	} else {
6651331766Sken		icmnd->xbl = TRUE;
6652331766Sken
6653331766Sken		icmnd->bde.bde_type = SLI4_BDE_TYPE_BLP;
6654331766Sken
6655331766Sken		icmnd->bde.buffer_length = sgl->size;
6656331766Sken		icmnd->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6657331766Sken		icmnd->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6658331766Sken	}
6659331766Sken
6660331766Sken	icmnd->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
6661331766Sken	icmnd->xri_tag = xri;
6662331766Sken	icmnd->context_tag = rpi;
6663331766Sken	icmnd->timer = timeout;
6664331766Sken
6665331766Sken	icmnd->pu = 2;	/* WQE word 4 contains read transfer length */
6666331766Sken	icmnd->class = SLI4_ELS_REQUEST64_CLASS_3;
6667331766Sken	icmnd->command = SLI4_WQE_FCP_ICMND64;
6668331766Sken	icmnd->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6669331766Sken
6670331766Sken	icmnd->abort_tag = xri;
6671331766Sken
6672331766Sken	icmnd->request_tag = tag;
6673331766Sken	icmnd->len_loc = 3;
6674331766Sken	if (rnode->node_group) {
6675331766Sken		icmnd->hlm = TRUE;
6676331766Sken		icmnd->remote_n_port_id = rnode->fc_id & 0x00ffffff;
6677331766Sken	}
6678331766Sken	if (((ocs_node_t *)rnode->node)->fcp2device) {
6679331766Sken		icmnd->erp = TRUE;
6680331766Sken	}
6681331766Sken	icmnd->cmd_type = SLI4_CMD_FCP_ICMND64_WQE;
6682331766Sken	icmnd->cq_id = cq_id;
6683331766Sken
6684331766Sken	return  0;
6685331766Sken}
6686331766Sken
6687331766Sken/**
6688331766Sken * @ingroup sli_fc
6689331766Sken * @brief Write an FCP_IREAD64_WQE work queue entry.
6690331766Sken *
6691331766Sken * @param sli4 SLI context.
6692331766Sken * @param buf Destination buffer for the WQE.
6693331766Sken * @param size Buffer size, in bytes.
6694331766Sken * @param sgl DMA memory for the scatter gather list.
6695331766Sken * @param first_data_sge Index of first data sge (used if perf hints are enabled)
6696331766Sken * @param xfer_len Data transfer length.
6697331766Sken * @param xri XRI for this exchange.
6698331766Sken * @param tag IO tag value.
6699331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
6700331766Sken * @param rpi remote node indicator (RPI)
6701331766Sken * @param rnode Destination request (i.e. remote node).
6702331766Sken * @param dif T10 DIF operation, or 0 to disable.
6703331766Sken * @param bs T10 DIF block size, or 0 if DIF is disabled.
6704331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
6705331766Sken *
6706331766Sken * @return Returns 0 on success, or a non-zero value on failure.
6707331766Sken */
6708331766Skenint32_t
6709331766Skensli_fcp_iread64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
6710331766Sken		    uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
6711331766Sken		    uint32_t rpi, ocs_remote_node_t *rnode,
6712331766Sken		    uint8_t dif, uint8_t bs, uint8_t timeout)
6713331766Sken{
6714331766Sken	sli4_fcp_iread64_wqe_t *iread = buf;
6715331766Sken	sli4_sge_t	*sge = NULL;
6716331766Sken
6717331766Sken	ocs_memset(buf, 0, size);
6718331766Sken
6719331766Sken	if (!sgl || !sgl->virt) {
6720331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6721331766Sken			    sgl, sgl ? sgl->virt : NULL);
6722331766Sken		return -1;
6723331766Sken	}
6724331766Sken	sge = sgl->virt;
6725331766Sken
6726331766Sken	if (sli4->config.sgl_pre_registered) {
6727331766Sken		iread->xbl = FALSE;
6728331766Sken
6729331766Sken		iread->dbde = TRUE;
6730331766Sken		iread->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6731331766Sken
6732331766Sken		iread->bde.buffer_length = sge[0].buffer_length;
6733331766Sken		iread->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6734331766Sken		iread->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6735331766Sken	} else {
6736331766Sken		iread->xbl = TRUE;
6737331766Sken
6738331766Sken		iread->bde.bde_type = SLI4_BDE_TYPE_BLP;
6739331766Sken
6740331766Sken		iread->bde.buffer_length = sgl->size;
6741331766Sken		iread->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6742331766Sken		iread->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6743331766Sken
6744331766Sken		/* fill out fcp_cmnd buffer len and change resp buffer to be of type
6745331766Sken		 * "skip" (note: response will still be written to sge[1] if necessary) */
6746331766Sken		iread->fcp_cmd_buffer_length = sge[0].buffer_length;
6747331766Sken		sge[1].sge_type = SLI4_SGE_TYPE_SKIP;
6748331766Sken	}
6749331766Sken
6750331766Sken	iread->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
6751331766Sken	iread->total_transfer_length = xfer_len;
6752331766Sken
6753331766Sken	iread->xri_tag = xri;
6754331766Sken	iread->context_tag = rpi;
6755331766Sken
6756331766Sken	iread->timer = timeout;
6757331766Sken
6758331766Sken	iread->pu = 2;	/* WQE word 4 contains read transfer length */
6759331766Sken	iread->class = SLI4_ELS_REQUEST64_CLASS_3;
6760331766Sken	iread->command = SLI4_WQE_FCP_IREAD64;
6761331766Sken	iread->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6762331766Sken	iread->dif = dif;
6763331766Sken	iread->bs  = bs;
6764331766Sken
6765331766Sken	iread->abort_tag = xri;
6766331766Sken
6767331766Sken	iread->request_tag = tag;
6768331766Sken	iread->len_loc = 3;
6769331766Sken	if (rnode->node_group) {
6770331766Sken		iread->hlm = TRUE;
6771331766Sken		iread->remote_n_port_id = rnode->fc_id & 0x00ffffff;
6772331766Sken	}
6773331766Sken	if (((ocs_node_t *)rnode->node)->fcp2device) {
6774331766Sken		iread->erp = TRUE;
6775331766Sken	}
6776331766Sken	iread->iod = 1;
6777331766Sken	iread->cmd_type = SLI4_CMD_FCP_IREAD64_WQE;
6778331766Sken	iread->cq_id = cq_id;
6779331766Sken
6780331766Sken	if (sli4->config.perf_hint) {
6781331766Sken		iread->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6782331766Sken		iread->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
6783331766Sken		iread->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
6784331766Sken		iread->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
6785331766Sken	}
6786331766Sken
6787331766Sken	return  0;
6788331766Sken}
6789331766Sken
6790331766Sken
6791331766Sken/**
6792331766Sken * @ingroup sli_fc
6793331766Sken * @brief Write an FCP_IWRITE64_WQE work queue entry.
6794331766Sken *
6795331766Sken * @param sli4 SLI context.
6796331766Sken * @param buf Destination buffer for the WQE.
6797331766Sken * @param size Buffer size, in bytes.
6798331766Sken * @param sgl DMA memory for the scatter gather list.
6799331766Sken * @param first_data_sge Index of first data sge (used if perf hints are enabled)
6800331766Sken * @param xfer_len Data transfer length.
6801331766Sken * @param first_burst The number of first burst bytes
6802331766Sken * @param xri XRI for this exchange.
6803331766Sken * @param tag IO tag value.
6804331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
6805331766Sken * @param rpi remote node indicator (RPI)
6806331766Sken * @param rnode Destination request (i.e. remote node)
6807331766Sken * @param dif T10 DIF operation, or 0 to disable
6808331766Sken * @param bs T10 DIF block size, or 0 if DIF is disabled
6809331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
6810331766Sken *
6811331766Sken * @return Returns 0 on success, or a non-zero value on failure.
6812331766Sken */
6813331766Skenint32_t
6814331766Skensli_fcp_iwrite64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
6815331766Sken		     uint32_t xfer_len, uint32_t first_burst, uint16_t xri, uint16_t tag, uint16_t cq_id,
6816331766Sken		     uint32_t rpi, ocs_remote_node_t *rnode,
6817331766Sken		     uint8_t dif, uint8_t bs, uint8_t timeout)
6818331766Sken{
6819331766Sken	sli4_fcp_iwrite64_wqe_t *iwrite = buf;
6820331766Sken	sli4_sge_t	*sge = NULL;
6821331766Sken
6822331766Sken	ocs_memset(buf, 0, size);
6823331766Sken
6824331766Sken	if (!sgl || !sgl->virt) {
6825331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6826331766Sken			    sgl, sgl ? sgl->virt : NULL);
6827331766Sken		return -1;
6828331766Sken	}
6829331766Sken	sge = sgl->virt;
6830331766Sken
6831331766Sken	if (sli4->config.sgl_pre_registered) {
6832331766Sken		iwrite->xbl = FALSE;
6833331766Sken
6834331766Sken		iwrite->dbde = TRUE;
6835331766Sken		iwrite->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6836331766Sken
6837331766Sken		iwrite->bde.buffer_length = sge[0].buffer_length;
6838331766Sken		iwrite->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6839331766Sken		iwrite->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6840331766Sken	} else {
6841331766Sken		iwrite->xbl = TRUE;
6842331766Sken
6843331766Sken		iwrite->bde.bde_type = SLI4_BDE_TYPE_BLP;
6844331766Sken
6845331766Sken		iwrite->bde.buffer_length = sgl->size;
6846331766Sken		iwrite->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6847331766Sken		iwrite->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6848331766Sken
6849331766Sken		/* fill out fcp_cmnd buffer len and change resp buffer to be of type
6850331766Sken		 * "skip" (note: response will still be written to sge[1] if necessary) */
6851331766Sken		iwrite->fcp_cmd_buffer_length = sge[0].buffer_length;
6852331766Sken		sge[1].sge_type = SLI4_SGE_TYPE_SKIP;
6853331766Sken	}
6854331766Sken
6855331766Sken	iwrite->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
6856331766Sken	iwrite->total_transfer_length = xfer_len;
6857331766Sken	iwrite->initial_transfer_length = MIN(xfer_len, first_burst);
6858331766Sken
6859331766Sken	iwrite->xri_tag = xri;
6860331766Sken	iwrite->context_tag = rpi;
6861331766Sken
6862331766Sken	iwrite->timer = timeout;
6863331766Sken
6864331766Sken	iwrite->pu = 2;	/* WQE word 4 contains read transfer length */
6865331766Sken	iwrite->class = SLI4_ELS_REQUEST64_CLASS_3;
6866331766Sken	iwrite->command = SLI4_WQE_FCP_IWRITE64;
6867331766Sken	iwrite->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6868331766Sken	iwrite->dif = dif;
6869331766Sken	iwrite->bs  = bs;
6870331766Sken
6871331766Sken	iwrite->abort_tag = xri;
6872331766Sken
6873331766Sken	iwrite->request_tag = tag;
6874331766Sken	iwrite->len_loc = 3;
6875331766Sken	if (rnode->node_group) {
6876331766Sken		iwrite->hlm = TRUE;
6877331766Sken		iwrite->remote_n_port_id = rnode->fc_id & 0x00ffffff;
6878331766Sken	}
6879331766Sken	if (((ocs_node_t *)rnode->node)->fcp2device) {
6880331766Sken		iwrite->erp = TRUE;
6881331766Sken	}
6882331766Sken	iwrite->cmd_type = SLI4_CMD_FCP_IWRITE64_WQE;
6883331766Sken	iwrite->cq_id = cq_id;
6884331766Sken
6885331766Sken	if (sli4->config.perf_hint) {
6886331766Sken		iwrite->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6887331766Sken		iwrite->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
6888331766Sken		iwrite->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
6889331766Sken		iwrite->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
6890331766Sken	}
6891331766Sken
6892331766Sken	return  0;
6893331766Sken}
6894331766Sken
6895331766Sken/**
6896331766Sken * @ingroup sli_fc
6897331766Sken * @brief Write an FCP_TRECEIVE64_WQE work queue entry.
6898331766Sken *
6899331766Sken * @param sli4 SLI context.
6900331766Sken * @param buf Destination buffer for the WQE.
6901331766Sken * @param size Buffer size, in bytes.
6902331766Sken * @param sgl DMA memory for the Scatter-Gather List.
6903331766Sken * @param first_data_sge Index of first data sge (used if perf hints are enabled)
6904331766Sken * @param relative_off Relative offset of the IO (if any).
6905331766Sken * @param xfer_len Data transfer length.
6906331766Sken * @param xri XRI for this exchange.
6907331766Sken * @param tag IO tag value.
6908331766Sken * @param xid OX_ID for the exchange.
6909331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
6910331766Sken * @param rpi remote node indicator (RPI)
6911331766Sken * @param rnode Destination request (i.e. remote node).
6912331766Sken * @param flags Optional attributes, including:
6913331766Sken *  - ACTIVE - IO is already active.
6914331766Sken *  - AUTO RSP - Automatically generate a good FCP_RSP.
6915331766Sken * @param dif T10 DIF operation, or 0 to disable.
6916331766Sken * @param bs T10 DIF block size, or 0 if DIF is disabled.
6917331766Sken * @param csctl value of csctl field.
6918331766Sken * @param app_id value for VM application header.
6919331766Sken *
6920331766Sken * @return Returns 0 on success, or a non-zero value on failure.
6921331766Sken */
6922331766Skenint32_t
6923331766Skensli_fcp_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
6924331766Sken		       uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
6925331766Sken		       uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags, uint8_t dif, uint8_t bs,
6926331766Sken		       uint8_t csctl, uint32_t app_id)
6927331766Sken{
6928331766Sken	sli4_fcp_treceive64_wqe_t *trecv = buf;
6929331766Sken	sli4_fcp_128byte_wqe_t *trecv_128 = buf;
6930331766Sken	sli4_sge_t	*sge = NULL;
6931331766Sken
6932331766Sken	ocs_memset(buf, 0, size);
6933331766Sken
6934331766Sken	if (!sgl || !sgl->virt) {
6935331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
6936331766Sken			    sgl, sgl ? sgl->virt : NULL);
6937331766Sken		return -1;
6938331766Sken	}
6939331766Sken	sge = sgl->virt;
6940331766Sken
6941331766Sken	if (sli4->config.sgl_pre_registered) {
6942331766Sken		trecv->xbl = FALSE;
6943331766Sken
6944331766Sken		trecv->dbde = TRUE;
6945331766Sken		trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6946331766Sken
6947331766Sken		trecv->bde.buffer_length = sge[0].buffer_length;
6948331766Sken		trecv->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
6949331766Sken		trecv->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
6950331766Sken
6951331766Sken		trecv->payload_offset_length = sge[0].buffer_length;
6952331766Sken	} else {
6953331766Sken		trecv->xbl = TRUE;
6954331766Sken
6955331766Sken		/* if data is a single physical address, use a BDE */
6956331766Sken		if (!dif && (xfer_len <= sge[2].buffer_length)) {
6957331766Sken			trecv->dbde = TRUE;
6958331766Sken			trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
6959331766Sken
6960331766Sken			trecv->bde.buffer_length = sge[2].buffer_length;
6961331766Sken			trecv->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
6962331766Sken			trecv->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
6963331766Sken		} else {
6964331766Sken			trecv->bde.bde_type = SLI4_BDE_TYPE_BLP;
6965331766Sken			trecv->bde.buffer_length = sgl->size;
6966331766Sken			trecv->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
6967331766Sken			trecv->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
6968331766Sken		}
6969331766Sken	}
6970331766Sken
6971331766Sken	trecv->relative_offset = relative_off;
6972331766Sken
6973331766Sken	if (flags & SLI4_IO_CONTINUATION) {
6974331766Sken		trecv->xc = TRUE;
6975331766Sken	}
6976331766Sken	trecv->xri_tag = xri;
6977331766Sken
6978331766Sken	trecv->context_tag = rpi;
6979331766Sken
6980331766Sken	trecv->pu = TRUE;	/* WQE uses relative offset */
6981331766Sken
6982331766Sken	if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
6983331766Sken		trecv->ar = TRUE;
6984331766Sken	}
6985331766Sken
6986331766Sken	trecv->command = SLI4_WQE_FCP_TRECEIVE64;
6987331766Sken	trecv->class = SLI4_ELS_REQUEST64_CLASS_3;
6988331766Sken	trecv->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
6989331766Sken	trecv->dif = dif;
6990331766Sken	trecv->bs  = bs;
6991331766Sken
6992331766Sken	trecv->remote_xid = xid;
6993331766Sken
6994331766Sken	trecv->request_tag = tag;
6995331766Sken
6996331766Sken	trecv->iod = 1;
6997331766Sken
6998331766Sken	trecv->len_loc = 0x2;
6999331766Sken
7000331766Sken	if (rnode->node_group) {
7001331766Sken		trecv->hlm = TRUE;
7002331766Sken		trecv->dword5.dword = rnode->fc_id & 0x00ffffff;
7003331766Sken	}
7004331766Sken
7005331766Sken	trecv->cmd_type = SLI4_CMD_FCP_TRECEIVE64_WQE;
7006331766Sken
7007331766Sken	trecv->cq_id = cq_id;
7008331766Sken
7009331766Sken	trecv->fcp_data_receive_length = xfer_len;
7010331766Sken
7011331766Sken	if (sli4->config.perf_hint) {
7012331766Sken		trecv->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7013331766Sken		trecv->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
7014331766Sken		trecv->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
7015331766Sken		trecv->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
7016331766Sken	}
7017331766Sken
7018331766Sken	/* The upper 7 bits of csctl is the priority */
7019331766Sken	if (csctl & SLI4_MASK_CCP) {
7020331766Sken		trecv->ccpe = 1;
7021331766Sken		trecv->ccp = (csctl & SLI4_MASK_CCP);
7022331766Sken	}
7023331766Sken
7024331766Sken	if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trecv->eat) {
7025331766Sken		trecv->app_id_valid = 1;
7026331766Sken		trecv->wqes = 1;
7027331766Sken		trecv_128->dw[31] = app_id;
7028331766Sken	}
7029331766Sken	return 0;
7030331766Sken}
7031331766Sken
7032331766Sken/**
7033331766Sken * @ingroup sli_fc
7034331766Sken * @brief Write an FCP_CONT_TRECEIVE64_WQE work queue entry.
7035331766Sken *
7036331766Sken * @param sli4 SLI context.
7037331766Sken * @param buf Destination buffer for the WQE.
7038331766Sken * @param size Buffer size, in bytes.
7039331766Sken * @param sgl DMA memory for the Scatter-Gather List.
7040331766Sken * @param first_data_sge Index of first data sge (used if perf hints are enabled)
7041331766Sken * @param relative_off Relative offset of the IO (if any).
7042331766Sken * @param xfer_len Data transfer length.
7043331766Sken * @param xri XRI for this exchange.
7044331766Sken * @param sec_xri Secondary XRI for this exchange. (BZ 161832 workaround)
7045331766Sken * @param tag IO tag value.
7046331766Sken * @param xid OX_ID for the exchange.
7047331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7048331766Sken * @param rpi remote node indicator (RPI)
7049331766Sken * @param rnode Destination request (i.e. remote node).
7050331766Sken * @param flags Optional attributes, including:
7051331766Sken *  - ACTIVE - IO is already active.
7052331766Sken *  - AUTO RSP - Automatically generate a good FCP_RSP.
7053331766Sken * @param dif T10 DIF operation, or 0 to disable.
7054331766Sken * @param bs T10 DIF block size, or 0 if DIF is disabled.
7055331766Sken * @param csctl value of csctl field.
7056331766Sken * @param app_id value for VM application header.
7057331766Sken *
7058331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7059331766Sken */
7060331766Skenint32_t
7061331766Skensli_fcp_cont_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
7062331766Sken			uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t sec_xri, uint16_t tag,
7063331766Sken			uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags,
7064331766Sken			uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id)
7065331766Sken{
7066331766Sken	int32_t rc;
7067331766Sken
7068331766Sken	rc = sli_fcp_treceive64_wqe(sli4, buf, size, sgl, first_data_sge, relative_off, xfer_len, xri, tag,
7069331766Sken			cq_id, xid, rpi, rnode, flags, dif, bs, csctl, app_id);
7070331766Sken	if (rc == 0) {
7071331766Sken		sli4_fcp_treceive64_wqe_t *trecv = buf;
7072331766Sken
7073331766Sken		trecv->command = SLI4_WQE_FCP_CONT_TRECEIVE64;
7074331766Sken		trecv->dword5.sec_xri_tag = sec_xri;
7075331766Sken	}
7076331766Sken	return rc;
7077331766Sken}
7078331766Sken
7079331766Sken/**
7080331766Sken * @ingroup sli_fc
7081331766Sken * @brief Write an FCP_TRSP64_WQE work queue entry.
7082331766Sken *
7083331766Sken * @param sli4 SLI context.
7084331766Sken * @param buf Destination buffer for the WQE.
7085331766Sken * @param size Buffer size, in bytes.
7086331766Sken * @param sgl DMA memory for the Scatter-Gather List.
7087331766Sken * @param rsp_len Response data length.
7088331766Sken * @param xri XRI for this exchange.
7089331766Sken * @param tag IO tag value.
7090331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7091331766Sken * @param xid OX_ID for the exchange.
7092331766Sken * @param rpi remote node indicator (RPI)
7093331766Sken * @param rnode Destination request (i.e. remote node).
7094331766Sken * @param flags Optional attributes, including:
7095331766Sken *  - ACTIVE - IO is already active
7096331766Sken *  - AUTO RSP - Automatically generate a good FCP_RSP.
7097331766Sken * @param csctl value of csctl field.
7098331766Sken * @param port_owned 0/1 to indicate if the XRI is port owned (used to set XBL=0)
7099331766Sken * @param app_id value for VM application header.
7100331766Sken *
7101331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7102331766Sken */
7103331766Skenint32_t
7104331766Skensli_fcp_trsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t rsp_len,
7105331766Sken		   uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode,
7106331766Sken		   uint32_t flags, uint8_t csctl, uint8_t port_owned, uint32_t app_id)
7107331766Sken{
7108331766Sken	sli4_fcp_trsp64_wqe_t *trsp = buf;
7109331766Sken	sli4_fcp_128byte_wqe_t *trsp_128 = buf;
7110331766Sken
7111331766Sken	ocs_memset(buf, 0, size);
7112331766Sken
7113331766Sken	if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
7114331766Sken		trsp->ag = TRUE;
7115331766Sken		/*
7116331766Sken		 * The SLI-4 documentation states that the BDE is ignored when
7117331766Sken		 * using auto-good response, but, at least for IF_TYPE 0 devices,
7118331766Sken		 * this does not appear to be true.
7119331766Sken		 */
7120331766Sken		if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
7121331766Sken			trsp->bde.buffer_length = 12;	/* byte size of RSP */
7122331766Sken		}
7123331766Sken	} else {
7124331766Sken		sli4_sge_t	*sge = sgl->virt;
7125331766Sken
7126331766Sken		if (sli4->config.sgl_pre_registered || port_owned) {
7127331766Sken			trsp->dbde = TRUE;
7128331766Sken		} else {
7129331766Sken			trsp->xbl = TRUE;
7130331766Sken		}
7131331766Sken
7132331766Sken		trsp->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7133331766Sken		trsp->bde.buffer_length = sge[0].buffer_length;
7134331766Sken		trsp->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
7135331766Sken		trsp->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
7136331766Sken
7137331766Sken		trsp->fcp_response_length = rsp_len;
7138331766Sken	}
7139331766Sken
7140331766Sken	if (flags & SLI4_IO_CONTINUATION) {
7141331766Sken		trsp->xc = TRUE;
7142331766Sken	}
7143331766Sken
7144331766Sken	if (rnode->node_group) {
7145331766Sken		trsp->hlm = TRUE;
7146331766Sken		trsp->dword5 = rnode->fc_id & 0x00ffffff;
7147331766Sken	}
7148331766Sken
7149331766Sken	trsp->xri_tag = xri;
7150331766Sken	trsp->rpi = rpi;
7151331766Sken
7152331766Sken	trsp->command = SLI4_WQE_FCP_TRSP64;
7153331766Sken	trsp->class = SLI4_ELS_REQUEST64_CLASS_3;
7154331766Sken
7155331766Sken	trsp->remote_xid = xid;
7156331766Sken	trsp->request_tag = tag;
7157331766Sken	trsp->dnrx = ((flags & SLI4_IO_DNRX) == 0 ? 0 : 1);
7158331766Sken	trsp->len_loc = 0x1;
7159331766Sken	trsp->cq_id = cq_id;
7160331766Sken	trsp->cmd_type = SLI4_CMD_FCP_TRSP64_WQE;
7161331766Sken
7162331766Sken	/* The upper 7 bits of csctl is the priority */
7163331766Sken	if (csctl & SLI4_MASK_CCP) {
7164331766Sken		trsp->ccpe = 1;
7165331766Sken		trsp->ccp = (csctl & SLI4_MASK_CCP);
7166331766Sken	}
7167331766Sken
7168331766Sken	if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trsp->eat) {
7169331766Sken		trsp->app_id_valid = 1;
7170331766Sken		trsp->wqes = 1;
7171331766Sken		trsp_128->dw[31] = app_id;
7172331766Sken	}
7173331766Sken	return 0;
7174331766Sken}
7175331766Sken
7176331766Sken/**
7177331766Sken * @ingroup sli_fc
7178331766Sken * @brief Write an FCP_TSEND64_WQE work queue entry.
7179331766Sken *
7180331766Sken * @param sli4 SLI context.
7181331766Sken * @param buf Destination buffer for the WQE.
7182331766Sken * @param size Buffer size, in bytes.
7183331766Sken * @param sgl DMA memory for the scatter gather list.
7184331766Sken * @param first_data_sge Index of first data sge (used if perf hints are enabled)
7185331766Sken * @param relative_off Relative offset of the IO (if any).
7186331766Sken * @param xfer_len Data transfer length.
7187331766Sken * @param xri XRI for this exchange.
7188331766Sken * @param tag IO tag value.
7189331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7190331766Sken * @param xid OX_ID for the exchange.
7191331766Sken * @param rpi remote node indicator (RPI)
7192331766Sken * @param rnode Destination request (i.e. remote node).
7193331766Sken * @param flags Optional attributes, including:
7194331766Sken *  - ACTIVE - IO is already active.
7195331766Sken *  - AUTO RSP - Automatically generate a good FCP_RSP.
7196331766Sken * @param dif T10 DIF operation, or 0 to disable.
7197331766Sken * @param bs T10 DIF block size, or 0 if DIF is disabled.
7198331766Sken * @param csctl value of csctl field.
7199331766Sken * @param app_id value for VM application header.
7200331766Sken *
7201331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7202331766Sken */
7203331766Skenint32_t
7204331766Skensli_fcp_tsend64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
7205331766Sken		    uint32_t relative_off, uint32_t xfer_len,
7206331766Sken		    uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode,
7207331766Sken		    uint32_t flags, uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id)
7208331766Sken{
7209331766Sken	sli4_fcp_tsend64_wqe_t *tsend = buf;
7210331766Sken	sli4_fcp_128byte_wqe_t *tsend_128 = buf;
7211331766Sken	sli4_sge_t	*sge = NULL;
7212331766Sken
7213331766Sken	ocs_memset(buf, 0, size);
7214331766Sken
7215331766Sken	if (!sgl || !sgl->virt) {
7216331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7217331766Sken			    sgl, sgl ? sgl->virt : NULL);
7218331766Sken		return -1;
7219331766Sken	}
7220331766Sken	sge = sgl->virt;
7221331766Sken
7222331766Sken	if (sli4->config.sgl_pre_registered) {
7223331766Sken		tsend->xbl = FALSE;
7224331766Sken
7225331766Sken		tsend->dbde = TRUE;
7226331766Sken		tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7227331766Sken
7228331766Sken		/* TSEND64_WQE specifies first two SGE are skipped
7229331766Sken		 * (i.e. 3rd is valid) */
7230331766Sken		tsend->bde.buffer_length = sge[2].buffer_length;
7231331766Sken		tsend->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
7232331766Sken		tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
7233331766Sken	} else {
7234331766Sken		tsend->xbl = TRUE;
7235331766Sken
7236331766Sken		/* if data is a single physical address, use a BDE */
7237331766Sken		if (!dif && (xfer_len <= sge[2].buffer_length)) {
7238331766Sken			tsend->dbde = TRUE;
7239331766Sken			tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7240331766Sken			/* TSEND64_WQE specifies first two SGE are skipped
7241331766Sken			 * (i.e. 3rd is valid) */
7242331766Sken			tsend->bde.buffer_length = sge[2].buffer_length;
7243331766Sken			tsend->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
7244331766Sken			tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
7245331766Sken		} else {
7246331766Sken			tsend->bde.bde_type = SLI4_BDE_TYPE_BLP;
7247331766Sken			tsend->bde.buffer_length = sgl->size;
7248331766Sken			tsend->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
7249331766Sken			tsend->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
7250331766Sken		}
7251331766Sken	}
7252331766Sken
7253331766Sken	tsend->relative_offset = relative_off;
7254331766Sken
7255331766Sken	if (flags & SLI4_IO_CONTINUATION) {
7256331766Sken		tsend->xc = TRUE;
7257331766Sken	}
7258331766Sken	tsend->xri_tag = xri;
7259331766Sken
7260331766Sken	tsend->rpi = rpi;
7261331766Sken
7262331766Sken	tsend->pu = TRUE;	/* WQE uses relative offset */
7263331766Sken
7264331766Sken	if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
7265331766Sken		tsend->ar = TRUE;
7266331766Sken	}
7267331766Sken
7268331766Sken	tsend->command = SLI4_WQE_FCP_TSEND64;
7269331766Sken	tsend->class = SLI4_ELS_REQUEST64_CLASS_3;
7270331766Sken	tsend->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7271331766Sken	tsend->dif = dif;
7272331766Sken	tsend->bs  = bs;
7273331766Sken
7274331766Sken	tsend->remote_xid = xid;
7275331766Sken
7276331766Sken	tsend->request_tag = tag;
7277331766Sken
7278331766Sken	tsend->len_loc = 0x2;
7279331766Sken
7280331766Sken	if (rnode->node_group) {
7281331766Sken		tsend->hlm = TRUE;
7282331766Sken		tsend->dword5 = rnode->fc_id & 0x00ffffff;
7283331766Sken	}
7284331766Sken
7285331766Sken	tsend->cq_id = cq_id;
7286331766Sken
7287331766Sken	tsend->cmd_type = SLI4_CMD_FCP_TSEND64_WQE;
7288331766Sken
7289331766Sken	tsend->fcp_data_transmit_length = xfer_len;
7290331766Sken
7291331766Sken	if (sli4->config.perf_hint) {
7292331766Sken		tsend->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7293331766Sken		tsend->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
7294331766Sken		tsend->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
7295331766Sken		tsend->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
7296331766Sken	}
7297331766Sken
7298331766Sken	/* The upper 7 bits of csctl is the priority */
7299331766Sken	if (csctl & SLI4_MASK_CCP) {
7300331766Sken		tsend->ccpe = 1;
7301331766Sken		tsend->ccp = (csctl & SLI4_MASK_CCP);
7302331766Sken	}
7303331766Sken
7304331766Sken	if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !tsend->eat) {
7305331766Sken		tsend->app_id_valid = 1;
7306331766Sken		tsend->wqes = 1;
7307331766Sken		tsend_128->dw[31] = app_id;
7308331766Sken	}
7309331766Sken	return 0;
7310331766Sken}
7311331766Sken
7312331766Sken/**
7313331766Sken * @ingroup sli_fc
7314331766Sken * @brief Write a GEN_REQUEST64 work queue entry.
7315331766Sken *
7316331766Sken * @note This WQE is only used to send FC-CT commands.
7317331766Sken *
7318331766Sken * @param sli4 SLI context.
7319331766Sken * @param buf Destination buffer for the WQE.
7320331766Sken * @param size Buffer size, in bytes.
7321331766Sken * @param sgl DMA memory for the request.
7322331766Sken * @param req_len Length of request.
7323331766Sken * @param max_rsp_len Max length of response.
7324331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
7325331766Sken * @param xri XRI for this exchange.
7326331766Sken * @param tag IO tag value.
7327331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7328331766Sken * @param rnode Destination of request (that is, the remote node).
7329331766Sken * @param r_ctl R_CTL value for sequence.
7330331766Sken * @param type TYPE value for sequence.
7331331766Sken * @param df_ctl DF_CTL value for sequence.
7332331766Sken *
7333331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7334331766Sken */
7335331766Skenint32_t
7336331766Skensli_gen_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl,
7337331766Sken		      uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
7338331766Sken		      uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode,
7339331766Sken		      uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
7340331766Sken{
7341331766Sken	sli4_gen_request64_wqe_t	*gen = buf;
7342331766Sken	sli4_sge_t	*sge = NULL;
7343331766Sken
7344331766Sken	ocs_memset(buf, 0, size);
7345331766Sken
7346331766Sken	if (!sgl || !sgl->virt) {
7347331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7348331766Sken			    sgl, sgl ? sgl->virt : NULL);
7349331766Sken		return -1;
7350331766Sken	}
7351331766Sken	sge = sgl->virt;
7352331766Sken
7353331766Sken	if (sli4->config.sgl_pre_registered) {
7354331766Sken		gen->xbl = FALSE;
7355331766Sken
7356331766Sken		gen->dbde = TRUE;
7357331766Sken		gen->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7358331766Sken
7359331766Sken		gen->bde.buffer_length = req_len;
7360331766Sken		gen->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
7361331766Sken		gen->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
7362331766Sken	} else {
7363331766Sken		gen->xbl = TRUE;
7364331766Sken
7365331766Sken		gen->bde.bde_type = SLI4_BDE_TYPE_BLP;
7366331766Sken
7367331766Sken		gen->bde.buffer_length = 2 * sizeof(sli4_sge_t);
7368331766Sken		gen->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
7369331766Sken		gen->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
7370331766Sken	}
7371331766Sken
7372331766Sken	gen->request_payload_length = req_len;
7373331766Sken	gen->max_response_payload_length = max_rsp_len;
7374331766Sken
7375331766Sken	gen->df_ctl = df_ctl;
7376331766Sken	gen->type = type;
7377331766Sken	gen->r_ctl = r_ctl;
7378331766Sken
7379331766Sken	gen->xri_tag = xri;
7380331766Sken
7381331766Sken	gen->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7382331766Sken	gen->context_tag = rnode->indicator;
7383331766Sken
7384331766Sken	gen->class = SLI4_ELS_REQUEST64_CLASS_3;
7385331766Sken
7386331766Sken	gen->command = SLI4_WQE_GEN_REQUEST64;
7387331766Sken
7388331766Sken	gen->timer = timeout;
7389331766Sken
7390331766Sken	gen->request_tag = tag;
7391331766Sken
7392331766Sken	gen->iod = SLI4_ELS_REQUEST64_DIR_READ;
7393331766Sken
7394331766Sken	gen->qosd = TRUE;
7395331766Sken
7396331766Sken	if (rnode->node_group) {
7397331766Sken		gen->hlm = TRUE;
7398331766Sken		gen->remote_n_port_id = rnode->fc_id & 0x00ffffff;
7399331766Sken	}
7400331766Sken
7401331766Sken	gen->cmd_type = SLI4_CMD_GEN_REQUEST64_WQE;
7402331766Sken
7403331766Sken	gen->cq_id = cq_id;
7404331766Sken
7405331766Sken	return 0;
7406331766Sken}
7407331766Sken
7408331766Sken/**
7409331766Sken * @ingroup sli_fc
7410331766Sken * @brief Write a SEND_FRAME work queue entry
7411331766Sken *
7412331766Sken * @param sli4 SLI context.
7413331766Sken * @param buf Destination buffer for the WQE.
7414331766Sken * @param size Buffer size, in bytes.
7415331766Sken * @param sof Start of frame value
7416331766Sken * @param eof End of frame value
7417331766Sken * @param hdr Pointer to FC header data
7418331766Sken * @param payload DMA memory for the payload.
7419331766Sken * @param req_len Length of payload.
7420331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
7421331766Sken * @param xri XRI for this exchange.
7422331766Sken * @param req_tag IO tag value.
7423331766Sken *
7424331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7425331766Sken */
7426331766Skenint32_t
7427331766Skensli_send_frame_wqe(sli4_t *sli4, void *buf, size_t size, uint8_t sof, uint8_t eof, uint32_t *hdr,
7428331766Sken		   ocs_dma_t *payload, uint32_t req_len, uint8_t timeout,
7429331766Sken		   uint16_t xri, uint16_t req_tag)
7430331766Sken{
7431331766Sken	sli4_send_frame_wqe_t *sf = buf;
7432331766Sken
7433331766Sken	ocs_memset(buf, 0, size);
7434331766Sken
7435331766Sken	sf->dbde = TRUE;
7436331766Sken	sf->bde.buffer_length = req_len;
7437331766Sken	sf->bde.u.data.buffer_address_low = ocs_addr32_lo(payload->phys);
7438331766Sken	sf->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
7439331766Sken
7440331766Sken	/* Copy FC header */
7441331766Sken	sf->fc_header_0_1[0] = hdr[0];
7442331766Sken	sf->fc_header_0_1[1] = hdr[1];
7443331766Sken	sf->fc_header_2_5[0] = hdr[2];
7444331766Sken	sf->fc_header_2_5[1] = hdr[3];
7445331766Sken	sf->fc_header_2_5[2] = hdr[4];
7446331766Sken	sf->fc_header_2_5[3] = hdr[5];
7447331766Sken
7448331766Sken	sf->frame_length = req_len;
7449331766Sken
7450331766Sken	sf->xri_tag = xri;
7451331766Sken	sf->pu = 0;
7452331766Sken	sf->context_tag = 0;
7453331766Sken
7454331766Sken
7455331766Sken	sf->ct = 0;
7456331766Sken	sf->command = SLI4_WQE_SEND_FRAME;
7457331766Sken	sf->class = SLI4_ELS_REQUEST64_CLASS_3;
7458331766Sken	sf->timer = timeout;
7459331766Sken
7460331766Sken	sf->request_tag = req_tag;
7461331766Sken	sf->eof = eof;
7462331766Sken	sf->sof = sof;
7463331766Sken
7464331766Sken	sf->qosd = 0;
7465331766Sken	sf->lenloc = 1;
7466331766Sken	sf->xc = 0;
7467331766Sken
7468331766Sken	sf->xbl = 1;
7469331766Sken
7470331766Sken	sf->cmd_type = SLI4_CMD_SEND_FRAME_WQE;
7471331766Sken	sf->cq_id = 0xffff;
7472331766Sken
7473331766Sken	return 0;
7474331766Sken}
7475331766Sken
7476331766Sken/**
7477331766Sken * @ingroup sli_fc
7478331766Sken * @brief Write a XMIT_SEQUENCE64 work queue entry.
7479331766Sken *
7480331766Sken * This WQE is used to send FC-CT response frames.
7481331766Sken *
7482331766Sken * @note This API implements a restricted use for this WQE, a TODO: would
7483331766Sken * include passing in sequence initiative, and full SGL's
7484331766Sken *
7485331766Sken * @param sli4 SLI context.
7486331766Sken * @param buf Destination buffer for the WQE.
7487331766Sken * @param size Buffer size, in bytes.
7488331766Sken * @param payload DMA memory for the request.
7489331766Sken * @param payload_len Length of request.
7490331766Sken * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
7491331766Sken * @param ox_id originator exchange ID
7492331766Sken * @param xri XRI for this exchange.
7493331766Sken * @param tag IO tag value.
7494331766Sken * @param rnode Destination of request (that is, the remote node).
7495331766Sken * @param r_ctl R_CTL value for sequence.
7496331766Sken * @param type TYPE value for sequence.
7497331766Sken * @param df_ctl DF_CTL value for sequence.
7498331766Sken *
7499331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7500331766Sken */
7501331766Skenint32_t
7502331766Skensli_xmit_sequence64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload,
7503331766Sken		      uint32_t payload_len, uint8_t timeout, uint16_t ox_id,
7504331766Sken		      uint16_t xri, uint16_t tag, ocs_remote_node_t *rnode,
7505331766Sken		      uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
7506331766Sken{
7507331766Sken	sli4_xmit_sequence64_wqe_t	*xmit = buf;
7508331766Sken
7509331766Sken	ocs_memset(buf, 0, size);
7510331766Sken
7511331766Sken	if ((payload == NULL) || (payload->virt == NULL)) {
7512331766Sken		ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
7513331766Sken			    payload, payload ? payload->virt : NULL);
7514331766Sken		return -1;
7515331766Sken	}
7516331766Sken
7517331766Sken	if (sli4->config.sgl_pre_registered) {
7518331766Sken		xmit->dbde = TRUE;
7519331766Sken	} else {
7520331766Sken		xmit->xbl = TRUE;
7521331766Sken	}
7522331766Sken
7523331766Sken	xmit->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
7524331766Sken	xmit->bde.buffer_length = payload_len;
7525331766Sken	xmit->bde.u.data.buffer_address_low  = ocs_addr32_lo(payload->phys);
7526331766Sken	xmit->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
7527331766Sken	xmit->sequence_payload_len = payload_len;
7528331766Sken
7529331766Sken	xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff;
7530331766Sken
7531331766Sken	xmit->relative_offset = 0;
7532331766Sken
7533331766Sken	xmit->si = 0;			/* sequence initiative - this matches what is seen from
7534331766Sken					 * FC switches in response to FCGS commands */
7535331766Sken	xmit->ft = 0;			/* force transmit */
7536331766Sken	xmit->xo = 0;			/* exchange responder */
7537331766Sken	xmit->ls = 1;			/* last in seqence */
7538331766Sken	xmit->df_ctl = df_ctl;
7539331766Sken	xmit->type = type;
7540331766Sken	xmit->r_ctl = r_ctl;
7541331766Sken
7542331766Sken	xmit->xri_tag = xri;
7543331766Sken	xmit->context_tag = rnode->indicator;
7544331766Sken
7545331766Sken	xmit->dif = 0;
7546331766Sken	xmit->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7547331766Sken	xmit->bs = 0;
7548331766Sken
7549331766Sken	xmit->command = SLI4_WQE_XMIT_SEQUENCE64;
7550331766Sken	xmit->class = SLI4_ELS_REQUEST64_CLASS_3;
7551331766Sken	xmit->pu = 0;
7552331766Sken	xmit->timer = timeout;
7553331766Sken
7554331766Sken	xmit->abort_tag = 0;
7555331766Sken	xmit->request_tag = tag;
7556331766Sken	xmit->remote_xid = ox_id;
7557331766Sken
7558331766Sken	xmit->iod = SLI4_ELS_REQUEST64_DIR_READ;
7559331766Sken
7560331766Sken	if (rnode->node_group) {
7561331766Sken		xmit->hlm = TRUE;
7562331766Sken		xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff;
7563331766Sken	}
7564331766Sken
7565331766Sken	xmit->cmd_type = SLI4_CMD_XMIT_SEQUENCE64_WQE;
7566331766Sken
7567331766Sken	xmit->len_loc = 2;
7568331766Sken
7569331766Sken	xmit->cq_id = 0xFFFF;
7570331766Sken
7571331766Sken	return 0;
7572331766Sken}
7573331766Sken
7574331766Sken/**
7575331766Sken * @ingroup sli_fc
7576331766Sken * @brief Write a REQUEUE_XRI_WQE work queue entry.
7577331766Sken *
7578331766Sken * @param sli4 SLI context.
7579331766Sken * @param buf Destination buffer for the WQE.
7580331766Sken * @param size Buffer size, in bytes.
7581331766Sken * @param xri XRI for this exchange.
7582331766Sken * @param tag IO tag value.
7583331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7584331766Sken *
7585331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7586331766Sken */
7587331766Skenint32_t
7588331766Skensli_requeue_xri_wqe(sli4_t *sli4, void *buf, size_t size, uint16_t xri, uint16_t tag, uint16_t cq_id)
7589331766Sken{
7590331766Sken	sli4_requeue_xri_wqe_t	*requeue = buf;
7591331766Sken
7592331766Sken	ocs_memset(buf, 0, size);
7593331766Sken
7594331766Sken	requeue->command = SLI4_WQE_REQUEUE_XRI;
7595331766Sken	requeue->xri_tag = xri;
7596331766Sken	requeue->request_tag = tag;
7597331766Sken	requeue->xc = 1;
7598331766Sken	requeue->qosd = 1;
7599331766Sken	requeue->cq_id = cq_id;
7600331766Sken	requeue->cmd_type = SLI4_CMD_REQUEUE_XRI_WQE;
7601331766Sken	return 0;
7602331766Sken}
7603331766Sken
7604331766Skenint32_t
7605331766Skensli_xmit_bcast64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload,
7606331766Sken		uint32_t payload_len, uint8_t timeout, uint16_t xri, uint16_t tag,
7607331766Sken		uint16_t cq_id, ocs_remote_node_t *rnode,
7608331766Sken		uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
7609331766Sken{
7610331766Sken	sli4_xmit_bcast64_wqe_t *bcast = buf;
7611331766Sken
7612331766Sken	/* Command requires a temporary RPI (i.e. unused remote node) */
7613331766Sken	if (rnode->attached) {
7614331766Sken		ocs_log_test(sli4->os, "remote node %d in use\n", rnode->indicator);
7615331766Sken		return -1;
7616331766Sken	}
7617331766Sken
7618331766Sken	ocs_memset(buf, 0, size);
7619331766Sken
7620331766Sken	bcast->dbde = TRUE;
7621331766Sken	bcast->sequence_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
7622331766Sken	bcast->sequence_payload.buffer_length = payload_len;
7623331766Sken	bcast->sequence_payload.u.data.buffer_address_low  = ocs_addr32_lo(payload->phys);
7624331766Sken	bcast->sequence_payload.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
7625331766Sken
7626331766Sken	bcast->sequence_payload_length = payload_len;
7627331766Sken
7628331766Sken	bcast->df_ctl = df_ctl;
7629331766Sken	bcast->type = type;
7630331766Sken	bcast->r_ctl = r_ctl;
7631331766Sken
7632331766Sken	bcast->xri_tag = xri;
7633331766Sken
7634331766Sken	bcast->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
7635331766Sken	bcast->context_tag = rnode->sport->indicator;
7636331766Sken
7637331766Sken	bcast->class = SLI4_ELS_REQUEST64_CLASS_3;
7638331766Sken
7639331766Sken	bcast->command = SLI4_WQE_XMIT_BCAST64;
7640331766Sken
7641331766Sken	bcast->timer = timeout;
7642331766Sken
7643331766Sken	bcast->request_tag = tag;
7644331766Sken
7645331766Sken	bcast->temporary_rpi = rnode->indicator;
7646331766Sken
7647331766Sken	bcast->len_loc = 0x1;
7648331766Sken
7649331766Sken	bcast->iod = SLI4_ELS_REQUEST64_DIR_WRITE;
7650331766Sken
7651331766Sken	bcast->cmd_type = SLI4_CMD_XMIT_BCAST64_WQE;
7652331766Sken
7653331766Sken	bcast->cq_id = cq_id;
7654331766Sken
7655331766Sken	return 0;
7656331766Sken}
7657331766Sken
7658331766Sken/**
7659331766Sken * @ingroup sli_fc
7660331766Sken * @brief Write an XMIT_BLS_RSP64_WQE work queue entry.
7661331766Sken *
7662331766Sken * @param sli4 SLI context.
7663331766Sken * @param buf Destination buffer for the WQE.
7664331766Sken * @param size Buffer size, in bytes.
7665331766Sken * @param payload Contents of the BLS payload to be sent.
7666331766Sken * @param xri XRI for this exchange.
7667331766Sken * @param tag IO tag value.
7668331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7669331766Sken * @param rnode Destination of request (that is, the remote node).
7670331766Sken * @param s_id Source ID to use in the response. If UINT32_MAX, use SLI Port's ID.
7671331766Sken *
7672331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7673331766Sken */
7674331766Skenint32_t
7675331766Skensli_xmit_bls_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, sli_bls_payload_t *payload,
7676331766Sken		       uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode, uint32_t s_id)
7677331766Sken{
7678331766Sken	sli4_xmit_bls_rsp_wqe_t *bls = buf;
7679331766Sken
7680331766Sken	/*
7681331766Sken	 * Callers can either specify RPI or S_ID, but not both
7682331766Sken	 */
7683331766Sken	if (rnode->attached && (s_id != UINT32_MAX)) {
7684331766Sken		ocs_log_test(sli4->os, "S_ID specified for attached remote node %d\n",
7685331766Sken			     rnode->indicator);
7686331766Sken		return -1;
7687331766Sken	}
7688331766Sken
7689331766Sken	ocs_memset(buf, 0, size);
7690331766Sken
7691331766Sken	if (SLI_BLS_ACC == payload->type) {
7692331766Sken		bls->payload_word0 = (payload->u.acc.seq_id_last << 16) |
7693331766Sken			(payload->u.acc.seq_id_validity << 24);
7694331766Sken		bls->high_seq_cnt = payload->u.acc.high_seq_cnt;
7695331766Sken		bls->low_seq_cnt = payload->u.acc.low_seq_cnt;
7696331766Sken	} else if (SLI_BLS_RJT == payload->type) {
7697331766Sken		bls->payload_word0 = *((uint32_t *)&payload->u.rjt);
7698331766Sken		bls->ar = TRUE;
7699331766Sken	} else {
7700331766Sken		ocs_log_test(sli4->os, "bad BLS type %#x\n",
7701331766Sken				payload->type);
7702331766Sken		return -1;
7703331766Sken	}
7704331766Sken
7705331766Sken	bls->ox_id = payload->ox_id;
7706331766Sken	bls->rx_id = payload->rx_id;
7707331766Sken
7708331766Sken	if (rnode->attached) {
7709331766Sken		bls->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7710331766Sken		bls->context_tag = rnode->indicator;
7711331766Sken	} else {
7712331766Sken		bls->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
7713331766Sken		bls->context_tag = rnode->sport->indicator;
7714331766Sken
7715331766Sken		if (UINT32_MAX != s_id) {
7716331766Sken			bls->local_n_port_id = s_id & 0x00ffffff;
7717331766Sken		} else {
7718331766Sken			bls->local_n_port_id = rnode->sport->fc_id & 0x00ffffff;
7719331766Sken		}
7720331766Sken		bls->remote_id = rnode->fc_id & 0x00ffffff;
7721331766Sken
7722331766Sken		bls->temporary_rpi = rnode->indicator;
7723331766Sken	}
7724331766Sken
7725331766Sken	bls->xri_tag = xri;
7726331766Sken
7727331766Sken	bls->class = SLI4_ELS_REQUEST64_CLASS_3;
7728331766Sken
7729331766Sken	bls->command = SLI4_WQE_XMIT_BLS_RSP;
7730331766Sken
7731331766Sken	bls->request_tag = tag;
7732331766Sken
7733331766Sken	bls->qosd = TRUE;
7734331766Sken
7735331766Sken	if (rnode->node_group) {
7736331766Sken		bls->hlm = TRUE;
7737331766Sken		bls->remote_id = rnode->fc_id & 0x00ffffff;
7738331766Sken	}
7739331766Sken
7740331766Sken	bls->cq_id = cq_id;
7741331766Sken
7742331766Sken	bls->cmd_type = SLI4_CMD_XMIT_BLS_RSP64_WQE;
7743331766Sken
7744331766Sken	return 0;
7745331766Sken}
7746331766Sken
7747331766Sken/**
7748331766Sken * @ingroup sli_fc
7749331766Sken * @brief Write a XMIT_ELS_RSP64_WQE work queue entry.
7750331766Sken *
7751331766Sken * @param sli4 SLI context.
7752331766Sken * @param buf Destination buffer for the WQE.
7753331766Sken * @param size Buffer size, in bytes.
7754331766Sken * @param rsp DMA memory for the ELS response.
7755331766Sken * @param rsp_len Length of ELS response, in bytes.
7756331766Sken * @param xri XRI for this exchange.
7757331766Sken * @param tag IO tag value.
7758331766Sken * @param cq_id The id of the completion queue where the WQE response is sent.
7759331766Sken * @param ox_id OX_ID of the exchange containing the request.
7760331766Sken * @param rnode Destination of the ELS response (that is, the remote node).
7761331766Sken * @param flags Optional attributes, including:
7762331766Sken *  - SLI4_IO_CONTINUATION - IO is already active.
7763331766Sken * @param s_id S_ID used for special responses.
7764331766Sken *
7765331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7766331766Sken */
7767331766Skenint32_t
7768331766Skensli_xmit_els_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *rsp,
7769331766Sken		       uint32_t rsp_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
7770331766Sken		       uint16_t ox_id, ocs_remote_node_t *rnode, uint32_t flags, uint32_t s_id)
7771331766Sken{
7772331766Sken	sli4_xmit_els_rsp64_wqe_t	*els = buf;
7773331766Sken
7774331766Sken	ocs_memset(buf, 0, size);
7775331766Sken
7776331766Sken	if (sli4->config.sgl_pre_registered) {
7777331766Sken		els->dbde = TRUE;
7778331766Sken	} else {
7779331766Sken		els->xbl = TRUE;
7780331766Sken	}
7781331766Sken
7782331766Sken	els->els_response_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
7783331766Sken	els->els_response_payload.buffer_length = rsp_len;
7784331766Sken	els->els_response_payload.u.data.buffer_address_low  = ocs_addr32_lo(rsp->phys);
7785331766Sken	els->els_response_payload.u.data.buffer_address_high = ocs_addr32_hi(rsp->phys);
7786331766Sken
7787331766Sken	els->els_response_payload_length = rsp_len;
7788331766Sken
7789331766Sken	els->xri_tag = xri;
7790331766Sken
7791331766Sken	els->class = SLI4_ELS_REQUEST64_CLASS_3;
7792331766Sken
7793331766Sken	els->command = SLI4_WQE_ELS_RSP64;
7794331766Sken
7795331766Sken	els->request_tag = tag;
7796331766Sken
7797331766Sken	els->ox_id = ox_id;
7798331766Sken
7799331766Sken	els->iod = SLI4_ELS_REQUEST64_DIR_WRITE;
7800331766Sken
7801331766Sken	els->qosd = TRUE;
7802331766Sken
7803331766Sken	if (flags & SLI4_IO_CONTINUATION) {
7804331766Sken		els->xc = TRUE;
7805331766Sken	}
7806331766Sken
7807331766Sken	if (rnode->attached) {
7808331766Sken		els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
7809331766Sken		els->context_tag = rnode->indicator;
7810331766Sken	} else {
7811331766Sken		els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
7812331766Sken		els->context_tag = rnode->sport->indicator;
7813331766Sken		els->remote_id = rnode->fc_id & 0x00ffffff;
7814331766Sken		els->temporary_rpi = rnode->indicator;
7815331766Sken		if (UINT32_MAX != s_id) {
7816331766Sken			els->sp = TRUE;
7817331766Sken			els->s_id = s_id & 0x00ffffff;
7818331766Sken		}
7819331766Sken	}
7820331766Sken
7821331766Sken	if (rnode->node_group) {
7822331766Sken		els->hlm = TRUE;
7823331766Sken		els->remote_id = rnode->fc_id & 0x00ffffff;
7824331766Sken	}
7825331766Sken
7826331766Sken	els->cmd_type = SLI4_ELS_REQUEST64_CMD_GEN;
7827331766Sken
7828331766Sken	els->cq_id = cq_id;
7829331766Sken
7830331766Sken	return 0;
7831331766Sken}
7832331766Sken
7833331766Sken/**
7834331766Sken * @ingroup sli_fc
7835331766Sken * @brief Process an asynchronous Link State event entry.
7836331766Sken *
7837331766Sken * @par Description
7838331766Sken * Parses Asynchronous Completion Queue Entry (ACQE),
7839331766Sken * creates an abstracted event, and calls registered callback functions.
7840331766Sken *
7841331766Sken * @param sli4 SLI context.
7842331766Sken * @param acqe Pointer to the ACQE.
7843331766Sken *
7844331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7845331766Sken */
7846331766Skenint32_t
7847331766Skensli_fc_process_link_state(sli4_t *sli4, void *acqe)
7848331766Sken{
7849331766Sken	sli4_link_state_t	*link_state = acqe;
7850331766Sken	sli4_link_event_t	event = { 0 };
7851331766Sken	int32_t			rc = 0;
7852331766Sken
7853331766Sken	if (!sli4->link) {
7854331766Sken		/* bail if there is no callback */
7855331766Sken		return 0;
7856331766Sken	}
7857331766Sken
7858331766Sken	if (SLI4_LINK_TYPE_ETHERNET == link_state->link_type) {
7859331766Sken		event.topology = SLI_LINK_TOPO_NPORT;
7860331766Sken		event.medium   = SLI_LINK_MEDIUM_ETHERNET;
7861331766Sken	} else {
7862331766Sken		/* TODO is this supported for anything other than FCoE? */
7863331766Sken		ocs_log_test(sli4->os, "unsupported link type %#x\n",
7864331766Sken				link_state->link_type);
7865331766Sken		event.topology = SLI_LINK_TOPO_MAX;
7866331766Sken		event.medium   = SLI_LINK_MEDIUM_MAX;
7867331766Sken		rc = -1;
7868331766Sken	}
7869331766Sken
7870331766Sken	switch (link_state->port_link_status) {
7871331766Sken	case SLI4_PORT_LINK_STATUS_PHYSICAL_DOWN:
7872331766Sken	case SLI4_PORT_LINK_STATUS_LOGICAL_DOWN:
7873331766Sken		event.status = SLI_LINK_STATUS_DOWN;
7874331766Sken		break;
7875331766Sken	case SLI4_PORT_LINK_STATUS_PHYSICAL_UP:
7876331766Sken	case SLI4_PORT_LINK_STATUS_LOGICAL_UP:
7877331766Sken		event.status = SLI_LINK_STATUS_UP;
7878331766Sken		break;
7879331766Sken	default:
7880331766Sken		ocs_log_test(sli4->os, "unsupported link status %#x\n",
7881331766Sken				link_state->port_link_status);
7882331766Sken		event.status = SLI_LINK_STATUS_MAX;
7883331766Sken		rc = -1;
7884331766Sken	}
7885331766Sken
7886331766Sken	switch (link_state->port_speed) {
7887331766Sken	case 0:
7888331766Sken		event.speed = 0;
7889331766Sken		break;
7890331766Sken	case 1:
7891331766Sken		event.speed = 10;
7892331766Sken		break;
7893331766Sken	case 2:
7894331766Sken		event.speed = 100;
7895331766Sken		break;
7896331766Sken	case 3:
7897331766Sken		event.speed = 1000;
7898331766Sken		break;
7899331766Sken	case 4:
7900331766Sken		event.speed = 10000;
7901331766Sken		break;
7902331766Sken	case 5:
7903331766Sken		event.speed = 20000;
7904331766Sken		break;
7905331766Sken	case 6:
7906331766Sken		event.speed = 25000;
7907331766Sken		break;
7908331766Sken	case 7:
7909331766Sken		event.speed = 40000;
7910331766Sken		break;
7911331766Sken	case 8:
7912331766Sken		event.speed = 100000;
7913331766Sken		break;
7914331766Sken	default:
7915331766Sken		ocs_log_test(sli4->os, "unsupported port_speed %#x\n",
7916331766Sken				link_state->port_speed);
7917331766Sken		rc = -1;
7918331766Sken	}
7919331766Sken
7920331766Sken	sli4->link(sli4->link_arg, (void *)&event);
7921331766Sken
7922331766Sken	return rc;
7923331766Sken}
7924331766Sken
7925331766Sken/**
7926331766Sken * @ingroup sli_fc
7927331766Sken * @brief Process an asynchronous Link Attention event entry.
7928331766Sken *
7929331766Sken * @par Description
7930331766Sken * Parses Asynchronous Completion Queue Entry (ACQE),
7931331766Sken * creates an abstracted event, and calls the registered callback functions.
7932331766Sken *
7933331766Sken * @param sli4 SLI context.
7934331766Sken * @param acqe Pointer to the ACQE.
7935331766Sken *
7936331766Sken * @todo XXX all events return LINK_UP.
7937331766Sken *
7938331766Sken * @return Returns 0 on success, or a non-zero value on failure.
7939331766Sken */
7940331766Skenint32_t
7941331766Skensli_fc_process_link_attention(sli4_t *sli4, void *acqe)
7942331766Sken{
7943331766Sken	sli4_link_attention_t	*link_attn = acqe;
7944331766Sken	sli4_link_event_t	event = { 0 };
7945331766Sken
7946331766Sken	ocs_log_debug(sli4->os, "link_number=%d attn_type=%#x topology=%#x port_speed=%#x "
7947331766Sken			"port_fault=%#x shared_link_status=%#x logical_link_speed=%#x "
7948331766Sken			"event_tag=%#x\n", link_attn->link_number, link_attn->attn_type,
7949331766Sken			link_attn->topology, link_attn->port_speed, link_attn->port_fault,
7950331766Sken			link_attn->shared_link_status, link_attn->logical_link_speed,
7951331766Sken			link_attn->event_tag);
7952331766Sken
7953331766Sken	if (!sli4->link) {
7954331766Sken		return 0;
7955331766Sken	}
7956331766Sken
7957331766Sken	event.medium   = SLI_LINK_MEDIUM_FC;
7958331766Sken
7959331766Sken	switch (link_attn->attn_type) {
7960331766Sken	case SLI4_LINK_ATTN_TYPE_LINK_UP:
7961331766Sken		event.status = SLI_LINK_STATUS_UP;
7962331766Sken		break;
7963331766Sken	case SLI4_LINK_ATTN_TYPE_LINK_DOWN:
7964331766Sken		event.status = SLI_LINK_STATUS_DOWN;
7965331766Sken		break;
7966331766Sken	case SLI4_LINK_ATTN_TYPE_NO_HARD_ALPA:
7967331766Sken		ocs_log_debug(sli4->os, "attn_type: no hard alpa\n");
7968331766Sken		event.status = SLI_LINK_STATUS_NO_ALPA;
7969331766Sken		break;
7970331766Sken	default:
7971331766Sken		ocs_log_test(sli4->os, "attn_type: unknown\n");
7972331766Sken		break;
7973331766Sken	}
7974331766Sken
7975331766Sken	switch (link_attn->event_type) {
7976331766Sken	case SLI4_FC_EVENT_LINK_ATTENTION:
7977331766Sken		break;
7978331766Sken	case SLI4_FC_EVENT_SHARED_LINK_ATTENTION:
7979331766Sken		ocs_log_debug(sli4->os, "event_type: FC shared link event \n");
7980331766Sken		break;
7981331766Sken	default:
7982331766Sken		ocs_log_test(sli4->os, "event_type: unknown\n");
7983331766Sken		break;
7984331766Sken	}
7985331766Sken
7986331766Sken	switch (link_attn->topology) {
7987331766Sken	case SLI4_LINK_ATTN_P2P:
7988331766Sken		event.topology = SLI_LINK_TOPO_NPORT;
7989331766Sken		break;
7990331766Sken	case SLI4_LINK_ATTN_FC_AL:
7991331766Sken		event.topology = SLI_LINK_TOPO_LOOP;
7992331766Sken		break;
7993331766Sken	case SLI4_LINK_ATTN_INTERNAL_LOOPBACK:
7994331766Sken		ocs_log_debug(sli4->os, "topology Internal loopback\n");
7995331766Sken		event.topology = SLI_LINK_TOPO_LOOPBACK_INTERNAL;
7996331766Sken		break;
7997331766Sken	case SLI4_LINK_ATTN_SERDES_LOOPBACK:
7998331766Sken		ocs_log_debug(sli4->os, "topology serdes loopback\n");
7999331766Sken		event.topology = SLI_LINK_TOPO_LOOPBACK_EXTERNAL;
8000331766Sken		break;
8001331766Sken	default:
8002331766Sken		ocs_log_test(sli4->os, "topology: unknown\n");
8003331766Sken		break;
8004331766Sken	}
8005331766Sken
8006331766Sken	event.speed    = link_attn->port_speed * 1000;
8007331766Sken
8008331766Sken	sli4->link(sli4->link_arg, (void *)&event);
8009331766Sken
8010331766Sken	return 0;
8011331766Sken}
8012331766Sken
8013331766Sken/**
8014331766Sken * @ingroup sli_fc
8015331766Sken * @brief Parse an FC/FCoE work queue CQ entry.
8016331766Sken *
8017331766Sken * @param sli4 SLI context.
8018331766Sken * @param cq CQ to process.
8019331766Sken * @param cqe Pointer to the CQ entry.
8020331766Sken * @param etype CQ event type.
8021331766Sken * @param r_id Resource ID associated with this completion message (such as the IO tag).
8022331766Sken *
8023331766Sken * @return Returns 0 on success, or a non-zero value on failure.
8024331766Sken */
8025331766Skenint32_t
8026331766Skensli_fc_cqe_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
8027331766Sken		uint16_t *r_id)
8028331766Sken{
8029331766Sken	uint8_t		code = cqe[SLI4_CQE_CODE_OFFSET];
8030331766Sken	int32_t		rc = -1;
8031331766Sken
8032331766Sken	switch (code) {
8033331766Sken	case SLI4_CQE_CODE_WORK_REQUEST_COMPLETION:
8034331766Sken	{
8035331766Sken		sli4_fc_wcqe_t *wcqe = (void *)cqe;
8036331766Sken
8037331766Sken		*etype = SLI_QENTRY_WQ;
8038331766Sken		*r_id = wcqe->request_tag;
8039331766Sken		rc = wcqe->status;
8040331766Sken
8041331766Sken		/* Flag errors except for FCP_RSP_FAILURE */
8042331766Sken		if (rc && (rc != SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE)) {
8043331766Sken
8044331766Sken			ocs_log_test(sli4->os, "WCQE: status=%#x hw_status=%#x tag=%#x w1=%#x w2=%#x xb=%d\n",
8045331766Sken				wcqe->status, wcqe->hw_status,
8046331766Sken				wcqe->request_tag, wcqe->wqe_specific_1,
8047331766Sken				wcqe->wqe_specific_2, wcqe->xb);
8048331766Sken			ocs_log_test(sli4->os, "      %08X %08X %08X %08X\n", ((uint32_t*) cqe)[0], ((uint32_t*) cqe)[1],
8049331766Sken				((uint32_t*) cqe)[2], ((uint32_t*) cqe)[3]);
8050331766Sken		}
8051331766Sken
8052331766Sken		/* TODO: need to pass additional status back out of here as well
8053331766Sken		 * as status (could overload rc as status/addlstatus are only 8 bits each)
8054331766Sken		 */
8055331766Sken
8056331766Sken		break;
8057331766Sken	}
8058331766Sken	case SLI4_CQE_CODE_RQ_ASYNC:
8059331766Sken	{
8060331766Sken		sli4_fc_async_rcqe_t *rcqe = (void *)cqe;
8061331766Sken
8062331766Sken		*etype = SLI_QENTRY_RQ;
8063331766Sken		*r_id = rcqe->rq_id;
8064331766Sken		rc = rcqe->status;
8065331766Sken		break;
8066331766Sken	}
8067331766Sken	case SLI4_CQE_CODE_RQ_ASYNC_V1:
8068331766Sken	{
8069331766Sken		sli4_fc_async_rcqe_v1_t *rcqe = (void *)cqe;
8070331766Sken
8071331766Sken		*etype = SLI_QENTRY_RQ;
8072331766Sken		*r_id = rcqe->rq_id;
8073331766Sken		rc = rcqe->status;
8074331766Sken		break;
8075331766Sken	}
8076331766Sken	case SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD:
8077331766Sken	{
8078331766Sken		sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe;
8079331766Sken
8080331766Sken		*etype = SLI_QENTRY_OPT_WRITE_CMD;
8081331766Sken		*r_id = optcqe->rq_id;
8082331766Sken		rc = optcqe->status;
8083331766Sken		break;
8084331766Sken	}
8085331766Sken	case SLI4_CQE_CODE_OPTIMIZED_WRITE_DATA:
8086331766Sken	{
8087331766Sken		sli4_fc_optimized_write_data_cqe_t *dcqe = (void *)cqe;
8088331766Sken
8089331766Sken		*etype = SLI_QENTRY_OPT_WRITE_DATA;
8090331766Sken		*r_id = dcqe->xri;
8091331766Sken		rc = dcqe->status;
8092331766Sken
8093331766Sken		/* Flag errors */
8094331766Sken		if (rc != SLI4_FC_WCQE_STATUS_SUCCESS) {
8095331766Sken			ocs_log_test(sli4->os, "Optimized DATA CQE: status=%#x hw_status=%#x xri=%#x dpl=%#x w3=%#x xb=%d\n",
8096331766Sken				dcqe->status, dcqe->hw_status,
8097331766Sken				dcqe->xri, dcqe->total_data_placed,
8098331766Sken				((uint32_t*) cqe)[3], dcqe->xb);
8099331766Sken		}
8100331766Sken		break;
8101331766Sken	}
8102331766Sken	case SLI4_CQE_CODE_RQ_COALESCING:
8103331766Sken	{
8104331766Sken		sli4_fc_coalescing_rcqe_t *rcqe = (void *)cqe;
8105331766Sken
8106331766Sken		*etype = SLI_QENTRY_RQ;
8107331766Sken		*r_id = rcqe->rq_id;
8108331766Sken		rc = rcqe->status;
8109331766Sken		break;
8110331766Sken	}
8111331766Sken	case SLI4_CQE_CODE_XRI_ABORTED:
8112331766Sken	{
8113331766Sken		sli4_fc_xri_aborted_cqe_t *xa = (void *)cqe;
8114331766Sken
8115331766Sken		*etype = SLI_QENTRY_XABT;
8116331766Sken		*r_id = xa->xri;
8117331766Sken		rc = 0;
8118331766Sken		break;
8119331766Sken	}
8120331766Sken	case SLI4_CQE_CODE_RELEASE_WQE: {
8121331766Sken		sli4_fc_wqec_t *wqec = (void*) cqe;
8122331766Sken
8123331766Sken		*etype = SLI_QENTRY_WQ_RELEASE;
8124331766Sken		*r_id = wqec->wq_id;
8125331766Sken		rc = 0;
8126331766Sken		break;
8127331766Sken	}
8128331766Sken	default:
8129331766Sken		ocs_log_test(sli4->os, "CQE completion code %d not handled\n", code);
8130331766Sken		*etype = SLI_QENTRY_MAX;
8131331766Sken		*r_id = UINT16_MAX;
8132331766Sken	}
8133331766Sken
8134331766Sken	return rc;
8135331766Sken}
8136331766Sken
8137331766Sken/**
8138331766Sken * @ingroup sli_fc
8139331766Sken * @brief Return the ELS/CT response length.
8140331766Sken *
8141331766Sken * @param sli4 SLI context.
8142331766Sken * @param cqe Pointer to the CQ entry.
8143331766Sken *
8144331766Sken * @return Returns the length, in bytes.
8145331766Sken */
8146331766Skenuint32_t
8147331766Skensli_fc_response_length(sli4_t *sli4, uint8_t *cqe)
8148331766Sken{
8149331766Sken	sli4_fc_wcqe_t *wcqe = (void *)cqe;
8150331766Sken
8151331766Sken	return wcqe->wqe_specific_1;
8152331766Sken}
8153331766Sken
8154331766Sken/**
8155331766Sken * @ingroup sli_fc
8156331766Sken * @brief Return the FCP IO length.
8157331766Sken *
8158331766Sken * @param sli4 SLI context.
8159331766Sken * @param cqe Pointer to the CQ entry.
8160331766Sken *
8161331766Sken * @return Returns the length, in bytes.
8162331766Sken */
8163331766Skenuint32_t
8164331766Skensli_fc_io_length(sli4_t *sli4, uint8_t *cqe)
8165331766Sken{
8166331766Sken	sli4_fc_wcqe_t *wcqe = (void *)cqe;
8167331766Sken
8168331766Sken	return wcqe->wqe_specific_1;
8169331766Sken}
8170331766Sken
8171331766Sken/**
8172331766Sken * @ingroup sli_fc
8173331766Sken * @brief Retrieve the D_ID from the completion.
8174331766Sken *
8175331766Sken * @param sli4 SLI context.
8176331766Sken * @param cqe Pointer to the CQ entry.
8177331766Sken * @param d_id Pointer where the D_ID is written.
8178331766Sken *
8179331766Sken * @return Returns 0 on success, or a non-zero value on failure.
8180331766Sken */
8181331766Skenint32_t
8182331766Skensli_fc_els_did(sli4_t *sli4, uint8_t *cqe, uint32_t *d_id)
8183331766Sken{
8184331766Sken	sli4_fc_wcqe_t *wcqe = (void *)cqe;
8185331766Sken
8186331766Sken	*d_id = 0;
8187331766Sken
8188331766Sken	if (wcqe->status) {
8189331766Sken		return -1;
8190331766Sken	} else {
8191331766Sken		*d_id = wcqe->wqe_specific_2 & 0x00ffffff;
8192331766Sken		return 0;
8193331766Sken	}
8194331766Sken}
8195331766Sken
8196331766Skenuint32_t
8197331766Skensli_fc_ext_status(sli4_t *sli4, uint8_t *cqe)
8198331766Sken{
8199331766Sken	sli4_fc_wcqe_t *wcqe = (void *)cqe;
8200331766Sken	uint32_t	mask;
8201331766Sken
8202331766Sken	switch (wcqe->status) {
8203331766Sken	case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE:
8204331766Sken		mask = UINT32_MAX;
8205331766Sken		break;
8206331766Sken	case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
8207331766Sken	case SLI4_FC_WCQE_STATUS_CMD_REJECT:
8208331766Sken		mask = 0xff;
8209331766Sken		break;
8210331766Sken	case SLI4_FC_WCQE_STATUS_NPORT_RJT:
8211331766Sken	case SLI4_FC_WCQE_STATUS_FABRIC_RJT:
8212331766Sken	case SLI4_FC_WCQE_STATUS_NPORT_BSY:
8213331766Sken	case SLI4_FC_WCQE_STATUS_FABRIC_BSY:
8214331766Sken	case SLI4_FC_WCQE_STATUS_LS_RJT:
8215331766Sken		mask = UINT32_MAX;
8216331766Sken		break;
8217331766Sken	case SLI4_FC_WCQE_STATUS_DI_ERROR:
8218331766Sken		mask = UINT32_MAX;
8219331766Sken		break;
8220331766Sken	default:
8221331766Sken		mask = 0;
8222331766Sken	}
8223331766Sken
8224331766Sken	return wcqe->wqe_specific_2 & mask;
8225331766Sken}
8226331766Sken
8227331766Sken/**
8228331766Sken * @ingroup sli_fc
8229331766Sken * @brief Retrieve the RQ index from the completion.
8230331766Sken *
8231331766Sken * @param sli4 SLI context.
8232331766Sken * @param cqe Pointer to the CQ entry.
8233331766Sken * @param rq_id Pointer where the rq_id is written.
8234331766Sken * @param index Pointer where the index is written.
8235331766Sken *
8236331766Sken * @return Returns 0 on success, or a non-zero value on failure.
8237331766Sken */
8238331766Skenint32_t
8239331766Skensli_fc_rqe_rqid_and_index(sli4_t *sli4, uint8_t *cqe, uint16_t *rq_id, uint32_t *index)
8240331766Sken{
8241331766Sken	sli4_fc_async_rcqe_t	*rcqe = (void *)cqe;
8242331766Sken	sli4_fc_async_rcqe_v1_t	*rcqe_v1 = (void *)cqe;
8243331766Sken	int32_t	rc = -1;
8244331766Sken	uint8_t	code = 0;
8245331766Sken
8246331766Sken	*rq_id = 0;
8247331766Sken	*index = UINT32_MAX;
8248331766Sken
8249331766Sken	code = cqe[SLI4_CQE_CODE_OFFSET];
8250331766Sken
8251331766Sken	if (code == SLI4_CQE_CODE_RQ_ASYNC) {
8252331766Sken		*rq_id = rcqe->rq_id;
8253331766Sken		if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe->status) {
8254331766Sken			*index = rcqe->rq_element_index;
8255331766Sken			rc = 0;
8256331766Sken		} else {
8257331766Sken			*index = rcqe->rq_element_index;
8258331766Sken			rc = rcqe->status;
8259331766Sken			ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
8260331766Sken				rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id,
8261331766Sken				rcqe->rq_element_index, rcqe->payload_data_placement_length, rcqe->sof_byte,
8262331766Sken				rcqe->eof_byte, rcqe->header_data_placement_length);
8263331766Sken		}
8264331766Sken	} else if (code == SLI4_CQE_CODE_RQ_ASYNC_V1) {
8265331766Sken		*rq_id = rcqe_v1->rq_id;
8266331766Sken		if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe_v1->status) {
8267331766Sken			*index = rcqe_v1->rq_element_index;
8268331766Sken			rc = 0;
8269331766Sken		} else {
8270331766Sken			*index = rcqe_v1->rq_element_index;
8271331766Sken			rc = rcqe_v1->status;
8272331766Sken			ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
8273331766Sken				rcqe_v1->status, sli_fc_get_status_string(rcqe_v1->status),
8274331766Sken				rcqe_v1->rq_id, rcqe_v1->rq_element_index,
8275331766Sken				rcqe_v1->payload_data_placement_length, rcqe_v1->sof_byte,
8276331766Sken				rcqe_v1->eof_byte, rcqe_v1->header_data_placement_length);
8277331766Sken		}
8278331766Sken	} else if (code == SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD) {
8279331766Sken		sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe;
8280331766Sken
8281331766Sken		*rq_id = optcqe->rq_id;
8282331766Sken		if (SLI4_FC_ASYNC_RQ_SUCCESS == optcqe->status) {
8283331766Sken			*index = optcqe->rq_element_index;
8284331766Sken			rc = 0;
8285331766Sken		} else {
8286331766Sken			*index = optcqe->rq_element_index;
8287331766Sken			rc = optcqe->status;
8288331766Sken			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",
8289331766Sken				optcqe->status, sli_fc_get_status_string(optcqe->status), optcqe->rq_id,
8290331766Sken				optcqe->rq_element_index, optcqe->payload_data_placement_length,
8291331766Sken				optcqe->header_data_placement_length, optcqe->oox, optcqe->agxr, optcqe->xri,
8292331766Sken				optcqe->rpi);
8293331766Sken		}
8294331766Sken	} else if (code == SLI4_CQE_CODE_RQ_COALESCING) {
8295331766Sken		sli4_fc_coalescing_rcqe_t	*rcqe = (void *)cqe;
8296331766Sken
8297331766Sken		*rq_id = rcqe->rq_id;
8298331766Sken		if (SLI4_FC_COALESCE_RQ_SUCCESS == rcqe->status) {
8299331766Sken			*index = rcqe->rq_element_index;
8300331766Sken			rc = 0;
8301331766Sken		} else {
8302331766Sken			*index = UINT32_MAX;
8303331766Sken			rc = rcqe->status;
8304331766Sken
8305331766Sken			ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x rq_id=%#x sdpl=%x\n",
8306331766Sken				rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id,
8307331766Sken				rcqe->rq_element_index, rcqe->rq_id, rcqe->sequence_reporting_placement_length);
8308331766Sken		}
8309331766Sken	} else {
8310331766Sken		*index = UINT32_MAX;
8311331766Sken
8312331766Sken		rc = rcqe->status;
8313331766Sken
8314331766Sken		ocs_log_debug(sli4->os, "status=%02x rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
8315331766Sken			rcqe->status, rcqe->rq_id, rcqe->rq_element_index, rcqe->payload_data_placement_length,
8316331766Sken			rcqe->sof_byte, rcqe->eof_byte, rcqe->header_data_placement_length);
8317331766Sken	}
8318331766Sken
8319331766Sken	return rc;
8320331766Sken}
8321331766Sken
8322331766Sken/**
8323331766Sken * @ingroup sli_fc
8324331766Sken * @brief Process an asynchronous FCoE event entry.
8325331766Sken *
8326331766Sken * @par Description
8327331766Sken * Parses Asynchronous Completion Queue Entry (ACQE),
8328331766Sken * creates an abstracted event, and calls the registered callback functions.
8329331766Sken *
8330331766Sken * @param sli4 SLI context.
8331331766Sken * @param acqe Pointer to the ACQE.
8332331766Sken *
8333331766Sken * @return Returns 0 on success, or a non-zero value on failure.
8334331766Sken */
8335331766Skenint32_t
8336331766Skensli_fc_process_fcoe(sli4_t *sli4, void *acqe)
8337331766Sken{
8338331766Sken	sli4_fcoe_fip_t	*fcoe = acqe;
8339331766Sken	sli4_fip_event_t event = { 0 };
8340331766Sken	uint32_t	mask = UINT32_MAX;
8341331766Sken
8342331766Sken	ocs_log_debug(sli4->os, "ACQE FCoE FIP type=%02x count=%d tag=%#x\n",
8343331766Sken			fcoe->event_type,
8344331766Sken			fcoe->fcf_count,
8345331766Sken			fcoe->event_tag);
8346331766Sken
8347331766Sken	if (!sli4->fip) {
8348331766Sken		return 0;
8349331766Sken	}
8350331766Sken
8351331766Sken	event.type = fcoe->event_type;
8352331766Sken	event.index = UINT32_MAX;
8353331766Sken
8354331766Sken	switch (fcoe->event_type) {
8355331766Sken	case SLI4_FCOE_FIP_FCF_DISCOVERED:
8356331766Sken		ocs_log_debug(sli4->os, "FCF Discovered index=%d\n", fcoe->event_information);
8357331766Sken		break;
8358331766Sken	case SLI4_FCOE_FIP_FCF_TABLE_FULL:
8359331766Sken		ocs_log_debug(sli4->os, "FCF Table Full\n");
8360331766Sken		mask = 0;
8361331766Sken		break;
8362331766Sken	case SLI4_FCOE_FIP_FCF_DEAD:
8363331766Sken		ocs_log_debug(sli4->os, "FCF Dead/Gone index=%d\n", fcoe->event_information);
8364331766Sken		break;
8365331766Sken	case SLI4_FCOE_FIP_FCF_CLEAR_VLINK:
8366331766Sken		mask = UINT16_MAX;
8367331766Sken		ocs_log_debug(sli4->os, "Clear VLINK Received VPI=%#x\n", fcoe->event_information & mask);
8368331766Sken		break;
8369331766Sken	case SLI4_FCOE_FIP_FCF_MODIFIED:
8370331766Sken		ocs_log_debug(sli4->os, "FCF Modified\n");
8371331766Sken		break;
8372331766Sken	default:
8373331766Sken		ocs_log_test(sli4->os, "bad FCoE type %#x", fcoe->event_type);
8374331766Sken		mask = 0;
8375331766Sken	}
8376331766Sken
8377331766Sken	if (mask != 0) {
8378331766Sken		event.index = fcoe->event_information & mask;
8379331766Sken	}
8380331766Sken
8381331766Sken	sli4->fip(sli4->fip_arg, &event);
8382331766Sken
8383331766Sken	return 0;
8384331766Sken}
8385331766Sken
8386331766Sken/**
8387331766Sken * @ingroup sli_fc
8388331766Sken * @brief Allocate a receive queue.
8389331766Sken *
8390331766Sken * @par Description
8391331766Sken * Allocates DMA memory and configures the requested queue type.
8392331766Sken *
8393331766Sken * @param sli4 SLI context.
8394331766Sken * @param q Pointer to the queue object for the header.
8395331766Sken * @param n_entries Number of entries to allocate.
8396331766Sken * @param buffer_size buffer size for the queue.
8397331766Sken * @param cq Associated CQ.
8398331766Sken * @param ulp The ULP to bind
8399331766Sken * @param is_hdr Used to validate the rq_id and set the type of queue
8400331766Sken *
8401331766Sken * @return Returns 0 on success, or -1 on failure.
8402331766Sken */
8403331766Skenint32_t
8404331766Skensli_fc_rq_alloc(sli4_t *sli4, sli4_queue_t *q,
8405331766Sken		uint32_t n_entries, uint32_t buffer_size,
8406331766Sken		sli4_queue_t *cq, uint16_t ulp, uint8_t is_hdr)
8407331766Sken{
8408331766Sken	int32_t (*rq_create)(sli4_t *, void *, size_t, ocs_dma_t *, uint16_t, uint16_t, uint16_t);
8409331766Sken
8410331766Sken	if ((sli4 == NULL) || (q == NULL)) {
8411331766Sken		void *os = sli4 != NULL ? sli4->os : NULL;
8412331766Sken
8413331766Sken		ocs_log_err(os, "bad parameter sli4=%p q=%p\n", sli4, q);
8414331766Sken		return -1;
8415331766Sken	}
8416331766Sken
8417331766Sken	if (__sli_queue_init(sli4, q, SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE,
8418331766Sken				n_entries, SLI_PAGE_SIZE)) {
8419331766Sken		return -1;
8420331766Sken	}
8421331766Sken
8422331766Sken	if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
8423331766Sken		rq_create = sli_cmd_fcoe_rq_create;
8424331766Sken	} else {
8425331766Sken		rq_create = sli_cmd_fcoe_rq_create_v1;
8426331766Sken	}
8427331766Sken
8428331766Sken	if (rq_create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma,
8429331766Sken		      cq->id, ulp, buffer_size)) {
8430331766Sken		if (__sli_create_queue(sli4, q)) {
8431331766Sken			ocs_dma_free(sli4->os, &q->dma);
8432331766Sken			return -1;
8433331766Sken		}
8434331766Sken		if (is_hdr && q->id & 1) {
8435331766Sken			ocs_log_test(sli4->os, "bad header RQ_ID %d\n", q->id);
8436331766Sken			ocs_dma_free(sli4->os, &q->dma);
8437331766Sken			return -1;
8438331766Sken		} else if (!is_hdr  && (q->id & 1) == 0) {
8439331766Sken			ocs_log_test(sli4->os, "bad data RQ_ID %d\n", q->id);
8440331766Sken			ocs_dma_free(sli4->os, &q->dma);
8441331766Sken			return -1;
8442331766Sken		}
8443331766Sken	} else {
8444331766Sken		return -1;
8445331766Sken	}
8446331766Sken	q->u.flag.is_hdr = is_hdr;
8447331766Sken	if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
8448331766Sken		q->u.flag.rq_batch = TRUE;
8449331766Sken	}
8450331766Sken	return 0;
8451331766Sken}
8452331766Sken
8453331766Sken
8454331766Sken/**
8455331766Sken * @ingroup sli_fc
8456331766Sken * @brief Allocate a receive queue set.
8457331766Sken *
8458331766Sken * @param sli4 SLI context.
8459331766Sken * @param num_rq_pairs to create
8460331766Sken * @param qs Pointers to the queue objects for both header and data.
8461331766Sken *	Length of this arrays should be 2 * num_rq_pairs
8462331766Sken * @param base_cq_id. Assumes base_cq_id : (base_cq_id + num_rq_pairs) cqs as allotted.
8463331766Sken * @param n_entries number of entries in each RQ queue.
8464331766Sken * @param header_buffer_size
8465331766Sken * @param payload_buffer_size
8466331766Sken * @param ulp The ULP to bind
8467331766Sken *
8468331766Sken * @return Returns 0 on success, or -1 on failure.
8469331766Sken */
8470331766Skenint32_t
8471331766Skensli_fc_rq_set_alloc(sli4_t *sli4, uint32_t num_rq_pairs,
8472331766Sken		    sli4_queue_t *qs[], uint32_t base_cq_id,
8473331766Sken		    uint32_t n_entries, uint32_t header_buffer_size,
8474331766Sken		    uint32_t payload_buffer_size,  uint16_t ulp)
8475331766Sken{
8476331766Sken	uint32_t i, p, offset = 0;
8477331766Sken	uint32_t payload_size, total_page_count = 0;
8478331766Sken	uintptr_t addr;
8479331766Sken	ocs_dma_t dma;
8480331766Sken	sli4_res_common_create_queue_set_t *rsp = NULL;
8481331766Sken	sli4_req_fcoe_rq_create_v2_t    *req = NULL;
8482331766Sken
8483331766Sken	for (i = 0; i < (num_rq_pairs * 2); i++) {
8484331766Sken		if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE,
8485331766Sken					n_entries, SLI_PAGE_SIZE)) {
8486331766Sken			goto error;
8487331766Sken		}
8488331766Sken	}
8489331766Sken
8490331766Sken	total_page_count = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE) * num_rq_pairs * 2;
8491331766Sken
8492331766Sken	/* Payload length must accommodate both request and response */
8493331766Sken	payload_size = max((sizeof(sli4_req_fcoe_rq_create_v1_t) + (8 * total_page_count)),
8494331766Sken			 sizeof(sli4_res_common_create_queue_set_t));
8495331766Sken
8496331766Sken	if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
8497331766Sken		ocs_log_err(sli4->os, "DMA allocation failed\n");
8498331766Sken		goto error;
8499331766Sken	}
8500331766Sken	ocs_memset(dma.virt, 0, payload_size);
8501331766Sken
8502331766Sken	if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
8503331766Sken			payload_size, &dma) == -1) {
8504331766Sken		goto error;
8505331766Sken	}
8506331766Sken	req = (sli4_req_fcoe_rq_create_v2_t *)((uint8_t *)dma.virt);
8507331766Sken
8508331766Sken	/* Fill Header fields */
8509331766Sken	req->hdr.opcode    = SLI4_OPC_FCOE_RQ_CREATE;
8510331766Sken	req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
8511331766Sken	req->hdr.version   = 2;
8512331766Sken	req->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v2_t) - sizeof(sli4_req_hdr_t)
8513331766Sken					+ (8 * total_page_count);
8514331766Sken
8515331766Sken	/* Fill Payload fields */
8516331766Sken	req->dnb           = TRUE;
8517331766Sken	req->num_pages     = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE);
8518331766Sken	req->rqe_count     = qs[0]->dma.size / SLI4_FCOE_RQE_SIZE;
8519331766Sken	req->rqe_size      = SLI4_FCOE_RQE_SIZE_8;
8520331766Sken	req->page_size     = SLI4_FCOE_RQ_PAGE_SIZE_4096;
8521331766Sken	req->rq_count      = num_rq_pairs * 2;
8522331766Sken	req->base_cq_id    = base_cq_id;
8523331766Sken	req->hdr_buffer_size     = header_buffer_size;
8524331766Sken	req->payload_buffer_size = payload_buffer_size;
8525331766Sken
8526331766Sken	for (i = 0; i < (num_rq_pairs * 2); i++) {
8527331766Sken		for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += SLI_PAGE_SIZE) {
8528331766Sken			req->page_physical_address[offset].low  = ocs_addr32_lo(addr);
8529331766Sken			req->page_physical_address[offset].high = ocs_addr32_hi(addr);
8530331766Sken			offset++;
8531331766Sken		}
8532331766Sken	}
8533331766Sken
8534331766Sken	if (sli_bmbx_command(sli4)){
8535331766Sken		ocs_log_crit(sli4->os, "bootstrap mailbox write faild RQSet\n");
8536331766Sken		goto error;
8537331766Sken	}
8538331766Sken
8539331766Sken
8540331766Sken	rsp = (void *)((uint8_t *)dma.virt);
8541331766Sken	if (rsp->hdr.status) {
8542331766Sken		ocs_log_err(sli4->os, "bad create RQSet status=%#x addl=%#x\n",
8543331766Sken			rsp->hdr.status, rsp->hdr.additional_status);
8544331766Sken		goto error;
8545331766Sken	} else {
8546331766Sken		for (i = 0; i < (num_rq_pairs * 2); i++) {
8547331766Sken			qs[i]->id = i + rsp->q_id;
8548331766Sken			if ((qs[i]->id & 1) == 0) {
8549331766Sken				qs[i]->u.flag.is_hdr = TRUE;
8550331766Sken			} else {
8551331766Sken				qs[i]->u.flag.is_hdr = FALSE;
8552331766Sken			}
8553331766Sken			qs[i]->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
8554331766Sken			qs[i]->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
8555331766Sken		}
8556331766Sken	}
8557331766Sken
8558331766Sken	ocs_dma_free(sli4->os, &dma);
8559331766Sken
8560331766Sken	return 0;
8561331766Sken
8562331766Skenerror:
8563331766Sken	for (i = 0; i < (num_rq_pairs * 2); i++) {
8564331766Sken		if (qs[i]->dma.size) {
8565331766Sken			ocs_dma_free(sli4->os, &qs[i]->dma);
8566331766Sken		}
8567331766Sken	}
8568331766Sken
8569331766Sken	if (dma.size) {
8570331766Sken		ocs_dma_free(sli4->os, &dma);
8571331766Sken	}
8572331766Sken
8573331766Sken	return -1;
8574331766Sken}
8575331766Sken
8576331766Sken/**
8577331766Sken * @ingroup sli_fc
8578331766Sken * @brief Get the RPI resource requirements.
8579331766Sken *
8580331766Sken * @param sli4 SLI context.
8581331766Sken * @param n_rpi Number of RPIs desired.
8582331766Sken *
8583331766Sken * @return Returns the number of bytes needed. This value may be zero.
8584331766Sken */
8585331766Skenuint32_t
8586331766Skensli_fc_get_rpi_requirements(sli4_t *sli4, uint32_t n_rpi)
8587331766Sken{
8588331766Sken	uint32_t	bytes = 0;
8589331766Sken
8590331766Sken	/* Check if header templates needed */
8591331766Sken	if (sli4->config.hdr_template_req) {
8592331766Sken		/* round up to a page */
8593331766Sken		bytes = SLI_ROUND_PAGE(n_rpi * SLI4_FCOE_HDR_TEMPLATE_SIZE);
8594331766Sken	}
8595331766Sken
8596331766Sken	return bytes;
8597331766Sken}
8598331766Sken
8599331766Sken/**
8600331766Sken * @ingroup sli_fc
8601331766Sken * @brief Return a text string corresponding to a CQE status value
8602331766Sken *
8603331766Sken * @param status Status value
8604331766Sken *
8605331766Sken * @return Returns corresponding string, otherwise "unknown"
8606331766Sken */
8607331766Skenconst char *
8608331766Skensli_fc_get_status_string(uint32_t status)
8609331766Sken{
8610331766Sken	static struct {
8611331766Sken		uint32_t code;
8612331766Sken		const char *label;
8613331766Sken	} lookup[] = {
8614331766Sken		{SLI4_FC_WCQE_STATUS_SUCCESS,			"SUCCESS"},
8615331766Sken		{SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE,		"FCP_RSP_FAILURE"},
8616331766Sken		{SLI4_FC_WCQE_STATUS_REMOTE_STOP,		"REMOTE_STOP"},
8617331766Sken		{SLI4_FC_WCQE_STATUS_LOCAL_REJECT,		"LOCAL_REJECT"},
8618331766Sken		{SLI4_FC_WCQE_STATUS_NPORT_RJT,			"NPORT_RJT"},
8619331766Sken		{SLI4_FC_WCQE_STATUS_FABRIC_RJT,		"FABRIC_RJT"},
8620331766Sken		{SLI4_FC_WCQE_STATUS_NPORT_BSY,			"NPORT_BSY"},
8621331766Sken		{SLI4_FC_WCQE_STATUS_FABRIC_BSY,		"FABRIC_BSY"},
8622331766Sken		{SLI4_FC_WCQE_STATUS_LS_RJT,			"LS_RJT"},
8623331766Sken		{SLI4_FC_WCQE_STATUS_CMD_REJECT,		"CMD_REJECT"},
8624331766Sken		{SLI4_FC_WCQE_STATUS_FCP_TGT_LENCHECK,		"FCP_TGT_LENCHECK"},
8625331766Sken		{SLI4_FC_WCQE_STATUS_RQ_BUF_LEN_EXCEEDED,	"BUF_LEN_EXCEEDED"},
8626331766Sken		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_BUF_NEEDED,	"RQ_INSUFF_BUF_NEEDED"},
8627331766Sken		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_FRM_DISC,	"RQ_INSUFF_FRM_DESC"},
8628331766Sken		{SLI4_FC_WCQE_STATUS_RQ_DMA_FAILURE,		"RQ_DMA_FAILURE"},
8629331766Sken		{SLI4_FC_WCQE_STATUS_FCP_RSP_TRUNCATE,		"FCP_RSP_TRUNCATE"},
8630331766Sken		{SLI4_FC_WCQE_STATUS_DI_ERROR,			"DI_ERROR"},
8631331766Sken		{SLI4_FC_WCQE_STATUS_BA_RJT,			"BA_RJT"},
8632331766Sken		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_NEEDED,	"RQ_INSUFF_XRI_NEEDED"},
8633331766Sken		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_DISC,	"INSUFF_XRI_DISC"},
8634331766Sken		{SLI4_FC_WCQE_STATUS_RX_ERROR_DETECT,		"RX_ERROR_DETECT"},
8635331766Sken		{SLI4_FC_WCQE_STATUS_RX_ABORT_REQUEST,		"RX_ABORT_REQUEST"},
8636331766Sken		};
8637331766Sken	uint32_t i;
8638331766Sken
8639331766Sken	for (i = 0; i < ARRAY_SIZE(lookup); i++) {
8640331766Sken		if (status == lookup[i].code) {
8641331766Sken			return lookup[i].label;
8642331766Sken		}
8643331766Sken	}
8644331766Sken	return "unknown";
8645331766Sken}
8646