162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
462306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci/*
862306a36Sopenharmony_ci * All common (i.e. transport-independent) SLI-4 functions are implemented
962306a36Sopenharmony_ci * in this file.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include "sli4.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic struct sli4_asic_entry_t sli4_asic_table[] = {
1462306a36Sopenharmony_ci	{ SLI4_ASIC_REV_B0, SLI4_ASIC_GEN_5},
1562306a36Sopenharmony_ci	{ SLI4_ASIC_REV_D0, SLI4_ASIC_GEN_5},
1662306a36Sopenharmony_ci	{ SLI4_ASIC_REV_A3, SLI4_ASIC_GEN_6},
1762306a36Sopenharmony_ci	{ SLI4_ASIC_REV_A0, SLI4_ASIC_GEN_6},
1862306a36Sopenharmony_ci	{ SLI4_ASIC_REV_A1, SLI4_ASIC_GEN_6},
1962306a36Sopenharmony_ci	{ SLI4_ASIC_REV_A3, SLI4_ASIC_GEN_6},
2062306a36Sopenharmony_ci	{ SLI4_ASIC_REV_A1, SLI4_ASIC_GEN_7},
2162306a36Sopenharmony_ci	{ SLI4_ASIC_REV_A0, SLI4_ASIC_GEN_7},
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* Convert queue type enum (SLI_QTYPE_*) into a string */
2562306a36Sopenharmony_cistatic char *SLI4_QNAME[] = {
2662306a36Sopenharmony_ci	"Event Queue",
2762306a36Sopenharmony_ci	"Completion Queue",
2862306a36Sopenharmony_ci	"Mailbox Queue",
2962306a36Sopenharmony_ci	"Work Queue",
3062306a36Sopenharmony_ci	"Receive Queue",
3162306a36Sopenharmony_ci	"Undefined"
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/**
3562306a36Sopenharmony_ci * sli_config_cmd_init() - Write a SLI_CONFIG command to the provided buffer.
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * @sli4: SLI context pointer.
3862306a36Sopenharmony_ci * @buf: Destination buffer for the command.
3962306a36Sopenharmony_ci * @length: Length in bytes of attached command.
4062306a36Sopenharmony_ci * @dma: DMA buffer for non-embedded commands.
4162306a36Sopenharmony_ci * Return: Command payload buffer.
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_cistatic void *
4462306a36Sopenharmony_cisli_config_cmd_init(struct sli4 *sli4, void *buf, u32 length,
4562306a36Sopenharmony_ci		    struct efc_dma *dma)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	struct sli4_cmd_sli_config *config;
4862306a36Sopenharmony_ci	u32 flags;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (length > sizeof(config->payload.embed) && !dma) {
5162306a36Sopenharmony_ci		efc_log_err(sli4, "Too big for an embedded cmd with len(%d)\n",
5262306a36Sopenharmony_ci			    length);
5362306a36Sopenharmony_ci		return NULL;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	config = buf;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	config->hdr.command = SLI4_MBX_CMD_SLI_CONFIG;
6162306a36Sopenharmony_ci	if (!dma) {
6262306a36Sopenharmony_ci		flags = SLI4_SLICONF_EMB;
6362306a36Sopenharmony_ci		config->dw1_flags = cpu_to_le32(flags);
6462306a36Sopenharmony_ci		config->payload_len = cpu_to_le32(length);
6562306a36Sopenharmony_ci		return config->payload.embed;
6662306a36Sopenharmony_ci	}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	flags = SLI4_SLICONF_PMDCMD_VAL_1;
6962306a36Sopenharmony_ci	flags &= ~SLI4_SLICONF_EMB;
7062306a36Sopenharmony_ci	config->dw1_flags = cpu_to_le32(flags);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	config->payload.mem.addr.low = cpu_to_le32(lower_32_bits(dma->phys));
7362306a36Sopenharmony_ci	config->payload.mem.addr.high =	cpu_to_le32(upper_32_bits(dma->phys));
7462306a36Sopenharmony_ci	config->payload.mem.length =
7562306a36Sopenharmony_ci				cpu_to_le32(dma->size & SLI4_SLICONF_PMD_LEN);
7662306a36Sopenharmony_ci	config->payload_len = cpu_to_le32(dma->size);
7762306a36Sopenharmony_ci	/* save pointer to DMA for BMBX dumping purposes */
7862306a36Sopenharmony_ci	sli4->bmbx_non_emb_pmd = dma;
7962306a36Sopenharmony_ci	return dma->virt;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/**
8362306a36Sopenharmony_ci * sli_cmd_common_create_cq() - Write a COMMON_CREATE_CQ V2 command.
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci * @sli4: SLI context pointer.
8662306a36Sopenharmony_ci * @buf: Destination buffer for the command.
8762306a36Sopenharmony_ci * @qmem: DMA memory for queue.
8862306a36Sopenharmony_ci * @eq_id: EQ id assosiated with this cq.
8962306a36Sopenharmony_ci * Return: status -EIO/0.
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_cistatic int
9262306a36Sopenharmony_cisli_cmd_common_create_cq(struct sli4 *sli4, void *buf, struct efc_dma *qmem,
9362306a36Sopenharmony_ci			 u16 eq_id)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	struct sli4_rqst_cmn_create_cq_v2 *cqv2 = NULL;
9662306a36Sopenharmony_ci	u32 p;
9762306a36Sopenharmony_ci	uintptr_t addr;
9862306a36Sopenharmony_ci	u32 num_pages = 0;
9962306a36Sopenharmony_ci	size_t cmd_size = 0;
10062306a36Sopenharmony_ci	u32 page_size = 0;
10162306a36Sopenharmony_ci	u32 n_cqe = 0;
10262306a36Sopenharmony_ci	u32 dw5_flags = 0;
10362306a36Sopenharmony_ci	u16 dw6w1_arm = 0;
10462306a36Sopenharmony_ci	__le32 len;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	/* First calculate number of pages and the mailbox cmd length */
10762306a36Sopenharmony_ci	n_cqe = qmem->size / SLI4_CQE_BYTES;
10862306a36Sopenharmony_ci	switch (n_cqe) {
10962306a36Sopenharmony_ci	case 256:
11062306a36Sopenharmony_ci	case 512:
11162306a36Sopenharmony_ci	case 1024:
11262306a36Sopenharmony_ci	case 2048:
11362306a36Sopenharmony_ci		page_size = SZ_4K;
11462306a36Sopenharmony_ci		break;
11562306a36Sopenharmony_ci	case 4096:
11662306a36Sopenharmony_ci		page_size = SZ_8K;
11762306a36Sopenharmony_ci		break;
11862306a36Sopenharmony_ci	default:
11962306a36Sopenharmony_ci		return -EIO;
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci	num_pages = sli_page_count(qmem->size, page_size);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	cmd_size = SLI4_RQST_CMDSZ(cmn_create_cq_v2)
12462306a36Sopenharmony_ci		   + SZ_DMAADDR * num_pages;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	cqv2 = sli_config_cmd_init(sli4, buf, cmd_size, NULL);
12762306a36Sopenharmony_ci	if (!cqv2)
12862306a36Sopenharmony_ci		return -EIO;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	len = SLI4_RQST_PYLD_LEN_VAR(cmn_create_cq_v2, SZ_DMAADDR * num_pages);
13162306a36Sopenharmony_ci	sli_cmd_fill_hdr(&cqv2->hdr, SLI4_CMN_CREATE_CQ, SLI4_SUBSYSTEM_COMMON,
13262306a36Sopenharmony_ci			 CMD_V2, len);
13362306a36Sopenharmony_ci	cqv2->page_size = page_size / SLI_PAGE_SIZE;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.3) */
13662306a36Sopenharmony_ci	cqv2->num_pages = cpu_to_le16(num_pages);
13762306a36Sopenharmony_ci	if (!num_pages || num_pages > SLI4_CREATE_CQV2_MAX_PAGES)
13862306a36Sopenharmony_ci		return -EIO;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	switch (num_pages) {
14162306a36Sopenharmony_ci	case 1:
14262306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(256);
14362306a36Sopenharmony_ci		break;
14462306a36Sopenharmony_ci	case 2:
14562306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(512);
14662306a36Sopenharmony_ci		break;
14762306a36Sopenharmony_ci	case 4:
14862306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(1024);
14962306a36Sopenharmony_ci		break;
15062306a36Sopenharmony_ci	case 8:
15162306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(LARGE);
15262306a36Sopenharmony_ci		cqv2->cqe_count = cpu_to_le16(n_cqe);
15362306a36Sopenharmony_ci		break;
15462306a36Sopenharmony_ci	default:
15562306a36Sopenharmony_ci		efc_log_err(sli4, "num_pages %d not valid\n", num_pages);
15662306a36Sopenharmony_ci		return -EIO;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
16062306a36Sopenharmony_ci		dw5_flags |= SLI4_CREATE_CQV2_AUTOVALID;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	dw5_flags |= SLI4_CREATE_CQV2_EVT;
16362306a36Sopenharmony_ci	dw5_flags |= SLI4_CREATE_CQV2_VALID;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	cqv2->dw5_flags = cpu_to_le32(dw5_flags);
16662306a36Sopenharmony_ci	cqv2->dw6w1_arm = cpu_to_le16(dw6w1_arm);
16762306a36Sopenharmony_ci	cqv2->eq_id = cpu_to_le16(eq_id);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	for (p = 0, addr = qmem->phys; p < num_pages; p++, addr += page_size) {
17062306a36Sopenharmony_ci		cqv2->page_phys_addr[p].low = cpu_to_le32(lower_32_bits(addr));
17162306a36Sopenharmony_ci		cqv2->page_phys_addr[p].high = cpu_to_le32(upper_32_bits(addr));
17262306a36Sopenharmony_ci	}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	return 0;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic int
17862306a36Sopenharmony_cisli_cmd_common_create_eq(struct sli4 *sli4, void *buf, struct efc_dma *qmem)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct sli4_rqst_cmn_create_eq *eq;
18162306a36Sopenharmony_ci	u32 p;
18262306a36Sopenharmony_ci	uintptr_t addr;
18362306a36Sopenharmony_ci	u16 num_pages;
18462306a36Sopenharmony_ci	u32 dw5_flags = 0;
18562306a36Sopenharmony_ci	u32 dw6_flags = 0, ver;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	eq = sli_config_cmd_init(sli4, buf, SLI4_CFG_PYLD_LENGTH(cmn_create_eq),
18862306a36Sopenharmony_ci				 NULL);
18962306a36Sopenharmony_ci	if (!eq)
19062306a36Sopenharmony_ci		return -EIO;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
19362306a36Sopenharmony_ci		ver = CMD_V2;
19462306a36Sopenharmony_ci	else
19562306a36Sopenharmony_ci		ver = CMD_V0;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	sli_cmd_fill_hdr(&eq->hdr, SLI4_CMN_CREATE_EQ, SLI4_SUBSYSTEM_COMMON,
19862306a36Sopenharmony_ci			 ver, SLI4_RQST_PYLD_LEN(cmn_create_eq));
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
20162306a36Sopenharmony_ci	num_pages = qmem->size / SLI_PAGE_SIZE;
20262306a36Sopenharmony_ci	eq->num_pages = cpu_to_le16(num_pages);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	switch (num_pages) {
20562306a36Sopenharmony_ci	case 1:
20662306a36Sopenharmony_ci		dw5_flags |= SLI4_EQE_SIZE_4;
20762306a36Sopenharmony_ci		dw6_flags |= SLI4_EQ_CNT_VAL(1024);
20862306a36Sopenharmony_ci		break;
20962306a36Sopenharmony_ci	case 2:
21062306a36Sopenharmony_ci		dw5_flags |= SLI4_EQE_SIZE_4;
21162306a36Sopenharmony_ci		dw6_flags |= SLI4_EQ_CNT_VAL(2048);
21262306a36Sopenharmony_ci		break;
21362306a36Sopenharmony_ci	case 4:
21462306a36Sopenharmony_ci		dw5_flags |= SLI4_EQE_SIZE_4;
21562306a36Sopenharmony_ci		dw6_flags |= SLI4_EQ_CNT_VAL(4096);
21662306a36Sopenharmony_ci		break;
21762306a36Sopenharmony_ci	default:
21862306a36Sopenharmony_ci		efc_log_err(sli4, "num_pages %d not valid\n", num_pages);
21962306a36Sopenharmony_ci		return -EIO;
22062306a36Sopenharmony_ci	}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
22362306a36Sopenharmony_ci		dw5_flags |= SLI4_CREATE_EQ_AUTOVALID;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	dw5_flags |= SLI4_CREATE_EQ_VALID;
22662306a36Sopenharmony_ci	dw6_flags &= (~SLI4_CREATE_EQ_ARM);
22762306a36Sopenharmony_ci	eq->dw5_flags = cpu_to_le32(dw5_flags);
22862306a36Sopenharmony_ci	eq->dw6_flags = cpu_to_le32(dw6_flags);
22962306a36Sopenharmony_ci	eq->dw7_delaymulti = cpu_to_le32(SLI4_CREATE_EQ_DELAYMULTI);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	for (p = 0, addr = qmem->phys; p < num_pages;
23262306a36Sopenharmony_ci	     p++, addr += SLI_PAGE_SIZE) {
23362306a36Sopenharmony_ci		eq->page_address[p].low = cpu_to_le32(lower_32_bits(addr));
23462306a36Sopenharmony_ci		eq->page_address[p].high = cpu_to_le32(upper_32_bits(addr));
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	return 0;
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic int
24162306a36Sopenharmony_cisli_cmd_common_create_mq_ext(struct sli4 *sli4, void *buf, struct efc_dma *qmem,
24262306a36Sopenharmony_ci			     u16 cq_id)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	struct sli4_rqst_cmn_create_mq_ext *mq;
24562306a36Sopenharmony_ci	u32 p;
24662306a36Sopenharmony_ci	uintptr_t addr;
24762306a36Sopenharmony_ci	u32 num_pages;
24862306a36Sopenharmony_ci	u16 dw6w1_flags = 0;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	mq = sli_config_cmd_init(sli4, buf,
25162306a36Sopenharmony_ci				 SLI4_CFG_PYLD_LENGTH(cmn_create_mq_ext), NULL);
25262306a36Sopenharmony_ci	if (!mq)
25362306a36Sopenharmony_ci		return -EIO;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	sli_cmd_fill_hdr(&mq->hdr, SLI4_CMN_CREATE_MQ_EXT,
25662306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
25762306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_create_mq_ext));
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	/* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */
26062306a36Sopenharmony_ci	num_pages = qmem->size / SLI_PAGE_SIZE;
26162306a36Sopenharmony_ci	mq->num_pages = cpu_to_le16(num_pages);
26262306a36Sopenharmony_ci	switch (num_pages) {
26362306a36Sopenharmony_ci	case 1:
26462306a36Sopenharmony_ci		dw6w1_flags |= SLI4_MQE_SIZE_16;
26562306a36Sopenharmony_ci		break;
26662306a36Sopenharmony_ci	case 2:
26762306a36Sopenharmony_ci		dw6w1_flags |= SLI4_MQE_SIZE_32;
26862306a36Sopenharmony_ci		break;
26962306a36Sopenharmony_ci	case 4:
27062306a36Sopenharmony_ci		dw6w1_flags |= SLI4_MQE_SIZE_64;
27162306a36Sopenharmony_ci		break;
27262306a36Sopenharmony_ci	case 8:
27362306a36Sopenharmony_ci		dw6w1_flags |= SLI4_MQE_SIZE_128;
27462306a36Sopenharmony_ci		break;
27562306a36Sopenharmony_ci	default:
27662306a36Sopenharmony_ci		efc_log_info(sli4, "num_pages %d not valid\n", num_pages);
27762306a36Sopenharmony_ci		return -EIO;
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	mq->async_event_bitmap = cpu_to_le32(SLI4_ASYNC_EVT_FC_ALL);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	if (sli4->params.mq_create_version) {
28362306a36Sopenharmony_ci		mq->cq_id_v1 = cpu_to_le16(cq_id);
28462306a36Sopenharmony_ci		mq->hdr.dw3_version = cpu_to_le32(CMD_V1);
28562306a36Sopenharmony_ci	} else {
28662306a36Sopenharmony_ci		dw6w1_flags |= (cq_id << SLI4_CREATE_MQEXT_CQID_SHIFT);
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	mq->dw7_val = cpu_to_le32(SLI4_CREATE_MQEXT_VAL);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	mq->dw6w1_flags = cpu_to_le16(dw6w1_flags);
29162306a36Sopenharmony_ci	for (p = 0, addr = qmem->phys; p < num_pages;
29262306a36Sopenharmony_ci	     p++, addr += SLI_PAGE_SIZE) {
29362306a36Sopenharmony_ci		mq->page_phys_addr[p].low = cpu_to_le32(lower_32_bits(addr));
29462306a36Sopenharmony_ci		mq->page_phys_addr[p].high = cpu_to_le32(upper_32_bits(addr));
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	return 0;
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ciint
30162306a36Sopenharmony_cisli_cmd_wq_create(struct sli4 *sli4, void *buf, struct efc_dma *qmem, u16 cq_id)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	struct sli4_rqst_wq_create *wq;
30462306a36Sopenharmony_ci	u32 p;
30562306a36Sopenharmony_ci	uintptr_t addr;
30662306a36Sopenharmony_ci	u32 page_size = 0;
30762306a36Sopenharmony_ci	u32 n_wqe = 0;
30862306a36Sopenharmony_ci	u16 num_pages;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	wq = sli_config_cmd_init(sli4, buf, SLI4_CFG_PYLD_LENGTH(wq_create),
31162306a36Sopenharmony_ci				 NULL);
31262306a36Sopenharmony_ci	if (!wq)
31362306a36Sopenharmony_ci		return -EIO;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	sli_cmd_fill_hdr(&wq->hdr, SLI4_OPC_WQ_CREATE, SLI4_SUBSYSTEM_FC,
31662306a36Sopenharmony_ci			 CMD_V1, SLI4_RQST_PYLD_LEN(wq_create));
31762306a36Sopenharmony_ci	n_wqe = qmem->size / sli4->wqe_size;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	switch (qmem->size) {
32062306a36Sopenharmony_ci	case 4096:
32162306a36Sopenharmony_ci	case 8192:
32262306a36Sopenharmony_ci	case 16384:
32362306a36Sopenharmony_ci	case 32768:
32462306a36Sopenharmony_ci		page_size = SZ_4K;
32562306a36Sopenharmony_ci		break;
32662306a36Sopenharmony_ci	case 65536:
32762306a36Sopenharmony_ci		page_size = SZ_8K;
32862306a36Sopenharmony_ci		break;
32962306a36Sopenharmony_ci	case 131072:
33062306a36Sopenharmony_ci		page_size = SZ_16K;
33162306a36Sopenharmony_ci		break;
33262306a36Sopenharmony_ci	case 262144:
33362306a36Sopenharmony_ci		page_size = SZ_32K;
33462306a36Sopenharmony_ci		break;
33562306a36Sopenharmony_ci	case 524288:
33662306a36Sopenharmony_ci		page_size = SZ_64K;
33762306a36Sopenharmony_ci		break;
33862306a36Sopenharmony_ci	default:
33962306a36Sopenharmony_ci		return -EIO;
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	/* valid values for number of pages(num_pages): 1-8 */
34362306a36Sopenharmony_ci	num_pages = sli_page_count(qmem->size, page_size);
34462306a36Sopenharmony_ci	wq->num_pages = cpu_to_le16(num_pages);
34562306a36Sopenharmony_ci	if (!num_pages || num_pages > SLI4_WQ_CREATE_MAX_PAGES)
34662306a36Sopenharmony_ci		return -EIO;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	wq->cq_id = cpu_to_le16(cq_id);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	wq->page_size = page_size / SLI_PAGE_SIZE;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (sli4->wqe_size == SLI4_WQE_EXT_BYTES)
35362306a36Sopenharmony_ci		wq->wqe_size_byte |= SLI4_WQE_EXT_SIZE;
35462306a36Sopenharmony_ci	else
35562306a36Sopenharmony_ci		wq->wqe_size_byte |= SLI4_WQE_SIZE;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	wq->wqe_count = cpu_to_le16(n_wqe);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	for (p = 0, addr = qmem->phys; p < num_pages; p++, addr += page_size) {
36062306a36Sopenharmony_ci		wq->page_phys_addr[p].low  = cpu_to_le32(lower_32_bits(addr));
36162306a36Sopenharmony_ci		wq->page_phys_addr[p].high = cpu_to_le32(upper_32_bits(addr));
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return 0;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic int
36862306a36Sopenharmony_cisli_cmd_rq_create_v1(struct sli4 *sli4, void *buf, struct efc_dma *qmem,
36962306a36Sopenharmony_ci		     u16 cq_id, u16 buffer_size)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	struct sli4_rqst_rq_create_v1 *rq;
37262306a36Sopenharmony_ci	u32 p;
37362306a36Sopenharmony_ci	uintptr_t addr;
37462306a36Sopenharmony_ci	u32 num_pages;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	rq = sli_config_cmd_init(sli4, buf, SLI4_CFG_PYLD_LENGTH(rq_create_v1),
37762306a36Sopenharmony_ci				 NULL);
37862306a36Sopenharmony_ci	if (!rq)
37962306a36Sopenharmony_ci		return -EIO;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	sli_cmd_fill_hdr(&rq->hdr, SLI4_OPC_RQ_CREATE, SLI4_SUBSYSTEM_FC,
38262306a36Sopenharmony_ci			 CMD_V1, SLI4_RQST_PYLD_LEN(rq_create_v1));
38362306a36Sopenharmony_ci	/* Disable "no buffer warnings" to avoid Lancer bug */
38462306a36Sopenharmony_ci	rq->dim_dfd_dnb |= SLI4_RQ_CREATE_V1_DNB;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* valid values for number of pages: 1-8 (sec 4.5.6) */
38762306a36Sopenharmony_ci	num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
38862306a36Sopenharmony_ci	rq->num_pages = cpu_to_le16(num_pages);
38962306a36Sopenharmony_ci	if (!num_pages ||
39062306a36Sopenharmony_ci	    num_pages > SLI4_RQ_CREATE_V1_MAX_PAGES) {
39162306a36Sopenharmony_ci		efc_log_info(sli4, "num_pages %d not valid, max %d\n",
39262306a36Sopenharmony_ci			     num_pages, SLI4_RQ_CREATE_V1_MAX_PAGES);
39362306a36Sopenharmony_ci		return -EIO;
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	/*
39762306a36Sopenharmony_ci	 * RQE count is the total number of entries (note not lg2(# entries))
39862306a36Sopenharmony_ci	 */
39962306a36Sopenharmony_ci	rq->rqe_count = cpu_to_le16(qmem->size / SLI4_RQE_SIZE);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	rq->rqe_size_byte |= SLI4_RQE_SIZE_8;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	rq->page_size = SLI4_RQ_PAGE_SIZE_4096;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	if (buffer_size < sli4->rq_min_buf_size ||
40662306a36Sopenharmony_ci	    buffer_size > sli4->rq_max_buf_size) {
40762306a36Sopenharmony_ci		efc_log_err(sli4, "buffer_size %d out of range (%d-%d)\n",
40862306a36Sopenharmony_ci			    buffer_size, sli4->rq_min_buf_size,
40962306a36Sopenharmony_ci			    sli4->rq_max_buf_size);
41062306a36Sopenharmony_ci		return -EIO;
41162306a36Sopenharmony_ci	}
41262306a36Sopenharmony_ci	rq->buffer_size = cpu_to_le32(buffer_size);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	rq->cq_id = cpu_to_le16(cq_id);
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	for (p = 0, addr = qmem->phys;
41762306a36Sopenharmony_ci			p < num_pages;
41862306a36Sopenharmony_ci			p++, addr += SLI_PAGE_SIZE) {
41962306a36Sopenharmony_ci		rq->page_phys_addr[p].low  = cpu_to_le32(lower_32_bits(addr));
42062306a36Sopenharmony_ci		rq->page_phys_addr[p].high = cpu_to_le32(upper_32_bits(addr));
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	return 0;
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic int
42762306a36Sopenharmony_cisli_cmd_rq_create_v2(struct sli4 *sli4, u32 num_rqs,
42862306a36Sopenharmony_ci		     struct sli4_queue *qs[], u32 base_cq_id,
42962306a36Sopenharmony_ci		     u32 header_buffer_size,
43062306a36Sopenharmony_ci		     u32 payload_buffer_size, struct efc_dma *dma)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	struct sli4_rqst_rq_create_v2 *req = NULL;
43362306a36Sopenharmony_ci	u32 i, p, offset = 0;
43462306a36Sopenharmony_ci	u32 payload_size, page_count;
43562306a36Sopenharmony_ci	uintptr_t addr;
43662306a36Sopenharmony_ci	u32 num_pages;
43762306a36Sopenharmony_ci	__le32 len;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	page_count =  sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE) * num_rqs;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	/* Payload length must accommodate both request and response */
44262306a36Sopenharmony_ci	payload_size = max(SLI4_RQST_CMDSZ(rq_create_v2) +
44362306a36Sopenharmony_ci			   SZ_DMAADDR * page_count,
44462306a36Sopenharmony_ci			   sizeof(struct sli4_rsp_cmn_create_queue_set));
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	dma->size = payload_size;
44762306a36Sopenharmony_ci	dma->virt = dma_alloc_coherent(&sli4->pci->dev, dma->size,
44862306a36Sopenharmony_ci				       &dma->phys, GFP_KERNEL);
44962306a36Sopenharmony_ci	if (!dma->virt)
45062306a36Sopenharmony_ci		return -EIO;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	memset(dma->virt, 0, payload_size);
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, sli4->bmbx.virt, payload_size, dma);
45562306a36Sopenharmony_ci	if (!req)
45662306a36Sopenharmony_ci		return -EIO;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	len =  SLI4_RQST_PYLD_LEN_VAR(rq_create_v2, SZ_DMAADDR * page_count);
45962306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_OPC_RQ_CREATE, SLI4_SUBSYSTEM_FC,
46062306a36Sopenharmony_ci			 CMD_V2, len);
46162306a36Sopenharmony_ci	/* Fill Payload fields */
46262306a36Sopenharmony_ci	req->dim_dfd_dnb |= SLI4_RQCREATEV2_DNB;
46362306a36Sopenharmony_ci	num_pages = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE);
46462306a36Sopenharmony_ci	req->num_pages = cpu_to_le16(num_pages);
46562306a36Sopenharmony_ci	req->rqe_count = cpu_to_le16(qs[0]->dma.size / SLI4_RQE_SIZE);
46662306a36Sopenharmony_ci	req->rqe_size_byte |= SLI4_RQE_SIZE_8;
46762306a36Sopenharmony_ci	req->page_size = SLI4_RQ_PAGE_SIZE_4096;
46862306a36Sopenharmony_ci	req->rq_count = num_rqs;
46962306a36Sopenharmony_ci	req->base_cq_id = cpu_to_le16(base_cq_id);
47062306a36Sopenharmony_ci	req->hdr_buffer_size = cpu_to_le16(header_buffer_size);
47162306a36Sopenharmony_ci	req->payload_buffer_size = cpu_to_le16(payload_buffer_size);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	for (i = 0; i < num_rqs; i++) {
47462306a36Sopenharmony_ci		for (p = 0, addr = qs[i]->dma.phys; p < num_pages;
47562306a36Sopenharmony_ci		     p++, addr += SLI_PAGE_SIZE) {
47662306a36Sopenharmony_ci			req->page_phys_addr[offset].low =
47762306a36Sopenharmony_ci					cpu_to_le32(lower_32_bits(addr));
47862306a36Sopenharmony_ci			req->page_phys_addr[offset].high =
47962306a36Sopenharmony_ci					cpu_to_le32(upper_32_bits(addr));
48062306a36Sopenharmony_ci			offset++;
48162306a36Sopenharmony_ci		}
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return 0;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic void
48862306a36Sopenharmony_ci__sli_queue_destroy(struct sli4 *sli4, struct sli4_queue *q)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	if (!q->dma.size)
49162306a36Sopenharmony_ci		return;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	dma_free_coherent(&sli4->pci->dev, q->dma.size,
49462306a36Sopenharmony_ci			  q->dma.virt, q->dma.phys);
49562306a36Sopenharmony_ci	memset(&q->dma, 0, sizeof(struct efc_dma));
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ciint
49962306a36Sopenharmony_ci__sli_queue_init(struct sli4 *sli4, struct sli4_queue *q, u32 qtype,
50062306a36Sopenharmony_ci		 size_t size, u32 n_entries, u32 align)
50162306a36Sopenharmony_ci{
50262306a36Sopenharmony_ci	if (q->dma.virt) {
50362306a36Sopenharmony_ci		efc_log_err(sli4, "%s failed\n", __func__);
50462306a36Sopenharmony_ci		return -EIO;
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	memset(q, 0, sizeof(struct sli4_queue));
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	q->dma.size = size * n_entries;
51062306a36Sopenharmony_ci	q->dma.virt = dma_alloc_coherent(&sli4->pci->dev, q->dma.size,
51162306a36Sopenharmony_ci					 &q->dma.phys, GFP_KERNEL);
51262306a36Sopenharmony_ci	if (!q->dma.virt) {
51362306a36Sopenharmony_ci		memset(&q->dma, 0, sizeof(struct efc_dma));
51462306a36Sopenharmony_ci		efc_log_err(sli4, "%s allocation failed\n", SLI4_QNAME[qtype]);
51562306a36Sopenharmony_ci		return -EIO;
51662306a36Sopenharmony_ci	}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	memset(q->dma.virt, 0, size * n_entries);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	spin_lock_init(&q->lock);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	q->type = qtype;
52362306a36Sopenharmony_ci	q->size = size;
52462306a36Sopenharmony_ci	q->length = n_entries;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	if (q->type == SLI4_QTYPE_EQ || q->type == SLI4_QTYPE_CQ) {
52762306a36Sopenharmony_ci		/* For prism, phase will be flipped after
52862306a36Sopenharmony_ci		 * a sweep through eq and cq
52962306a36Sopenharmony_ci		 */
53062306a36Sopenharmony_ci		q->phase = 1;
53162306a36Sopenharmony_ci	}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	/* Limit to hwf the queue size per interrupt */
53462306a36Sopenharmony_ci	q->proc_limit = n_entries / 2;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (q->type == SLI4_QTYPE_EQ)
53762306a36Sopenharmony_ci		q->posted_limit = q->length / 2;
53862306a36Sopenharmony_ci	else
53962306a36Sopenharmony_ci		q->posted_limit = 64;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	return 0;
54262306a36Sopenharmony_ci}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ciint
54562306a36Sopenharmony_cisli_fc_rq_alloc(struct sli4 *sli4, struct sli4_queue *q,
54662306a36Sopenharmony_ci		u32 n_entries, u32 buffer_size,
54762306a36Sopenharmony_ci		struct sli4_queue *cq, bool is_hdr)
54862306a36Sopenharmony_ci{
54962306a36Sopenharmony_ci	if (__sli_queue_init(sli4, q, SLI4_QTYPE_RQ, SLI4_RQE_SIZE,
55062306a36Sopenharmony_ci			     n_entries, SLI_PAGE_SIZE))
55162306a36Sopenharmony_ci		return -EIO;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	if (sli_cmd_rq_create_v1(sli4, sli4->bmbx.virt, &q->dma, cq->id,
55462306a36Sopenharmony_ci				 buffer_size))
55562306a36Sopenharmony_ci		goto error;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	if (__sli_create_queue(sli4, q))
55862306a36Sopenharmony_ci		goto error;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	if (is_hdr && q->id & 1) {
56162306a36Sopenharmony_ci		efc_log_info(sli4, "bad header RQ_ID %d\n", q->id);
56262306a36Sopenharmony_ci		goto error;
56362306a36Sopenharmony_ci	} else if (!is_hdr  && (q->id & 1) == 0) {
56462306a36Sopenharmony_ci		efc_log_info(sli4, "bad data RQ_ID %d\n", q->id);
56562306a36Sopenharmony_ci		goto error;
56662306a36Sopenharmony_ci	}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	if (is_hdr)
56962306a36Sopenharmony_ci		q->u.flag |= SLI4_QUEUE_FLAG_HDR;
57062306a36Sopenharmony_ci	else
57162306a36Sopenharmony_ci		q->u.flag &= ~SLI4_QUEUE_FLAG_HDR;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	return 0;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cierror:
57662306a36Sopenharmony_ci	__sli_queue_destroy(sli4, q);
57762306a36Sopenharmony_ci	return -EIO;
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ciint
58162306a36Sopenharmony_cisli_fc_rq_set_alloc(struct sli4 *sli4, u32 num_rq_pairs,
58262306a36Sopenharmony_ci		    struct sli4_queue *qs[], u32 base_cq_id,
58362306a36Sopenharmony_ci		    u32 n_entries, u32 header_buffer_size,
58462306a36Sopenharmony_ci		    u32 payload_buffer_size)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	u32 i;
58762306a36Sopenharmony_ci	struct efc_dma dma = {0};
58862306a36Sopenharmony_ci	struct sli4_rsp_cmn_create_queue_set *rsp = NULL;
58962306a36Sopenharmony_ci	void __iomem *db_regaddr = NULL;
59062306a36Sopenharmony_ci	u32 num_rqs = num_rq_pairs * 2;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	for (i = 0; i < num_rqs; i++) {
59362306a36Sopenharmony_ci		if (__sli_queue_init(sli4, qs[i], SLI4_QTYPE_RQ,
59462306a36Sopenharmony_ci				     SLI4_RQE_SIZE, n_entries,
59562306a36Sopenharmony_ci				     SLI_PAGE_SIZE)) {
59662306a36Sopenharmony_ci			goto error;
59762306a36Sopenharmony_ci		}
59862306a36Sopenharmony_ci	}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (sli_cmd_rq_create_v2(sli4, num_rqs, qs, base_cq_id,
60162306a36Sopenharmony_ci				 header_buffer_size, payload_buffer_size,
60262306a36Sopenharmony_ci				 &dma)) {
60362306a36Sopenharmony_ci		goto error;
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
60762306a36Sopenharmony_ci		efc_log_err(sli4, "bootstrap mailbox write failed RQSet\n");
60862306a36Sopenharmony_ci		goto error;
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
61262306a36Sopenharmony_ci		db_regaddr = sli4->reg[1] + SLI4_IF6_RQ_DB_REG;
61362306a36Sopenharmony_ci	else
61462306a36Sopenharmony_ci		db_regaddr = sli4->reg[0] + SLI4_RQ_DB_REG;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	rsp = dma.virt;
61762306a36Sopenharmony_ci	if (rsp->hdr.status) {
61862306a36Sopenharmony_ci		efc_log_err(sli4, "bad create RQSet status=%#x addl=%#x\n",
61962306a36Sopenharmony_ci			    rsp->hdr.status, rsp->hdr.additional_status);
62062306a36Sopenharmony_ci		goto error;
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	for (i = 0; i < num_rqs; i++) {
62462306a36Sopenharmony_ci		qs[i]->id = i + le16_to_cpu(rsp->q_id);
62562306a36Sopenharmony_ci		if ((qs[i]->id & 1) == 0)
62662306a36Sopenharmony_ci			qs[i]->u.flag |= SLI4_QUEUE_FLAG_HDR;
62762306a36Sopenharmony_ci		else
62862306a36Sopenharmony_ci			qs[i]->u.flag &= ~SLI4_QUEUE_FLAG_HDR;
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci		qs[i]->db_regaddr = db_regaddr;
63162306a36Sopenharmony_ci	}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt, dma.phys);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return 0;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_cierror:
63862306a36Sopenharmony_ci	for (i = 0; i < num_rqs; i++)
63962306a36Sopenharmony_ci		__sli_queue_destroy(sli4, qs[i]);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	if (dma.virt)
64262306a36Sopenharmony_ci		dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt,
64362306a36Sopenharmony_ci				  dma.phys);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	return -EIO;
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_cistatic int
64962306a36Sopenharmony_cisli_res_sli_config(struct sli4 *sli4, void *buf)
65062306a36Sopenharmony_ci{
65162306a36Sopenharmony_ci	struct sli4_cmd_sli_config *sli_config = buf;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	/* sanity check */
65462306a36Sopenharmony_ci	if (!buf || sli_config->hdr.command !=
65562306a36Sopenharmony_ci		    SLI4_MBX_CMD_SLI_CONFIG) {
65662306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter buf=%p cmd=%#x\n", buf,
65762306a36Sopenharmony_ci			    buf ? sli_config->hdr.command : -1);
65862306a36Sopenharmony_ci		return -EIO;
65962306a36Sopenharmony_ci	}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (le16_to_cpu(sli_config->hdr.status))
66262306a36Sopenharmony_ci		return le16_to_cpu(sli_config->hdr.status);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	if (le32_to_cpu(sli_config->dw1_flags) & SLI4_SLICONF_EMB)
66562306a36Sopenharmony_ci		return sli_config->payload.embed[4];
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	efc_log_info(sli4, "external buffers not supported\n");
66862306a36Sopenharmony_ci	return -EIO;
66962306a36Sopenharmony_ci}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ciint
67262306a36Sopenharmony_ci__sli_create_queue(struct sli4 *sli4, struct sli4_queue *q)
67362306a36Sopenharmony_ci{
67462306a36Sopenharmony_ci	struct sli4_rsp_cmn_create_queue *res_q = NULL;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
67762306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox write fail %s\n",
67862306a36Sopenharmony_ci			     SLI4_QNAME[q->type]);
67962306a36Sopenharmony_ci		return -EIO;
68062306a36Sopenharmony_ci	}
68162306a36Sopenharmony_ci	if (sli_res_sli_config(sli4, sli4->bmbx.virt)) {
68262306a36Sopenharmony_ci		efc_log_err(sli4, "bad status create %s\n",
68362306a36Sopenharmony_ci			    SLI4_QNAME[q->type]);
68462306a36Sopenharmony_ci		return -EIO;
68562306a36Sopenharmony_ci	}
68662306a36Sopenharmony_ci	res_q = (void *)((u8 *)sli4->bmbx.virt +
68762306a36Sopenharmony_ci			offsetof(struct sli4_cmd_sli_config, payload));
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	if (res_q->hdr.status) {
69062306a36Sopenharmony_ci		efc_log_err(sli4, "bad create %s status=%#x addl=%#x\n",
69162306a36Sopenharmony_ci			    SLI4_QNAME[q->type], res_q->hdr.status,
69262306a36Sopenharmony_ci			    res_q->hdr.additional_status);
69362306a36Sopenharmony_ci		return -EIO;
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci	q->id = le16_to_cpu(res_q->q_id);
69662306a36Sopenharmony_ci	switch (q->type) {
69762306a36Sopenharmony_ci	case SLI4_QTYPE_EQ:
69862306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
69962306a36Sopenharmony_ci			q->db_regaddr = sli4->reg[1] + SLI4_IF6_EQ_DB_REG;
70062306a36Sopenharmony_ci		else
70162306a36Sopenharmony_ci			q->db_regaddr =	sli4->reg[0] + SLI4_EQCQ_DB_REG;
70262306a36Sopenharmony_ci		break;
70362306a36Sopenharmony_ci	case SLI4_QTYPE_CQ:
70462306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
70562306a36Sopenharmony_ci			q->db_regaddr = sli4->reg[1] + SLI4_IF6_CQ_DB_REG;
70662306a36Sopenharmony_ci		else
70762306a36Sopenharmony_ci			q->db_regaddr =	sli4->reg[0] + SLI4_EQCQ_DB_REG;
70862306a36Sopenharmony_ci		break;
70962306a36Sopenharmony_ci	case SLI4_QTYPE_MQ:
71062306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
71162306a36Sopenharmony_ci			q->db_regaddr = sli4->reg[1] + SLI4_IF6_MQ_DB_REG;
71262306a36Sopenharmony_ci		else
71362306a36Sopenharmony_ci			q->db_regaddr =	sli4->reg[0] + SLI4_MQ_DB_REG;
71462306a36Sopenharmony_ci		break;
71562306a36Sopenharmony_ci	case SLI4_QTYPE_RQ:
71662306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
71762306a36Sopenharmony_ci			q->db_regaddr = sli4->reg[1] + SLI4_IF6_RQ_DB_REG;
71862306a36Sopenharmony_ci		else
71962306a36Sopenharmony_ci			q->db_regaddr =	sli4->reg[0] + SLI4_RQ_DB_REG;
72062306a36Sopenharmony_ci		break;
72162306a36Sopenharmony_ci	case SLI4_QTYPE_WQ:
72262306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
72362306a36Sopenharmony_ci			q->db_regaddr = sli4->reg[1] + SLI4_IF6_WQ_DB_REG;
72462306a36Sopenharmony_ci		else
72562306a36Sopenharmony_ci			q->db_regaddr =	sli4->reg[0] + SLI4_IO_WQ_DB_REG;
72662306a36Sopenharmony_ci		break;
72762306a36Sopenharmony_ci	default:
72862306a36Sopenharmony_ci		break;
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	return 0;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ciint
73562306a36Sopenharmony_cisli_get_queue_entry_size(struct sli4 *sli4, u32 qtype)
73662306a36Sopenharmony_ci{
73762306a36Sopenharmony_ci	u32 size = 0;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	switch (qtype) {
74062306a36Sopenharmony_ci	case SLI4_QTYPE_EQ:
74162306a36Sopenharmony_ci		size = sizeof(u32);
74262306a36Sopenharmony_ci		break;
74362306a36Sopenharmony_ci	case SLI4_QTYPE_CQ:
74462306a36Sopenharmony_ci		size = 16;
74562306a36Sopenharmony_ci		break;
74662306a36Sopenharmony_ci	case SLI4_QTYPE_MQ:
74762306a36Sopenharmony_ci		size = 256;
74862306a36Sopenharmony_ci		break;
74962306a36Sopenharmony_ci	case SLI4_QTYPE_WQ:
75062306a36Sopenharmony_ci		size = sli4->wqe_size;
75162306a36Sopenharmony_ci		break;
75262306a36Sopenharmony_ci	case SLI4_QTYPE_RQ:
75362306a36Sopenharmony_ci		size = SLI4_RQE_SIZE;
75462306a36Sopenharmony_ci		break;
75562306a36Sopenharmony_ci	default:
75662306a36Sopenharmony_ci		efc_log_info(sli4, "unknown queue type %d\n", qtype);
75762306a36Sopenharmony_ci		return -1;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci	return size;
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ciint
76362306a36Sopenharmony_cisli_queue_alloc(struct sli4 *sli4, u32 qtype,
76462306a36Sopenharmony_ci		struct sli4_queue *q, u32 n_entries,
76562306a36Sopenharmony_ci		     struct sli4_queue *assoc)
76662306a36Sopenharmony_ci{
76762306a36Sopenharmony_ci	int size;
76862306a36Sopenharmony_ci	u32 align = 0;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	/* get queue size */
77162306a36Sopenharmony_ci	size = sli_get_queue_entry_size(sli4, qtype);
77262306a36Sopenharmony_ci	if (size < 0)
77362306a36Sopenharmony_ci		return -EIO;
77462306a36Sopenharmony_ci	align = SLI_PAGE_SIZE;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	if (__sli_queue_init(sli4, q, qtype, size, n_entries, align))
77762306a36Sopenharmony_ci		return -EIO;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	switch (qtype) {
78062306a36Sopenharmony_ci	case SLI4_QTYPE_EQ:
78162306a36Sopenharmony_ci		if (!sli_cmd_common_create_eq(sli4, sli4->bmbx.virt, &q->dma) &&
78262306a36Sopenharmony_ci		    !__sli_create_queue(sli4, q))
78362306a36Sopenharmony_ci			return 0;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci		break;
78662306a36Sopenharmony_ci	case SLI4_QTYPE_CQ:
78762306a36Sopenharmony_ci		if (!sli_cmd_common_create_cq(sli4, sli4->bmbx.virt, &q->dma,
78862306a36Sopenharmony_ci					      assoc ? assoc->id : 0) &&
78962306a36Sopenharmony_ci		    !__sli_create_queue(sli4, q))
79062306a36Sopenharmony_ci			return 0;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci		break;
79362306a36Sopenharmony_ci	case SLI4_QTYPE_MQ:
79462306a36Sopenharmony_ci		assoc->u.flag |= SLI4_QUEUE_FLAG_MQ;
79562306a36Sopenharmony_ci		if (!sli_cmd_common_create_mq_ext(sli4, sli4->bmbx.virt,
79662306a36Sopenharmony_ci						  &q->dma, assoc->id) &&
79762306a36Sopenharmony_ci		    !__sli_create_queue(sli4, q))
79862306a36Sopenharmony_ci			return 0;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci		break;
80162306a36Sopenharmony_ci	case SLI4_QTYPE_WQ:
80262306a36Sopenharmony_ci		if (!sli_cmd_wq_create(sli4, sli4->bmbx.virt, &q->dma,
80362306a36Sopenharmony_ci				       assoc ? assoc->id : 0) &&
80462306a36Sopenharmony_ci		    !__sli_create_queue(sli4, q))
80562306a36Sopenharmony_ci			return 0;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci		break;
80862306a36Sopenharmony_ci	default:
80962306a36Sopenharmony_ci		efc_log_info(sli4, "unknown queue type %d\n", qtype);
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	__sli_queue_destroy(sli4, q);
81362306a36Sopenharmony_ci	return -EIO;
81462306a36Sopenharmony_ci}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_cistatic int sli_cmd_cq_set_create(struct sli4 *sli4,
81762306a36Sopenharmony_ci				 struct sli4_queue *qs[], u32 num_cqs,
81862306a36Sopenharmony_ci				 struct sli4_queue *eqs[],
81962306a36Sopenharmony_ci				 struct efc_dma *dma)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct sli4_rqst_cmn_create_cq_set_v0 *req = NULL;
82262306a36Sopenharmony_ci	uintptr_t addr;
82362306a36Sopenharmony_ci	u32 i, offset = 0,  page_bytes = 0, payload_size;
82462306a36Sopenharmony_ci	u32 p = 0, page_size = 0, n_cqe = 0, num_pages_cq;
82562306a36Sopenharmony_ci	u32 dw5_flags = 0;
82662306a36Sopenharmony_ci	u16 dw6w1_flags = 0;
82762306a36Sopenharmony_ci	__le32 req_len;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	n_cqe = qs[0]->dma.size / SLI4_CQE_BYTES;
83062306a36Sopenharmony_ci	switch (n_cqe) {
83162306a36Sopenharmony_ci	case 256:
83262306a36Sopenharmony_ci	case 512:
83362306a36Sopenharmony_ci	case 1024:
83462306a36Sopenharmony_ci	case 2048:
83562306a36Sopenharmony_ci		page_size = 1;
83662306a36Sopenharmony_ci		break;
83762306a36Sopenharmony_ci	case 4096:
83862306a36Sopenharmony_ci		page_size = 2;
83962306a36Sopenharmony_ci		break;
84062306a36Sopenharmony_ci	default:
84162306a36Sopenharmony_ci		return -EIO;
84262306a36Sopenharmony_ci	}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	page_bytes = page_size * SLI_PAGE_SIZE;
84562306a36Sopenharmony_ci	num_pages_cq = sli_page_count(qs[0]->dma.size, page_bytes);
84662306a36Sopenharmony_ci	payload_size = max(SLI4_RQST_CMDSZ(cmn_create_cq_set_v0) +
84762306a36Sopenharmony_ci			   (SZ_DMAADDR * num_pages_cq * num_cqs),
84862306a36Sopenharmony_ci			   sizeof(struct sli4_rsp_cmn_create_queue_set));
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	dma->size = payload_size;
85162306a36Sopenharmony_ci	dma->virt = dma_alloc_coherent(&sli4->pci->dev, dma->size,
85262306a36Sopenharmony_ci				       &dma->phys, GFP_KERNEL);
85362306a36Sopenharmony_ci	if (!dma->virt)
85462306a36Sopenharmony_ci		return -EIO;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	memset(dma->virt, 0, payload_size);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, sli4->bmbx.virt, payload_size, dma);
85962306a36Sopenharmony_ci	if (!req)
86062306a36Sopenharmony_ci		return -EIO;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	req_len = SLI4_RQST_PYLD_LEN_VAR(cmn_create_cq_set_v0,
86362306a36Sopenharmony_ci					 SZ_DMAADDR * num_pages_cq * num_cqs);
86462306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_CMN_CREATE_CQ_SET, SLI4_SUBSYSTEM_FC,
86562306a36Sopenharmony_ci			 CMD_V0, req_len);
86662306a36Sopenharmony_ci	req->page_size = page_size;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	req->num_pages = cpu_to_le16(num_pages_cq);
86962306a36Sopenharmony_ci	switch (num_pages_cq) {
87062306a36Sopenharmony_ci	case 1:
87162306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(256);
87262306a36Sopenharmony_ci		break;
87362306a36Sopenharmony_ci	case 2:
87462306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(512);
87562306a36Sopenharmony_ci		break;
87662306a36Sopenharmony_ci	case 4:
87762306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(1024);
87862306a36Sopenharmony_ci		break;
87962306a36Sopenharmony_ci	case 8:
88062306a36Sopenharmony_ci		dw5_flags |= SLI4_CQ_CNT_VAL(LARGE);
88162306a36Sopenharmony_ci		dw6w1_flags |= (n_cqe & SLI4_CREATE_CQSETV0_CQE_COUNT);
88262306a36Sopenharmony_ci		break;
88362306a36Sopenharmony_ci	default:
88462306a36Sopenharmony_ci		efc_log_info(sli4, "num_pages %d not valid\n", num_pages_cq);
88562306a36Sopenharmony_ci		return -EIO;
88662306a36Sopenharmony_ci	}
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	dw5_flags |= SLI4_CREATE_CQSETV0_EVT;
88962306a36Sopenharmony_ci	dw5_flags |= SLI4_CREATE_CQSETV0_VALID;
89062306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
89162306a36Sopenharmony_ci		dw5_flags |= SLI4_CREATE_CQSETV0_AUTOVALID;
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	dw6w1_flags &= ~SLI4_CREATE_CQSETV0_ARM;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	req->dw5_flags = cpu_to_le32(dw5_flags);
89662306a36Sopenharmony_ci	req->dw6w1_flags = cpu_to_le16(dw6w1_flags);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	req->num_cq_req = cpu_to_le16(num_cqs);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	/* Fill page addresses of all the CQs. */
90162306a36Sopenharmony_ci	for (i = 0; i < num_cqs; i++) {
90262306a36Sopenharmony_ci		req->eq_id[i] = cpu_to_le16(eqs[i]->id);
90362306a36Sopenharmony_ci		for (p = 0, addr = qs[i]->dma.phys; p < num_pages_cq;
90462306a36Sopenharmony_ci		     p++, addr += page_bytes) {
90562306a36Sopenharmony_ci			req->page_phys_addr[offset].low =
90662306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(addr));
90762306a36Sopenharmony_ci			req->page_phys_addr[offset].high =
90862306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(addr));
90962306a36Sopenharmony_ci			offset++;
91062306a36Sopenharmony_ci		}
91162306a36Sopenharmony_ci	}
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	return 0;
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ciint
91762306a36Sopenharmony_cisli_cq_alloc_set(struct sli4 *sli4, struct sli4_queue *qs[],
91862306a36Sopenharmony_ci		 u32 num_cqs, u32 n_entries, struct sli4_queue *eqs[])
91962306a36Sopenharmony_ci{
92062306a36Sopenharmony_ci	u32 i;
92162306a36Sopenharmony_ci	struct efc_dma dma = {0};
92262306a36Sopenharmony_ci	struct sli4_rsp_cmn_create_queue_set *res;
92362306a36Sopenharmony_ci	void __iomem *db_regaddr;
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	/* Align the queue DMA memory */
92662306a36Sopenharmony_ci	for (i = 0; i < num_cqs; i++) {
92762306a36Sopenharmony_ci		if (__sli_queue_init(sli4, qs[i], SLI4_QTYPE_CQ, SLI4_CQE_BYTES,
92862306a36Sopenharmony_ci				     n_entries, SLI_PAGE_SIZE))
92962306a36Sopenharmony_ci			goto error;
93062306a36Sopenharmony_ci	}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	if (sli_cmd_cq_set_create(sli4, qs, num_cqs, eqs, &dma))
93362306a36Sopenharmony_ci		goto error;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	if (sli_bmbx_command(sli4))
93662306a36Sopenharmony_ci		goto error;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
93962306a36Sopenharmony_ci		db_regaddr = sli4->reg[1] + SLI4_IF6_CQ_DB_REG;
94062306a36Sopenharmony_ci	else
94162306a36Sopenharmony_ci		db_regaddr = sli4->reg[0] + SLI4_EQCQ_DB_REG;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	res = dma.virt;
94462306a36Sopenharmony_ci	if (res->hdr.status) {
94562306a36Sopenharmony_ci		efc_log_err(sli4, "bad create CQSet status=%#x addl=%#x\n",
94662306a36Sopenharmony_ci			    res->hdr.status, res->hdr.additional_status);
94762306a36Sopenharmony_ci		goto error;
94862306a36Sopenharmony_ci	}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	/* Check if we got all requested CQs. */
95162306a36Sopenharmony_ci	if (le16_to_cpu(res->num_q_allocated) != num_cqs) {
95262306a36Sopenharmony_ci		efc_log_crit(sli4, "Requested count CQs doesn't match.\n");
95362306a36Sopenharmony_ci		goto error;
95462306a36Sopenharmony_ci	}
95562306a36Sopenharmony_ci	/* Fill the resp cq ids. */
95662306a36Sopenharmony_ci	for (i = 0; i < num_cqs; i++) {
95762306a36Sopenharmony_ci		qs[i]->id = le16_to_cpu(res->q_id) + i;
95862306a36Sopenharmony_ci		qs[i]->db_regaddr = db_regaddr;
95962306a36Sopenharmony_ci	}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt, dma.phys);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	return 0;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_cierror:
96662306a36Sopenharmony_ci	for (i = 0; i < num_cqs; i++)
96762306a36Sopenharmony_ci		__sli_queue_destroy(sli4, qs[i]);
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (dma.virt)
97062306a36Sopenharmony_ci		dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt,
97162306a36Sopenharmony_ci				  dma.phys);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	return -EIO;
97462306a36Sopenharmony_ci}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_cistatic int
97762306a36Sopenharmony_cisli_cmd_common_destroy_q(struct sli4 *sli4, u8 opc, u8 subsystem, u16 q_id)
97862306a36Sopenharmony_ci{
97962306a36Sopenharmony_ci	struct sli4_rqst_cmn_destroy_q *req;
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	/* Payload length must accommodate both request and response */
98262306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, sli4->bmbx.virt,
98362306a36Sopenharmony_ci				  SLI4_CFG_PYLD_LENGTH(cmn_destroy_q), NULL);
98462306a36Sopenharmony_ci	if (!req)
98562306a36Sopenharmony_ci		return -EIO;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, opc, subsystem,
98862306a36Sopenharmony_ci			 CMD_V0, SLI4_RQST_PYLD_LEN(cmn_destroy_q));
98962306a36Sopenharmony_ci	req->q_id = cpu_to_le16(q_id);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	return 0;
99262306a36Sopenharmony_ci}
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ciint
99562306a36Sopenharmony_cisli_queue_free(struct sli4 *sli4, struct sli4_queue *q,
99662306a36Sopenharmony_ci	       u32 destroy_queues, u32 free_memory)
99762306a36Sopenharmony_ci{
99862306a36Sopenharmony_ci	int rc = 0;
99962306a36Sopenharmony_ci	u8 opcode, subsystem;
100062306a36Sopenharmony_ci	struct sli4_rsp_hdr *res;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	if (!q) {
100362306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter sli4=%p q=%p\n", sli4, q);
100462306a36Sopenharmony_ci		return -EIO;
100562306a36Sopenharmony_ci	}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	if (!destroy_queues)
100862306a36Sopenharmony_ci		goto free_mem;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	switch (q->type) {
101162306a36Sopenharmony_ci	case SLI4_QTYPE_EQ:
101262306a36Sopenharmony_ci		opcode = SLI4_CMN_DESTROY_EQ;
101362306a36Sopenharmony_ci		subsystem = SLI4_SUBSYSTEM_COMMON;
101462306a36Sopenharmony_ci		break;
101562306a36Sopenharmony_ci	case SLI4_QTYPE_CQ:
101662306a36Sopenharmony_ci		opcode = SLI4_CMN_DESTROY_CQ;
101762306a36Sopenharmony_ci		subsystem = SLI4_SUBSYSTEM_COMMON;
101862306a36Sopenharmony_ci		break;
101962306a36Sopenharmony_ci	case SLI4_QTYPE_MQ:
102062306a36Sopenharmony_ci		opcode = SLI4_CMN_DESTROY_MQ;
102162306a36Sopenharmony_ci		subsystem = SLI4_SUBSYSTEM_COMMON;
102262306a36Sopenharmony_ci		break;
102362306a36Sopenharmony_ci	case SLI4_QTYPE_WQ:
102462306a36Sopenharmony_ci		opcode = SLI4_OPC_WQ_DESTROY;
102562306a36Sopenharmony_ci		subsystem = SLI4_SUBSYSTEM_FC;
102662306a36Sopenharmony_ci		break;
102762306a36Sopenharmony_ci	case SLI4_QTYPE_RQ:
102862306a36Sopenharmony_ci		opcode = SLI4_OPC_RQ_DESTROY;
102962306a36Sopenharmony_ci		subsystem = SLI4_SUBSYSTEM_FC;
103062306a36Sopenharmony_ci		break;
103162306a36Sopenharmony_ci	default:
103262306a36Sopenharmony_ci		efc_log_info(sli4, "bad queue type %d\n", q->type);
103362306a36Sopenharmony_ci		rc = -EIO;
103462306a36Sopenharmony_ci		goto free_mem;
103562306a36Sopenharmony_ci	}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	rc = sli_cmd_common_destroy_q(sli4, opcode, subsystem, q->id);
103862306a36Sopenharmony_ci	if (rc)
103962306a36Sopenharmony_ci		goto free_mem;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	rc = sli_bmbx_command(sli4);
104262306a36Sopenharmony_ci	if (rc)
104362306a36Sopenharmony_ci		goto free_mem;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	rc = sli_res_sli_config(sli4, sli4->bmbx.virt);
104662306a36Sopenharmony_ci	if (rc)
104762306a36Sopenharmony_ci		goto free_mem;
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci	res = (void *)((u8 *)sli4->bmbx.virt +
105062306a36Sopenharmony_ci			     offsetof(struct sli4_cmd_sli_config, payload));
105162306a36Sopenharmony_ci	if (res->status) {
105262306a36Sopenharmony_ci		efc_log_err(sli4, "destroy %s st=%#x addl=%#x\n",
105362306a36Sopenharmony_ci			    SLI4_QNAME[q->type], res->status,
105462306a36Sopenharmony_ci			    res->additional_status);
105562306a36Sopenharmony_ci		rc = -EIO;
105662306a36Sopenharmony_ci		goto free_mem;
105762306a36Sopenharmony_ci	}
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_cifree_mem:
106062306a36Sopenharmony_ci	if (free_memory)
106162306a36Sopenharmony_ci		__sli_queue_destroy(sli4, q);
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	return rc;
106462306a36Sopenharmony_ci}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ciint
106762306a36Sopenharmony_cisli_queue_eq_arm(struct sli4 *sli4, struct sli4_queue *q, bool arm)
106862306a36Sopenharmony_ci{
106962306a36Sopenharmony_ci	u32 val;
107062306a36Sopenharmony_ci	unsigned long flags = 0;
107162306a36Sopenharmony_ci	u32 a = arm ? SLI4_EQCQ_ARM : SLI4_EQCQ_UNARM;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	spin_lock_irqsave(&q->lock, flags);
107462306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
107562306a36Sopenharmony_ci		val = sli_format_if6_eq_db_data(q->n_posted, q->id, a);
107662306a36Sopenharmony_ci	else
107762306a36Sopenharmony_ci		val = sli_format_eq_db_data(q->n_posted, q->id, a);
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	writel(val, q->db_regaddr);
108062306a36Sopenharmony_ci	q->n_posted = 0;
108162306a36Sopenharmony_ci	spin_unlock_irqrestore(&q->lock, flags);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	return 0;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ciint
108762306a36Sopenharmony_cisli_queue_arm(struct sli4 *sli4, struct sli4_queue *q, bool arm)
108862306a36Sopenharmony_ci{
108962306a36Sopenharmony_ci	u32 val = 0;
109062306a36Sopenharmony_ci	unsigned long flags = 0;
109162306a36Sopenharmony_ci	u32 a = arm ? SLI4_EQCQ_ARM : SLI4_EQCQ_UNARM;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	spin_lock_irqsave(&q->lock, flags);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	switch (q->type) {
109662306a36Sopenharmony_ci	case SLI4_QTYPE_EQ:
109762306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
109862306a36Sopenharmony_ci			val = sli_format_if6_eq_db_data(q->n_posted, q->id, a);
109962306a36Sopenharmony_ci		else
110062306a36Sopenharmony_ci			val = sli_format_eq_db_data(q->n_posted, q->id, a);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci		writel(val, q->db_regaddr);
110362306a36Sopenharmony_ci		q->n_posted = 0;
110462306a36Sopenharmony_ci		break;
110562306a36Sopenharmony_ci	case SLI4_QTYPE_CQ:
110662306a36Sopenharmony_ci		if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
110762306a36Sopenharmony_ci			val = sli_format_if6_cq_db_data(q->n_posted, q->id, a);
110862306a36Sopenharmony_ci		else
110962306a36Sopenharmony_ci			val = sli_format_cq_db_data(q->n_posted, q->id, a);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci		writel(val, q->db_regaddr);
111262306a36Sopenharmony_ci		q->n_posted = 0;
111362306a36Sopenharmony_ci		break;
111462306a36Sopenharmony_ci	default:
111562306a36Sopenharmony_ci		efc_log_info(sli4, "should only be used for EQ/CQ, not %s\n",
111662306a36Sopenharmony_ci			     SLI4_QNAME[q->type]);
111762306a36Sopenharmony_ci	}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	spin_unlock_irqrestore(&q->lock, flags);
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	return 0;
112262306a36Sopenharmony_ci}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ciint
112562306a36Sopenharmony_cisli_wq_write(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
112662306a36Sopenharmony_ci{
112762306a36Sopenharmony_ci	u8 *qe = q->dma.virt;
112862306a36Sopenharmony_ci	u32 qindex;
112962306a36Sopenharmony_ci	u32 val = 0;
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	qindex = q->index;
113262306a36Sopenharmony_ci	qe += q->index * q->size;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	if (sli4->params.perf_wq_id_association)
113562306a36Sopenharmony_ci		sli_set_wq_id_association(entry, q->id);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	memcpy(qe, entry, q->size);
113862306a36Sopenharmony_ci	val = sli_format_wq_db_data(q->id);
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	writel(val, q->db_regaddr);
114162306a36Sopenharmony_ci	q->index = (q->index + 1) & (q->length - 1);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	return qindex;
114462306a36Sopenharmony_ci}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ciint
114762306a36Sopenharmony_cisli_mq_write(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	u8 *qe = q->dma.virt;
115062306a36Sopenharmony_ci	u32 qindex;
115162306a36Sopenharmony_ci	u32 val = 0;
115262306a36Sopenharmony_ci	unsigned long flags;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	spin_lock_irqsave(&q->lock, flags);
115562306a36Sopenharmony_ci	qindex = q->index;
115662306a36Sopenharmony_ci	qe += q->index * q->size;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	memcpy(qe, entry, q->size);
115962306a36Sopenharmony_ci	val = sli_format_mq_db_data(q->id);
116062306a36Sopenharmony_ci	writel(val, q->db_regaddr);
116162306a36Sopenharmony_ci	q->index = (q->index + 1) & (q->length - 1);
116262306a36Sopenharmony_ci	spin_unlock_irqrestore(&q->lock, flags);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	return qindex;
116562306a36Sopenharmony_ci}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ciint
116862306a36Sopenharmony_cisli_rq_write(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
116962306a36Sopenharmony_ci{
117062306a36Sopenharmony_ci	u8 *qe = q->dma.virt;
117162306a36Sopenharmony_ci	u32 qindex;
117262306a36Sopenharmony_ci	u32 val = 0;
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	qindex = q->index;
117562306a36Sopenharmony_ci	qe += q->index * q->size;
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	memcpy(qe, entry, q->size);
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	/*
118062306a36Sopenharmony_ci	 * In RQ-pair, an RQ either contains the FC header
118162306a36Sopenharmony_ci	 * (i.e. is_hdr == TRUE) or the payload.
118262306a36Sopenharmony_ci	 *
118362306a36Sopenharmony_ci	 * Don't ring doorbell for payload RQ
118462306a36Sopenharmony_ci	 */
118562306a36Sopenharmony_ci	if (!(q->u.flag & SLI4_QUEUE_FLAG_HDR))
118662306a36Sopenharmony_ci		goto skip;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	val = sli_format_rq_db_data(q->id);
118962306a36Sopenharmony_ci	writel(val, q->db_regaddr);
119062306a36Sopenharmony_ciskip:
119162306a36Sopenharmony_ci	q->index = (q->index + 1) & (q->length - 1);
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	return qindex;
119462306a36Sopenharmony_ci}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ciint
119762306a36Sopenharmony_cisli_eq_read(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
119862306a36Sopenharmony_ci{
119962306a36Sopenharmony_ci	u8 *qe = q->dma.virt;
120062306a36Sopenharmony_ci	unsigned long flags = 0;
120162306a36Sopenharmony_ci	u16 wflags = 0;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	spin_lock_irqsave(&q->lock, flags);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	qe += q->index * q->size;
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	/* Check if eqe is valid */
120862306a36Sopenharmony_ci	wflags = le16_to_cpu(((struct sli4_eqe *)qe)->dw0w0_flags);
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	if ((wflags & SLI4_EQE_VALID) != q->phase) {
121162306a36Sopenharmony_ci		spin_unlock_irqrestore(&q->lock, flags);
121262306a36Sopenharmony_ci		return -EIO;
121362306a36Sopenharmony_ci	}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	if (sli4->if_type != SLI4_INTF_IF_TYPE_6) {
121662306a36Sopenharmony_ci		wflags &= ~SLI4_EQE_VALID;
121762306a36Sopenharmony_ci		((struct sli4_eqe *)qe)->dw0w0_flags = cpu_to_le16(wflags);
121862306a36Sopenharmony_ci	}
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	memcpy(entry, qe, q->size);
122162306a36Sopenharmony_ci	q->index = (q->index + 1) & (q->length - 1);
122262306a36Sopenharmony_ci	q->n_posted++;
122362306a36Sopenharmony_ci	/*
122462306a36Sopenharmony_ci	 * For prism, the phase value will be used
122562306a36Sopenharmony_ci	 * to check the validity of eq/cq entries.
122662306a36Sopenharmony_ci	 * The value toggles after a complete sweep
122762306a36Sopenharmony_ci	 * through the queue.
122862306a36Sopenharmony_ci	 */
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6 && q->index == 0)
123162306a36Sopenharmony_ci		q->phase ^= (u16)0x1;
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	spin_unlock_irqrestore(&q->lock, flags);
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	return 0;
123662306a36Sopenharmony_ci}
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ciint
123962306a36Sopenharmony_cisli_cq_read(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
124062306a36Sopenharmony_ci{
124162306a36Sopenharmony_ci	u8 *qe = q->dma.virt;
124262306a36Sopenharmony_ci	unsigned long flags = 0;
124362306a36Sopenharmony_ci	u32 dwflags = 0;
124462306a36Sopenharmony_ci	bool valid_bit_set;
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	spin_lock_irqsave(&q->lock, flags);
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	qe += q->index * q->size;
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	/* Check if cqe is valid */
125162306a36Sopenharmony_ci	dwflags = le32_to_cpu(((struct sli4_mcqe *)qe)->dw3_flags);
125262306a36Sopenharmony_ci	valid_bit_set = (dwflags & SLI4_MCQE_VALID) != 0;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	if (valid_bit_set != q->phase) {
125562306a36Sopenharmony_ci		spin_unlock_irqrestore(&q->lock, flags);
125662306a36Sopenharmony_ci		return -EIO;
125762306a36Sopenharmony_ci	}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	if (sli4->if_type != SLI4_INTF_IF_TYPE_6) {
126062306a36Sopenharmony_ci		dwflags &= ~SLI4_MCQE_VALID;
126162306a36Sopenharmony_ci		((struct sli4_mcqe *)qe)->dw3_flags = cpu_to_le32(dwflags);
126262306a36Sopenharmony_ci	}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	memcpy(entry, qe, q->size);
126562306a36Sopenharmony_ci	q->index = (q->index + 1) & (q->length - 1);
126662306a36Sopenharmony_ci	q->n_posted++;
126762306a36Sopenharmony_ci	/*
126862306a36Sopenharmony_ci	 * For prism, the phase value will be used
126962306a36Sopenharmony_ci	 * to check the validity of eq/cq entries.
127062306a36Sopenharmony_ci	 * The value toggles after a complete sweep
127162306a36Sopenharmony_ci	 * through the queue.
127262306a36Sopenharmony_ci	 */
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	if (sli4->if_type == SLI4_INTF_IF_TYPE_6 && q->index == 0)
127562306a36Sopenharmony_ci		q->phase ^= (u16)0x1;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	spin_unlock_irqrestore(&q->lock, flags);
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	return 0;
128062306a36Sopenharmony_ci}
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ciint
128362306a36Sopenharmony_cisli_mq_read(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
128462306a36Sopenharmony_ci{
128562306a36Sopenharmony_ci	u8 *qe = q->dma.virt;
128662306a36Sopenharmony_ci	unsigned long flags = 0;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	spin_lock_irqsave(&q->lock, flags);
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	qe += q->u.r_idx * q->size;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	/* Check if mqe is valid */
129362306a36Sopenharmony_ci	if (q->index == q->u.r_idx) {
129462306a36Sopenharmony_ci		spin_unlock_irqrestore(&q->lock, flags);
129562306a36Sopenharmony_ci		return -EIO;
129662306a36Sopenharmony_ci	}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	memcpy(entry, qe, q->size);
129962306a36Sopenharmony_ci	q->u.r_idx = (q->u.r_idx + 1) & (q->length - 1);
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	spin_unlock_irqrestore(&q->lock, flags);
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	return 0;
130462306a36Sopenharmony_ci}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ciint
130762306a36Sopenharmony_cisli_eq_parse(struct sli4 *sli4, u8 *buf, u16 *cq_id)
130862306a36Sopenharmony_ci{
130962306a36Sopenharmony_ci	struct sli4_eqe *eqe = (void *)buf;
131062306a36Sopenharmony_ci	int rc = 0;
131162306a36Sopenharmony_ci	u16 flags = 0;
131262306a36Sopenharmony_ci	u16 majorcode;
131362306a36Sopenharmony_ci	u16 minorcode;
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	if (!buf || !cq_id) {
131662306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameters sli4=%p buf=%p cq_id=%p\n",
131762306a36Sopenharmony_ci			    sli4, buf, cq_id);
131862306a36Sopenharmony_ci		return -EIO;
131962306a36Sopenharmony_ci	}
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	flags = le16_to_cpu(eqe->dw0w0_flags);
132262306a36Sopenharmony_ci	majorcode = (flags & SLI4_EQE_MJCODE) >> 1;
132362306a36Sopenharmony_ci	minorcode = (flags & SLI4_EQE_MNCODE) >> 4;
132462306a36Sopenharmony_ci	switch (majorcode) {
132562306a36Sopenharmony_ci	case SLI4_MAJOR_CODE_STANDARD:
132662306a36Sopenharmony_ci		*cq_id = le16_to_cpu(eqe->resource_id);
132762306a36Sopenharmony_ci		break;
132862306a36Sopenharmony_ci	case SLI4_MAJOR_CODE_SENTINEL:
132962306a36Sopenharmony_ci		efc_log_info(sli4, "sentinel EQE\n");
133062306a36Sopenharmony_ci		rc = SLI4_EQE_STATUS_EQ_FULL;
133162306a36Sopenharmony_ci		break;
133262306a36Sopenharmony_ci	default:
133362306a36Sopenharmony_ci		efc_log_info(sli4, "Unsupported EQE: major %x minor %x\n",
133462306a36Sopenharmony_ci			     majorcode, minorcode);
133562306a36Sopenharmony_ci		rc = -EIO;
133662306a36Sopenharmony_ci	}
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	return rc;
133962306a36Sopenharmony_ci}
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ciint
134262306a36Sopenharmony_cisli_cq_parse(struct sli4 *sli4, struct sli4_queue *cq, u8 *cqe,
134362306a36Sopenharmony_ci	     enum sli4_qentry *etype, u16 *q_id)
134462306a36Sopenharmony_ci{
134562306a36Sopenharmony_ci	int rc = 0;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	if (!cq || !cqe || !etype) {
134862306a36Sopenharmony_ci		efc_log_err(sli4, "bad params sli4=%p cq=%p cqe=%p etype=%p q_id=%p\n",
134962306a36Sopenharmony_ci			    sli4, cq, cqe, etype, q_id);
135062306a36Sopenharmony_ci		return -EINVAL;
135162306a36Sopenharmony_ci	}
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	/* Parse a CQ entry to retrieve the event type and the queue id */
135462306a36Sopenharmony_ci	if (cq->u.flag & SLI4_QUEUE_FLAG_MQ) {
135562306a36Sopenharmony_ci		struct sli4_mcqe	*mcqe = (void *)cqe;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci		if (le32_to_cpu(mcqe->dw3_flags) & SLI4_MCQE_AE) {
135862306a36Sopenharmony_ci			*etype = SLI4_QENTRY_ASYNC;
135962306a36Sopenharmony_ci		} else {
136062306a36Sopenharmony_ci			*etype = SLI4_QENTRY_MQ;
136162306a36Sopenharmony_ci			rc = sli_cqe_mq(sli4, mcqe);
136262306a36Sopenharmony_ci		}
136362306a36Sopenharmony_ci		*q_id = -1;
136462306a36Sopenharmony_ci	} else {
136562306a36Sopenharmony_ci		rc = sli_fc_cqe_parse(sli4, cq, cqe, etype, q_id);
136662306a36Sopenharmony_ci	}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	return rc;
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ciint
137262306a36Sopenharmony_cisli_abort_wqe(struct sli4 *sli, void *buf, enum sli4_abort_type type,
137362306a36Sopenharmony_ci	      bool send_abts, u32 ids, u32 mask, u16 tag, u16 cq_id)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	struct sli4_abort_wqe *abort = buf;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	switch (type) {
138062306a36Sopenharmony_ci	case SLI4_ABORT_XRI:
138162306a36Sopenharmony_ci		abort->criteria = SLI4_ABORT_CRITERIA_XRI_TAG;
138262306a36Sopenharmony_ci		if (mask) {
138362306a36Sopenharmony_ci			efc_log_warn(sli, "%#x aborting XRI %#x warning non-zero mask",
138462306a36Sopenharmony_ci				     mask, ids);
138562306a36Sopenharmony_ci			mask = 0;
138662306a36Sopenharmony_ci		}
138762306a36Sopenharmony_ci		break;
138862306a36Sopenharmony_ci	case SLI4_ABORT_ABORT_ID:
138962306a36Sopenharmony_ci		abort->criteria = SLI4_ABORT_CRITERIA_ABORT_TAG;
139062306a36Sopenharmony_ci		break;
139162306a36Sopenharmony_ci	case SLI4_ABORT_REQUEST_ID:
139262306a36Sopenharmony_ci		abort->criteria = SLI4_ABORT_CRITERIA_REQUEST_TAG;
139362306a36Sopenharmony_ci		break;
139462306a36Sopenharmony_ci	default:
139562306a36Sopenharmony_ci		efc_log_info(sli, "unsupported type %#x\n", type);
139662306a36Sopenharmony_ci		return -EIO;
139762306a36Sopenharmony_ci	}
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	abort->ia_ir_byte |= send_abts ? 0 : 1;
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	/* Suppress ABTS retries */
140262306a36Sopenharmony_ci	abort->ia_ir_byte |= SLI4_ABRT_WQE_IR;
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	abort->t_mask = cpu_to_le32(mask);
140562306a36Sopenharmony_ci	abort->t_tag  = cpu_to_le32(ids);
140662306a36Sopenharmony_ci	abort->command = SLI4_WQE_ABORT;
140762306a36Sopenharmony_ci	abort->request_tag = cpu_to_le16(tag);
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	abort->dw10w0_flags = cpu_to_le16(SLI4_ABRT_WQE_QOSD);
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	abort->cq_id = cpu_to_le16(cq_id);
141262306a36Sopenharmony_ci	abort->cmdtype_wqec_byte |= SLI4_CMD_ABORT_WQE;
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	return 0;
141562306a36Sopenharmony_ci}
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ciint
141862306a36Sopenharmony_cisli_els_request64_wqe(struct sli4 *sli, void *buf, struct efc_dma *sgl,
141962306a36Sopenharmony_ci		      struct sli_els_params *params)
142062306a36Sopenharmony_ci{
142162306a36Sopenharmony_ci	struct sli4_els_request64_wqe *els = buf;
142262306a36Sopenharmony_ci	struct sli4_sge *sge = sgl->virt;
142362306a36Sopenharmony_ci	bool is_fabric = false;
142462306a36Sopenharmony_ci	struct sli4_bde *bptr;
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	bptr = &els->els_request_payload;
142962306a36Sopenharmony_ci	if (sli->params.sgl_pre_registered) {
143062306a36Sopenharmony_ci		els->qosd_xbl_hlm_iod_dbde_wqes &= ~SLI4_REQ_WQE_XBL;
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci		els->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_REQ_WQE_DBDE;
143362306a36Sopenharmony_ci		bptr->bde_type_buflen =
143462306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
143562306a36Sopenharmony_ci				    (params->xmit_len & SLI4_BDE_LEN_MASK));
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci		bptr->u.data.low  = sge[0].buffer_address_low;
143862306a36Sopenharmony_ci		bptr->u.data.high = sge[0].buffer_address_high;
143962306a36Sopenharmony_ci	} else {
144062306a36Sopenharmony_ci		els->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_REQ_WQE_XBL;
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci		bptr->bde_type_buflen =
144362306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(BLP)) |
144462306a36Sopenharmony_ci				    ((2 * sizeof(struct sli4_sge)) &
144562306a36Sopenharmony_ci				     SLI4_BDE_LEN_MASK));
144662306a36Sopenharmony_ci		bptr->u.blp.low  = cpu_to_le32(lower_32_bits(sgl->phys));
144762306a36Sopenharmony_ci		bptr->u.blp.high = cpu_to_le32(upper_32_bits(sgl->phys));
144862306a36Sopenharmony_ci	}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci	els->els_request_payload_length = cpu_to_le32(params->xmit_len);
145162306a36Sopenharmony_ci	els->max_response_payload_length = cpu_to_le32(params->rsp_len);
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci	els->xri_tag = cpu_to_le16(params->xri);
145462306a36Sopenharmony_ci	els->timer = params->timeout;
145562306a36Sopenharmony_ci	els->class_byte |= SLI4_GENERIC_CLASS_CLASS_3;
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	els->command = SLI4_WQE_ELS_REQUEST64;
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	els->request_tag = cpu_to_le16(params->tag);
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	els->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_REQ_WQE_IOD;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	els->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_REQ_WQE_QOSD;
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	/* figure out the ELS_ID value from the request buffer */
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	switch (params->cmd) {
146862306a36Sopenharmony_ci	case ELS_LOGO:
146962306a36Sopenharmony_ci		els->cmdtype_elsid_byte |=
147062306a36Sopenharmony_ci			SLI4_ELS_REQUEST64_LOGO << SLI4_REQ_WQE_ELSID_SHFT;
147162306a36Sopenharmony_ci		if (params->rpi_registered) {
147262306a36Sopenharmony_ci			els->ct_byte |=
147362306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_RPI << SLI4_REQ_WQE_CT_SHFT;
147462306a36Sopenharmony_ci			els->context_tag = cpu_to_le16(params->rpi);
147562306a36Sopenharmony_ci		} else {
147662306a36Sopenharmony_ci			els->ct_byte |=
147762306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_VPI << SLI4_REQ_WQE_CT_SHFT;
147862306a36Sopenharmony_ci			els->context_tag = cpu_to_le16(params->vpi);
147962306a36Sopenharmony_ci		}
148062306a36Sopenharmony_ci		if (params->d_id == FC_FID_FLOGI)
148162306a36Sopenharmony_ci			is_fabric = true;
148262306a36Sopenharmony_ci		break;
148362306a36Sopenharmony_ci	case ELS_FDISC:
148462306a36Sopenharmony_ci		if (params->d_id == FC_FID_FLOGI)
148562306a36Sopenharmony_ci			is_fabric = true;
148662306a36Sopenharmony_ci		if (params->s_id == 0) {
148762306a36Sopenharmony_ci			els->cmdtype_elsid_byte |=
148862306a36Sopenharmony_ci			SLI4_ELS_REQUEST64_FDISC << SLI4_REQ_WQE_ELSID_SHFT;
148962306a36Sopenharmony_ci			is_fabric = true;
149062306a36Sopenharmony_ci		} else {
149162306a36Sopenharmony_ci			els->cmdtype_elsid_byte |=
149262306a36Sopenharmony_ci			SLI4_ELS_REQUEST64_OTHER << SLI4_REQ_WQE_ELSID_SHFT;
149362306a36Sopenharmony_ci		}
149462306a36Sopenharmony_ci		els->ct_byte |=
149562306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_VPI << SLI4_REQ_WQE_CT_SHFT;
149662306a36Sopenharmony_ci		els->context_tag = cpu_to_le16(params->vpi);
149762306a36Sopenharmony_ci		els->sid_sp_dword |= cpu_to_le32(1 << SLI4_REQ_WQE_SP_SHFT);
149862306a36Sopenharmony_ci		break;
149962306a36Sopenharmony_ci	case ELS_FLOGI:
150062306a36Sopenharmony_ci		els->ct_byte |=
150162306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_VPI << SLI4_REQ_WQE_CT_SHFT;
150262306a36Sopenharmony_ci		els->context_tag = cpu_to_le16(params->vpi);
150362306a36Sopenharmony_ci		/*
150462306a36Sopenharmony_ci		 * Set SP here ... we haven't done a REG_VPI yet
150562306a36Sopenharmony_ci		 * need to maybe not set this when we have
150662306a36Sopenharmony_ci		 * completed VFI/VPI registrations ...
150762306a36Sopenharmony_ci		 *
150862306a36Sopenharmony_ci		 * Use the FC_ID of the SPORT if it has been allocated,
150962306a36Sopenharmony_ci		 * otherwise use an S_ID of zero.
151062306a36Sopenharmony_ci		 */
151162306a36Sopenharmony_ci		els->sid_sp_dword |= cpu_to_le32(1 << SLI4_REQ_WQE_SP_SHFT);
151262306a36Sopenharmony_ci		if (params->s_id != U32_MAX)
151362306a36Sopenharmony_ci			els->sid_sp_dword |= cpu_to_le32(params->s_id);
151462306a36Sopenharmony_ci		break;
151562306a36Sopenharmony_ci	case ELS_PLOGI:
151662306a36Sopenharmony_ci		els->cmdtype_elsid_byte |=
151762306a36Sopenharmony_ci			SLI4_ELS_REQUEST64_PLOGI << SLI4_REQ_WQE_ELSID_SHFT;
151862306a36Sopenharmony_ci		els->ct_byte |=
151962306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_VPI << SLI4_REQ_WQE_CT_SHFT;
152062306a36Sopenharmony_ci		els->context_tag = cpu_to_le16(params->vpi);
152162306a36Sopenharmony_ci		break;
152262306a36Sopenharmony_ci	case ELS_SCR:
152362306a36Sopenharmony_ci		els->cmdtype_elsid_byte |=
152462306a36Sopenharmony_ci			SLI4_ELS_REQUEST64_OTHER << SLI4_REQ_WQE_ELSID_SHFT;
152562306a36Sopenharmony_ci		els->ct_byte |=
152662306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_VPI << SLI4_REQ_WQE_CT_SHFT;
152762306a36Sopenharmony_ci		els->context_tag = cpu_to_le16(params->vpi);
152862306a36Sopenharmony_ci		break;
152962306a36Sopenharmony_ci	default:
153062306a36Sopenharmony_ci		els->cmdtype_elsid_byte |=
153162306a36Sopenharmony_ci			SLI4_ELS_REQUEST64_OTHER << SLI4_REQ_WQE_ELSID_SHFT;
153262306a36Sopenharmony_ci		if (params->rpi_registered) {
153362306a36Sopenharmony_ci			els->ct_byte |= (SLI4_GENERIC_CONTEXT_RPI <<
153462306a36Sopenharmony_ci					 SLI4_REQ_WQE_CT_SHFT);
153562306a36Sopenharmony_ci			els->context_tag = cpu_to_le16(params->vpi);
153662306a36Sopenharmony_ci		} else {
153762306a36Sopenharmony_ci			els->ct_byte |=
153862306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_VPI << SLI4_REQ_WQE_CT_SHFT;
153962306a36Sopenharmony_ci			els->context_tag = cpu_to_le16(params->vpi);
154062306a36Sopenharmony_ci		}
154162306a36Sopenharmony_ci		break;
154262306a36Sopenharmony_ci	}
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_ci	if (is_fabric)
154562306a36Sopenharmony_ci		els->cmdtype_elsid_byte |= SLI4_ELS_REQUEST64_CMD_FABRIC;
154662306a36Sopenharmony_ci	else
154762306a36Sopenharmony_ci		els->cmdtype_elsid_byte |= SLI4_ELS_REQUEST64_CMD_NON_FABRIC;
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	els->cq_id = cpu_to_le16(SLI4_CQ_DEFAULT);
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	if (((els->ct_byte & SLI4_REQ_WQE_CT) >> SLI4_REQ_WQE_CT_SHFT) !=
155262306a36Sopenharmony_ci					SLI4_GENERIC_CONTEXT_RPI)
155362306a36Sopenharmony_ci		els->remote_id_dword = cpu_to_le32(params->d_id);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	if (((els->ct_byte & SLI4_REQ_WQE_CT) >> SLI4_REQ_WQE_CT_SHFT) ==
155662306a36Sopenharmony_ci					SLI4_GENERIC_CONTEXT_VPI)
155762306a36Sopenharmony_ci		els->temporary_rpi = cpu_to_le16(params->rpi);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	return 0;
156062306a36Sopenharmony_ci}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ciint
156362306a36Sopenharmony_cisli_fcp_icmnd64_wqe(struct sli4 *sli, void *buf, struct efc_dma *sgl, u16 xri,
156462306a36Sopenharmony_ci		    u16 tag, u16 cq_id, u32 rpi, u32 rnode_fcid, u8 timeout)
156562306a36Sopenharmony_ci{
156662306a36Sopenharmony_ci	struct sli4_fcp_icmnd64_wqe *icmnd = buf;
156762306a36Sopenharmony_ci	struct sli4_sge *sge = NULL;
156862306a36Sopenharmony_ci	struct sli4_bde *bptr;
156962306a36Sopenharmony_ci	u32 len;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	if (!sgl || !sgl->virt) {
157462306a36Sopenharmony_ci		efc_log_err(sli, "bad parameter sgl=%p virt=%p\n",
157562306a36Sopenharmony_ci			    sgl, sgl ? sgl->virt : NULL);
157662306a36Sopenharmony_ci		return -EIO;
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci	sge = sgl->virt;
157962306a36Sopenharmony_ci	bptr = &icmnd->bde;
158062306a36Sopenharmony_ci	if (sli->params.sgl_pre_registered) {
158162306a36Sopenharmony_ci		icmnd->qosd_xbl_hlm_iod_dbde_wqes &= ~SLI4_ICMD_WQE_XBL;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci		icmnd->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_ICMD_WQE_DBDE;
158462306a36Sopenharmony_ci		bptr->bde_type_buflen =
158562306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
158662306a36Sopenharmony_ci				    (le32_to_cpu(sge[0].buffer_length) &
158762306a36Sopenharmony_ci				     SLI4_BDE_LEN_MASK));
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci		bptr->u.data.low  = sge[0].buffer_address_low;
159062306a36Sopenharmony_ci		bptr->u.data.high = sge[0].buffer_address_high;
159162306a36Sopenharmony_ci	} else {
159262306a36Sopenharmony_ci		icmnd->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_ICMD_WQE_XBL;
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci		bptr->bde_type_buflen =
159562306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(BLP)) |
159662306a36Sopenharmony_ci				    (sgl->size & SLI4_BDE_LEN_MASK));
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci		bptr->u.blp.low  = cpu_to_le32(lower_32_bits(sgl->phys));
159962306a36Sopenharmony_ci		bptr->u.blp.high = cpu_to_le32(upper_32_bits(sgl->phys));
160062306a36Sopenharmony_ci	}
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci	len = le32_to_cpu(sge[0].buffer_length) +
160362306a36Sopenharmony_ci	      le32_to_cpu(sge[1].buffer_length);
160462306a36Sopenharmony_ci	icmnd->payload_offset_length = cpu_to_le16(len);
160562306a36Sopenharmony_ci	icmnd->xri_tag = cpu_to_le16(xri);
160662306a36Sopenharmony_ci	icmnd->context_tag = cpu_to_le16(rpi);
160762306a36Sopenharmony_ci	icmnd->timer = timeout;
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	/* WQE word 4 contains read transfer length */
161062306a36Sopenharmony_ci	icmnd->class_pu_byte |= 2 << SLI4_ICMD_WQE_PU_SHFT;
161162306a36Sopenharmony_ci	icmnd->class_pu_byte |= SLI4_GENERIC_CLASS_CLASS_3;
161262306a36Sopenharmony_ci	icmnd->command = SLI4_WQE_FCP_ICMND64;
161362306a36Sopenharmony_ci	icmnd->dif_ct_bs_byte |=
161462306a36Sopenharmony_ci		SLI4_GENERIC_CONTEXT_RPI << SLI4_ICMD_WQE_CT_SHFT;
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci	icmnd->abort_tag = cpu_to_le32(xri);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	icmnd->request_tag = cpu_to_le16(tag);
161962306a36Sopenharmony_ci	icmnd->len_loc1_byte |= SLI4_ICMD_WQE_LEN_LOC_BIT1;
162062306a36Sopenharmony_ci	icmnd->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_ICMD_WQE_LEN_LOC_BIT2;
162162306a36Sopenharmony_ci	icmnd->cmd_type_byte |= SLI4_CMD_FCP_ICMND64_WQE;
162262306a36Sopenharmony_ci	icmnd->cq_id = cpu_to_le16(cq_id);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	return  0;
162562306a36Sopenharmony_ci}
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ciint
162862306a36Sopenharmony_cisli_fcp_iread64_wqe(struct sli4 *sli, void *buf, struct efc_dma *sgl,
162962306a36Sopenharmony_ci		    u32 first_data_sge, u32 xfer_len, u16 xri, u16 tag,
163062306a36Sopenharmony_ci		    u16 cq_id, u32 rpi, u32 rnode_fcid,
163162306a36Sopenharmony_ci		    u8 dif, u8 bs, u8 timeout)
163262306a36Sopenharmony_ci{
163362306a36Sopenharmony_ci	struct sli4_fcp_iread64_wqe *iread = buf;
163462306a36Sopenharmony_ci	struct sli4_sge *sge = NULL;
163562306a36Sopenharmony_ci	struct sli4_bde *bptr;
163662306a36Sopenharmony_ci	u32 sge_flags, len;
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	if (!sgl || !sgl->virt) {
164162306a36Sopenharmony_ci		efc_log_err(sli, "bad parameter sgl=%p virt=%p\n",
164262306a36Sopenharmony_ci			    sgl, sgl ? sgl->virt : NULL);
164362306a36Sopenharmony_ci		return -EIO;
164462306a36Sopenharmony_ci	}
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	sge = sgl->virt;
164762306a36Sopenharmony_ci	bptr = &iread->bde;
164862306a36Sopenharmony_ci	if (sli->params.sgl_pre_registered) {
164962306a36Sopenharmony_ci		iread->qosd_xbl_hlm_iod_dbde_wqes &= ~SLI4_IR_WQE_XBL;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci		iread->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IR_WQE_DBDE;
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci		bptr->bde_type_buflen =
165462306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
165562306a36Sopenharmony_ci				    (le32_to_cpu(sge[0].buffer_length) &
165662306a36Sopenharmony_ci				     SLI4_BDE_LEN_MASK));
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci		bptr->u.blp.low  = sge[0].buffer_address_low;
165962306a36Sopenharmony_ci		bptr->u.blp.high = sge[0].buffer_address_high;
166062306a36Sopenharmony_ci	} else {
166162306a36Sopenharmony_ci		iread->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IR_WQE_XBL;
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci		bptr->bde_type_buflen =
166462306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(BLP)) |
166562306a36Sopenharmony_ci				    (sgl->size & SLI4_BDE_LEN_MASK));
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci		bptr->u.blp.low  =
166862306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(sgl->phys));
166962306a36Sopenharmony_ci		bptr->u.blp.high =
167062306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(sgl->phys));
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci		/*
167362306a36Sopenharmony_ci		 * fill out fcp_cmnd buffer len and change resp buffer to be of
167462306a36Sopenharmony_ci		 * type "skip" (note: response will still be written to sge[1]
167562306a36Sopenharmony_ci		 * if necessary)
167662306a36Sopenharmony_ci		 */
167762306a36Sopenharmony_ci		len = le32_to_cpu(sge[0].buffer_length);
167862306a36Sopenharmony_ci		iread->fcp_cmd_buffer_length = cpu_to_le16(len);
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_ci		sge_flags = le32_to_cpu(sge[1].dw2_flags);
168162306a36Sopenharmony_ci		sge_flags &= (~SLI4_SGE_TYPE_MASK);
168262306a36Sopenharmony_ci		sge_flags |= (SLI4_SGE_TYPE_SKIP << SLI4_SGE_TYPE_SHIFT);
168362306a36Sopenharmony_ci		sge[1].dw2_flags = cpu_to_le32(sge_flags);
168462306a36Sopenharmony_ci	}
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	len = le32_to_cpu(sge[0].buffer_length) +
168762306a36Sopenharmony_ci	      le32_to_cpu(sge[1].buffer_length);
168862306a36Sopenharmony_ci	iread->payload_offset_length = cpu_to_le16(len);
168962306a36Sopenharmony_ci	iread->total_transfer_length = cpu_to_le32(xfer_len);
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_ci	iread->xri_tag = cpu_to_le16(xri);
169262306a36Sopenharmony_ci	iread->context_tag = cpu_to_le16(rpi);
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	iread->timer = timeout;
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	/* WQE word 4 contains read transfer length */
169762306a36Sopenharmony_ci	iread->class_pu_byte |= 2 << SLI4_IR_WQE_PU_SHFT;
169862306a36Sopenharmony_ci	iread->class_pu_byte |= SLI4_GENERIC_CLASS_CLASS_3;
169962306a36Sopenharmony_ci	iread->command = SLI4_WQE_FCP_IREAD64;
170062306a36Sopenharmony_ci	iread->dif_ct_bs_byte |=
170162306a36Sopenharmony_ci		SLI4_GENERIC_CONTEXT_RPI << SLI4_IR_WQE_CT_SHFT;
170262306a36Sopenharmony_ci	iread->dif_ct_bs_byte |= dif;
170362306a36Sopenharmony_ci	iread->dif_ct_bs_byte  |= bs << SLI4_IR_WQE_BS_SHFT;
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_ci	iread->abort_tag = cpu_to_le32(xri);
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_ci	iread->request_tag = cpu_to_le16(tag);
170862306a36Sopenharmony_ci	iread->len_loc1_byte |= SLI4_IR_WQE_LEN_LOC_BIT1;
170962306a36Sopenharmony_ci	iread->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IR_WQE_LEN_LOC_BIT2;
171062306a36Sopenharmony_ci	iread->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IR_WQE_IOD;
171162306a36Sopenharmony_ci	iread->cmd_type_byte |= SLI4_CMD_FCP_IREAD64_WQE;
171262306a36Sopenharmony_ci	iread->cq_id = cpu_to_le16(cq_id);
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	if (sli->params.perf_hint) {
171562306a36Sopenharmony_ci		bptr = &iread->first_data_bde;
171662306a36Sopenharmony_ci		bptr->bde_type_buflen =	cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
171762306a36Sopenharmony_ci			  (le32_to_cpu(sge[first_data_sge].buffer_length) &
171862306a36Sopenharmony_ci			     SLI4_BDE_LEN_MASK));
171962306a36Sopenharmony_ci		bptr->u.data.low =
172062306a36Sopenharmony_ci			sge[first_data_sge].buffer_address_low;
172162306a36Sopenharmony_ci		bptr->u.data.high =
172262306a36Sopenharmony_ci			sge[first_data_sge].buffer_address_high;
172362306a36Sopenharmony_ci	}
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci	return  0;
172662306a36Sopenharmony_ci}
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ciint
172962306a36Sopenharmony_cisli_fcp_iwrite64_wqe(struct sli4 *sli, void *buf, struct efc_dma *sgl,
173062306a36Sopenharmony_ci		     u32 first_data_sge, u32 xfer_len,
173162306a36Sopenharmony_ci		     u32 first_burst, u16 xri, u16 tag,
173262306a36Sopenharmony_ci		     u16 cq_id, u32 rpi,
173362306a36Sopenharmony_ci		     u32 rnode_fcid,
173462306a36Sopenharmony_ci		     u8 dif, u8 bs, u8 timeout)
173562306a36Sopenharmony_ci{
173662306a36Sopenharmony_ci	struct sli4_fcp_iwrite64_wqe *iwrite = buf;
173762306a36Sopenharmony_ci	struct sli4_sge *sge = NULL;
173862306a36Sopenharmony_ci	struct sli4_bde *bptr;
173962306a36Sopenharmony_ci	u32 sge_flags, min, len;
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	if (!sgl || !sgl->virt) {
174462306a36Sopenharmony_ci		efc_log_err(sli, "bad parameter sgl=%p virt=%p\n",
174562306a36Sopenharmony_ci			    sgl, sgl ? sgl->virt : NULL);
174662306a36Sopenharmony_ci		return -EIO;
174762306a36Sopenharmony_ci	}
174862306a36Sopenharmony_ci	sge = sgl->virt;
174962306a36Sopenharmony_ci	bptr = &iwrite->bde;
175062306a36Sopenharmony_ci	if (sli->params.sgl_pre_registered) {
175162306a36Sopenharmony_ci		iwrite->qosd_xbl_hlm_iod_dbde_wqes &= ~SLI4_IWR_WQE_XBL;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci		iwrite->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IWR_WQE_DBDE;
175462306a36Sopenharmony_ci		bptr->bde_type_buflen = cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
175562306a36Sopenharmony_ci		       (le32_to_cpu(sge[0].buffer_length) & SLI4_BDE_LEN_MASK));
175662306a36Sopenharmony_ci		bptr->u.data.low  = sge[0].buffer_address_low;
175762306a36Sopenharmony_ci		bptr->u.data.high = sge[0].buffer_address_high;
175862306a36Sopenharmony_ci	} else {
175962306a36Sopenharmony_ci		iwrite->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IWR_WQE_XBL;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci		bptr->bde_type_buflen =	cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
176262306a36Sopenharmony_ci					(sgl->size & SLI4_BDE_LEN_MASK));
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci		bptr->u.blp.low  = cpu_to_le32(lower_32_bits(sgl->phys));
176562306a36Sopenharmony_ci		bptr->u.blp.high = cpu_to_le32(upper_32_bits(sgl->phys));
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci		/*
176862306a36Sopenharmony_ci		 * fill out fcp_cmnd buffer len and change resp buffer to be of
176962306a36Sopenharmony_ci		 * type "skip" (note: response will still be written to sge[1]
177062306a36Sopenharmony_ci		 * if necessary)
177162306a36Sopenharmony_ci		 */
177262306a36Sopenharmony_ci		len = le32_to_cpu(sge[0].buffer_length);
177362306a36Sopenharmony_ci		iwrite->fcp_cmd_buffer_length = cpu_to_le16(len);
177462306a36Sopenharmony_ci		sge_flags = le32_to_cpu(sge[1].dw2_flags);
177562306a36Sopenharmony_ci		sge_flags &= ~SLI4_SGE_TYPE_MASK;
177662306a36Sopenharmony_ci		sge_flags |= (SLI4_SGE_TYPE_SKIP << SLI4_SGE_TYPE_SHIFT);
177762306a36Sopenharmony_ci		sge[1].dw2_flags = cpu_to_le32(sge_flags);
177862306a36Sopenharmony_ci	}
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	len = le32_to_cpu(sge[0].buffer_length) +
178162306a36Sopenharmony_ci	      le32_to_cpu(sge[1].buffer_length);
178262306a36Sopenharmony_ci	iwrite->payload_offset_length = cpu_to_le16(len);
178362306a36Sopenharmony_ci	iwrite->total_transfer_length = cpu_to_le16(xfer_len);
178462306a36Sopenharmony_ci	min = (xfer_len < first_burst) ? xfer_len : first_burst;
178562306a36Sopenharmony_ci	iwrite->initial_transfer_length = cpu_to_le16(min);
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	iwrite->xri_tag = cpu_to_le16(xri);
178862306a36Sopenharmony_ci	iwrite->context_tag = cpu_to_le16(rpi);
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	iwrite->timer = timeout;
179162306a36Sopenharmony_ci	/* WQE word 4 contains read transfer length */
179262306a36Sopenharmony_ci	iwrite->class_pu_byte |= 2 << SLI4_IWR_WQE_PU_SHFT;
179362306a36Sopenharmony_ci	iwrite->class_pu_byte |= SLI4_GENERIC_CLASS_CLASS_3;
179462306a36Sopenharmony_ci	iwrite->command = SLI4_WQE_FCP_IWRITE64;
179562306a36Sopenharmony_ci	iwrite->dif_ct_bs_byte |=
179662306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_RPI << SLI4_IWR_WQE_CT_SHFT;
179762306a36Sopenharmony_ci	iwrite->dif_ct_bs_byte |= dif;
179862306a36Sopenharmony_ci	iwrite->dif_ct_bs_byte |= bs << SLI4_IWR_WQE_BS_SHFT;
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	iwrite->abort_tag = cpu_to_le32(xri);
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	iwrite->request_tag = cpu_to_le16(tag);
180362306a36Sopenharmony_ci	iwrite->len_loc1_byte |= SLI4_IWR_WQE_LEN_LOC_BIT1;
180462306a36Sopenharmony_ci	iwrite->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_IWR_WQE_LEN_LOC_BIT2;
180562306a36Sopenharmony_ci	iwrite->cmd_type_byte |= SLI4_CMD_FCP_IWRITE64_WQE;
180662306a36Sopenharmony_ci	iwrite->cq_id = cpu_to_le16(cq_id);
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	if (sli->params.perf_hint) {
180962306a36Sopenharmony_ci		bptr = &iwrite->first_data_bde;
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_ci		bptr->bde_type_buflen =	cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
181262306a36Sopenharmony_ci			 (le32_to_cpu(sge[first_data_sge].buffer_length) &
181362306a36Sopenharmony_ci			     SLI4_BDE_LEN_MASK));
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci		bptr->u.data.low = sge[first_data_sge].buffer_address_low;
181662306a36Sopenharmony_ci		bptr->u.data.high = sge[first_data_sge].buffer_address_high;
181762306a36Sopenharmony_ci	}
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	return  0;
182062306a36Sopenharmony_ci}
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ciint
182362306a36Sopenharmony_cisli_fcp_treceive64_wqe(struct sli4 *sli, void *buf, struct efc_dma *sgl,
182462306a36Sopenharmony_ci		       u32 first_data_sge, u16 cq_id, u8 dif, u8 bs,
182562306a36Sopenharmony_ci		       struct sli_fcp_tgt_params *params)
182662306a36Sopenharmony_ci{
182762306a36Sopenharmony_ci	struct sli4_fcp_treceive64_wqe *trecv = buf;
182862306a36Sopenharmony_ci	struct sli4_fcp_128byte_wqe *trecv_128 = buf;
182962306a36Sopenharmony_ci	struct sli4_sge *sge = NULL;
183062306a36Sopenharmony_ci	struct sli4_bde *bptr;
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	if (!sgl || !sgl->virt) {
183562306a36Sopenharmony_ci		efc_log_err(sli, "bad parameter sgl=%p virt=%p\n",
183662306a36Sopenharmony_ci			    sgl, sgl ? sgl->virt : NULL);
183762306a36Sopenharmony_ci		return -EIO;
183862306a36Sopenharmony_ci	}
183962306a36Sopenharmony_ci	sge = sgl->virt;
184062306a36Sopenharmony_ci	bptr = &trecv->bde;
184162306a36Sopenharmony_ci	if (sli->params.sgl_pre_registered) {
184262306a36Sopenharmony_ci		trecv->qosd_xbl_hlm_iod_dbde_wqes &= ~SLI4_TRCV_WQE_XBL;
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci		trecv->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_TRCV_WQE_DBDE;
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci		bptr->bde_type_buflen =
184762306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
184862306a36Sopenharmony_ci				    (le32_to_cpu(sge[0].buffer_length)
184962306a36Sopenharmony_ci					& SLI4_BDE_LEN_MASK));
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci		bptr->u.data.low  = sge[0].buffer_address_low;
185262306a36Sopenharmony_ci		bptr->u.data.high = sge[0].buffer_address_high;
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci		trecv->payload_offset_length = sge[0].buffer_length;
185562306a36Sopenharmony_ci	} else {
185662306a36Sopenharmony_ci		trecv->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_TRCV_WQE_XBL;
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci		/* if data is a single physical address, use a BDE */
185962306a36Sopenharmony_ci		if (!dif &&
186062306a36Sopenharmony_ci		    params->xmit_len <= le32_to_cpu(sge[2].buffer_length)) {
186162306a36Sopenharmony_ci			trecv->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_TRCV_WQE_DBDE;
186262306a36Sopenharmony_ci			bptr->bde_type_buflen =
186362306a36Sopenharmony_ci			      cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
186462306a36Sopenharmony_ci					  (le32_to_cpu(sge[2].buffer_length)
186562306a36Sopenharmony_ci					  & SLI4_BDE_LEN_MASK));
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci			bptr->u.data.low = sge[2].buffer_address_low;
186862306a36Sopenharmony_ci			bptr->u.data.high = sge[2].buffer_address_high;
186962306a36Sopenharmony_ci		} else {
187062306a36Sopenharmony_ci			bptr->bde_type_buflen =
187162306a36Sopenharmony_ci				cpu_to_le32((SLI4_BDE_TYPE_VAL(BLP)) |
187262306a36Sopenharmony_ci				(sgl->size & SLI4_BDE_LEN_MASK));
187362306a36Sopenharmony_ci			bptr->u.blp.low = cpu_to_le32(lower_32_bits(sgl->phys));
187462306a36Sopenharmony_ci			bptr->u.blp.high =
187562306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(sgl->phys));
187662306a36Sopenharmony_ci		}
187762306a36Sopenharmony_ci	}
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci	trecv->relative_offset = cpu_to_le32(params->offset);
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	if (params->flags & SLI4_IO_CONTINUATION)
188262306a36Sopenharmony_ci		trecv->eat_xc_ccpe |= SLI4_TRCV_WQE_XC;
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	trecv->xri_tag = cpu_to_le16(params->xri);
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci	trecv->context_tag = cpu_to_le16(params->rpi);
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	/* WQE uses relative offset */
188962306a36Sopenharmony_ci	trecv->class_ar_pu_byte |= 1 << SLI4_TRCV_WQE_PU_SHFT;
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	if (params->flags & SLI4_IO_AUTO_GOOD_RESPONSE)
189262306a36Sopenharmony_ci		trecv->class_ar_pu_byte |= SLI4_TRCV_WQE_AR;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	trecv->command = SLI4_WQE_FCP_TRECEIVE64;
189562306a36Sopenharmony_ci	trecv->class_ar_pu_byte |= SLI4_GENERIC_CLASS_CLASS_3;
189662306a36Sopenharmony_ci	trecv->dif_ct_bs_byte |=
189762306a36Sopenharmony_ci		SLI4_GENERIC_CONTEXT_RPI << SLI4_TRCV_WQE_CT_SHFT;
189862306a36Sopenharmony_ci	trecv->dif_ct_bs_byte |= bs << SLI4_TRCV_WQE_BS_SHFT;
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci	trecv->remote_xid = cpu_to_le16(params->ox_id);
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci	trecv->request_tag = cpu_to_le16(params->tag);
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	trecv->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_TRCV_WQE_IOD;
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	trecv->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_TRCV_WQE_LEN_LOC_BIT2;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	trecv->cmd_type_byte |= SLI4_CMD_FCP_TRECEIVE64_WQE;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	trecv->cq_id = cpu_to_le16(cq_id);
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	trecv->fcp_data_receive_length = cpu_to_le32(params->xmit_len);
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	if (sli->params.perf_hint) {
191562306a36Sopenharmony_ci		bptr = &trecv->first_data_bde;
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci		bptr->bde_type_buflen =
191862306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
191962306a36Sopenharmony_ci			    (le32_to_cpu(sge[first_data_sge].buffer_length) &
192062306a36Sopenharmony_ci			     SLI4_BDE_LEN_MASK));
192162306a36Sopenharmony_ci		bptr->u.data.low = sge[first_data_sge].buffer_address_low;
192262306a36Sopenharmony_ci		bptr->u.data.high = sge[first_data_sge].buffer_address_high;
192362306a36Sopenharmony_ci	}
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	/* The upper 7 bits of csctl is the priority */
192662306a36Sopenharmony_ci	if (params->cs_ctl & SLI4_MASK_CCP) {
192762306a36Sopenharmony_ci		trecv->eat_xc_ccpe |= SLI4_TRCV_WQE_CCPE;
192862306a36Sopenharmony_ci		trecv->ccp = (params->cs_ctl & SLI4_MASK_CCP);
192962306a36Sopenharmony_ci	}
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	if (params->app_id && sli->wqe_size == SLI4_WQE_EXT_BYTES &&
193262306a36Sopenharmony_ci	    !(trecv->eat_xc_ccpe & SLI4_TRSP_WQE_EAT)) {
193362306a36Sopenharmony_ci		trecv->lloc1_appid |= SLI4_TRCV_WQE_APPID;
193462306a36Sopenharmony_ci		trecv->qosd_xbl_hlm_iod_dbde_wqes |= SLI4_TRCV_WQE_WQES;
193562306a36Sopenharmony_ci		trecv_128->dw[31] = params->app_id;
193662306a36Sopenharmony_ci	}
193762306a36Sopenharmony_ci	return 0;
193862306a36Sopenharmony_ci}
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ciint
194162306a36Sopenharmony_cisli_fcp_cont_treceive64_wqe(struct sli4 *sli, void *buf,
194262306a36Sopenharmony_ci			    struct efc_dma *sgl, u32 first_data_sge,
194362306a36Sopenharmony_ci			    u16 sec_xri, u16 cq_id, u8 dif, u8 bs,
194462306a36Sopenharmony_ci			    struct sli_fcp_tgt_params *params)
194562306a36Sopenharmony_ci{
194662306a36Sopenharmony_ci	int rc;
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	rc = sli_fcp_treceive64_wqe(sli, buf, sgl, first_data_sge,
194962306a36Sopenharmony_ci				    cq_id, dif, bs, params);
195062306a36Sopenharmony_ci	if (!rc) {
195162306a36Sopenharmony_ci		struct sli4_fcp_treceive64_wqe *trecv = buf;
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_ci		trecv->command = SLI4_WQE_FCP_CONT_TRECEIVE64;
195462306a36Sopenharmony_ci		trecv->dword5.sec_xri_tag = cpu_to_le16(sec_xri);
195562306a36Sopenharmony_ci	}
195662306a36Sopenharmony_ci	return rc;
195762306a36Sopenharmony_ci}
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ciint
196062306a36Sopenharmony_cisli_fcp_trsp64_wqe(struct sli4 *sli4, void *buf, struct efc_dma *sgl,
196162306a36Sopenharmony_ci		   u16 cq_id, u8 port_owned, struct sli_fcp_tgt_params *params)
196262306a36Sopenharmony_ci{
196362306a36Sopenharmony_ci	struct sli4_fcp_trsp64_wqe *trsp = buf;
196462306a36Sopenharmony_ci	struct sli4_fcp_128byte_wqe *trsp_128 = buf;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	memset(buf, 0, sli4->wqe_size);
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_ci	if (params->flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
196962306a36Sopenharmony_ci		trsp->class_ag_byte |= SLI4_TRSP_WQE_AG;
197062306a36Sopenharmony_ci	} else {
197162306a36Sopenharmony_ci		struct sli4_sge	*sge = sgl->virt;
197262306a36Sopenharmony_ci		struct sli4_bde *bptr;
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci		if (sli4->params.sgl_pre_registered || port_owned)
197562306a36Sopenharmony_ci			trsp->qosd_xbl_hlm_dbde_wqes |= SLI4_TRSP_WQE_DBDE;
197662306a36Sopenharmony_ci		else
197762306a36Sopenharmony_ci			trsp->qosd_xbl_hlm_dbde_wqes |= SLI4_TRSP_WQE_XBL;
197862306a36Sopenharmony_ci		bptr = &trsp->bde;
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci		bptr->bde_type_buflen =
198162306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
198262306a36Sopenharmony_ci				     (le32_to_cpu(sge[0].buffer_length) &
198362306a36Sopenharmony_ci				      SLI4_BDE_LEN_MASK));
198462306a36Sopenharmony_ci		bptr->u.data.low  = sge[0].buffer_address_low;
198562306a36Sopenharmony_ci		bptr->u.data.high = sge[0].buffer_address_high;
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci		trsp->fcp_response_length = cpu_to_le32(params->xmit_len);
198862306a36Sopenharmony_ci	}
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	if (params->flags & SLI4_IO_CONTINUATION)
199162306a36Sopenharmony_ci		trsp->eat_xc_ccpe |= SLI4_TRSP_WQE_XC;
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci	trsp->xri_tag = cpu_to_le16(params->xri);
199462306a36Sopenharmony_ci	trsp->rpi = cpu_to_le16(params->rpi);
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci	trsp->command = SLI4_WQE_FCP_TRSP64;
199762306a36Sopenharmony_ci	trsp->class_ag_byte |= SLI4_GENERIC_CLASS_CLASS_3;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	trsp->remote_xid = cpu_to_le16(params->ox_id);
200062306a36Sopenharmony_ci	trsp->request_tag = cpu_to_le16(params->tag);
200162306a36Sopenharmony_ci	if (params->flags & SLI4_IO_DNRX)
200262306a36Sopenharmony_ci		trsp->ct_dnrx_byte |= SLI4_TRSP_WQE_DNRX;
200362306a36Sopenharmony_ci	else
200462306a36Sopenharmony_ci		trsp->ct_dnrx_byte &= ~SLI4_TRSP_WQE_DNRX;
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci	trsp->lloc1_appid |= 0x1;
200762306a36Sopenharmony_ci	trsp->cq_id = cpu_to_le16(cq_id);
200862306a36Sopenharmony_ci	trsp->cmd_type_byte = SLI4_CMD_FCP_TRSP64_WQE;
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_ci	/* The upper 7 bits of csctl is the priority */
201162306a36Sopenharmony_ci	if (params->cs_ctl & SLI4_MASK_CCP) {
201262306a36Sopenharmony_ci		trsp->eat_xc_ccpe |= SLI4_TRSP_WQE_CCPE;
201362306a36Sopenharmony_ci		trsp->ccp = (params->cs_ctl & SLI4_MASK_CCP);
201462306a36Sopenharmony_ci	}
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	if (params->app_id && sli4->wqe_size == SLI4_WQE_EXT_BYTES &&
201762306a36Sopenharmony_ci	    !(trsp->eat_xc_ccpe & SLI4_TRSP_WQE_EAT)) {
201862306a36Sopenharmony_ci		trsp->lloc1_appid |= SLI4_TRSP_WQE_APPID;
201962306a36Sopenharmony_ci		trsp->qosd_xbl_hlm_dbde_wqes |= SLI4_TRSP_WQE_WQES;
202062306a36Sopenharmony_ci		trsp_128->dw[31] = params->app_id;
202162306a36Sopenharmony_ci	}
202262306a36Sopenharmony_ci	return 0;
202362306a36Sopenharmony_ci}
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ciint
202662306a36Sopenharmony_cisli_fcp_tsend64_wqe(struct sli4 *sli4, void *buf, struct efc_dma *sgl,
202762306a36Sopenharmony_ci		    u32 first_data_sge, u16 cq_id, u8 dif, u8 bs,
202862306a36Sopenharmony_ci		    struct sli_fcp_tgt_params *params)
202962306a36Sopenharmony_ci{
203062306a36Sopenharmony_ci	struct sli4_fcp_tsend64_wqe *tsend = buf;
203162306a36Sopenharmony_ci	struct sli4_fcp_128byte_wqe *tsend_128 = buf;
203262306a36Sopenharmony_ci	struct sli4_sge *sge = NULL;
203362306a36Sopenharmony_ci	struct sli4_bde *bptr;
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	memset(buf, 0, sli4->wqe_size);
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci	if (!sgl || !sgl->virt) {
203862306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter sgl=%p virt=%p\n",
203962306a36Sopenharmony_ci			    sgl, sgl ? sgl->virt : NULL);
204062306a36Sopenharmony_ci		return -EIO;
204162306a36Sopenharmony_ci	}
204262306a36Sopenharmony_ci	sge = sgl->virt;
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci	bptr = &tsend->bde;
204562306a36Sopenharmony_ci	if (sli4->params.sgl_pre_registered) {
204662306a36Sopenharmony_ci		tsend->ll_qd_xbl_hlm_iod_dbde &= ~SLI4_TSEND_WQE_XBL;
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci		tsend->ll_qd_xbl_hlm_iod_dbde |= SLI4_TSEND_WQE_DBDE;
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci		bptr->bde_type_buflen =
205162306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
205262306a36Sopenharmony_ci				   (le32_to_cpu(sge[2].buffer_length) &
205362306a36Sopenharmony_ci				    SLI4_BDE_LEN_MASK));
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci		/* TSEND64_WQE specifies first two SGE are skipped (3rd is
205662306a36Sopenharmony_ci		 * valid)
205762306a36Sopenharmony_ci		 */
205862306a36Sopenharmony_ci		bptr->u.data.low  = sge[2].buffer_address_low;
205962306a36Sopenharmony_ci		bptr->u.data.high = sge[2].buffer_address_high;
206062306a36Sopenharmony_ci	} else {
206162306a36Sopenharmony_ci		tsend->ll_qd_xbl_hlm_iod_dbde |= SLI4_TSEND_WQE_XBL;
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci		/* if data is a single physical address, use a BDE */
206462306a36Sopenharmony_ci		if (!dif &&
206562306a36Sopenharmony_ci		    params->xmit_len <= le32_to_cpu(sge[2].buffer_length)) {
206662306a36Sopenharmony_ci			tsend->ll_qd_xbl_hlm_iod_dbde |= SLI4_TSEND_WQE_DBDE;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci			bptr->bde_type_buflen =
206962306a36Sopenharmony_ci			    cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
207062306a36Sopenharmony_ci					(le32_to_cpu(sge[2].buffer_length) &
207162306a36Sopenharmony_ci					SLI4_BDE_LEN_MASK));
207262306a36Sopenharmony_ci			/*
207362306a36Sopenharmony_ci			 * TSEND64_WQE specifies first two SGE are skipped
207462306a36Sopenharmony_ci			 * (i.e. 3rd is valid)
207562306a36Sopenharmony_ci			 */
207662306a36Sopenharmony_ci			bptr->u.data.low =
207762306a36Sopenharmony_ci				sge[2].buffer_address_low;
207862306a36Sopenharmony_ci			bptr->u.data.high =
207962306a36Sopenharmony_ci				sge[2].buffer_address_high;
208062306a36Sopenharmony_ci		} else {
208162306a36Sopenharmony_ci			bptr->bde_type_buflen =
208262306a36Sopenharmony_ci				cpu_to_le32((SLI4_BDE_TYPE_VAL(BLP)) |
208362306a36Sopenharmony_ci					    (sgl->size &
208462306a36Sopenharmony_ci					     SLI4_BDE_LEN_MASK));
208562306a36Sopenharmony_ci			bptr->u.blp.low =
208662306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(sgl->phys));
208762306a36Sopenharmony_ci			bptr->u.blp.high =
208862306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(sgl->phys));
208962306a36Sopenharmony_ci		}
209062306a36Sopenharmony_ci	}
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	tsend->relative_offset = cpu_to_le32(params->offset);
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	if (params->flags & SLI4_IO_CONTINUATION)
209562306a36Sopenharmony_ci		tsend->dw10byte2 |= SLI4_TSEND_XC;
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	tsend->xri_tag = cpu_to_le16(params->xri);
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	tsend->rpi = cpu_to_le16(params->rpi);
210062306a36Sopenharmony_ci	/* WQE uses relative offset */
210162306a36Sopenharmony_ci	tsend->class_pu_ar_byte |= 1 << SLI4_TSEND_WQE_PU_SHFT;
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci	if (params->flags & SLI4_IO_AUTO_GOOD_RESPONSE)
210462306a36Sopenharmony_ci		tsend->class_pu_ar_byte |= SLI4_TSEND_WQE_AR;
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci	tsend->command = SLI4_WQE_FCP_TSEND64;
210762306a36Sopenharmony_ci	tsend->class_pu_ar_byte |= SLI4_GENERIC_CLASS_CLASS_3;
210862306a36Sopenharmony_ci	tsend->ct_byte |= SLI4_GENERIC_CONTEXT_RPI << SLI4_TSEND_CT_SHFT;
210962306a36Sopenharmony_ci	tsend->ct_byte |= dif;
211062306a36Sopenharmony_ci	tsend->ct_byte |= bs << SLI4_TSEND_BS_SHFT;
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci	tsend->remote_xid = cpu_to_le16(params->ox_id);
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci	tsend->request_tag = cpu_to_le16(params->tag);
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	tsend->ll_qd_xbl_hlm_iod_dbde |= SLI4_TSEND_LEN_LOC_BIT2;
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	tsend->cq_id = cpu_to_le16(cq_id);
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	tsend->cmd_type_byte |= SLI4_CMD_FCP_TSEND64_WQE;
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	tsend->fcp_data_transmit_length = cpu_to_le32(params->xmit_len);
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	if (sli4->params.perf_hint) {
212562306a36Sopenharmony_ci		bptr = &tsend->first_data_bde;
212662306a36Sopenharmony_ci		bptr->bde_type_buflen =
212762306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
212862306a36Sopenharmony_ci			    (le32_to_cpu(sge[first_data_sge].buffer_length) &
212962306a36Sopenharmony_ci			     SLI4_BDE_LEN_MASK));
213062306a36Sopenharmony_ci		bptr->u.data.low =
213162306a36Sopenharmony_ci			sge[first_data_sge].buffer_address_low;
213262306a36Sopenharmony_ci		bptr->u.data.high =
213362306a36Sopenharmony_ci			sge[first_data_sge].buffer_address_high;
213462306a36Sopenharmony_ci	}
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_ci	/* The upper 7 bits of csctl is the priority */
213762306a36Sopenharmony_ci	if (params->cs_ctl & SLI4_MASK_CCP) {
213862306a36Sopenharmony_ci		tsend->dw10byte2 |= SLI4_TSEND_CCPE;
213962306a36Sopenharmony_ci		tsend->ccp = (params->cs_ctl & SLI4_MASK_CCP);
214062306a36Sopenharmony_ci	}
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci	if (params->app_id && sli4->wqe_size == SLI4_WQE_EXT_BYTES &&
214362306a36Sopenharmony_ci	    !(tsend->dw10byte2 & SLI4_TSEND_EAT)) {
214462306a36Sopenharmony_ci		tsend->dw10byte0 |= SLI4_TSEND_APPID_VALID;
214562306a36Sopenharmony_ci		tsend->ll_qd_xbl_hlm_iod_dbde |= SLI4_TSEND_WQES;
214662306a36Sopenharmony_ci		tsend_128->dw[31] = params->app_id;
214762306a36Sopenharmony_ci	}
214862306a36Sopenharmony_ci	return 0;
214962306a36Sopenharmony_ci}
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ciint
215262306a36Sopenharmony_cisli_gen_request64_wqe(struct sli4 *sli4, void *buf, struct efc_dma *sgl,
215362306a36Sopenharmony_ci		      struct sli_ct_params *params)
215462306a36Sopenharmony_ci{
215562306a36Sopenharmony_ci	struct sli4_gen_request64_wqe *gen = buf;
215662306a36Sopenharmony_ci	struct sli4_sge *sge = NULL;
215762306a36Sopenharmony_ci	struct sli4_bde *bptr;
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	memset(buf, 0, sli4->wqe_size);
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci	if (!sgl || !sgl->virt) {
216262306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter sgl=%p virt=%p\n",
216362306a36Sopenharmony_ci			    sgl, sgl ? sgl->virt : NULL);
216462306a36Sopenharmony_ci		return -EIO;
216562306a36Sopenharmony_ci	}
216662306a36Sopenharmony_ci	sge = sgl->virt;
216762306a36Sopenharmony_ci	bptr = &gen->bde;
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	if (sli4->params.sgl_pre_registered) {
217062306a36Sopenharmony_ci		gen->dw10flags1 &= ~SLI4_GEN_REQ64_WQE_XBL;
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci		gen->dw10flags1 |= SLI4_GEN_REQ64_WQE_DBDE;
217362306a36Sopenharmony_ci		bptr->bde_type_buflen =
217462306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
217562306a36Sopenharmony_ci				    (params->xmit_len & SLI4_BDE_LEN_MASK));
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci		bptr->u.data.low  = sge[0].buffer_address_low;
217862306a36Sopenharmony_ci		bptr->u.data.high = sge[0].buffer_address_high;
217962306a36Sopenharmony_ci	} else {
218062306a36Sopenharmony_ci		gen->dw10flags1 |= SLI4_GEN_REQ64_WQE_XBL;
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci		bptr->bde_type_buflen =
218362306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(BLP)) |
218462306a36Sopenharmony_ci				    ((2 * sizeof(struct sli4_sge)) &
218562306a36Sopenharmony_ci				     SLI4_BDE_LEN_MASK));
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci		bptr->u.blp.low =
218862306a36Sopenharmony_ci			cpu_to_le32(lower_32_bits(sgl->phys));
218962306a36Sopenharmony_ci		bptr->u.blp.high =
219062306a36Sopenharmony_ci			cpu_to_le32(upper_32_bits(sgl->phys));
219162306a36Sopenharmony_ci	}
219262306a36Sopenharmony_ci
219362306a36Sopenharmony_ci	gen->request_payload_length = cpu_to_le32(params->xmit_len);
219462306a36Sopenharmony_ci	gen->max_response_payload_length = cpu_to_le32(params->rsp_len);
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	gen->df_ctl = params->df_ctl;
219762306a36Sopenharmony_ci	gen->type = params->type;
219862306a36Sopenharmony_ci	gen->r_ctl = params->r_ctl;
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	gen->xri_tag = cpu_to_le16(params->xri);
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	gen->ct_byte = SLI4_GENERIC_CONTEXT_RPI << SLI4_GEN_REQ64_CT_SHFT;
220362306a36Sopenharmony_ci	gen->context_tag = cpu_to_le16(params->rpi);
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci	gen->class_byte = SLI4_GENERIC_CLASS_CLASS_3;
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	gen->command = SLI4_WQE_GEN_REQUEST64;
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	gen->timer = params->timeout;
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci	gen->request_tag = cpu_to_le16(params->tag);
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	gen->dw10flags1 |= SLI4_GEN_REQ64_WQE_IOD;
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	gen->dw10flags0 |= SLI4_GEN_REQ64_WQE_QOSD;
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci	gen->cmd_type_byte = SLI4_CMD_GEN_REQUEST64_WQE;
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci	gen->cq_id = cpu_to_le16(SLI4_CQ_DEFAULT);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	return 0;
222262306a36Sopenharmony_ci}
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ciint
222562306a36Sopenharmony_cisli_send_frame_wqe(struct sli4 *sli, void *buf, u8 sof, u8 eof, u32 *hdr,
222662306a36Sopenharmony_ci		   struct efc_dma *payload, u32 req_len, u8 timeout, u16 xri,
222762306a36Sopenharmony_ci		   u16 req_tag)
222862306a36Sopenharmony_ci{
222962306a36Sopenharmony_ci	struct sli4_send_frame_wqe *sf = buf;
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci	sf->dw10flags1 |= SLI4_SF_WQE_DBDE;
223462306a36Sopenharmony_ci	sf->bde.bde_type_buflen = cpu_to_le32(req_len &
223562306a36Sopenharmony_ci					      SLI4_BDE_LEN_MASK);
223662306a36Sopenharmony_ci	sf->bde.u.data.low = cpu_to_le32(lower_32_bits(payload->phys));
223762306a36Sopenharmony_ci	sf->bde.u.data.high = cpu_to_le32(upper_32_bits(payload->phys));
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci	/* Copy FC header */
224062306a36Sopenharmony_ci	sf->fc_header_0_1[0] = cpu_to_le32(hdr[0]);
224162306a36Sopenharmony_ci	sf->fc_header_0_1[1] = cpu_to_le32(hdr[1]);
224262306a36Sopenharmony_ci	sf->fc_header_2_5[0] = cpu_to_le32(hdr[2]);
224362306a36Sopenharmony_ci	sf->fc_header_2_5[1] = cpu_to_le32(hdr[3]);
224462306a36Sopenharmony_ci	sf->fc_header_2_5[2] = cpu_to_le32(hdr[4]);
224562306a36Sopenharmony_ci	sf->fc_header_2_5[3] = cpu_to_le32(hdr[5]);
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci	sf->frame_length = cpu_to_le32(req_len);
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	sf->xri_tag = cpu_to_le16(xri);
225062306a36Sopenharmony_ci	sf->dw7flags0 &= ~SLI4_SF_PU;
225162306a36Sopenharmony_ci	sf->context_tag = 0;
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci	sf->ct_byte &= ~SLI4_SF_CT;
225462306a36Sopenharmony_ci	sf->command = SLI4_WQE_SEND_FRAME;
225562306a36Sopenharmony_ci	sf->dw7flags0 |= SLI4_GENERIC_CLASS_CLASS_3;
225662306a36Sopenharmony_ci	sf->timer = timeout;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	sf->request_tag = cpu_to_le16(req_tag);
225962306a36Sopenharmony_ci	sf->eof = eof;
226062306a36Sopenharmony_ci	sf->sof = sof;
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	sf->dw10flags1 &= ~SLI4_SF_QOSD;
226362306a36Sopenharmony_ci	sf->dw10flags0 |= SLI4_SF_LEN_LOC_BIT1;
226462306a36Sopenharmony_ci	sf->dw10flags2 &= ~SLI4_SF_XC;
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	sf->dw10flags1 |= SLI4_SF_XBL;
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ci	sf->cmd_type_byte |= SLI4_CMD_SEND_FRAME_WQE;
226962306a36Sopenharmony_ci	sf->cq_id = cpu_to_le16(0xffff);
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_ci	return 0;
227262306a36Sopenharmony_ci}
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ciint
227562306a36Sopenharmony_cisli_xmit_bls_rsp64_wqe(struct sli4 *sli, void *buf,
227662306a36Sopenharmony_ci		       struct sli_bls_payload *payload,
227762306a36Sopenharmony_ci		       struct sli_bls_params *params)
227862306a36Sopenharmony_ci{
227962306a36Sopenharmony_ci	struct sli4_xmit_bls_rsp_wqe *bls = buf;
228062306a36Sopenharmony_ci	u32 dw_ridflags = 0;
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_ci	/*
228362306a36Sopenharmony_ci	 * Callers can either specify RPI or S_ID, but not both
228462306a36Sopenharmony_ci	 */
228562306a36Sopenharmony_ci	if (params->rpi_registered && params->s_id != U32_MAX) {
228662306a36Sopenharmony_ci		efc_log_info(sli, "S_ID specified for attached remote node %d\n",
228762306a36Sopenharmony_ci			     params->rpi);
228862306a36Sopenharmony_ci		return -EIO;
228962306a36Sopenharmony_ci	}
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_ci	if (payload->type == SLI4_SLI_BLS_ACC) {
229462306a36Sopenharmony_ci		bls->payload_word0 =
229562306a36Sopenharmony_ci			cpu_to_le32((payload->u.acc.seq_id_last << 16) |
229662306a36Sopenharmony_ci				    (payload->u.acc.seq_id_validity << 24));
229762306a36Sopenharmony_ci		bls->high_seq_cnt = payload->u.acc.high_seq_cnt;
229862306a36Sopenharmony_ci		bls->low_seq_cnt = payload->u.acc.low_seq_cnt;
229962306a36Sopenharmony_ci	} else if (payload->type == SLI4_SLI_BLS_RJT) {
230062306a36Sopenharmony_ci		bls->payload_word0 =
230162306a36Sopenharmony_ci				cpu_to_le32(*((u32 *)&payload->u.rjt));
230262306a36Sopenharmony_ci		dw_ridflags |= SLI4_BLS_RSP_WQE_AR;
230362306a36Sopenharmony_ci	} else {
230462306a36Sopenharmony_ci		efc_log_info(sli, "bad BLS type %#x\n", payload->type);
230562306a36Sopenharmony_ci		return -EIO;
230662306a36Sopenharmony_ci	}
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	bls->ox_id = payload->ox_id;
230962306a36Sopenharmony_ci	bls->rx_id = payload->rx_id;
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	if (params->rpi_registered) {
231262306a36Sopenharmony_ci		bls->dw8flags0 |=
231362306a36Sopenharmony_ci		SLI4_GENERIC_CONTEXT_RPI << SLI4_BLS_RSP_WQE_CT_SHFT;
231462306a36Sopenharmony_ci		bls->context_tag = cpu_to_le16(params->rpi);
231562306a36Sopenharmony_ci	} else {
231662306a36Sopenharmony_ci		bls->dw8flags0 |=
231762306a36Sopenharmony_ci		SLI4_GENERIC_CONTEXT_VPI << SLI4_BLS_RSP_WQE_CT_SHFT;
231862306a36Sopenharmony_ci		bls->context_tag = cpu_to_le16(params->vpi);
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci		bls->local_n_port_id_dword |=
232162306a36Sopenharmony_ci			cpu_to_le32(params->s_id & 0x00ffffff);
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_ci		dw_ridflags = (dw_ridflags & ~SLI4_BLS_RSP_RID) |
232462306a36Sopenharmony_ci			       (params->d_id & SLI4_BLS_RSP_RID);
232562306a36Sopenharmony_ci
232662306a36Sopenharmony_ci		bls->temporary_rpi = cpu_to_le16(params->rpi);
232762306a36Sopenharmony_ci	}
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci	bls->xri_tag = cpu_to_le16(params->xri);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	bls->dw8flags1 |= SLI4_GENERIC_CLASS_CLASS_3;
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	bls->command = SLI4_WQE_XMIT_BLS_RSP;
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci	bls->request_tag = cpu_to_le16(params->tag);
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ci	bls->dw11flags1 |= SLI4_BLS_RSP_WQE_QOSD;
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	bls->remote_id_dword = cpu_to_le32(dw_ridflags);
234062306a36Sopenharmony_ci	bls->cq_id = cpu_to_le16(SLI4_CQ_DEFAULT);
234162306a36Sopenharmony_ci
234262306a36Sopenharmony_ci	bls->dw12flags0 |= SLI4_CMD_XMIT_BLS_RSP64_WQE;
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	return 0;
234562306a36Sopenharmony_ci}
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ciint
234862306a36Sopenharmony_cisli_xmit_els_rsp64_wqe(struct sli4 *sli, void *buf, struct efc_dma *rsp,
234962306a36Sopenharmony_ci		       struct sli_els_params *params)
235062306a36Sopenharmony_ci{
235162306a36Sopenharmony_ci	struct sli4_xmit_els_rsp64_wqe *els = buf;
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_ci	memset(buf, 0, sli->wqe_size);
235462306a36Sopenharmony_ci
235562306a36Sopenharmony_ci	if (sli->params.sgl_pre_registered)
235662306a36Sopenharmony_ci		els->flags2 |= SLI4_ELS_DBDE;
235762306a36Sopenharmony_ci	else
235862306a36Sopenharmony_ci		els->flags2 |= SLI4_ELS_XBL;
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	els->els_response_payload.bde_type_buflen =
236162306a36Sopenharmony_ci		cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
236262306a36Sopenharmony_ci			    (params->rsp_len & SLI4_BDE_LEN_MASK));
236362306a36Sopenharmony_ci	els->els_response_payload.u.data.low =
236462306a36Sopenharmony_ci		cpu_to_le32(lower_32_bits(rsp->phys));
236562306a36Sopenharmony_ci	els->els_response_payload.u.data.high =
236662306a36Sopenharmony_ci		cpu_to_le32(upper_32_bits(rsp->phys));
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	els->els_response_payload_length = cpu_to_le32(params->rsp_len);
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci	els->xri_tag = cpu_to_le16(params->xri);
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	els->class_byte |= SLI4_GENERIC_CLASS_CLASS_3;
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci	els->command = SLI4_WQE_ELS_RSP64;
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_ci	els->request_tag = cpu_to_le16(params->tag);
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	els->ox_id = cpu_to_le16(params->ox_id);
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	els->flags2 |= SLI4_ELS_QOSD;
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci	els->cmd_type_wqec = SLI4_ELS_REQUEST64_CMD_GEN;
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	els->cq_id = cpu_to_le16(SLI4_CQ_DEFAULT);
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	if (params->rpi_registered) {
238762306a36Sopenharmony_ci		els->ct_byte |=
238862306a36Sopenharmony_ci			SLI4_GENERIC_CONTEXT_RPI << SLI4_ELS_CT_OFFSET;
238962306a36Sopenharmony_ci		els->context_tag = cpu_to_le16(params->rpi);
239062306a36Sopenharmony_ci		return 0;
239162306a36Sopenharmony_ci	}
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	els->ct_byte |= SLI4_GENERIC_CONTEXT_VPI << SLI4_ELS_CT_OFFSET;
239462306a36Sopenharmony_ci	els->context_tag = cpu_to_le16(params->vpi);
239562306a36Sopenharmony_ci	els->rid_dw = cpu_to_le32(params->d_id & SLI4_ELS_RID);
239662306a36Sopenharmony_ci	els->temporary_rpi = cpu_to_le16(params->rpi);
239762306a36Sopenharmony_ci	if (params->s_id != U32_MAX) {
239862306a36Sopenharmony_ci		els->sid_dw |=
239962306a36Sopenharmony_ci		      cpu_to_le32(SLI4_ELS_SP | (params->s_id & SLI4_ELS_SID));
240062306a36Sopenharmony_ci	}
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	return 0;
240362306a36Sopenharmony_ci}
240462306a36Sopenharmony_ci
240562306a36Sopenharmony_ciint
240662306a36Sopenharmony_cisli_xmit_sequence64_wqe(struct sli4 *sli4, void *buf, struct efc_dma *payload,
240762306a36Sopenharmony_ci			struct sli_ct_params *params)
240862306a36Sopenharmony_ci{
240962306a36Sopenharmony_ci	struct sli4_xmit_sequence64_wqe *xmit = buf;
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	memset(buf, 0, sli4->wqe_size);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	if (!payload || !payload->virt) {
241462306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter sgl=%p virt=%p\n",
241562306a36Sopenharmony_ci			    payload, payload ? payload->virt : NULL);
241662306a36Sopenharmony_ci		return -EIO;
241762306a36Sopenharmony_ci	}
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	if (sli4->params.sgl_pre_registered)
242062306a36Sopenharmony_ci		xmit->dw10w0 |= cpu_to_le16(SLI4_SEQ_WQE_DBDE);
242162306a36Sopenharmony_ci	else
242262306a36Sopenharmony_ci		xmit->dw10w0 |= cpu_to_le16(SLI4_SEQ_WQE_XBL);
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci	xmit->bde.bde_type_buflen =
242562306a36Sopenharmony_ci		cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
242662306a36Sopenharmony_ci			(params->rsp_len & SLI4_BDE_LEN_MASK));
242762306a36Sopenharmony_ci	xmit->bde.u.data.low  =
242862306a36Sopenharmony_ci			cpu_to_le32(lower_32_bits(payload->phys));
242962306a36Sopenharmony_ci	xmit->bde.u.data.high =
243062306a36Sopenharmony_ci			cpu_to_le32(upper_32_bits(payload->phys));
243162306a36Sopenharmony_ci	xmit->sequence_payload_len = cpu_to_le32(params->rsp_len);
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	xmit->remote_n_port_id_dword |= cpu_to_le32(params->d_id & 0x00ffffff);
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci	xmit->relative_offset = 0;
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ci	/* sequence initiative - this matches what is seen from
243862306a36Sopenharmony_ci	 * FC switches in response to FCGS commands
243962306a36Sopenharmony_ci	 */
244062306a36Sopenharmony_ci	xmit->dw5flags0 &= (~SLI4_SEQ_WQE_SI);
244162306a36Sopenharmony_ci	xmit->dw5flags0 &= (~SLI4_SEQ_WQE_FT);/* force transmit */
244262306a36Sopenharmony_ci	xmit->dw5flags0 &= (~SLI4_SEQ_WQE_XO);/* exchange responder */
244362306a36Sopenharmony_ci	xmit->dw5flags0 |= SLI4_SEQ_WQE_LS;/* last in seqence */
244462306a36Sopenharmony_ci	xmit->df_ctl = params->df_ctl;
244562306a36Sopenharmony_ci	xmit->type = params->type;
244662306a36Sopenharmony_ci	xmit->r_ctl = params->r_ctl;
244762306a36Sopenharmony_ci
244862306a36Sopenharmony_ci	xmit->xri_tag = cpu_to_le16(params->xri);
244962306a36Sopenharmony_ci	xmit->context_tag = cpu_to_le16(params->rpi);
245062306a36Sopenharmony_ci
245162306a36Sopenharmony_ci	xmit->dw7flags0 &= ~SLI4_SEQ_WQE_DIF;
245262306a36Sopenharmony_ci	xmit->dw7flags0 |=
245362306a36Sopenharmony_ci		SLI4_GENERIC_CONTEXT_RPI << SLI4_SEQ_WQE_CT_SHIFT;
245462306a36Sopenharmony_ci	xmit->dw7flags0 &= ~SLI4_SEQ_WQE_BS;
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	xmit->command = SLI4_WQE_XMIT_SEQUENCE64;
245762306a36Sopenharmony_ci	xmit->dw7flags1 |= SLI4_GENERIC_CLASS_CLASS_3;
245862306a36Sopenharmony_ci	xmit->dw7flags1 &= ~SLI4_SEQ_WQE_PU;
245962306a36Sopenharmony_ci	xmit->timer = params->timeout;
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ci	xmit->abort_tag = 0;
246262306a36Sopenharmony_ci	xmit->request_tag = cpu_to_le16(params->tag);
246362306a36Sopenharmony_ci	xmit->remote_xid = cpu_to_le16(params->ox_id);
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	xmit->dw10w0 |=
246662306a36Sopenharmony_ci	cpu_to_le16(SLI4_ELS_REQUEST64_DIR_READ << SLI4_SEQ_WQE_IOD_SHIFT);
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci	xmit->cmd_type_wqec_byte |= SLI4_CMD_XMIT_SEQUENCE64_WQE;
246962306a36Sopenharmony_ci
247062306a36Sopenharmony_ci	xmit->dw10w0 |= cpu_to_le16(2 << SLI4_SEQ_WQE_LEN_LOC_SHIFT);
247162306a36Sopenharmony_ci
247262306a36Sopenharmony_ci	xmit->cq_id = cpu_to_le16(0xFFFF);
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	return 0;
247562306a36Sopenharmony_ci}
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ciint
247862306a36Sopenharmony_cisli_requeue_xri_wqe(struct sli4 *sli4, void *buf, u16 xri, u16 tag, u16 cq_id)
247962306a36Sopenharmony_ci{
248062306a36Sopenharmony_ci	struct sli4_requeue_xri_wqe *requeue = buf;
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_ci	memset(buf, 0, sli4->wqe_size);
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci	requeue->command = SLI4_WQE_REQUEUE_XRI;
248562306a36Sopenharmony_ci	requeue->xri_tag = cpu_to_le16(xri);
248662306a36Sopenharmony_ci	requeue->request_tag = cpu_to_le16(tag);
248762306a36Sopenharmony_ci	requeue->flags2 |= cpu_to_le16(SLI4_REQU_XRI_WQE_XC);
248862306a36Sopenharmony_ci	requeue->flags1 |= cpu_to_le16(SLI4_REQU_XRI_WQE_QOSD);
248962306a36Sopenharmony_ci	requeue->cq_id = cpu_to_le16(cq_id);
249062306a36Sopenharmony_ci	requeue->cmd_type_wqec_byte = SLI4_CMD_REQUEUE_XRI_WQE;
249162306a36Sopenharmony_ci	return 0;
249262306a36Sopenharmony_ci}
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_ciint
249562306a36Sopenharmony_cisli_fc_process_link_attention(struct sli4 *sli4, void *acqe)
249662306a36Sopenharmony_ci{
249762306a36Sopenharmony_ci	struct sli4_link_attention *link_attn = acqe;
249862306a36Sopenharmony_ci	struct sli4_link_event event = { 0 };
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	efc_log_info(sli4, "link=%d attn_type=%#x top=%#x speed=%#x pfault=%#x\n",
250162306a36Sopenharmony_ci		     link_attn->link_number, link_attn->attn_type,
250262306a36Sopenharmony_ci		     link_attn->topology, link_attn->port_speed,
250362306a36Sopenharmony_ci		     link_attn->port_fault);
250462306a36Sopenharmony_ci	efc_log_info(sli4, "shared_lnk_status=%#x logl_lnk_speed=%#x evttag=%#x\n",
250562306a36Sopenharmony_ci		     link_attn->shared_link_status,
250662306a36Sopenharmony_ci		     le16_to_cpu(link_attn->logical_link_speed),
250762306a36Sopenharmony_ci		     le32_to_cpu(link_attn->event_tag));
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci	if (!sli4->link)
251062306a36Sopenharmony_ci		return -EIO;
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci	event.medium   = SLI4_LINK_MEDIUM_FC;
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci	switch (link_attn->attn_type) {
251562306a36Sopenharmony_ci	case SLI4_LNK_ATTN_TYPE_LINK_UP:
251662306a36Sopenharmony_ci		event.status = SLI4_LINK_STATUS_UP;
251762306a36Sopenharmony_ci		break;
251862306a36Sopenharmony_ci	case SLI4_LNK_ATTN_TYPE_LINK_DOWN:
251962306a36Sopenharmony_ci		event.status = SLI4_LINK_STATUS_DOWN;
252062306a36Sopenharmony_ci		break;
252162306a36Sopenharmony_ci	case SLI4_LNK_ATTN_TYPE_NO_HARD_ALPA:
252262306a36Sopenharmony_ci		efc_log_info(sli4, "attn_type: no hard alpa\n");
252362306a36Sopenharmony_ci		event.status = SLI4_LINK_STATUS_NO_ALPA;
252462306a36Sopenharmony_ci		break;
252562306a36Sopenharmony_ci	default:
252662306a36Sopenharmony_ci		efc_log_info(sli4, "attn_type: unknown\n");
252762306a36Sopenharmony_ci		break;
252862306a36Sopenharmony_ci	}
252962306a36Sopenharmony_ci
253062306a36Sopenharmony_ci	switch (link_attn->event_type) {
253162306a36Sopenharmony_ci	case SLI4_EVENT_LINK_ATTENTION:
253262306a36Sopenharmony_ci		break;
253362306a36Sopenharmony_ci	case SLI4_EVENT_SHARED_LINK_ATTENTION:
253462306a36Sopenharmony_ci		efc_log_info(sli4, "event_type: FC shared link event\n");
253562306a36Sopenharmony_ci		break;
253662306a36Sopenharmony_ci	default:
253762306a36Sopenharmony_ci		efc_log_info(sli4, "event_type: unknown\n");
253862306a36Sopenharmony_ci		break;
253962306a36Sopenharmony_ci	}
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci	switch (link_attn->topology) {
254262306a36Sopenharmony_ci	case SLI4_LNK_ATTN_P2P:
254362306a36Sopenharmony_ci		event.topology = SLI4_LINK_TOPO_NON_FC_AL;
254462306a36Sopenharmony_ci		break;
254562306a36Sopenharmony_ci	case SLI4_LNK_ATTN_FC_AL:
254662306a36Sopenharmony_ci		event.topology = SLI4_LINK_TOPO_FC_AL;
254762306a36Sopenharmony_ci		break;
254862306a36Sopenharmony_ci	case SLI4_LNK_ATTN_INTERNAL_LOOPBACK:
254962306a36Sopenharmony_ci		efc_log_info(sli4, "topology Internal loopback\n");
255062306a36Sopenharmony_ci		event.topology = SLI4_LINK_TOPO_LOOPBACK_INTERNAL;
255162306a36Sopenharmony_ci		break;
255262306a36Sopenharmony_ci	case SLI4_LNK_ATTN_SERDES_LOOPBACK:
255362306a36Sopenharmony_ci		efc_log_info(sli4, "topology serdes loopback\n");
255462306a36Sopenharmony_ci		event.topology = SLI4_LINK_TOPO_LOOPBACK_EXTERNAL;
255562306a36Sopenharmony_ci		break;
255662306a36Sopenharmony_ci	default:
255762306a36Sopenharmony_ci		efc_log_info(sli4, "topology: unknown\n");
255862306a36Sopenharmony_ci		break;
255962306a36Sopenharmony_ci	}
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	event.speed = link_attn->port_speed * 1000;
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	sli4->link(sli4->link_arg, (void *)&event);
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	return 0;
256662306a36Sopenharmony_ci}
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ciint
256962306a36Sopenharmony_cisli_fc_cqe_parse(struct sli4 *sli4, struct sli4_queue *cq,
257062306a36Sopenharmony_ci		 u8 *cqe, enum sli4_qentry *etype, u16 *r_id)
257162306a36Sopenharmony_ci{
257262306a36Sopenharmony_ci	u8 code = cqe[SLI4_CQE_CODE_OFFSET];
257362306a36Sopenharmony_ci	int rc;
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	switch (code) {
257662306a36Sopenharmony_ci	case SLI4_CQE_CODE_WORK_REQUEST_COMPLETION:
257762306a36Sopenharmony_ci	{
257862306a36Sopenharmony_ci		struct sli4_fc_wcqe *wcqe = (void *)cqe;
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_ci		*etype = SLI4_QENTRY_WQ;
258162306a36Sopenharmony_ci		*r_id = le16_to_cpu(wcqe->request_tag);
258262306a36Sopenharmony_ci		rc = wcqe->status;
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci		/* Flag errors except for FCP_RSP_FAILURE */
258562306a36Sopenharmony_ci		if (rc && rc != SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE) {
258662306a36Sopenharmony_ci			efc_log_info(sli4, "WCQE: status=%#x hw_status=%#x tag=%#x\n",
258762306a36Sopenharmony_ci				     wcqe->status, wcqe->hw_status,
258862306a36Sopenharmony_ci				     le16_to_cpu(wcqe->request_tag));
258962306a36Sopenharmony_ci			efc_log_info(sli4, "w1=%#x w2=%#x xb=%d\n",
259062306a36Sopenharmony_ci				     le32_to_cpu(wcqe->wqe_specific_1),
259162306a36Sopenharmony_ci				     le32_to_cpu(wcqe->wqe_specific_2),
259262306a36Sopenharmony_ci				     (wcqe->flags & SLI4_WCQE_XB));
259362306a36Sopenharmony_ci			efc_log_info(sli4, "      %08X %08X %08X %08X\n",
259462306a36Sopenharmony_ci				     ((u32 *)cqe)[0], ((u32 *)cqe)[1],
259562306a36Sopenharmony_ci				     ((u32 *)cqe)[2], ((u32 *)cqe)[3]);
259662306a36Sopenharmony_ci		}
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci		break;
259962306a36Sopenharmony_ci	}
260062306a36Sopenharmony_ci	case SLI4_CQE_CODE_RQ_ASYNC:
260162306a36Sopenharmony_ci	{
260262306a36Sopenharmony_ci		struct sli4_fc_async_rcqe *rcqe = (void *)cqe;
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci		*etype = SLI4_QENTRY_RQ;
260562306a36Sopenharmony_ci		*r_id = le16_to_cpu(rcqe->fcfi_rq_id_word) & SLI4_RACQE_RQ_ID;
260662306a36Sopenharmony_ci		rc = rcqe->status;
260762306a36Sopenharmony_ci		break;
260862306a36Sopenharmony_ci	}
260962306a36Sopenharmony_ci	case SLI4_CQE_CODE_RQ_ASYNC_V1:
261062306a36Sopenharmony_ci	{
261162306a36Sopenharmony_ci		struct sli4_fc_async_rcqe_v1 *rcqe = (void *)cqe;
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci		*etype = SLI4_QENTRY_RQ;
261462306a36Sopenharmony_ci		*r_id = le16_to_cpu(rcqe->rq_id);
261562306a36Sopenharmony_ci		rc = rcqe->status;
261662306a36Sopenharmony_ci		break;
261762306a36Sopenharmony_ci	}
261862306a36Sopenharmony_ci	case SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD:
261962306a36Sopenharmony_ci	{
262062306a36Sopenharmony_ci		struct sli4_fc_optimized_write_cmd_cqe *optcqe = (void *)cqe;
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci		*etype = SLI4_QENTRY_OPT_WRITE_CMD;
262362306a36Sopenharmony_ci		*r_id = le16_to_cpu(optcqe->rq_id);
262462306a36Sopenharmony_ci		rc = optcqe->status;
262562306a36Sopenharmony_ci		break;
262662306a36Sopenharmony_ci	}
262762306a36Sopenharmony_ci	case SLI4_CQE_CODE_OPTIMIZED_WRITE_DATA:
262862306a36Sopenharmony_ci	{
262962306a36Sopenharmony_ci		struct sli4_fc_optimized_write_data_cqe *dcqe = (void *)cqe;
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci		*etype = SLI4_QENTRY_OPT_WRITE_DATA;
263262306a36Sopenharmony_ci		*r_id = le16_to_cpu(dcqe->xri);
263362306a36Sopenharmony_ci		rc = dcqe->status;
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_ci		/* Flag errors */
263662306a36Sopenharmony_ci		if (rc != SLI4_FC_WCQE_STATUS_SUCCESS) {
263762306a36Sopenharmony_ci			efc_log_info(sli4, "Optimized DATA CQE: status=%#x\n",
263862306a36Sopenharmony_ci				     dcqe->status);
263962306a36Sopenharmony_ci			efc_log_info(sli4, "hstat=%#x xri=%#x dpl=%#x w3=%#x xb=%d\n",
264062306a36Sopenharmony_ci				     dcqe->hw_status, le16_to_cpu(dcqe->xri),
264162306a36Sopenharmony_ci				     le32_to_cpu(dcqe->total_data_placed),
264262306a36Sopenharmony_ci				     ((u32 *)cqe)[3],
264362306a36Sopenharmony_ci				     (dcqe->flags & SLI4_OCQE_XB));
264462306a36Sopenharmony_ci		}
264562306a36Sopenharmony_ci		break;
264662306a36Sopenharmony_ci	}
264762306a36Sopenharmony_ci	case SLI4_CQE_CODE_RQ_COALESCING:
264862306a36Sopenharmony_ci	{
264962306a36Sopenharmony_ci		struct sli4_fc_coalescing_rcqe *rcqe = (void *)cqe;
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci		*etype = SLI4_QENTRY_RQ;
265262306a36Sopenharmony_ci		*r_id = le16_to_cpu(rcqe->rq_id);
265362306a36Sopenharmony_ci		rc = rcqe->status;
265462306a36Sopenharmony_ci		break;
265562306a36Sopenharmony_ci	}
265662306a36Sopenharmony_ci	case SLI4_CQE_CODE_XRI_ABORTED:
265762306a36Sopenharmony_ci	{
265862306a36Sopenharmony_ci		struct sli4_fc_xri_aborted_cqe *xa = (void *)cqe;
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_ci		*etype = SLI4_QENTRY_XABT;
266162306a36Sopenharmony_ci		*r_id = le16_to_cpu(xa->xri);
266262306a36Sopenharmony_ci		rc = 0;
266362306a36Sopenharmony_ci		break;
266462306a36Sopenharmony_ci	}
266562306a36Sopenharmony_ci	case SLI4_CQE_CODE_RELEASE_WQE:
266662306a36Sopenharmony_ci	{
266762306a36Sopenharmony_ci		struct sli4_fc_wqec *wqec = (void *)cqe;
266862306a36Sopenharmony_ci
266962306a36Sopenharmony_ci		*etype = SLI4_QENTRY_WQ_RELEASE;
267062306a36Sopenharmony_ci		*r_id = le16_to_cpu(wqec->wq_id);
267162306a36Sopenharmony_ci		rc = 0;
267262306a36Sopenharmony_ci		break;
267362306a36Sopenharmony_ci	}
267462306a36Sopenharmony_ci	default:
267562306a36Sopenharmony_ci		efc_log_info(sli4, "CQE completion code %d not handled\n",
267662306a36Sopenharmony_ci			     code);
267762306a36Sopenharmony_ci		*etype = SLI4_QENTRY_MAX;
267862306a36Sopenharmony_ci		*r_id = U16_MAX;
267962306a36Sopenharmony_ci		rc = -EINVAL;
268062306a36Sopenharmony_ci	}
268162306a36Sopenharmony_ci
268262306a36Sopenharmony_ci	return rc;
268362306a36Sopenharmony_ci}
268462306a36Sopenharmony_ci
268562306a36Sopenharmony_ciu32
268662306a36Sopenharmony_cisli_fc_response_length(struct sli4 *sli4, u8 *cqe)
268762306a36Sopenharmony_ci{
268862306a36Sopenharmony_ci	struct sli4_fc_wcqe *wcqe = (void *)cqe;
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci	return le32_to_cpu(wcqe->wqe_specific_1);
269162306a36Sopenharmony_ci}
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_ciu32
269462306a36Sopenharmony_cisli_fc_io_length(struct sli4 *sli4, u8 *cqe)
269562306a36Sopenharmony_ci{
269662306a36Sopenharmony_ci	struct sli4_fc_wcqe *wcqe = (void *)cqe;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci	return le32_to_cpu(wcqe->wqe_specific_1);
269962306a36Sopenharmony_ci}
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ciint
270262306a36Sopenharmony_cisli_fc_els_did(struct sli4 *sli4, u8 *cqe, u32 *d_id)
270362306a36Sopenharmony_ci{
270462306a36Sopenharmony_ci	struct sli4_fc_wcqe *wcqe = (void *)cqe;
270562306a36Sopenharmony_ci
270662306a36Sopenharmony_ci	*d_id = 0;
270762306a36Sopenharmony_ci
270862306a36Sopenharmony_ci	if (wcqe->status)
270962306a36Sopenharmony_ci		return -EIO;
271062306a36Sopenharmony_ci	*d_id = le32_to_cpu(wcqe->wqe_specific_2) & 0x00ffffff;
271162306a36Sopenharmony_ci	return 0;
271262306a36Sopenharmony_ci}
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_ciu32
271562306a36Sopenharmony_cisli_fc_ext_status(struct sli4 *sli4, u8 *cqe)
271662306a36Sopenharmony_ci{
271762306a36Sopenharmony_ci	struct sli4_fc_wcqe *wcqe = (void *)cqe;
271862306a36Sopenharmony_ci	u32	mask;
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci	switch (wcqe->status) {
272162306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE:
272262306a36Sopenharmony_ci		mask = U32_MAX;
272362306a36Sopenharmony_ci		break;
272462306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
272562306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_CMD_REJECT:
272662306a36Sopenharmony_ci		mask = 0xff;
272762306a36Sopenharmony_ci		break;
272862306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_NPORT_RJT:
272962306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_FABRIC_RJT:
273062306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_NPORT_BSY:
273162306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_FABRIC_BSY:
273262306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_LS_RJT:
273362306a36Sopenharmony_ci		mask = U32_MAX;
273462306a36Sopenharmony_ci		break;
273562306a36Sopenharmony_ci	case SLI4_FC_WCQE_STATUS_DI_ERROR:
273662306a36Sopenharmony_ci		mask = U32_MAX;
273762306a36Sopenharmony_ci		break;
273862306a36Sopenharmony_ci	default:
273962306a36Sopenharmony_ci		mask = 0;
274062306a36Sopenharmony_ci	}
274162306a36Sopenharmony_ci
274262306a36Sopenharmony_ci	return le32_to_cpu(wcqe->wqe_specific_2) & mask;
274362306a36Sopenharmony_ci}
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ciint
274662306a36Sopenharmony_cisli_fc_rqe_rqid_and_index(struct sli4 *sli4, u8 *cqe, u16 *rq_id, u32 *index)
274762306a36Sopenharmony_ci{
274862306a36Sopenharmony_ci	int rc = -EIO;
274962306a36Sopenharmony_ci	u8 code = 0;
275062306a36Sopenharmony_ci	u16 rq_element_index;
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	*rq_id = 0;
275362306a36Sopenharmony_ci	*index = U32_MAX;
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_ci	code = cqe[SLI4_CQE_CODE_OFFSET];
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_ci	/* Retrieve the RQ index from the completion */
275862306a36Sopenharmony_ci	if (code == SLI4_CQE_CODE_RQ_ASYNC) {
275962306a36Sopenharmony_ci		struct sli4_fc_async_rcqe *rcqe = (void *)cqe;
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci		*rq_id = le16_to_cpu(rcqe->fcfi_rq_id_word) & SLI4_RACQE_RQ_ID;
276262306a36Sopenharmony_ci		rq_element_index =
276362306a36Sopenharmony_ci		le16_to_cpu(rcqe->rq_elmt_indx_word) & SLI4_RACQE_RQ_EL_INDX;
276462306a36Sopenharmony_ci		*index = rq_element_index;
276562306a36Sopenharmony_ci		if (rcqe->status == SLI4_FC_ASYNC_RQ_SUCCESS) {
276662306a36Sopenharmony_ci			rc = 0;
276762306a36Sopenharmony_ci		} else {
276862306a36Sopenharmony_ci			rc = rcqe->status;
276962306a36Sopenharmony_ci			efc_log_info(sli4, "status=%02x (%s) rq_id=%d\n",
277062306a36Sopenharmony_ci				     rcqe->status,
277162306a36Sopenharmony_ci				     sli_fc_get_status_string(rcqe->status),
277262306a36Sopenharmony_ci				     le16_to_cpu(rcqe->fcfi_rq_id_word) &
277362306a36Sopenharmony_ci				     SLI4_RACQE_RQ_ID);
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci			efc_log_info(sli4, "pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
277662306a36Sopenharmony_ci				     le16_to_cpu(rcqe->data_placement_length),
277762306a36Sopenharmony_ci				     rcqe->sof_byte, rcqe->eof_byte,
277862306a36Sopenharmony_ci				     rcqe->hdpl_byte & SLI4_RACQE_HDPL);
277962306a36Sopenharmony_ci		}
278062306a36Sopenharmony_ci	} else if (code == SLI4_CQE_CODE_RQ_ASYNC_V1) {
278162306a36Sopenharmony_ci		struct sli4_fc_async_rcqe_v1 *rcqe_v1 = (void *)cqe;
278262306a36Sopenharmony_ci
278362306a36Sopenharmony_ci		*rq_id = le16_to_cpu(rcqe_v1->rq_id);
278462306a36Sopenharmony_ci		rq_element_index =
278562306a36Sopenharmony_ci			(le16_to_cpu(rcqe_v1->rq_elmt_indx_word) &
278662306a36Sopenharmony_ci			 SLI4_RACQE_RQ_EL_INDX);
278762306a36Sopenharmony_ci		*index = rq_element_index;
278862306a36Sopenharmony_ci		if (rcqe_v1->status == SLI4_FC_ASYNC_RQ_SUCCESS) {
278962306a36Sopenharmony_ci			rc = 0;
279062306a36Sopenharmony_ci		} else {
279162306a36Sopenharmony_ci			rc = rcqe_v1->status;
279262306a36Sopenharmony_ci			efc_log_info(sli4, "status=%02x (%s) rq_id=%d, index=%x\n",
279362306a36Sopenharmony_ci				     rcqe_v1->status,
279462306a36Sopenharmony_ci				     sli_fc_get_status_string(rcqe_v1->status),
279562306a36Sopenharmony_ci				     le16_to_cpu(rcqe_v1->rq_id), rq_element_index);
279662306a36Sopenharmony_ci
279762306a36Sopenharmony_ci			efc_log_info(sli4, "pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
279862306a36Sopenharmony_ci				     le16_to_cpu(rcqe_v1->data_placement_length),
279962306a36Sopenharmony_ci			rcqe_v1->sof_byte, rcqe_v1->eof_byte,
280062306a36Sopenharmony_ci			rcqe_v1->hdpl_byte & SLI4_RACQE_HDPL);
280162306a36Sopenharmony_ci		}
280262306a36Sopenharmony_ci	} else if (code == SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD) {
280362306a36Sopenharmony_ci		struct sli4_fc_optimized_write_cmd_cqe *optcqe = (void *)cqe;
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci		*rq_id = le16_to_cpu(optcqe->rq_id);
280662306a36Sopenharmony_ci		*index = le16_to_cpu(optcqe->w1) & SLI4_OCQE_RQ_EL_INDX;
280762306a36Sopenharmony_ci		if (optcqe->status == SLI4_FC_ASYNC_RQ_SUCCESS) {
280862306a36Sopenharmony_ci			rc = 0;
280962306a36Sopenharmony_ci		} else {
281062306a36Sopenharmony_ci			rc = optcqe->status;
281162306a36Sopenharmony_ci			efc_log_info(sli4, "stat=%02x (%s) rqid=%d, idx=%x pdpl=%x\n",
281262306a36Sopenharmony_ci				     optcqe->status,
281362306a36Sopenharmony_ci				     sli_fc_get_status_string(optcqe->status),
281462306a36Sopenharmony_ci				     le16_to_cpu(optcqe->rq_id), *index,
281562306a36Sopenharmony_ci				     le16_to_cpu(optcqe->data_placement_length));
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ci			efc_log_info(sli4, "hdpl=%x oox=%d agxr=%d xri=0x%x rpi=%x\n",
281862306a36Sopenharmony_ci				     (optcqe->hdpl_vld & SLI4_OCQE_HDPL),
281962306a36Sopenharmony_ci				     (optcqe->flags1 & SLI4_OCQE_OOX),
282062306a36Sopenharmony_ci				     (optcqe->flags1 & SLI4_OCQE_AGXR),
282162306a36Sopenharmony_ci				     optcqe->xri, le16_to_cpu(optcqe->rpi));
282262306a36Sopenharmony_ci		}
282362306a36Sopenharmony_ci	} else if (code == SLI4_CQE_CODE_RQ_COALESCING) {
282462306a36Sopenharmony_ci		struct sli4_fc_coalescing_rcqe  *rcqe = (void *)cqe;
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_ci		rq_element_index = (le16_to_cpu(rcqe->rq_elmt_indx_word) &
282762306a36Sopenharmony_ci				    SLI4_RCQE_RQ_EL_INDX);
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci		*rq_id = le16_to_cpu(rcqe->rq_id);
283062306a36Sopenharmony_ci		if (rcqe->status == SLI4_FC_COALESCE_RQ_SUCCESS) {
283162306a36Sopenharmony_ci			*index = rq_element_index;
283262306a36Sopenharmony_ci			rc = 0;
283362306a36Sopenharmony_ci		} else {
283462306a36Sopenharmony_ci			*index = U32_MAX;
283562306a36Sopenharmony_ci			rc = rcqe->status;
283662306a36Sopenharmony_ci
283762306a36Sopenharmony_ci			efc_log_info(sli4, "stat=%02x (%s) rq_id=%d, idx=%x\n",
283862306a36Sopenharmony_ci				     rcqe->status,
283962306a36Sopenharmony_ci				     sli_fc_get_status_string(rcqe->status),
284062306a36Sopenharmony_ci				     le16_to_cpu(rcqe->rq_id), rq_element_index);
284162306a36Sopenharmony_ci			efc_log_info(sli4, "rq_id=%#x sdpl=%x\n",
284262306a36Sopenharmony_ci				     le16_to_cpu(rcqe->rq_id),
284362306a36Sopenharmony_ci				     le16_to_cpu(rcqe->seq_placement_length));
284462306a36Sopenharmony_ci		}
284562306a36Sopenharmony_ci	} else {
284662306a36Sopenharmony_ci		struct sli4_fc_async_rcqe *rcqe = (void *)cqe;
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci		*index = U32_MAX;
284962306a36Sopenharmony_ci		rc = rcqe->status;
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci		efc_log_info(sli4, "status=%02x rq_id=%d, index=%x pdpl=%x\n",
285262306a36Sopenharmony_ci			     rcqe->status,
285362306a36Sopenharmony_ci			     le16_to_cpu(rcqe->fcfi_rq_id_word) & SLI4_RACQE_RQ_ID,
285462306a36Sopenharmony_ci			     (le16_to_cpu(rcqe->rq_elmt_indx_word) & SLI4_RACQE_RQ_EL_INDX),
285562306a36Sopenharmony_ci			     le16_to_cpu(rcqe->data_placement_length));
285662306a36Sopenharmony_ci		efc_log_info(sli4, "sof=%02x eof=%02x hdpl=%x\n",
285762306a36Sopenharmony_ci			     rcqe->sof_byte, rcqe->eof_byte,
285862306a36Sopenharmony_ci			     rcqe->hdpl_byte & SLI4_RACQE_HDPL);
285962306a36Sopenharmony_ci	}
286062306a36Sopenharmony_ci
286162306a36Sopenharmony_ci	return rc;
286262306a36Sopenharmony_ci}
286362306a36Sopenharmony_ci
286462306a36Sopenharmony_cistatic int
286562306a36Sopenharmony_cisli_bmbx_wait(struct sli4 *sli4, u32 msec)
286662306a36Sopenharmony_ci{
286762306a36Sopenharmony_ci	u32 val;
286862306a36Sopenharmony_ci	unsigned long end;
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_ci	/* Wait for the bootstrap mailbox to report "ready" */
287162306a36Sopenharmony_ci	end = jiffies + msecs_to_jiffies(msec);
287262306a36Sopenharmony_ci	do {
287362306a36Sopenharmony_ci		val = readl(sli4->reg[0] + SLI4_BMBX_REG);
287462306a36Sopenharmony_ci		if (val & SLI4_BMBX_RDY)
287562306a36Sopenharmony_ci			return 0;
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci		usleep_range(1000, 2000);
287862306a36Sopenharmony_ci	} while (time_before(jiffies, end));
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	return -EIO;
288162306a36Sopenharmony_ci}
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_cistatic int
288462306a36Sopenharmony_cisli_bmbx_write(struct sli4 *sli4)
288562306a36Sopenharmony_ci{
288662306a36Sopenharmony_ci	u32 val;
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ci	/* write buffer location to bootstrap mailbox register */
288962306a36Sopenharmony_ci	val = sli_bmbx_write_hi(sli4->bmbx.phys);
289062306a36Sopenharmony_ci	writel(val, (sli4->reg[0] + SLI4_BMBX_REG));
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci	if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
289362306a36Sopenharmony_ci		efc_log_crit(sli4, "BMBX WRITE_HI failed\n");
289462306a36Sopenharmony_ci		return -EIO;
289562306a36Sopenharmony_ci	}
289662306a36Sopenharmony_ci	val = sli_bmbx_write_lo(sli4->bmbx.phys);
289762306a36Sopenharmony_ci	writel(val, (sli4->reg[0] + SLI4_BMBX_REG));
289862306a36Sopenharmony_ci
289962306a36Sopenharmony_ci	/* wait for SLI Port to set ready bit */
290062306a36Sopenharmony_ci	return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC);
290162306a36Sopenharmony_ci}
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ciint
290462306a36Sopenharmony_cisli_bmbx_command(struct sli4 *sli4)
290562306a36Sopenharmony_ci{
290662306a36Sopenharmony_ci	void *cqe = (u8 *)sli4->bmbx.virt + SLI4_BMBX_SIZE;
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	if (sli_fw_error_status(sli4) > 0) {
290962306a36Sopenharmony_ci		efc_log_crit(sli4, "Chip is in an error state -Mailbox command rejected");
291062306a36Sopenharmony_ci		efc_log_crit(sli4, " status=%#x error1=%#x error2=%#x\n",
291162306a36Sopenharmony_ci			     sli_reg_read_status(sli4),
291262306a36Sopenharmony_ci			     sli_reg_read_err1(sli4),
291362306a36Sopenharmony_ci			     sli_reg_read_err2(sli4));
291462306a36Sopenharmony_ci		return -EIO;
291562306a36Sopenharmony_ci	}
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci	/* Submit a command to the bootstrap mailbox and check the status */
291862306a36Sopenharmony_ci	if (sli_bmbx_write(sli4)) {
291962306a36Sopenharmony_ci		efc_log_crit(sli4, "bmbx write fail phys=%pad reg=%#x\n",
292062306a36Sopenharmony_ci			     &sli4->bmbx.phys, readl(sli4->reg[0] + SLI4_BMBX_REG));
292162306a36Sopenharmony_ci		return -EIO;
292262306a36Sopenharmony_ci	}
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	/* check completion queue entry status */
292562306a36Sopenharmony_ci	if (le32_to_cpu(((struct sli4_mcqe *)cqe)->dw3_flags) &
292662306a36Sopenharmony_ci	    SLI4_MCQE_VALID) {
292762306a36Sopenharmony_ci		return sli_cqe_mq(sli4, cqe);
292862306a36Sopenharmony_ci	}
292962306a36Sopenharmony_ci	efc_log_crit(sli4, "invalid or wrong type\n");
293062306a36Sopenharmony_ci	return -EIO;
293162306a36Sopenharmony_ci}
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ciint
293462306a36Sopenharmony_cisli_cmd_config_link(struct sli4 *sli4, void *buf)
293562306a36Sopenharmony_ci{
293662306a36Sopenharmony_ci	struct sli4_cmd_config_link *config_link = buf;
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	config_link->hdr.command = SLI4_MBX_CMD_CONFIG_LINK;
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci	/* Port interprets zero in a field as "use default value" */
294362306a36Sopenharmony_ci
294462306a36Sopenharmony_ci	return 0;
294562306a36Sopenharmony_ci}
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ciint
294862306a36Sopenharmony_cisli_cmd_down_link(struct sli4 *sli4, void *buf)
294962306a36Sopenharmony_ci{
295062306a36Sopenharmony_ci	struct sli4_mbox_command_header *hdr = buf;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci	hdr->command = SLI4_MBX_CMD_DOWN_LINK;
295562306a36Sopenharmony_ci
295662306a36Sopenharmony_ci	/* Port interprets zero in a field as "use default value" */
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	return 0;
295962306a36Sopenharmony_ci}
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_ciint
296262306a36Sopenharmony_cisli_cmd_dump_type4(struct sli4 *sli4, void *buf, u16 wki)
296362306a36Sopenharmony_ci{
296462306a36Sopenharmony_ci	struct sli4_cmd_dump4 *cmd = buf;
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	cmd->hdr.command = SLI4_MBX_CMD_DUMP;
296962306a36Sopenharmony_ci	cmd->type_dword = cpu_to_le32(0x4);
297062306a36Sopenharmony_ci	cmd->wki_selection = cpu_to_le16(wki);
297162306a36Sopenharmony_ci	return 0;
297262306a36Sopenharmony_ci}
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ciint
297562306a36Sopenharmony_cisli_cmd_common_read_transceiver_data(struct sli4 *sli4, void *buf, u32 page_num,
297662306a36Sopenharmony_ci				     struct efc_dma *dma)
297762306a36Sopenharmony_ci{
297862306a36Sopenharmony_ci	struct sli4_rqst_cmn_read_transceiver_data *req = NULL;
297962306a36Sopenharmony_ci	u32 psize;
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_ci	if (!dma)
298262306a36Sopenharmony_ci		psize = SLI4_CFG_PYLD_LENGTH(cmn_read_transceiver_data);
298362306a36Sopenharmony_ci	else
298462306a36Sopenharmony_ci		psize = dma->size;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, buf, psize, dma);
298762306a36Sopenharmony_ci	if (!req)
298862306a36Sopenharmony_ci		return -EIO;
298962306a36Sopenharmony_ci
299062306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_CMN_READ_TRANS_DATA,
299162306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
299262306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_read_transceiver_data));
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_ci	req->page_number = cpu_to_le32(page_num);
299562306a36Sopenharmony_ci	req->port = cpu_to_le32(sli4->port_number);
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ci	return 0;
299862306a36Sopenharmony_ci}
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ciint
300162306a36Sopenharmony_cisli_cmd_read_link_stats(struct sli4 *sli4, void *buf, u8 req_ext_counters,
300262306a36Sopenharmony_ci			u8 clear_overflow_flags,
300362306a36Sopenharmony_ci			u8 clear_all_counters)
300462306a36Sopenharmony_ci{
300562306a36Sopenharmony_ci	struct sli4_cmd_read_link_stats *cmd = buf;
300662306a36Sopenharmony_ci	u32 flags;
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_ci	cmd->hdr.command = SLI4_MBX_CMD_READ_LNK_STAT;
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_ci	flags = 0;
301362306a36Sopenharmony_ci	if (req_ext_counters)
301462306a36Sopenharmony_ci		flags |= SLI4_READ_LNKSTAT_REC;
301562306a36Sopenharmony_ci	if (clear_all_counters)
301662306a36Sopenharmony_ci		flags |= SLI4_READ_LNKSTAT_CLRC;
301762306a36Sopenharmony_ci	if (clear_overflow_flags)
301862306a36Sopenharmony_ci		flags |= SLI4_READ_LNKSTAT_CLOF;
301962306a36Sopenharmony_ci
302062306a36Sopenharmony_ci	cmd->dw1_flags = cpu_to_le32(flags);
302162306a36Sopenharmony_ci	return 0;
302262306a36Sopenharmony_ci}
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_ciint
302562306a36Sopenharmony_cisli_cmd_read_status(struct sli4 *sli4, void *buf, u8 clear_counters)
302662306a36Sopenharmony_ci{
302762306a36Sopenharmony_ci	struct sli4_cmd_read_status *cmd = buf;
302862306a36Sopenharmony_ci	u32 flags = 0;
302962306a36Sopenharmony_ci
303062306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci	cmd->hdr.command = SLI4_MBX_CMD_READ_STATUS;
303362306a36Sopenharmony_ci	if (clear_counters)
303462306a36Sopenharmony_ci		flags |= SLI4_READSTATUS_CLEAR_COUNTERS;
303562306a36Sopenharmony_ci	else
303662306a36Sopenharmony_ci		flags &= ~SLI4_READSTATUS_CLEAR_COUNTERS;
303762306a36Sopenharmony_ci
303862306a36Sopenharmony_ci	cmd->dw1_flags = cpu_to_le32(flags);
303962306a36Sopenharmony_ci	return 0;
304062306a36Sopenharmony_ci}
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_ciint
304362306a36Sopenharmony_cisli_cmd_init_link(struct sli4 *sli4, void *buf, u32 speed, u8 reset_alpa)
304462306a36Sopenharmony_ci{
304562306a36Sopenharmony_ci	struct sli4_cmd_init_link *init_link = buf;
304662306a36Sopenharmony_ci	u32 flags = 0;
304762306a36Sopenharmony_ci
304862306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
304962306a36Sopenharmony_ci
305062306a36Sopenharmony_ci	init_link->hdr.command = SLI4_MBX_CMD_INIT_LINK;
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci	init_link->sel_reset_al_pa_dword =
305362306a36Sopenharmony_ci				cpu_to_le32(reset_alpa);
305462306a36Sopenharmony_ci	flags &= ~SLI4_INIT_LINK_F_LOOPBACK;
305562306a36Sopenharmony_ci
305662306a36Sopenharmony_ci	init_link->link_speed_sel_code = cpu_to_le32(speed);
305762306a36Sopenharmony_ci	switch (speed) {
305862306a36Sopenharmony_ci	case SLI4_LINK_SPEED_1G:
305962306a36Sopenharmony_ci	case SLI4_LINK_SPEED_2G:
306062306a36Sopenharmony_ci	case SLI4_LINK_SPEED_4G:
306162306a36Sopenharmony_ci	case SLI4_LINK_SPEED_8G:
306262306a36Sopenharmony_ci	case SLI4_LINK_SPEED_16G:
306362306a36Sopenharmony_ci	case SLI4_LINK_SPEED_32G:
306462306a36Sopenharmony_ci	case SLI4_LINK_SPEED_64G:
306562306a36Sopenharmony_ci		flags |= SLI4_INIT_LINK_F_FIXED_SPEED;
306662306a36Sopenharmony_ci		break;
306762306a36Sopenharmony_ci	case SLI4_LINK_SPEED_10G:
306862306a36Sopenharmony_ci		efc_log_info(sli4, "unsupported FC speed %d\n", speed);
306962306a36Sopenharmony_ci		init_link->flags0 = cpu_to_le32(flags);
307062306a36Sopenharmony_ci		return -EIO;
307162306a36Sopenharmony_ci	}
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci	switch (sli4->topology) {
307462306a36Sopenharmony_ci	case SLI4_READ_CFG_TOPO_FC:
307562306a36Sopenharmony_ci		/* Attempt P2P but failover to FC-AL */
307662306a36Sopenharmony_ci		flags |= SLI4_INIT_LINK_F_FAIL_OVER;
307762306a36Sopenharmony_ci		flags |= SLI4_INIT_LINK_F_P2P_FAIL_OVER;
307862306a36Sopenharmony_ci		break;
307962306a36Sopenharmony_ci	case SLI4_READ_CFG_TOPO_FC_AL:
308062306a36Sopenharmony_ci		flags |= SLI4_INIT_LINK_F_FCAL_ONLY;
308162306a36Sopenharmony_ci		if (speed == SLI4_LINK_SPEED_16G ||
308262306a36Sopenharmony_ci		    speed == SLI4_LINK_SPEED_32G) {
308362306a36Sopenharmony_ci			efc_log_info(sli4, "unsupported FC-AL speed %d\n",
308462306a36Sopenharmony_ci				     speed);
308562306a36Sopenharmony_ci			init_link->flags0 = cpu_to_le32(flags);
308662306a36Sopenharmony_ci			return -EIO;
308762306a36Sopenharmony_ci		}
308862306a36Sopenharmony_ci		break;
308962306a36Sopenharmony_ci	case SLI4_READ_CFG_TOPO_NON_FC_AL:
309062306a36Sopenharmony_ci		flags |= SLI4_INIT_LINK_F_P2P_ONLY;
309162306a36Sopenharmony_ci		break;
309262306a36Sopenharmony_ci	default:
309362306a36Sopenharmony_ci
309462306a36Sopenharmony_ci		efc_log_info(sli4, "unsupported topology %#x\n", sli4->topology);
309562306a36Sopenharmony_ci
309662306a36Sopenharmony_ci		init_link->flags0 = cpu_to_le32(flags);
309762306a36Sopenharmony_ci		return -EIO;
309862306a36Sopenharmony_ci	}
309962306a36Sopenharmony_ci
310062306a36Sopenharmony_ci	flags &= ~SLI4_INIT_LINK_F_UNFAIR;
310162306a36Sopenharmony_ci	flags &= ~SLI4_INIT_LINK_F_NO_LIRP;
310262306a36Sopenharmony_ci	flags &= ~SLI4_INIT_LINK_F_LOOP_VALID_CHK;
310362306a36Sopenharmony_ci	flags &= ~SLI4_INIT_LINK_F_NO_LISA;
310462306a36Sopenharmony_ci	flags &= ~SLI4_INIT_LINK_F_PICK_HI_ALPA;
310562306a36Sopenharmony_ci	init_link->flags0 = cpu_to_le32(flags);
310662306a36Sopenharmony_ci
310762306a36Sopenharmony_ci	return 0;
310862306a36Sopenharmony_ci}
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ciint
311162306a36Sopenharmony_cisli_cmd_init_vfi(struct sli4 *sli4, void *buf, u16 vfi, u16 fcfi, u16 vpi)
311262306a36Sopenharmony_ci{
311362306a36Sopenharmony_ci	struct sli4_cmd_init_vfi *init_vfi = buf;
311462306a36Sopenharmony_ci	u16 flags = 0;
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
311762306a36Sopenharmony_ci
311862306a36Sopenharmony_ci	init_vfi->hdr.command = SLI4_MBX_CMD_INIT_VFI;
311962306a36Sopenharmony_ci	init_vfi->vfi = cpu_to_le16(vfi);
312062306a36Sopenharmony_ci	init_vfi->fcfi = cpu_to_le16(fcfi);
312162306a36Sopenharmony_ci
312262306a36Sopenharmony_ci	/*
312362306a36Sopenharmony_ci	 * If the VPI is valid, initialize it at the same time as
312462306a36Sopenharmony_ci	 * the VFI
312562306a36Sopenharmony_ci	 */
312662306a36Sopenharmony_ci	if (vpi != U16_MAX) {
312762306a36Sopenharmony_ci		flags |= SLI4_INIT_VFI_FLAG_VP;
312862306a36Sopenharmony_ci		init_vfi->flags0_word = cpu_to_le16(flags);
312962306a36Sopenharmony_ci		init_vfi->vpi = cpu_to_le16(vpi);
313062306a36Sopenharmony_ci	}
313162306a36Sopenharmony_ci
313262306a36Sopenharmony_ci	return 0;
313362306a36Sopenharmony_ci}
313462306a36Sopenharmony_ci
313562306a36Sopenharmony_ciint
313662306a36Sopenharmony_cisli_cmd_init_vpi(struct sli4 *sli4, void *buf, u16 vpi, u16 vfi)
313762306a36Sopenharmony_ci{
313862306a36Sopenharmony_ci	struct sli4_cmd_init_vpi *init_vpi = buf;
313962306a36Sopenharmony_ci
314062306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci	init_vpi->hdr.command = SLI4_MBX_CMD_INIT_VPI;
314362306a36Sopenharmony_ci	init_vpi->vpi = cpu_to_le16(vpi);
314462306a36Sopenharmony_ci	init_vpi->vfi = cpu_to_le16(vfi);
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci	return 0;
314762306a36Sopenharmony_ci}
314862306a36Sopenharmony_ci
314962306a36Sopenharmony_ciint
315062306a36Sopenharmony_cisli_cmd_post_xri(struct sli4 *sli4, void *buf, u16 xri_base, u16 xri_count)
315162306a36Sopenharmony_ci{
315262306a36Sopenharmony_ci	struct sli4_cmd_post_xri *post_xri = buf;
315362306a36Sopenharmony_ci	u16 xri_count_flags = 0;
315462306a36Sopenharmony_ci
315562306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_ci	post_xri->hdr.command = SLI4_MBX_CMD_POST_XRI;
315862306a36Sopenharmony_ci	post_xri->xri_base = cpu_to_le16(xri_base);
315962306a36Sopenharmony_ci	xri_count_flags = xri_count & SLI4_POST_XRI_COUNT;
316062306a36Sopenharmony_ci	xri_count_flags |= SLI4_POST_XRI_FLAG_ENX;
316162306a36Sopenharmony_ci	xri_count_flags |= SLI4_POST_XRI_FLAG_VAL;
316262306a36Sopenharmony_ci	post_xri->xri_count_flags = cpu_to_le16(xri_count_flags);
316362306a36Sopenharmony_ci
316462306a36Sopenharmony_ci	return 0;
316562306a36Sopenharmony_ci}
316662306a36Sopenharmony_ci
316762306a36Sopenharmony_ciint
316862306a36Sopenharmony_cisli_cmd_release_xri(struct sli4 *sli4, void *buf, u8 num_xri)
316962306a36Sopenharmony_ci{
317062306a36Sopenharmony_ci	struct sli4_cmd_release_xri *release_xri = buf;
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
317362306a36Sopenharmony_ci
317462306a36Sopenharmony_ci	release_xri->hdr.command = SLI4_MBX_CMD_RELEASE_XRI;
317562306a36Sopenharmony_ci	release_xri->xri_count_word = cpu_to_le16(num_xri &
317662306a36Sopenharmony_ci					SLI4_RELEASE_XRI_COUNT);
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci	return 0;
317962306a36Sopenharmony_ci}
318062306a36Sopenharmony_ci
318162306a36Sopenharmony_cistatic int
318262306a36Sopenharmony_cisli_cmd_read_config(struct sli4 *sli4, void *buf)
318362306a36Sopenharmony_ci{
318462306a36Sopenharmony_ci	struct sli4_cmd_read_config *read_config = buf;
318562306a36Sopenharmony_ci
318662306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
318762306a36Sopenharmony_ci
318862306a36Sopenharmony_ci	read_config->hdr.command = SLI4_MBX_CMD_READ_CONFIG;
318962306a36Sopenharmony_ci
319062306a36Sopenharmony_ci	return 0;
319162306a36Sopenharmony_ci}
319262306a36Sopenharmony_ci
319362306a36Sopenharmony_ciint
319462306a36Sopenharmony_cisli_cmd_read_nvparms(struct sli4 *sli4, void *buf)
319562306a36Sopenharmony_ci{
319662306a36Sopenharmony_ci	struct sli4_cmd_read_nvparms *read_nvparms = buf;
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_ci	read_nvparms->hdr.command = SLI4_MBX_CMD_READ_NVPARMS;
320162306a36Sopenharmony_ci
320262306a36Sopenharmony_ci	return 0;
320362306a36Sopenharmony_ci}
320462306a36Sopenharmony_ci
320562306a36Sopenharmony_ciint
320662306a36Sopenharmony_cisli_cmd_write_nvparms(struct sli4 *sli4, void *buf, u8 *wwpn, u8 *wwnn,
320762306a36Sopenharmony_ci		      u8 hard_alpa, u32 preferred_d_id)
320862306a36Sopenharmony_ci{
320962306a36Sopenharmony_ci	struct sli4_cmd_write_nvparms *write_nvparms = buf;
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
321262306a36Sopenharmony_ci
321362306a36Sopenharmony_ci	write_nvparms->hdr.command = SLI4_MBX_CMD_WRITE_NVPARMS;
321462306a36Sopenharmony_ci	memcpy(write_nvparms->wwpn, wwpn, 8);
321562306a36Sopenharmony_ci	memcpy(write_nvparms->wwnn, wwnn, 8);
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci	write_nvparms->hard_alpa_d_id =
321862306a36Sopenharmony_ci			cpu_to_le32((preferred_d_id << 8) | hard_alpa);
321962306a36Sopenharmony_ci	return 0;
322062306a36Sopenharmony_ci}
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_cistatic int
322362306a36Sopenharmony_cisli_cmd_read_rev(struct sli4 *sli4, void *buf, struct efc_dma *vpd)
322462306a36Sopenharmony_ci{
322562306a36Sopenharmony_ci	struct sli4_cmd_read_rev *read_rev = buf;
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	read_rev->hdr.command = SLI4_MBX_CMD_READ_REV;
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci	if (vpd && vpd->size) {
323262306a36Sopenharmony_ci		read_rev->flags0_word |= cpu_to_le16(SLI4_READ_REV_FLAG_VPD);
323362306a36Sopenharmony_ci
323462306a36Sopenharmony_ci		read_rev->available_length_dword =
323562306a36Sopenharmony_ci			cpu_to_le32(vpd->size &
323662306a36Sopenharmony_ci				    SLI4_READ_REV_AVAILABLE_LENGTH);
323762306a36Sopenharmony_ci
323862306a36Sopenharmony_ci		read_rev->hostbuf.low =
323962306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(vpd->phys));
324062306a36Sopenharmony_ci		read_rev->hostbuf.high =
324162306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(vpd->phys));
324262306a36Sopenharmony_ci	}
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ci	return 0;
324562306a36Sopenharmony_ci}
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ciint
324862306a36Sopenharmony_cisli_cmd_read_sparm64(struct sli4 *sli4, void *buf, struct efc_dma *dma, u16 vpi)
324962306a36Sopenharmony_ci{
325062306a36Sopenharmony_ci	struct sli4_cmd_read_sparm64 *read_sparm64 = buf;
325162306a36Sopenharmony_ci
325262306a36Sopenharmony_ci	if (vpi == U16_MAX) {
325362306a36Sopenharmony_ci		efc_log_err(sli4, "special VPI not supported!!!\n");
325462306a36Sopenharmony_ci		return -EIO;
325562306a36Sopenharmony_ci	}
325662306a36Sopenharmony_ci
325762306a36Sopenharmony_ci	if (!dma || !dma->phys) {
325862306a36Sopenharmony_ci		efc_log_err(sli4, "bad DMA buffer\n");
325962306a36Sopenharmony_ci		return -EIO;
326062306a36Sopenharmony_ci	}
326162306a36Sopenharmony_ci
326262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
326362306a36Sopenharmony_ci
326462306a36Sopenharmony_ci	read_sparm64->hdr.command = SLI4_MBX_CMD_READ_SPARM64;
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	read_sparm64->bde_64.bde_type_buflen =
326762306a36Sopenharmony_ci			cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
326862306a36Sopenharmony_ci				    (dma->size & SLI4_BDE_LEN_MASK));
326962306a36Sopenharmony_ci	read_sparm64->bde_64.u.data.low =
327062306a36Sopenharmony_ci			cpu_to_le32(lower_32_bits(dma->phys));
327162306a36Sopenharmony_ci	read_sparm64->bde_64.u.data.high =
327262306a36Sopenharmony_ci			cpu_to_le32(upper_32_bits(dma->phys));
327362306a36Sopenharmony_ci
327462306a36Sopenharmony_ci	read_sparm64->vpi = cpu_to_le16(vpi);
327562306a36Sopenharmony_ci
327662306a36Sopenharmony_ci	return 0;
327762306a36Sopenharmony_ci}
327862306a36Sopenharmony_ci
327962306a36Sopenharmony_ciint
328062306a36Sopenharmony_cisli_cmd_read_topology(struct sli4 *sli4, void *buf, struct efc_dma *dma)
328162306a36Sopenharmony_ci{
328262306a36Sopenharmony_ci	struct sli4_cmd_read_topology *read_topo = buf;
328362306a36Sopenharmony_ci
328462306a36Sopenharmony_ci	if (!dma || !dma->size)
328562306a36Sopenharmony_ci		return -EIO;
328662306a36Sopenharmony_ci
328762306a36Sopenharmony_ci	if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) {
328862306a36Sopenharmony_ci		efc_log_err(sli4, "loop map buffer too small %zx\n", dma->size);
328962306a36Sopenharmony_ci		return -EIO;
329062306a36Sopenharmony_ci	}
329162306a36Sopenharmony_ci
329262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
329362306a36Sopenharmony_ci
329462306a36Sopenharmony_ci	read_topo->hdr.command = SLI4_MBX_CMD_READ_TOPOLOGY;
329562306a36Sopenharmony_ci
329662306a36Sopenharmony_ci	memset(dma->virt, 0, dma->size);
329762306a36Sopenharmony_ci
329862306a36Sopenharmony_ci	read_topo->bde_loop_map.bde_type_buflen =
329962306a36Sopenharmony_ci					cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
330062306a36Sopenharmony_ci					(dma->size & SLI4_BDE_LEN_MASK));
330162306a36Sopenharmony_ci	read_topo->bde_loop_map.u.data.low  =
330262306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(dma->phys));
330362306a36Sopenharmony_ci	read_topo->bde_loop_map.u.data.high =
330462306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(dma->phys));
330562306a36Sopenharmony_ci
330662306a36Sopenharmony_ci	return 0;
330762306a36Sopenharmony_ci}
330862306a36Sopenharmony_ci
330962306a36Sopenharmony_ciint
331062306a36Sopenharmony_cisli_cmd_reg_fcfi(struct sli4 *sli4, void *buf, u16 index,
331162306a36Sopenharmony_ci		 struct sli4_cmd_rq_cfg *rq_cfg)
331262306a36Sopenharmony_ci{
331362306a36Sopenharmony_ci	struct sli4_cmd_reg_fcfi *reg_fcfi = buf;
331462306a36Sopenharmony_ci	u32 i;
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ci	reg_fcfi->hdr.command = SLI4_MBX_CMD_REG_FCFI;
331962306a36Sopenharmony_ci
332062306a36Sopenharmony_ci	reg_fcfi->fcf_index = cpu_to_le16(index);
332162306a36Sopenharmony_ci
332262306a36Sopenharmony_ci	for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
332362306a36Sopenharmony_ci		switch (i) {
332462306a36Sopenharmony_ci		case 0:
332562306a36Sopenharmony_ci			reg_fcfi->rqid0 = rq_cfg[0].rq_id;
332662306a36Sopenharmony_ci			break;
332762306a36Sopenharmony_ci		case 1:
332862306a36Sopenharmony_ci			reg_fcfi->rqid1 = rq_cfg[1].rq_id;
332962306a36Sopenharmony_ci			break;
333062306a36Sopenharmony_ci		case 2:
333162306a36Sopenharmony_ci			reg_fcfi->rqid2 = rq_cfg[2].rq_id;
333262306a36Sopenharmony_ci			break;
333362306a36Sopenharmony_ci		case 3:
333462306a36Sopenharmony_ci			reg_fcfi->rqid3 = rq_cfg[3].rq_id;
333562306a36Sopenharmony_ci			break;
333662306a36Sopenharmony_ci		}
333762306a36Sopenharmony_ci		reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
333862306a36Sopenharmony_ci		reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
333962306a36Sopenharmony_ci		reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
334062306a36Sopenharmony_ci		reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match;
334162306a36Sopenharmony_ci	}
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	return 0;
334462306a36Sopenharmony_ci}
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ciint
334762306a36Sopenharmony_cisli_cmd_reg_fcfi_mrq(struct sli4 *sli4, void *buf, u8 mode, u16 fcf_index,
334862306a36Sopenharmony_ci		     u8 rq_selection_policy, u8 mrq_bit_mask, u16 num_mrqs,
334962306a36Sopenharmony_ci		     struct sli4_cmd_rq_cfg *rq_cfg)
335062306a36Sopenharmony_ci{
335162306a36Sopenharmony_ci	struct sli4_cmd_reg_fcfi_mrq *reg_fcfi_mrq = buf;
335262306a36Sopenharmony_ci	u32 i;
335362306a36Sopenharmony_ci	u32 mrq_flags = 0;
335462306a36Sopenharmony_ci
335562306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_ci	reg_fcfi_mrq->hdr.command = SLI4_MBX_CMD_REG_FCFI_MRQ;
335862306a36Sopenharmony_ci	if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) {
335962306a36Sopenharmony_ci		reg_fcfi_mrq->fcf_index = cpu_to_le16(fcf_index);
336062306a36Sopenharmony_ci		goto done;
336162306a36Sopenharmony_ci	}
336262306a36Sopenharmony_ci
336362306a36Sopenharmony_ci	reg_fcfi_mrq->dw8_vlan = cpu_to_le32(SLI4_REGFCFI_MRQ_MODE);
336462306a36Sopenharmony_ci
336562306a36Sopenharmony_ci	for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
336662306a36Sopenharmony_ci		reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
336762306a36Sopenharmony_ci		reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
336862306a36Sopenharmony_ci		reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
336962306a36Sopenharmony_ci		reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match;
337062306a36Sopenharmony_ci
337162306a36Sopenharmony_ci		switch (i) {
337262306a36Sopenharmony_ci		case 3:
337362306a36Sopenharmony_ci			reg_fcfi_mrq->rqid3 = rq_cfg[i].rq_id;
337462306a36Sopenharmony_ci			break;
337562306a36Sopenharmony_ci		case 2:
337662306a36Sopenharmony_ci			reg_fcfi_mrq->rqid2 = rq_cfg[i].rq_id;
337762306a36Sopenharmony_ci			break;
337862306a36Sopenharmony_ci		case 1:
337962306a36Sopenharmony_ci			reg_fcfi_mrq->rqid1 = rq_cfg[i].rq_id;
338062306a36Sopenharmony_ci			break;
338162306a36Sopenharmony_ci		case 0:
338262306a36Sopenharmony_ci			reg_fcfi_mrq->rqid0 = rq_cfg[i].rq_id;
338362306a36Sopenharmony_ci			break;
338462306a36Sopenharmony_ci		}
338562306a36Sopenharmony_ci	}
338662306a36Sopenharmony_ci
338762306a36Sopenharmony_ci	mrq_flags = num_mrqs & SLI4_REGFCFI_MRQ_MASK_NUM_PAIRS;
338862306a36Sopenharmony_ci	mrq_flags |= (mrq_bit_mask << 8);
338962306a36Sopenharmony_ci	mrq_flags |= (rq_selection_policy << 12);
339062306a36Sopenharmony_ci	reg_fcfi_mrq->dw9_mrqflags = cpu_to_le32(mrq_flags);
339162306a36Sopenharmony_cidone:
339262306a36Sopenharmony_ci	return 0;
339362306a36Sopenharmony_ci}
339462306a36Sopenharmony_ci
339562306a36Sopenharmony_ciint
339662306a36Sopenharmony_cisli_cmd_reg_rpi(struct sli4 *sli4, void *buf, u32 rpi, u32 vpi, u32 fc_id,
339762306a36Sopenharmony_ci		struct efc_dma *dma, u8 update, u8 enable_t10_pi)
339862306a36Sopenharmony_ci{
339962306a36Sopenharmony_ci	struct sli4_cmd_reg_rpi *reg_rpi = buf;
340062306a36Sopenharmony_ci	u32 rportid_flags = 0;
340162306a36Sopenharmony_ci
340262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_ci	reg_rpi->hdr.command = SLI4_MBX_CMD_REG_RPI;
340562306a36Sopenharmony_ci
340662306a36Sopenharmony_ci	reg_rpi->rpi = cpu_to_le16(rpi);
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_ci	rportid_flags = fc_id & SLI4_REGRPI_REMOTE_N_PORTID;
340962306a36Sopenharmony_ci
341062306a36Sopenharmony_ci	if (update)
341162306a36Sopenharmony_ci		rportid_flags |= SLI4_REGRPI_UPD;
341262306a36Sopenharmony_ci	else
341362306a36Sopenharmony_ci		rportid_flags &= ~SLI4_REGRPI_UPD;
341462306a36Sopenharmony_ci
341562306a36Sopenharmony_ci	if (enable_t10_pi)
341662306a36Sopenharmony_ci		rportid_flags |= SLI4_REGRPI_ETOW;
341762306a36Sopenharmony_ci	else
341862306a36Sopenharmony_ci		rportid_flags &= ~SLI4_REGRPI_ETOW;
341962306a36Sopenharmony_ci
342062306a36Sopenharmony_ci	reg_rpi->dw2_rportid_flags = cpu_to_le32(rportid_flags);
342162306a36Sopenharmony_ci
342262306a36Sopenharmony_ci	reg_rpi->bde_64.bde_type_buflen =
342362306a36Sopenharmony_ci		cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
342462306a36Sopenharmony_ci			    (SLI4_REG_RPI_BUF_LEN & SLI4_BDE_LEN_MASK));
342562306a36Sopenharmony_ci	reg_rpi->bde_64.u.data.low  =
342662306a36Sopenharmony_ci		cpu_to_le32(lower_32_bits(dma->phys));
342762306a36Sopenharmony_ci	reg_rpi->bde_64.u.data.high =
342862306a36Sopenharmony_ci		cpu_to_le32(upper_32_bits(dma->phys));
342962306a36Sopenharmony_ci
343062306a36Sopenharmony_ci	reg_rpi->vpi = cpu_to_le16(vpi);
343162306a36Sopenharmony_ci
343262306a36Sopenharmony_ci	return 0;
343362306a36Sopenharmony_ci}
343462306a36Sopenharmony_ci
343562306a36Sopenharmony_ciint
343662306a36Sopenharmony_cisli_cmd_reg_vfi(struct sli4 *sli4, void *buf, size_t size,
343762306a36Sopenharmony_ci		u16 vfi, u16 fcfi, struct efc_dma dma,
343862306a36Sopenharmony_ci		u16 vpi, __be64 sli_wwpn, u32 fc_id)
343962306a36Sopenharmony_ci{
344062306a36Sopenharmony_ci	struct sli4_cmd_reg_vfi *reg_vfi = buf;
344162306a36Sopenharmony_ci
344262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
344362306a36Sopenharmony_ci
344462306a36Sopenharmony_ci	reg_vfi->hdr.command = SLI4_MBX_CMD_REG_VFI;
344562306a36Sopenharmony_ci
344662306a36Sopenharmony_ci	reg_vfi->vfi = cpu_to_le16(vfi);
344762306a36Sopenharmony_ci
344862306a36Sopenharmony_ci	reg_vfi->fcfi = cpu_to_le16(fcfi);
344962306a36Sopenharmony_ci
345062306a36Sopenharmony_ci	reg_vfi->sparm.bde_type_buflen =
345162306a36Sopenharmony_ci		cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
345262306a36Sopenharmony_ci			    (SLI4_REG_RPI_BUF_LEN & SLI4_BDE_LEN_MASK));
345362306a36Sopenharmony_ci	reg_vfi->sparm.u.data.low  =
345462306a36Sopenharmony_ci		cpu_to_le32(lower_32_bits(dma.phys));
345562306a36Sopenharmony_ci	reg_vfi->sparm.u.data.high =
345662306a36Sopenharmony_ci		cpu_to_le32(upper_32_bits(dma.phys));
345762306a36Sopenharmony_ci
345862306a36Sopenharmony_ci	reg_vfi->e_d_tov = cpu_to_le32(sli4->e_d_tov);
345962306a36Sopenharmony_ci	reg_vfi->r_a_tov = cpu_to_le32(sli4->r_a_tov);
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_ci	reg_vfi->dw0w1_flags |= cpu_to_le16(SLI4_REGVFI_VP);
346262306a36Sopenharmony_ci	reg_vfi->vpi = cpu_to_le16(vpi);
346362306a36Sopenharmony_ci	memcpy(reg_vfi->wwpn, &sli_wwpn, sizeof(reg_vfi->wwpn));
346462306a36Sopenharmony_ci	reg_vfi->dw10_lportid_flags = cpu_to_le32(fc_id);
346562306a36Sopenharmony_ci
346662306a36Sopenharmony_ci	return 0;
346762306a36Sopenharmony_ci}
346862306a36Sopenharmony_ci
346962306a36Sopenharmony_ciint
347062306a36Sopenharmony_cisli_cmd_reg_vpi(struct sli4 *sli4, void *buf, u32 fc_id, __be64 sli_wwpn,
347162306a36Sopenharmony_ci		u16 vpi, u16 vfi, bool update)
347262306a36Sopenharmony_ci{
347362306a36Sopenharmony_ci	struct sli4_cmd_reg_vpi *reg_vpi = buf;
347462306a36Sopenharmony_ci	u32 flags = 0;
347562306a36Sopenharmony_ci
347662306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
347762306a36Sopenharmony_ci
347862306a36Sopenharmony_ci	reg_vpi->hdr.command = SLI4_MBX_CMD_REG_VPI;
347962306a36Sopenharmony_ci
348062306a36Sopenharmony_ci	flags = (fc_id & SLI4_REGVPI_LOCAL_N_PORTID);
348162306a36Sopenharmony_ci	if (update)
348262306a36Sopenharmony_ci		flags |= SLI4_REGVPI_UPD;
348362306a36Sopenharmony_ci	else
348462306a36Sopenharmony_ci		flags &= ~SLI4_REGVPI_UPD;
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_ci	reg_vpi->dw2_lportid_flags = cpu_to_le32(flags);
348762306a36Sopenharmony_ci	memcpy(reg_vpi->wwpn, &sli_wwpn, sizeof(reg_vpi->wwpn));
348862306a36Sopenharmony_ci	reg_vpi->vpi = cpu_to_le16(vpi);
348962306a36Sopenharmony_ci	reg_vpi->vfi = cpu_to_le16(vfi);
349062306a36Sopenharmony_ci
349162306a36Sopenharmony_ci	return 0;
349262306a36Sopenharmony_ci}
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_cistatic int
349562306a36Sopenharmony_cisli_cmd_request_features(struct sli4 *sli4, void *buf, u32 features_mask,
349662306a36Sopenharmony_ci			 bool query)
349762306a36Sopenharmony_ci{
349862306a36Sopenharmony_ci	struct sli4_cmd_request_features *req_features = buf;
349962306a36Sopenharmony_ci
350062306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_ci	req_features->hdr.command = SLI4_MBX_CMD_RQST_FEATURES;
350362306a36Sopenharmony_ci
350462306a36Sopenharmony_ci	if (query)
350562306a36Sopenharmony_ci		req_features->dw1_qry = cpu_to_le32(SLI4_REQFEAT_QRY);
350662306a36Sopenharmony_ci
350762306a36Sopenharmony_ci	req_features->cmd = cpu_to_le32(features_mask);
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci	return 0;
351062306a36Sopenharmony_ci}
351162306a36Sopenharmony_ci
351262306a36Sopenharmony_ciint
351362306a36Sopenharmony_cisli_cmd_unreg_fcfi(struct sli4 *sli4, void *buf, u16 indicator)
351462306a36Sopenharmony_ci{
351562306a36Sopenharmony_ci	struct sli4_cmd_unreg_fcfi *unreg_fcfi = buf;
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_ci	unreg_fcfi->hdr.command = SLI4_MBX_CMD_UNREG_FCFI;
352062306a36Sopenharmony_ci	unreg_fcfi->fcfi = cpu_to_le16(indicator);
352162306a36Sopenharmony_ci
352262306a36Sopenharmony_ci	return 0;
352362306a36Sopenharmony_ci}
352462306a36Sopenharmony_ci
352562306a36Sopenharmony_ciint
352662306a36Sopenharmony_cisli_cmd_unreg_rpi(struct sli4 *sli4, void *buf, u16 indicator,
352762306a36Sopenharmony_ci		  enum sli4_resource which, u32 fc_id)
352862306a36Sopenharmony_ci{
352962306a36Sopenharmony_ci	struct sli4_cmd_unreg_rpi *unreg_rpi = buf;
353062306a36Sopenharmony_ci	u32 flags = 0;
353162306a36Sopenharmony_ci
353262306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
353362306a36Sopenharmony_ci
353462306a36Sopenharmony_ci	unreg_rpi->hdr.command = SLI4_MBX_CMD_UNREG_RPI;
353562306a36Sopenharmony_ci	switch (which) {
353662306a36Sopenharmony_ci	case SLI4_RSRC_RPI:
353762306a36Sopenharmony_ci		flags |= SLI4_UNREG_RPI_II_RPI;
353862306a36Sopenharmony_ci		if (fc_id == U32_MAX)
353962306a36Sopenharmony_ci			break;
354062306a36Sopenharmony_ci
354162306a36Sopenharmony_ci		flags |= SLI4_UNREG_RPI_DP;
354262306a36Sopenharmony_ci		unreg_rpi->dw2_dest_n_portid =
354362306a36Sopenharmony_ci			cpu_to_le32(fc_id & SLI4_UNREG_RPI_DEST_N_PORTID_MASK);
354462306a36Sopenharmony_ci		break;
354562306a36Sopenharmony_ci	case SLI4_RSRC_VPI:
354662306a36Sopenharmony_ci		flags |= SLI4_UNREG_RPI_II_VPI;
354762306a36Sopenharmony_ci		break;
354862306a36Sopenharmony_ci	case SLI4_RSRC_VFI:
354962306a36Sopenharmony_ci		flags |= SLI4_UNREG_RPI_II_VFI;
355062306a36Sopenharmony_ci		break;
355162306a36Sopenharmony_ci	case SLI4_RSRC_FCFI:
355262306a36Sopenharmony_ci		flags |= SLI4_UNREG_RPI_II_FCFI;
355362306a36Sopenharmony_ci		break;
355462306a36Sopenharmony_ci	default:
355562306a36Sopenharmony_ci		efc_log_info(sli4, "unknown type %#x\n", which);
355662306a36Sopenharmony_ci		return -EIO;
355762306a36Sopenharmony_ci	}
355862306a36Sopenharmony_ci
355962306a36Sopenharmony_ci	unreg_rpi->dw1w1_flags = cpu_to_le16(flags);
356062306a36Sopenharmony_ci	unreg_rpi->index = cpu_to_le16(indicator);
356162306a36Sopenharmony_ci
356262306a36Sopenharmony_ci	return 0;
356362306a36Sopenharmony_ci}
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_ciint
356662306a36Sopenharmony_cisli_cmd_unreg_vfi(struct sli4 *sli4, void *buf, u16 index, u32 which)
356762306a36Sopenharmony_ci{
356862306a36Sopenharmony_ci	struct sli4_cmd_unreg_vfi *unreg_vfi = buf;
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	unreg_vfi->hdr.command = SLI4_MBX_CMD_UNREG_VFI;
357362306a36Sopenharmony_ci	switch (which) {
357462306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_DOMAIN:
357562306a36Sopenharmony_ci		unreg_vfi->index = cpu_to_le16(index);
357662306a36Sopenharmony_ci		break;
357762306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_FCF:
357862306a36Sopenharmony_ci		unreg_vfi->index = cpu_to_le16(index);
357962306a36Sopenharmony_ci		break;
358062306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_ALL:
358162306a36Sopenharmony_ci		unreg_vfi->index = cpu_to_le16(U32_MAX);
358262306a36Sopenharmony_ci		break;
358362306a36Sopenharmony_ci	default:
358462306a36Sopenharmony_ci		return -EIO;
358562306a36Sopenharmony_ci	}
358662306a36Sopenharmony_ci
358762306a36Sopenharmony_ci	if (which != SLI4_UNREG_TYPE_DOMAIN)
358862306a36Sopenharmony_ci		unreg_vfi->dw2_flags = cpu_to_le16(SLI4_UNREG_VFI_II_FCFI);
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci	return 0;
359162306a36Sopenharmony_ci}
359262306a36Sopenharmony_ci
359362306a36Sopenharmony_ciint
359462306a36Sopenharmony_cisli_cmd_unreg_vpi(struct sli4 *sli4, void *buf, u16 indicator, u32 which)
359562306a36Sopenharmony_ci{
359662306a36Sopenharmony_ci	struct sli4_cmd_unreg_vpi *unreg_vpi = buf;
359762306a36Sopenharmony_ci	u32 flags = 0;
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_ci	memset(buf, 0, SLI4_BMBX_SIZE);
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ci	unreg_vpi->hdr.command = SLI4_MBX_CMD_UNREG_VPI;
360262306a36Sopenharmony_ci	unreg_vpi->index = cpu_to_le16(indicator);
360362306a36Sopenharmony_ci	switch (which) {
360462306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_PORT:
360562306a36Sopenharmony_ci		flags |= SLI4_UNREG_VPI_II_VPI;
360662306a36Sopenharmony_ci		break;
360762306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_DOMAIN:
360862306a36Sopenharmony_ci		flags |= SLI4_UNREG_VPI_II_VFI;
360962306a36Sopenharmony_ci		break;
361062306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_FCF:
361162306a36Sopenharmony_ci		flags |= SLI4_UNREG_VPI_II_FCFI;
361262306a36Sopenharmony_ci		break;
361362306a36Sopenharmony_ci	case SLI4_UNREG_TYPE_ALL:
361462306a36Sopenharmony_ci		/* override indicator */
361562306a36Sopenharmony_ci		unreg_vpi->index = cpu_to_le16(U32_MAX);
361662306a36Sopenharmony_ci		flags |= SLI4_UNREG_VPI_II_FCFI;
361762306a36Sopenharmony_ci		break;
361862306a36Sopenharmony_ci	default:
361962306a36Sopenharmony_ci		return -EIO;
362062306a36Sopenharmony_ci	}
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ci	unreg_vpi->dw2w0_flags = cpu_to_le16(flags);
362362306a36Sopenharmony_ci	return 0;
362462306a36Sopenharmony_ci}
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_cistatic int
362762306a36Sopenharmony_cisli_cmd_common_modify_eq_delay(struct sli4 *sli4, void *buf,
362862306a36Sopenharmony_ci			       struct sli4_queue *q, int num_q, u32 shift,
362962306a36Sopenharmony_ci			       u32 delay_mult)
363062306a36Sopenharmony_ci{
363162306a36Sopenharmony_ci	struct sli4_rqst_cmn_modify_eq_delay *req = NULL;
363262306a36Sopenharmony_ci	int i;
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, buf,
363562306a36Sopenharmony_ci			SLI4_CFG_PYLD_LENGTH(cmn_modify_eq_delay), NULL);
363662306a36Sopenharmony_ci	if (!req)
363762306a36Sopenharmony_ci		return -EIO;
363862306a36Sopenharmony_ci
363962306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_CMN_MODIFY_EQ_DELAY,
364062306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
364162306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_modify_eq_delay));
364262306a36Sopenharmony_ci	req->num_eq = cpu_to_le32(num_q);
364362306a36Sopenharmony_ci
364462306a36Sopenharmony_ci	for (i = 0; i < num_q; i++) {
364562306a36Sopenharmony_ci		req->eq_delay_record[i].eq_id = cpu_to_le32(q[i].id);
364662306a36Sopenharmony_ci		req->eq_delay_record[i].phase = cpu_to_le32(shift);
364762306a36Sopenharmony_ci		req->eq_delay_record[i].delay_multiplier =
364862306a36Sopenharmony_ci			cpu_to_le32(delay_mult);
364962306a36Sopenharmony_ci	}
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ci	return 0;
365262306a36Sopenharmony_ci}
365362306a36Sopenharmony_ci
365462306a36Sopenharmony_civoid
365562306a36Sopenharmony_cisli4_cmd_lowlevel_set_watchdog(struct sli4 *sli4, void *buf,
365662306a36Sopenharmony_ci			       size_t size, u16 timeout)
365762306a36Sopenharmony_ci{
365862306a36Sopenharmony_ci	struct sli4_rqst_lowlevel_set_watchdog *req = NULL;
365962306a36Sopenharmony_ci
366062306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, buf,
366162306a36Sopenharmony_ci			SLI4_CFG_PYLD_LENGTH(lowlevel_set_watchdog), NULL);
366262306a36Sopenharmony_ci	if (!req)
366362306a36Sopenharmony_ci		return;
366462306a36Sopenharmony_ci
366562306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_OPC_LOWLEVEL_SET_WATCHDOG,
366662306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_LOWLEVEL, CMD_V0,
366762306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(lowlevel_set_watchdog));
366862306a36Sopenharmony_ci	req->watchdog_timeout = cpu_to_le16(timeout);
366962306a36Sopenharmony_ci}
367062306a36Sopenharmony_ci
367162306a36Sopenharmony_cistatic int
367262306a36Sopenharmony_cisli_cmd_common_get_cntl_attributes(struct sli4 *sli4, void *buf,
367362306a36Sopenharmony_ci				   struct efc_dma *dma)
367462306a36Sopenharmony_ci{
367562306a36Sopenharmony_ci	struct sli4_rqst_hdr *hdr = NULL;
367662306a36Sopenharmony_ci
367762306a36Sopenharmony_ci	hdr = sli_config_cmd_init(sli4, buf, SLI4_RQST_CMDSZ(hdr), dma);
367862306a36Sopenharmony_ci	if (!hdr)
367962306a36Sopenharmony_ci		return -EIO;
368062306a36Sopenharmony_ci
368162306a36Sopenharmony_ci	hdr->opcode = SLI4_CMN_GET_CNTL_ATTRIBUTES;
368262306a36Sopenharmony_ci	hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
368362306a36Sopenharmony_ci	hdr->request_length = cpu_to_le32(dma->size);
368462306a36Sopenharmony_ci
368562306a36Sopenharmony_ci	return 0;
368662306a36Sopenharmony_ci}
368762306a36Sopenharmony_ci
368862306a36Sopenharmony_cistatic int
368962306a36Sopenharmony_cisli_cmd_common_get_cntl_addl_attributes(struct sli4 *sli4, void *buf,
369062306a36Sopenharmony_ci					struct efc_dma *dma)
369162306a36Sopenharmony_ci{
369262306a36Sopenharmony_ci	struct sli4_rqst_hdr *hdr = NULL;
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_ci	hdr = sli_config_cmd_init(sli4, buf, SLI4_RQST_CMDSZ(hdr), dma);
369562306a36Sopenharmony_ci	if (!hdr)
369662306a36Sopenharmony_ci		return -EIO;
369762306a36Sopenharmony_ci
369862306a36Sopenharmony_ci	hdr->opcode = SLI4_CMN_GET_CNTL_ADDL_ATTRS;
369962306a36Sopenharmony_ci	hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
370062306a36Sopenharmony_ci	hdr->request_length = cpu_to_le32(dma->size);
370162306a36Sopenharmony_ci
370262306a36Sopenharmony_ci	return 0;
370362306a36Sopenharmony_ci}
370462306a36Sopenharmony_ci
370562306a36Sopenharmony_ciint
370662306a36Sopenharmony_cisli_cmd_common_nop(struct sli4 *sli4, void *buf, uint64_t context)
370762306a36Sopenharmony_ci{
370862306a36Sopenharmony_ci	struct sli4_rqst_cmn_nop *nop = NULL;
370962306a36Sopenharmony_ci
371062306a36Sopenharmony_ci	nop = sli_config_cmd_init(sli4, buf, SLI4_CFG_PYLD_LENGTH(cmn_nop),
371162306a36Sopenharmony_ci				  NULL);
371262306a36Sopenharmony_ci	if (!nop)
371362306a36Sopenharmony_ci		return -EIO;
371462306a36Sopenharmony_ci
371562306a36Sopenharmony_ci	sli_cmd_fill_hdr(&nop->hdr, SLI4_CMN_NOP, SLI4_SUBSYSTEM_COMMON,
371662306a36Sopenharmony_ci			 CMD_V0, SLI4_RQST_PYLD_LEN(cmn_nop));
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci	memcpy(&nop->context, &context, sizeof(context));
371962306a36Sopenharmony_ci
372062306a36Sopenharmony_ci	return 0;
372162306a36Sopenharmony_ci}
372262306a36Sopenharmony_ci
372362306a36Sopenharmony_ciint
372462306a36Sopenharmony_cisli_cmd_common_get_resource_extent_info(struct sli4 *sli4, void *buf, u16 rtype)
372562306a36Sopenharmony_ci{
372662306a36Sopenharmony_ci	struct sli4_rqst_cmn_get_resource_extent_info *ext = NULL;
372762306a36Sopenharmony_ci
372862306a36Sopenharmony_ci	ext = sli_config_cmd_init(sli4, buf,
372962306a36Sopenharmony_ci			SLI4_RQST_CMDSZ(cmn_get_resource_extent_info), NULL);
373062306a36Sopenharmony_ci	if (!ext)
373162306a36Sopenharmony_ci		return -EIO;
373262306a36Sopenharmony_ci
373362306a36Sopenharmony_ci	sli_cmd_fill_hdr(&ext->hdr, SLI4_CMN_GET_RSC_EXTENT_INFO,
373462306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
373562306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_get_resource_extent_info));
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_ci	ext->resource_type = cpu_to_le16(rtype);
373862306a36Sopenharmony_ci
373962306a36Sopenharmony_ci	return 0;
374062306a36Sopenharmony_ci}
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ciint
374362306a36Sopenharmony_cisli_cmd_common_get_sli4_parameters(struct sli4 *sli4, void *buf)
374462306a36Sopenharmony_ci{
374562306a36Sopenharmony_ci	struct sli4_rqst_hdr *hdr = NULL;
374662306a36Sopenharmony_ci
374762306a36Sopenharmony_ci	hdr = sli_config_cmd_init(sli4, buf,
374862306a36Sopenharmony_ci			SLI4_CFG_PYLD_LENGTH(cmn_get_sli4_params), NULL);
374962306a36Sopenharmony_ci	if (!hdr)
375062306a36Sopenharmony_ci		return -EIO;
375162306a36Sopenharmony_ci
375262306a36Sopenharmony_ci	hdr->opcode = SLI4_CMN_GET_SLI4_PARAMS;
375362306a36Sopenharmony_ci	hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
375462306a36Sopenharmony_ci	hdr->request_length = SLI4_RQST_PYLD_LEN(cmn_get_sli4_params);
375562306a36Sopenharmony_ci
375662306a36Sopenharmony_ci	return 0;
375762306a36Sopenharmony_ci}
375862306a36Sopenharmony_ci
375962306a36Sopenharmony_cistatic int
376062306a36Sopenharmony_cisli_cmd_common_get_port_name(struct sli4 *sli4, void *buf)
376162306a36Sopenharmony_ci{
376262306a36Sopenharmony_ci	struct sli4_rqst_cmn_get_port_name *pname;
376362306a36Sopenharmony_ci
376462306a36Sopenharmony_ci	pname = sli_config_cmd_init(sli4, buf,
376562306a36Sopenharmony_ci			SLI4_CFG_PYLD_LENGTH(cmn_get_port_name), NULL);
376662306a36Sopenharmony_ci	if (!pname)
376762306a36Sopenharmony_ci		return -EIO;
376862306a36Sopenharmony_ci
376962306a36Sopenharmony_ci	sli_cmd_fill_hdr(&pname->hdr, SLI4_CMN_GET_PORT_NAME,
377062306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V1,
377162306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_get_port_name));
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ci	/* Set the port type value (ethernet=0, FC=1) for V1 commands */
377462306a36Sopenharmony_ci	pname->port_type = SLI4_PORT_TYPE_FC;
377562306a36Sopenharmony_ci
377662306a36Sopenharmony_ci	return 0;
377762306a36Sopenharmony_ci}
377862306a36Sopenharmony_ci
377962306a36Sopenharmony_ciint
378062306a36Sopenharmony_cisli_cmd_common_write_object(struct sli4 *sli4, void *buf, u16 noc,
378162306a36Sopenharmony_ci			    u16 eof, u32 desired_write_length,
378262306a36Sopenharmony_ci			    u32 offset, char *obj_name,
378362306a36Sopenharmony_ci			    struct efc_dma *dma)
378462306a36Sopenharmony_ci{
378562306a36Sopenharmony_ci	struct sli4_rqst_cmn_write_object *wr_obj = NULL;
378662306a36Sopenharmony_ci	struct sli4_bde *bde;
378762306a36Sopenharmony_ci	u32 dwflags = 0;
378862306a36Sopenharmony_ci
378962306a36Sopenharmony_ci	wr_obj = sli_config_cmd_init(sli4, buf,
379062306a36Sopenharmony_ci			SLI4_RQST_CMDSZ(cmn_write_object) + sizeof(*bde), NULL);
379162306a36Sopenharmony_ci	if (!wr_obj)
379262306a36Sopenharmony_ci		return -EIO;
379362306a36Sopenharmony_ci
379462306a36Sopenharmony_ci	sli_cmd_fill_hdr(&wr_obj->hdr, SLI4_CMN_WRITE_OBJECT,
379562306a36Sopenharmony_ci		SLI4_SUBSYSTEM_COMMON, CMD_V0,
379662306a36Sopenharmony_ci		SLI4_RQST_PYLD_LEN_VAR(cmn_write_object, sizeof(*bde)));
379762306a36Sopenharmony_ci
379862306a36Sopenharmony_ci	if (noc)
379962306a36Sopenharmony_ci		dwflags |= SLI4_RQ_DES_WRITE_LEN_NOC;
380062306a36Sopenharmony_ci	if (eof)
380162306a36Sopenharmony_ci		dwflags |= SLI4_RQ_DES_WRITE_LEN_EOF;
380262306a36Sopenharmony_ci	dwflags |= (desired_write_length & SLI4_RQ_DES_WRITE_LEN);
380362306a36Sopenharmony_ci
380462306a36Sopenharmony_ci	wr_obj->desired_write_len_dword = cpu_to_le32(dwflags);
380562306a36Sopenharmony_ci
380662306a36Sopenharmony_ci	wr_obj->write_offset = cpu_to_le32(offset);
380762306a36Sopenharmony_ci	strncpy(wr_obj->object_name, obj_name, sizeof(wr_obj->object_name) - 1);
380862306a36Sopenharmony_ci	wr_obj->host_buffer_descriptor_count = cpu_to_le32(1);
380962306a36Sopenharmony_ci
381062306a36Sopenharmony_ci	bde = (struct sli4_bde *)wr_obj->host_buffer_descriptor;
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci	/* Setup to transfer xfer_size bytes to device */
381362306a36Sopenharmony_ci	bde->bde_type_buflen =
381462306a36Sopenharmony_ci		cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
381562306a36Sopenharmony_ci			    (desired_write_length & SLI4_BDE_LEN_MASK));
381662306a36Sopenharmony_ci	bde->u.data.low = cpu_to_le32(lower_32_bits(dma->phys));
381762306a36Sopenharmony_ci	bde->u.data.high = cpu_to_le32(upper_32_bits(dma->phys));
381862306a36Sopenharmony_ci
381962306a36Sopenharmony_ci	return 0;
382062306a36Sopenharmony_ci}
382162306a36Sopenharmony_ci
382262306a36Sopenharmony_ciint
382362306a36Sopenharmony_cisli_cmd_common_delete_object(struct sli4 *sli4, void *buf, char *obj_name)
382462306a36Sopenharmony_ci{
382562306a36Sopenharmony_ci	struct sli4_rqst_cmn_delete_object *req = NULL;
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci	req = sli_config_cmd_init(sli4, buf,
382862306a36Sopenharmony_ci				  SLI4_RQST_CMDSZ(cmn_delete_object), NULL);
382962306a36Sopenharmony_ci	if (!req)
383062306a36Sopenharmony_ci		return -EIO;
383162306a36Sopenharmony_ci
383262306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_CMN_DELETE_OBJECT,
383362306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
383462306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_delete_object));
383562306a36Sopenharmony_ci
383662306a36Sopenharmony_ci	strncpy(req->object_name, obj_name, sizeof(req->object_name) - 1);
383762306a36Sopenharmony_ci	return 0;
383862306a36Sopenharmony_ci}
383962306a36Sopenharmony_ci
384062306a36Sopenharmony_ciint
384162306a36Sopenharmony_cisli_cmd_common_read_object(struct sli4 *sli4, void *buf, u32 desired_read_len,
384262306a36Sopenharmony_ci			   u32 offset, char *obj_name, struct efc_dma *dma)
384362306a36Sopenharmony_ci{
384462306a36Sopenharmony_ci	struct sli4_rqst_cmn_read_object *rd_obj = NULL;
384562306a36Sopenharmony_ci	struct sli4_bde *bde;
384662306a36Sopenharmony_ci
384762306a36Sopenharmony_ci	rd_obj = sli_config_cmd_init(sli4, buf,
384862306a36Sopenharmony_ci			SLI4_RQST_CMDSZ(cmn_read_object) + sizeof(*bde), NULL);
384962306a36Sopenharmony_ci	if (!rd_obj)
385062306a36Sopenharmony_ci		return -EIO;
385162306a36Sopenharmony_ci
385262306a36Sopenharmony_ci	sli_cmd_fill_hdr(&rd_obj->hdr, SLI4_CMN_READ_OBJECT,
385362306a36Sopenharmony_ci		SLI4_SUBSYSTEM_COMMON, CMD_V0,
385462306a36Sopenharmony_ci		SLI4_RQST_PYLD_LEN_VAR(cmn_read_object, sizeof(*bde)));
385562306a36Sopenharmony_ci	rd_obj->desired_read_length_dword =
385662306a36Sopenharmony_ci		cpu_to_le32(desired_read_len & SLI4_REQ_DESIRE_READLEN);
385762306a36Sopenharmony_ci
385862306a36Sopenharmony_ci	rd_obj->read_offset = cpu_to_le32(offset);
385962306a36Sopenharmony_ci	strncpy(rd_obj->object_name, obj_name, sizeof(rd_obj->object_name) - 1);
386062306a36Sopenharmony_ci	rd_obj->host_buffer_descriptor_count = cpu_to_le32(1);
386162306a36Sopenharmony_ci
386262306a36Sopenharmony_ci	bde = (struct sli4_bde *)rd_obj->host_buffer_descriptor;
386362306a36Sopenharmony_ci
386462306a36Sopenharmony_ci	/* Setup to transfer xfer_size bytes to device */
386562306a36Sopenharmony_ci	bde->bde_type_buflen =
386662306a36Sopenharmony_ci		cpu_to_le32((SLI4_BDE_TYPE_VAL(64)) |
386762306a36Sopenharmony_ci			    (desired_read_len & SLI4_BDE_LEN_MASK));
386862306a36Sopenharmony_ci	if (dma) {
386962306a36Sopenharmony_ci		bde->u.data.low = cpu_to_le32(lower_32_bits(dma->phys));
387062306a36Sopenharmony_ci		bde->u.data.high = cpu_to_le32(upper_32_bits(dma->phys));
387162306a36Sopenharmony_ci	} else {
387262306a36Sopenharmony_ci		bde->u.data.low = 0;
387362306a36Sopenharmony_ci		bde->u.data.high = 0;
387462306a36Sopenharmony_ci	}
387562306a36Sopenharmony_ci
387662306a36Sopenharmony_ci	return 0;
387762306a36Sopenharmony_ci}
387862306a36Sopenharmony_ci
387962306a36Sopenharmony_ciint
388062306a36Sopenharmony_cisli_cmd_dmtf_exec_clp_cmd(struct sli4 *sli4, void *buf, struct efc_dma *cmd,
388162306a36Sopenharmony_ci			  struct efc_dma *resp)
388262306a36Sopenharmony_ci{
388362306a36Sopenharmony_ci	struct sli4_rqst_dmtf_exec_clp_cmd *clp_cmd = NULL;
388462306a36Sopenharmony_ci
388562306a36Sopenharmony_ci	clp_cmd = sli_config_cmd_init(sli4, buf,
388662306a36Sopenharmony_ci				SLI4_RQST_CMDSZ(dmtf_exec_clp_cmd), NULL);
388762306a36Sopenharmony_ci	if (!clp_cmd)
388862306a36Sopenharmony_ci		return -EIO;
388962306a36Sopenharmony_ci
389062306a36Sopenharmony_ci	sli_cmd_fill_hdr(&clp_cmd->hdr, DMTF_EXEC_CLP_CMD, SLI4_SUBSYSTEM_DMTF,
389162306a36Sopenharmony_ci			 CMD_V0, SLI4_RQST_PYLD_LEN(dmtf_exec_clp_cmd));
389262306a36Sopenharmony_ci
389362306a36Sopenharmony_ci	clp_cmd->cmd_buf_length = cpu_to_le32(cmd->size);
389462306a36Sopenharmony_ci	clp_cmd->cmd_buf_addr_low =  cpu_to_le32(lower_32_bits(cmd->phys));
389562306a36Sopenharmony_ci	clp_cmd->cmd_buf_addr_high =  cpu_to_le32(upper_32_bits(cmd->phys));
389662306a36Sopenharmony_ci	clp_cmd->resp_buf_length = cpu_to_le32(resp->size);
389762306a36Sopenharmony_ci	clp_cmd->resp_buf_addr_low =  cpu_to_le32(lower_32_bits(resp->phys));
389862306a36Sopenharmony_ci	clp_cmd->resp_buf_addr_high =  cpu_to_le32(upper_32_bits(resp->phys));
389962306a36Sopenharmony_ci	return 0;
390062306a36Sopenharmony_ci}
390162306a36Sopenharmony_ci
390262306a36Sopenharmony_ciint
390362306a36Sopenharmony_cisli_cmd_common_set_dump_location(struct sli4 *sli4, void *buf, bool query,
390462306a36Sopenharmony_ci				 bool is_buffer_list,
390562306a36Sopenharmony_ci				 struct efc_dma *buffer, u8 fdb)
390662306a36Sopenharmony_ci{
390762306a36Sopenharmony_ci	struct sli4_rqst_cmn_set_dump_location *set_dump_loc = NULL;
390862306a36Sopenharmony_ci	u32 buffer_length_flag = 0;
390962306a36Sopenharmony_ci
391062306a36Sopenharmony_ci	set_dump_loc = sli_config_cmd_init(sli4, buf,
391162306a36Sopenharmony_ci				SLI4_RQST_CMDSZ(cmn_set_dump_location), NULL);
391262306a36Sopenharmony_ci	if (!set_dump_loc)
391362306a36Sopenharmony_ci		return -EIO;
391462306a36Sopenharmony_ci
391562306a36Sopenharmony_ci	sli_cmd_fill_hdr(&set_dump_loc->hdr, SLI4_CMN_SET_DUMP_LOCATION,
391662306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
391762306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_set_dump_location));
391862306a36Sopenharmony_ci
391962306a36Sopenharmony_ci	if (is_buffer_list)
392062306a36Sopenharmony_ci		buffer_length_flag |= SLI4_CMN_SET_DUMP_BLP;
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci	if (query)
392362306a36Sopenharmony_ci		buffer_length_flag |= SLI4_CMN_SET_DUMP_QRY;
392462306a36Sopenharmony_ci
392562306a36Sopenharmony_ci	if (fdb)
392662306a36Sopenharmony_ci		buffer_length_flag |= SLI4_CMN_SET_DUMP_FDB;
392762306a36Sopenharmony_ci
392862306a36Sopenharmony_ci	if (buffer) {
392962306a36Sopenharmony_ci		set_dump_loc->buf_addr_low =
393062306a36Sopenharmony_ci			cpu_to_le32(lower_32_bits(buffer->phys));
393162306a36Sopenharmony_ci		set_dump_loc->buf_addr_high =
393262306a36Sopenharmony_ci			cpu_to_le32(upper_32_bits(buffer->phys));
393362306a36Sopenharmony_ci
393462306a36Sopenharmony_ci		buffer_length_flag |=
393562306a36Sopenharmony_ci			buffer->len & SLI4_CMN_SET_DUMP_BUFFER_LEN;
393662306a36Sopenharmony_ci	} else {
393762306a36Sopenharmony_ci		set_dump_loc->buf_addr_low = 0;
393862306a36Sopenharmony_ci		set_dump_loc->buf_addr_high = 0;
393962306a36Sopenharmony_ci		set_dump_loc->buffer_length_dword = 0;
394062306a36Sopenharmony_ci	}
394162306a36Sopenharmony_ci	set_dump_loc->buffer_length_dword = cpu_to_le32(buffer_length_flag);
394262306a36Sopenharmony_ci	return 0;
394362306a36Sopenharmony_ci}
394462306a36Sopenharmony_ci
394562306a36Sopenharmony_ciint
394662306a36Sopenharmony_cisli_cmd_common_set_features(struct sli4 *sli4, void *buf, u32 feature,
394762306a36Sopenharmony_ci			    u32 param_len, void *parameter)
394862306a36Sopenharmony_ci{
394962306a36Sopenharmony_ci	struct sli4_rqst_cmn_set_features *cmd = NULL;
395062306a36Sopenharmony_ci
395162306a36Sopenharmony_ci	cmd = sli_config_cmd_init(sli4, buf,
395262306a36Sopenharmony_ci				  SLI4_RQST_CMDSZ(cmn_set_features), NULL);
395362306a36Sopenharmony_ci	if (!cmd)
395462306a36Sopenharmony_ci		return -EIO;
395562306a36Sopenharmony_ci
395662306a36Sopenharmony_ci	sli_cmd_fill_hdr(&cmd->hdr, SLI4_CMN_SET_FEATURES,
395762306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_COMMON, CMD_V0,
395862306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(cmn_set_features));
395962306a36Sopenharmony_ci
396062306a36Sopenharmony_ci	cmd->feature = cpu_to_le32(feature);
396162306a36Sopenharmony_ci	cmd->param_len = cpu_to_le32(param_len);
396262306a36Sopenharmony_ci	memcpy(cmd->params, parameter, param_len);
396362306a36Sopenharmony_ci
396462306a36Sopenharmony_ci	return 0;
396562306a36Sopenharmony_ci}
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ciint
396862306a36Sopenharmony_cisli_cqe_mq(struct sli4 *sli4, void *buf)
396962306a36Sopenharmony_ci{
397062306a36Sopenharmony_ci	struct sli4_mcqe *mcqe = buf;
397162306a36Sopenharmony_ci	u32 dwflags = le32_to_cpu(mcqe->dw3_flags);
397262306a36Sopenharmony_ci	/*
397362306a36Sopenharmony_ci	 * Firmware can split mbx completions into two MCQEs: first with only
397462306a36Sopenharmony_ci	 * the "consumed" bit set and a second with the "complete" bit set.
397562306a36Sopenharmony_ci	 * Thus, ignore MCQE unless "complete" is set.
397662306a36Sopenharmony_ci	 */
397762306a36Sopenharmony_ci	if (!(dwflags & SLI4_MCQE_COMPLETED))
397862306a36Sopenharmony_ci		return SLI4_MCQE_STATUS_NOT_COMPLETED;
397962306a36Sopenharmony_ci
398062306a36Sopenharmony_ci	if (le16_to_cpu(mcqe->completion_status)) {
398162306a36Sopenharmony_ci		efc_log_info(sli4, "status(st=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
398262306a36Sopenharmony_ci			     le16_to_cpu(mcqe->completion_status),
398362306a36Sopenharmony_ci			     le16_to_cpu(mcqe->extended_status),
398462306a36Sopenharmony_ci			     (dwflags & SLI4_MCQE_CONSUMED),
398562306a36Sopenharmony_ci			     (dwflags & SLI4_MCQE_COMPLETED),
398662306a36Sopenharmony_ci			     (dwflags & SLI4_MCQE_AE),
398762306a36Sopenharmony_ci			     (dwflags & SLI4_MCQE_VALID));
398862306a36Sopenharmony_ci	}
398962306a36Sopenharmony_ci
399062306a36Sopenharmony_ci	return le16_to_cpu(mcqe->completion_status);
399162306a36Sopenharmony_ci}
399262306a36Sopenharmony_ci
399362306a36Sopenharmony_ciint
399462306a36Sopenharmony_cisli_cqe_async(struct sli4 *sli4, void *buf)
399562306a36Sopenharmony_ci{
399662306a36Sopenharmony_ci	struct sli4_acqe *acqe = buf;
399762306a36Sopenharmony_ci	int rc = -EIO;
399862306a36Sopenharmony_ci
399962306a36Sopenharmony_ci	if (!buf) {
400062306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter sli4=%p buf=%p\n", sli4, buf);
400162306a36Sopenharmony_ci		return -EIO;
400262306a36Sopenharmony_ci	}
400362306a36Sopenharmony_ci
400462306a36Sopenharmony_ci	switch (acqe->event_code) {
400562306a36Sopenharmony_ci	case SLI4_ACQE_EVENT_CODE_LINK_STATE:
400662306a36Sopenharmony_ci		efc_log_info(sli4, "Unsupported by FC link, evt code:%#x\n",
400762306a36Sopenharmony_ci			     acqe->event_code);
400862306a36Sopenharmony_ci		break;
400962306a36Sopenharmony_ci	case SLI4_ACQE_EVENT_CODE_GRP_5:
401062306a36Sopenharmony_ci		efc_log_info(sli4, "ACQE GRP5\n");
401162306a36Sopenharmony_ci		break;
401262306a36Sopenharmony_ci	case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT:
401362306a36Sopenharmony_ci		efc_log_info(sli4, "ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n",
401462306a36Sopenharmony_ci			     acqe->event_type,
401562306a36Sopenharmony_ci			     le32_to_cpu(acqe->event_data[0]),
401662306a36Sopenharmony_ci			     le32_to_cpu(acqe->event_data[1]));
401762306a36Sopenharmony_ci		break;
401862306a36Sopenharmony_ci	case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT:
401962306a36Sopenharmony_ci		rc = sli_fc_process_link_attention(sli4, buf);
402062306a36Sopenharmony_ci		break;
402162306a36Sopenharmony_ci	default:
402262306a36Sopenharmony_ci		efc_log_info(sli4, "ACQE unknown=%#x\n", acqe->event_code);
402362306a36Sopenharmony_ci	}
402462306a36Sopenharmony_ci
402562306a36Sopenharmony_ci	return rc;
402662306a36Sopenharmony_ci}
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_cibool
402962306a36Sopenharmony_cisli_fw_ready(struct sli4 *sli4)
403062306a36Sopenharmony_ci{
403162306a36Sopenharmony_ci	u32 val;
403262306a36Sopenharmony_ci
403362306a36Sopenharmony_ci	/* Determine if the chip FW is in a ready state */
403462306a36Sopenharmony_ci	val = sli_reg_read_status(sli4);
403562306a36Sopenharmony_ci	return (val & SLI4_PORT_STATUS_RDY) ? 1 : 0;
403662306a36Sopenharmony_ci}
403762306a36Sopenharmony_ci
403862306a36Sopenharmony_cistatic bool
403962306a36Sopenharmony_cisli_wait_for_fw_ready(struct sli4 *sli4, u32 timeout_ms)
404062306a36Sopenharmony_ci{
404162306a36Sopenharmony_ci	unsigned long end;
404262306a36Sopenharmony_ci
404362306a36Sopenharmony_ci	end = jiffies + msecs_to_jiffies(timeout_ms);
404462306a36Sopenharmony_ci
404562306a36Sopenharmony_ci	do {
404662306a36Sopenharmony_ci		if (sli_fw_ready(sli4))
404762306a36Sopenharmony_ci			return true;
404862306a36Sopenharmony_ci
404962306a36Sopenharmony_ci		usleep_range(1000, 2000);
405062306a36Sopenharmony_ci	} while (time_before(jiffies, end));
405162306a36Sopenharmony_ci
405262306a36Sopenharmony_ci	return false;
405362306a36Sopenharmony_ci}
405462306a36Sopenharmony_ci
405562306a36Sopenharmony_cistatic bool
405662306a36Sopenharmony_cisli_sliport_reset(struct sli4 *sli4)
405762306a36Sopenharmony_ci{
405862306a36Sopenharmony_ci	bool rc;
405962306a36Sopenharmony_ci	u32 val;
406062306a36Sopenharmony_ci
406162306a36Sopenharmony_ci	val = SLI4_PORT_CTRL_IP;
406262306a36Sopenharmony_ci	/* Initialize port, endian */
406362306a36Sopenharmony_ci	writel(val, (sli4->reg[0] + SLI4_PORT_CTRL_REG));
406462306a36Sopenharmony_ci
406562306a36Sopenharmony_ci	rc = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
406662306a36Sopenharmony_ci	if (!rc)
406762306a36Sopenharmony_ci		efc_log_crit(sli4, "port failed to become ready after initialization\n");
406862306a36Sopenharmony_ci
406962306a36Sopenharmony_ci	return rc;
407062306a36Sopenharmony_ci}
407162306a36Sopenharmony_ci
407262306a36Sopenharmony_cistatic bool
407362306a36Sopenharmony_cisli_fw_init(struct sli4 *sli4)
407462306a36Sopenharmony_ci{
407562306a36Sopenharmony_ci	/*
407662306a36Sopenharmony_ci	 * Is firmware ready for operation?
407762306a36Sopenharmony_ci	 */
407862306a36Sopenharmony_ci	if (!sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC)) {
407962306a36Sopenharmony_ci		efc_log_crit(sli4, "FW status is NOT ready\n");
408062306a36Sopenharmony_ci		return false;
408162306a36Sopenharmony_ci	}
408262306a36Sopenharmony_ci
408362306a36Sopenharmony_ci	/*
408462306a36Sopenharmony_ci	 * Reset port to a known state
408562306a36Sopenharmony_ci	 */
408662306a36Sopenharmony_ci	return sli_sliport_reset(sli4);
408762306a36Sopenharmony_ci}
408862306a36Sopenharmony_ci
408962306a36Sopenharmony_cistatic int
409062306a36Sopenharmony_cisli_request_features(struct sli4 *sli4, u32 *features, bool query)
409162306a36Sopenharmony_ci{
409262306a36Sopenharmony_ci	struct sli4_cmd_request_features *req_features = sli4->bmbx.virt;
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci	if (sli_cmd_request_features(sli4, sli4->bmbx.virt, *features, query)) {
409562306a36Sopenharmony_ci		efc_log_err(sli4, "bad REQUEST_FEATURES write\n");
409662306a36Sopenharmony_ci		return -EIO;
409762306a36Sopenharmony_ci	}
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
410062306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox write fail\n");
410162306a36Sopenharmony_ci		return -EIO;
410262306a36Sopenharmony_ci	}
410362306a36Sopenharmony_ci
410462306a36Sopenharmony_ci	if (le16_to_cpu(req_features->hdr.status)) {
410562306a36Sopenharmony_ci		efc_log_err(sli4, "REQUEST_FEATURES bad status %#x\n",
410662306a36Sopenharmony_ci			    le16_to_cpu(req_features->hdr.status));
410762306a36Sopenharmony_ci		return -EIO;
410862306a36Sopenharmony_ci	}
410962306a36Sopenharmony_ci
411062306a36Sopenharmony_ci	*features = le32_to_cpu(req_features->resp);
411162306a36Sopenharmony_ci	return 0;
411262306a36Sopenharmony_ci}
411362306a36Sopenharmony_ci
411462306a36Sopenharmony_civoid
411562306a36Sopenharmony_cisli_calc_max_qentries(struct sli4 *sli4)
411662306a36Sopenharmony_ci{
411762306a36Sopenharmony_ci	enum sli4_qtype q;
411862306a36Sopenharmony_ci	u32 qentries;
411962306a36Sopenharmony_ci
412062306a36Sopenharmony_ci	for (q = SLI4_QTYPE_EQ; q < SLI4_QTYPE_MAX; q++) {
412162306a36Sopenharmony_ci		sli4->qinfo.max_qentries[q] =
412262306a36Sopenharmony_ci			sli_convert_mask_to_count(sli4->qinfo.count_method[q],
412362306a36Sopenharmony_ci						  sli4->qinfo.count_mask[q]);
412462306a36Sopenharmony_ci	}
412562306a36Sopenharmony_ci
412662306a36Sopenharmony_ci	/* single, contiguous DMA allocations will be called for each queue
412762306a36Sopenharmony_ci	 * of size (max_qentries * queue entry size); since these can be large,
412862306a36Sopenharmony_ci	 * check against the OS max DMA allocation size
412962306a36Sopenharmony_ci	 */
413062306a36Sopenharmony_ci	for (q = SLI4_QTYPE_EQ; q < SLI4_QTYPE_MAX; q++) {
413162306a36Sopenharmony_ci		qentries = sli4->qinfo.max_qentries[q];
413262306a36Sopenharmony_ci
413362306a36Sopenharmony_ci		efc_log_info(sli4, "[%s]: max_qentries from %d to %d\n",
413462306a36Sopenharmony_ci			     SLI4_QNAME[q],
413562306a36Sopenharmony_ci			     sli4->qinfo.max_qentries[q], qentries);
413662306a36Sopenharmony_ci		sli4->qinfo.max_qentries[q] = qentries;
413762306a36Sopenharmony_ci	}
413862306a36Sopenharmony_ci}
413962306a36Sopenharmony_ci
414062306a36Sopenharmony_cistatic int
414162306a36Sopenharmony_cisli_get_read_config(struct sli4 *sli4)
414262306a36Sopenharmony_ci{
414362306a36Sopenharmony_ci	struct sli4_rsp_read_config *conf = sli4->bmbx.virt;
414462306a36Sopenharmony_ci	u32 i, total;
414562306a36Sopenharmony_ci	u32 *base;
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ci	if (sli_cmd_read_config(sli4, sli4->bmbx.virt)) {
414862306a36Sopenharmony_ci		efc_log_err(sli4, "bad READ_CONFIG write\n");
414962306a36Sopenharmony_ci		return -EIO;
415062306a36Sopenharmony_ci	}
415162306a36Sopenharmony_ci
415262306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
415362306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox fail (READ_CONFIG)\n");
415462306a36Sopenharmony_ci		return -EIO;
415562306a36Sopenharmony_ci	}
415662306a36Sopenharmony_ci
415762306a36Sopenharmony_ci	if (le16_to_cpu(conf->hdr.status)) {
415862306a36Sopenharmony_ci		efc_log_err(sli4, "READ_CONFIG bad status %#x\n",
415962306a36Sopenharmony_ci			    le16_to_cpu(conf->hdr.status));
416062306a36Sopenharmony_ci		return -EIO;
416162306a36Sopenharmony_ci	}
416262306a36Sopenharmony_ci
416362306a36Sopenharmony_ci	sli4->params.has_extents =
416462306a36Sopenharmony_ci	  le32_to_cpu(conf->ext_dword) & SLI4_READ_CFG_RESP_RESOURCE_EXT;
416562306a36Sopenharmony_ci	if (sli4->params.has_extents) {
416662306a36Sopenharmony_ci		efc_log_err(sli4, "extents not supported\n");
416762306a36Sopenharmony_ci		return -EIO;
416862306a36Sopenharmony_ci	}
416962306a36Sopenharmony_ci
417062306a36Sopenharmony_ci	base = sli4->ext[0].base;
417162306a36Sopenharmony_ci	if (!base) {
417262306a36Sopenharmony_ci		int size = SLI4_RSRC_MAX * sizeof(u32);
417362306a36Sopenharmony_ci
417462306a36Sopenharmony_ci		base = kzalloc(size, GFP_KERNEL);
417562306a36Sopenharmony_ci		if (!base)
417662306a36Sopenharmony_ci			return -EIO;
417762306a36Sopenharmony_ci	}
417862306a36Sopenharmony_ci
417962306a36Sopenharmony_ci	for (i = 0; i < SLI4_RSRC_MAX; i++) {
418062306a36Sopenharmony_ci		sli4->ext[i].number = 1;
418162306a36Sopenharmony_ci		sli4->ext[i].n_alloc = 0;
418262306a36Sopenharmony_ci		sli4->ext[i].base = &base[i];
418362306a36Sopenharmony_ci	}
418462306a36Sopenharmony_ci
418562306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_VFI].base[0] = le16_to_cpu(conf->vfi_base);
418662306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_VFI].size = le16_to_cpu(conf->vfi_count);
418762306a36Sopenharmony_ci
418862306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_VPI].base[0] = le16_to_cpu(conf->vpi_base);
418962306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_VPI].size = le16_to_cpu(conf->vpi_count);
419062306a36Sopenharmony_ci
419162306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_RPI].base[0] = le16_to_cpu(conf->rpi_base);
419262306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_RPI].size = le16_to_cpu(conf->rpi_count);
419362306a36Sopenharmony_ci
419462306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_XRI].base[0] = le16_to_cpu(conf->xri_base);
419562306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_XRI].size = le16_to_cpu(conf->xri_count);
419662306a36Sopenharmony_ci
419762306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_FCFI].base[0] = 0;
419862306a36Sopenharmony_ci	sli4->ext[SLI4_RSRC_FCFI].size = le16_to_cpu(conf->fcfi_count);
419962306a36Sopenharmony_ci
420062306a36Sopenharmony_ci	for (i = 0; i < SLI4_RSRC_MAX; i++) {
420162306a36Sopenharmony_ci		total = sli4->ext[i].number * sli4->ext[i].size;
420262306a36Sopenharmony_ci		sli4->ext[i].use_map = bitmap_zalloc(total, GFP_KERNEL);
420362306a36Sopenharmony_ci		if (!sli4->ext[i].use_map) {
420462306a36Sopenharmony_ci			efc_log_err(sli4, "bitmap memory allocation failed %d\n",
420562306a36Sopenharmony_ci				    i);
420662306a36Sopenharmony_ci			return -EIO;
420762306a36Sopenharmony_ci		}
420862306a36Sopenharmony_ci		sli4->ext[i].map_size = total;
420962306a36Sopenharmony_ci	}
421062306a36Sopenharmony_ci
421162306a36Sopenharmony_ci	sli4->topology = (le32_to_cpu(conf->topology_dword) &
421262306a36Sopenharmony_ci			  SLI4_READ_CFG_RESP_TOPOLOGY) >> 24;
421362306a36Sopenharmony_ci	switch (sli4->topology) {
421462306a36Sopenharmony_ci	case SLI4_READ_CFG_TOPO_FC:
421562306a36Sopenharmony_ci		efc_log_info(sli4, "FC (unknown)\n");
421662306a36Sopenharmony_ci		break;
421762306a36Sopenharmony_ci	case SLI4_READ_CFG_TOPO_NON_FC_AL:
421862306a36Sopenharmony_ci		efc_log_info(sli4, "FC (direct attach)\n");
421962306a36Sopenharmony_ci		break;
422062306a36Sopenharmony_ci	case SLI4_READ_CFG_TOPO_FC_AL:
422162306a36Sopenharmony_ci		efc_log_info(sli4, "FC (arbitrated loop)\n");
422262306a36Sopenharmony_ci		break;
422362306a36Sopenharmony_ci	default:
422462306a36Sopenharmony_ci		efc_log_info(sli4, "bad topology %#x\n", sli4->topology);
422562306a36Sopenharmony_ci	}
422662306a36Sopenharmony_ci
422762306a36Sopenharmony_ci	sli4->e_d_tov = le16_to_cpu(conf->e_d_tov);
422862306a36Sopenharmony_ci	sli4->r_a_tov = le16_to_cpu(conf->r_a_tov);
422962306a36Sopenharmony_ci
423062306a36Sopenharmony_ci	sli4->link_module_type = le16_to_cpu(conf->lmt);
423162306a36Sopenharmony_ci
423262306a36Sopenharmony_ci	sli4->qinfo.max_qcount[SLI4_QTYPE_EQ] =	le16_to_cpu(conf->eq_count);
423362306a36Sopenharmony_ci	sli4->qinfo.max_qcount[SLI4_QTYPE_CQ] =	le16_to_cpu(conf->cq_count);
423462306a36Sopenharmony_ci	sli4->qinfo.max_qcount[SLI4_QTYPE_WQ] =	le16_to_cpu(conf->wq_count);
423562306a36Sopenharmony_ci	sli4->qinfo.max_qcount[SLI4_QTYPE_RQ] =	le16_to_cpu(conf->rq_count);
423662306a36Sopenharmony_ci
423762306a36Sopenharmony_ci	/*
423862306a36Sopenharmony_ci	 * READ_CONFIG doesn't give the max number of MQ. Applications
423962306a36Sopenharmony_ci	 * will typically want 1, but we may need another at some future
424062306a36Sopenharmony_ci	 * date. Dummy up a "max" MQ count here.
424162306a36Sopenharmony_ci	 */
424262306a36Sopenharmony_ci	sli4->qinfo.max_qcount[SLI4_QTYPE_MQ] = SLI4_USER_MQ_COUNT;
424362306a36Sopenharmony_ci	return 0;
424462306a36Sopenharmony_ci}
424562306a36Sopenharmony_ci
424662306a36Sopenharmony_cistatic int
424762306a36Sopenharmony_cisli_get_sli4_parameters(struct sli4 *sli4)
424862306a36Sopenharmony_ci{
424962306a36Sopenharmony_ci	struct sli4_rsp_cmn_get_sli4_params *parms;
425062306a36Sopenharmony_ci	u32 dw_loopback;
425162306a36Sopenharmony_ci	u32 dw_eq_pg_cnt;
425262306a36Sopenharmony_ci	u32 dw_cq_pg_cnt;
425362306a36Sopenharmony_ci	u32 dw_mq_pg_cnt;
425462306a36Sopenharmony_ci	u32 dw_wq_pg_cnt;
425562306a36Sopenharmony_ci	u32 dw_rq_pg_cnt;
425662306a36Sopenharmony_ci	u32 dw_sgl_pg_cnt;
425762306a36Sopenharmony_ci
425862306a36Sopenharmony_ci	if (sli_cmd_common_get_sli4_parameters(sli4, sli4->bmbx.virt))
425962306a36Sopenharmony_ci		return -EIO;
426062306a36Sopenharmony_ci
426162306a36Sopenharmony_ci	parms = (struct sli4_rsp_cmn_get_sli4_params *)
426262306a36Sopenharmony_ci		 (((u8 *)sli4->bmbx.virt) +
426362306a36Sopenharmony_ci		  offsetof(struct sli4_cmd_sli_config, payload.embed));
426462306a36Sopenharmony_ci
426562306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
426662306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox write fail\n");
426762306a36Sopenharmony_ci		return -EIO;
426862306a36Sopenharmony_ci	}
426962306a36Sopenharmony_ci
427062306a36Sopenharmony_ci	if (parms->hdr.status) {
427162306a36Sopenharmony_ci		efc_log_err(sli4, "COMMON_GET_SLI4_PARAMETERS bad status %#x",
427262306a36Sopenharmony_ci			    parms->hdr.status);
427362306a36Sopenharmony_ci		efc_log_err(sli4, "additional status %#x\n",
427462306a36Sopenharmony_ci			    parms->hdr.additional_status);
427562306a36Sopenharmony_ci		return -EIO;
427662306a36Sopenharmony_ci	}
427762306a36Sopenharmony_ci
427862306a36Sopenharmony_ci	dw_loopback = le32_to_cpu(parms->dw16_loopback_scope);
427962306a36Sopenharmony_ci	dw_eq_pg_cnt = le32_to_cpu(parms->dw6_eq_page_cnt);
428062306a36Sopenharmony_ci	dw_cq_pg_cnt = le32_to_cpu(parms->dw8_cq_page_cnt);
428162306a36Sopenharmony_ci	dw_mq_pg_cnt = le32_to_cpu(parms->dw10_mq_page_cnt);
428262306a36Sopenharmony_ci	dw_wq_pg_cnt = le32_to_cpu(parms->dw12_wq_page_cnt);
428362306a36Sopenharmony_ci	dw_rq_pg_cnt = le32_to_cpu(parms->dw14_rq_page_cnt);
428462306a36Sopenharmony_ci
428562306a36Sopenharmony_ci	sli4->params.auto_reg =	(dw_loopback & SLI4_PARAM_AREG);
428662306a36Sopenharmony_ci	sli4->params.auto_xfer_rdy = (dw_loopback & SLI4_PARAM_AGXF);
428762306a36Sopenharmony_ci	sli4->params.hdr_template_req =	(dw_loopback & SLI4_PARAM_HDRR);
428862306a36Sopenharmony_ci	sli4->params.t10_dif_inline_capable = (dw_loopback & SLI4_PARAM_TIMM);
428962306a36Sopenharmony_ci	sli4->params.t10_dif_separate_capable =	(dw_loopback & SLI4_PARAM_TSMM);
429062306a36Sopenharmony_ci
429162306a36Sopenharmony_ci	sli4->params.mq_create_version = GET_Q_CREATE_VERSION(dw_mq_pg_cnt);
429262306a36Sopenharmony_ci	sli4->params.cq_create_version = GET_Q_CREATE_VERSION(dw_cq_pg_cnt);
429362306a36Sopenharmony_ci
429462306a36Sopenharmony_ci	sli4->rq_min_buf_size =	le16_to_cpu(parms->min_rq_buffer_size);
429562306a36Sopenharmony_ci	sli4->rq_max_buf_size = le32_to_cpu(parms->max_rq_buffer_size);
429662306a36Sopenharmony_ci
429762306a36Sopenharmony_ci	sli4->qinfo.qpage_count[SLI4_QTYPE_EQ] =
429862306a36Sopenharmony_ci		(dw_eq_pg_cnt & SLI4_PARAM_EQ_PAGE_CNT_MASK);
429962306a36Sopenharmony_ci	sli4->qinfo.qpage_count[SLI4_QTYPE_CQ] =
430062306a36Sopenharmony_ci		(dw_cq_pg_cnt & SLI4_PARAM_CQ_PAGE_CNT_MASK);
430162306a36Sopenharmony_ci	sli4->qinfo.qpage_count[SLI4_QTYPE_MQ] =
430262306a36Sopenharmony_ci		(dw_mq_pg_cnt & SLI4_PARAM_MQ_PAGE_CNT_MASK);
430362306a36Sopenharmony_ci	sli4->qinfo.qpage_count[SLI4_QTYPE_WQ] =
430462306a36Sopenharmony_ci		(dw_wq_pg_cnt & SLI4_PARAM_WQ_PAGE_CNT_MASK);
430562306a36Sopenharmony_ci	sli4->qinfo.qpage_count[SLI4_QTYPE_RQ] =
430662306a36Sopenharmony_ci		(dw_rq_pg_cnt & SLI4_PARAM_RQ_PAGE_CNT_MASK);
430762306a36Sopenharmony_ci
430862306a36Sopenharmony_ci	/* save count methods and masks for each queue type */
430962306a36Sopenharmony_ci
431062306a36Sopenharmony_ci	sli4->qinfo.count_mask[SLI4_QTYPE_EQ] =
431162306a36Sopenharmony_ci			le16_to_cpu(parms->eqe_count_mask);
431262306a36Sopenharmony_ci	sli4->qinfo.count_method[SLI4_QTYPE_EQ] =
431362306a36Sopenharmony_ci			GET_Q_CNT_METHOD(dw_eq_pg_cnt);
431462306a36Sopenharmony_ci
431562306a36Sopenharmony_ci	sli4->qinfo.count_mask[SLI4_QTYPE_CQ] =
431662306a36Sopenharmony_ci			le16_to_cpu(parms->cqe_count_mask);
431762306a36Sopenharmony_ci	sli4->qinfo.count_method[SLI4_QTYPE_CQ] =
431862306a36Sopenharmony_ci			GET_Q_CNT_METHOD(dw_cq_pg_cnt);
431962306a36Sopenharmony_ci
432062306a36Sopenharmony_ci	sli4->qinfo.count_mask[SLI4_QTYPE_MQ] =
432162306a36Sopenharmony_ci			le16_to_cpu(parms->mqe_count_mask);
432262306a36Sopenharmony_ci	sli4->qinfo.count_method[SLI4_QTYPE_MQ] =
432362306a36Sopenharmony_ci			GET_Q_CNT_METHOD(dw_mq_pg_cnt);
432462306a36Sopenharmony_ci
432562306a36Sopenharmony_ci	sli4->qinfo.count_mask[SLI4_QTYPE_WQ] =
432662306a36Sopenharmony_ci			le16_to_cpu(parms->wqe_count_mask);
432762306a36Sopenharmony_ci	sli4->qinfo.count_method[SLI4_QTYPE_WQ] =
432862306a36Sopenharmony_ci			GET_Q_CNT_METHOD(dw_wq_pg_cnt);
432962306a36Sopenharmony_ci
433062306a36Sopenharmony_ci	sli4->qinfo.count_mask[SLI4_QTYPE_RQ] =
433162306a36Sopenharmony_ci			le16_to_cpu(parms->rqe_count_mask);
433262306a36Sopenharmony_ci	sli4->qinfo.count_method[SLI4_QTYPE_RQ] =
433362306a36Sopenharmony_ci			GET_Q_CNT_METHOD(dw_rq_pg_cnt);
433462306a36Sopenharmony_ci
433562306a36Sopenharmony_ci	/* now calculate max queue entries */
433662306a36Sopenharmony_ci	sli_calc_max_qentries(sli4);
433762306a36Sopenharmony_ci
433862306a36Sopenharmony_ci	dw_sgl_pg_cnt = le32_to_cpu(parms->dw18_sgl_page_cnt);
433962306a36Sopenharmony_ci
434062306a36Sopenharmony_ci	/* max # of pages */
434162306a36Sopenharmony_ci	sli4->max_sgl_pages = (dw_sgl_pg_cnt & SLI4_PARAM_SGL_PAGE_CNT_MASK);
434262306a36Sopenharmony_ci
434362306a36Sopenharmony_ci	/* bit map of available sizes */
434462306a36Sopenharmony_ci	sli4->sgl_page_sizes = (dw_sgl_pg_cnt &
434562306a36Sopenharmony_ci				SLI4_PARAM_SGL_PAGE_SZS_MASK) >> 8;
434662306a36Sopenharmony_ci	/* ignore HLM here. Use value from REQUEST_FEATURES */
434762306a36Sopenharmony_ci	sli4->sge_supported_length = le32_to_cpu(parms->sge_supported_length);
434862306a36Sopenharmony_ci	sli4->params.sgl_pre_reg_required = (dw_loopback & SLI4_PARAM_SGLR);
434962306a36Sopenharmony_ci	/* default to using pre-registered SGL's */
435062306a36Sopenharmony_ci	sli4->params.sgl_pre_registered = true;
435162306a36Sopenharmony_ci
435262306a36Sopenharmony_ci	sli4->params.perf_hint = dw_loopback & SLI4_PARAM_PHON;
435362306a36Sopenharmony_ci	sli4->params.perf_wq_id_association = (dw_loopback & SLI4_PARAM_PHWQ);
435462306a36Sopenharmony_ci
435562306a36Sopenharmony_ci	sli4->rq_batch = (le16_to_cpu(parms->dw15w1_rq_db_window) &
435662306a36Sopenharmony_ci			  SLI4_PARAM_RQ_DB_WINDOW_MASK) >> 12;
435762306a36Sopenharmony_ci
435862306a36Sopenharmony_ci	/* Use the highest available WQE size. */
435962306a36Sopenharmony_ci	if (((dw_wq_pg_cnt & SLI4_PARAM_WQE_SZS_MASK) >> 8) &
436062306a36Sopenharmony_ci	    SLI4_128BYTE_WQE_SUPPORT)
436162306a36Sopenharmony_ci		sli4->wqe_size = SLI4_WQE_EXT_BYTES;
436262306a36Sopenharmony_ci	else
436362306a36Sopenharmony_ci		sli4->wqe_size = SLI4_WQE_BYTES;
436462306a36Sopenharmony_ci
436562306a36Sopenharmony_ci	return 0;
436662306a36Sopenharmony_ci}
436762306a36Sopenharmony_ci
436862306a36Sopenharmony_cistatic int
436962306a36Sopenharmony_cisli_get_ctrl_attributes(struct sli4 *sli4)
437062306a36Sopenharmony_ci{
437162306a36Sopenharmony_ci	struct sli4_rsp_cmn_get_cntl_attributes *attr;
437262306a36Sopenharmony_ci	struct sli4_rsp_cmn_get_cntl_addl_attributes *add_attr;
437362306a36Sopenharmony_ci	struct efc_dma data;
437462306a36Sopenharmony_ci	u32 psize;
437562306a36Sopenharmony_ci
437662306a36Sopenharmony_ci	/*
437762306a36Sopenharmony_ci	 * Issue COMMON_GET_CNTL_ATTRIBUTES to get port_number. Temporarily
437862306a36Sopenharmony_ci	 * uses VPD DMA buffer as the response won't fit in the embedded
437962306a36Sopenharmony_ci	 * buffer.
438062306a36Sopenharmony_ci	 */
438162306a36Sopenharmony_ci	memset(sli4->vpd_data.virt, 0, sli4->vpd_data.size);
438262306a36Sopenharmony_ci	if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt,
438362306a36Sopenharmony_ci					       &sli4->vpd_data)) {
438462306a36Sopenharmony_ci		efc_log_err(sli4, "bad COMMON_GET_CNTL_ATTRIBUTES write\n");
438562306a36Sopenharmony_ci		return -EIO;
438662306a36Sopenharmony_ci	}
438762306a36Sopenharmony_ci
438862306a36Sopenharmony_ci	attr =	sli4->vpd_data.virt;
438962306a36Sopenharmony_ci
439062306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
439162306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox write fail\n");
439262306a36Sopenharmony_ci		return -EIO;
439362306a36Sopenharmony_ci	}
439462306a36Sopenharmony_ci
439562306a36Sopenharmony_ci	if (attr->hdr.status) {
439662306a36Sopenharmony_ci		efc_log_err(sli4, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x",
439762306a36Sopenharmony_ci			    attr->hdr.status);
439862306a36Sopenharmony_ci		efc_log_err(sli4, "additional status %#x\n",
439962306a36Sopenharmony_ci			    attr->hdr.additional_status);
440062306a36Sopenharmony_ci		return -EIO;
440162306a36Sopenharmony_ci	}
440262306a36Sopenharmony_ci
440362306a36Sopenharmony_ci	sli4->port_number = attr->port_num_type_flags & SLI4_CNTL_ATTR_PORTNUM;
440462306a36Sopenharmony_ci
440562306a36Sopenharmony_ci	memcpy(sli4->bios_version_string, attr->bios_version_str,
440662306a36Sopenharmony_ci	       sizeof(sli4->bios_version_string));
440762306a36Sopenharmony_ci
440862306a36Sopenharmony_ci	/* get additional attributes */
440962306a36Sopenharmony_ci	psize = sizeof(struct sli4_rsp_cmn_get_cntl_addl_attributes);
441062306a36Sopenharmony_ci	data.size = psize;
441162306a36Sopenharmony_ci	data.virt = dma_alloc_coherent(&sli4->pci->dev, data.size,
441262306a36Sopenharmony_ci				       &data.phys, GFP_KERNEL);
441362306a36Sopenharmony_ci	if (!data.virt) {
441462306a36Sopenharmony_ci		memset(&data, 0, sizeof(struct efc_dma));
441562306a36Sopenharmony_ci		efc_log_err(sli4, "Failed to allocate memory for GET_CNTL_ADDL_ATTR\n");
441662306a36Sopenharmony_ci		return -EIO;
441762306a36Sopenharmony_ci	}
441862306a36Sopenharmony_ci
441962306a36Sopenharmony_ci	if (sli_cmd_common_get_cntl_addl_attributes(sli4, sli4->bmbx.virt,
442062306a36Sopenharmony_ci						    &data)) {
442162306a36Sopenharmony_ci		efc_log_err(sli4, "bad GET_CNTL_ADDL_ATTR write\n");
442262306a36Sopenharmony_ci		dma_free_coherent(&sli4->pci->dev, data.size,
442362306a36Sopenharmony_ci				  data.virt, data.phys);
442462306a36Sopenharmony_ci		return -EIO;
442562306a36Sopenharmony_ci	}
442662306a36Sopenharmony_ci
442762306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
442862306a36Sopenharmony_ci		efc_log_crit(sli4, "mailbox fail (GET_CNTL_ADDL_ATTR)\n");
442962306a36Sopenharmony_ci		dma_free_coherent(&sli4->pci->dev, data.size,
443062306a36Sopenharmony_ci				  data.virt, data.phys);
443162306a36Sopenharmony_ci		return -EIO;
443262306a36Sopenharmony_ci	}
443362306a36Sopenharmony_ci
443462306a36Sopenharmony_ci	add_attr = data.virt;
443562306a36Sopenharmony_ci	if (add_attr->hdr.status) {
443662306a36Sopenharmony_ci		efc_log_err(sli4, "GET_CNTL_ADDL_ATTR bad status %#x\n",
443762306a36Sopenharmony_ci			    add_attr->hdr.status);
443862306a36Sopenharmony_ci		dma_free_coherent(&sli4->pci->dev, data.size,
443962306a36Sopenharmony_ci				  data.virt, data.phys);
444062306a36Sopenharmony_ci		return -EIO;
444162306a36Sopenharmony_ci	}
444262306a36Sopenharmony_ci
444362306a36Sopenharmony_ci	memcpy(sli4->ipl_name, add_attr->ipl_file_name, sizeof(sli4->ipl_name));
444462306a36Sopenharmony_ci
444562306a36Sopenharmony_ci	efc_log_info(sli4, "IPL:%s\n", (char *)sli4->ipl_name);
444662306a36Sopenharmony_ci
444762306a36Sopenharmony_ci	dma_free_coherent(&sli4->pci->dev, data.size, data.virt,
444862306a36Sopenharmony_ci			  data.phys);
444962306a36Sopenharmony_ci	memset(&data, 0, sizeof(struct efc_dma));
445062306a36Sopenharmony_ci	return 0;
445162306a36Sopenharmony_ci}
445262306a36Sopenharmony_ci
445362306a36Sopenharmony_cistatic int
445462306a36Sopenharmony_cisli_get_fw_rev(struct sli4 *sli4)
445562306a36Sopenharmony_ci{
445662306a36Sopenharmony_ci	struct sli4_cmd_read_rev	*read_rev = sli4->bmbx.virt;
445762306a36Sopenharmony_ci
445862306a36Sopenharmony_ci	if (sli_cmd_read_rev(sli4, sli4->bmbx.virt, &sli4->vpd_data))
445962306a36Sopenharmony_ci		return -EIO;
446062306a36Sopenharmony_ci
446162306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
446262306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox write fail (READ_REV)\n");
446362306a36Sopenharmony_ci		return -EIO;
446462306a36Sopenharmony_ci	}
446562306a36Sopenharmony_ci
446662306a36Sopenharmony_ci	if (le16_to_cpu(read_rev->hdr.status)) {
446762306a36Sopenharmony_ci		efc_log_err(sli4, "READ_REV bad status %#x\n",
446862306a36Sopenharmony_ci			    le16_to_cpu(read_rev->hdr.status));
446962306a36Sopenharmony_ci		return -EIO;
447062306a36Sopenharmony_ci	}
447162306a36Sopenharmony_ci
447262306a36Sopenharmony_ci	sli4->fw_rev[0] = le32_to_cpu(read_rev->first_fw_id);
447362306a36Sopenharmony_ci	memcpy(sli4->fw_name[0], read_rev->first_fw_name,
447462306a36Sopenharmony_ci	       sizeof(sli4->fw_name[0]));
447562306a36Sopenharmony_ci
447662306a36Sopenharmony_ci	sli4->fw_rev[1] = le32_to_cpu(read_rev->second_fw_id);
447762306a36Sopenharmony_ci	memcpy(sli4->fw_name[1], read_rev->second_fw_name,
447862306a36Sopenharmony_ci	       sizeof(sli4->fw_name[1]));
447962306a36Sopenharmony_ci
448062306a36Sopenharmony_ci	sli4->hw_rev[0] = le32_to_cpu(read_rev->first_hw_rev);
448162306a36Sopenharmony_ci	sli4->hw_rev[1] = le32_to_cpu(read_rev->second_hw_rev);
448262306a36Sopenharmony_ci	sli4->hw_rev[2] = le32_to_cpu(read_rev->third_hw_rev);
448362306a36Sopenharmony_ci
448462306a36Sopenharmony_ci	efc_log_info(sli4, "FW1:%s (%08x) / FW2:%s (%08x)\n",
448562306a36Sopenharmony_ci		     read_rev->first_fw_name, le32_to_cpu(read_rev->first_fw_id),
448662306a36Sopenharmony_ci		     read_rev->second_fw_name, le32_to_cpu(read_rev->second_fw_id));
448762306a36Sopenharmony_ci
448862306a36Sopenharmony_ci	efc_log_info(sli4, "HW1: %08x / HW2: %08x\n",
448962306a36Sopenharmony_ci		     le32_to_cpu(read_rev->first_hw_rev),
449062306a36Sopenharmony_ci		     le32_to_cpu(read_rev->second_hw_rev));
449162306a36Sopenharmony_ci
449262306a36Sopenharmony_ci	/* Check that all VPD data was returned */
449362306a36Sopenharmony_ci	if (le32_to_cpu(read_rev->returned_vpd_length) !=
449462306a36Sopenharmony_ci	    le32_to_cpu(read_rev->actual_vpd_length)) {
449562306a36Sopenharmony_ci		efc_log_info(sli4, "VPD length: avail=%d return=%d actual=%d\n",
449662306a36Sopenharmony_ci			     le32_to_cpu(read_rev->available_length_dword) &
449762306a36Sopenharmony_ci				    SLI4_READ_REV_AVAILABLE_LENGTH,
449862306a36Sopenharmony_ci			     le32_to_cpu(read_rev->returned_vpd_length),
449962306a36Sopenharmony_ci			     le32_to_cpu(read_rev->actual_vpd_length));
450062306a36Sopenharmony_ci	}
450162306a36Sopenharmony_ci	sli4->vpd_length = le32_to_cpu(read_rev->returned_vpd_length);
450262306a36Sopenharmony_ci	return 0;
450362306a36Sopenharmony_ci}
450462306a36Sopenharmony_ci
450562306a36Sopenharmony_cistatic int
450662306a36Sopenharmony_cisli_get_config(struct sli4 *sli4)
450762306a36Sopenharmony_ci{
450862306a36Sopenharmony_ci	struct sli4_rsp_cmn_get_port_name *port_name;
450962306a36Sopenharmony_ci	struct sli4_cmd_read_nvparms *read_nvparms;
451062306a36Sopenharmony_ci
451162306a36Sopenharmony_ci	/*
451262306a36Sopenharmony_ci	 * Read the device configuration
451362306a36Sopenharmony_ci	 */
451462306a36Sopenharmony_ci	if (sli_get_read_config(sli4))
451562306a36Sopenharmony_ci		return -EIO;
451662306a36Sopenharmony_ci
451762306a36Sopenharmony_ci	if (sli_get_sli4_parameters(sli4))
451862306a36Sopenharmony_ci		return -EIO;
451962306a36Sopenharmony_ci
452062306a36Sopenharmony_ci	if (sli_get_ctrl_attributes(sli4))
452162306a36Sopenharmony_ci		return -EIO;
452262306a36Sopenharmony_ci
452362306a36Sopenharmony_ci	if (sli_cmd_common_get_port_name(sli4, sli4->bmbx.virt))
452462306a36Sopenharmony_ci		return -EIO;
452562306a36Sopenharmony_ci
452662306a36Sopenharmony_ci	port_name = (struct sli4_rsp_cmn_get_port_name *)
452762306a36Sopenharmony_ci		    (((u8 *)sli4->bmbx.virt) +
452862306a36Sopenharmony_ci		    offsetof(struct sli4_cmd_sli_config, payload.embed));
452962306a36Sopenharmony_ci
453062306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
453162306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox fail (GET_PORT_NAME)\n");
453262306a36Sopenharmony_ci		return -EIO;
453362306a36Sopenharmony_ci	}
453462306a36Sopenharmony_ci
453562306a36Sopenharmony_ci	sli4->port_name[0] = port_name->port_name[sli4->port_number];
453662306a36Sopenharmony_ci	sli4->port_name[1] = '\0';
453762306a36Sopenharmony_ci
453862306a36Sopenharmony_ci	if (sli_get_fw_rev(sli4))
453962306a36Sopenharmony_ci		return -EIO;
454062306a36Sopenharmony_ci
454162306a36Sopenharmony_ci	if (sli_cmd_read_nvparms(sli4, sli4->bmbx.virt)) {
454262306a36Sopenharmony_ci		efc_log_err(sli4, "bad READ_NVPARMS write\n");
454362306a36Sopenharmony_ci		return -EIO;
454462306a36Sopenharmony_ci	}
454562306a36Sopenharmony_ci
454662306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
454762306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox fail (READ_NVPARMS)\n");
454862306a36Sopenharmony_ci		return -EIO;
454962306a36Sopenharmony_ci	}
455062306a36Sopenharmony_ci
455162306a36Sopenharmony_ci	read_nvparms = sli4->bmbx.virt;
455262306a36Sopenharmony_ci	if (le16_to_cpu(read_nvparms->hdr.status)) {
455362306a36Sopenharmony_ci		efc_log_err(sli4, "READ_NVPARMS bad status %#x\n",
455462306a36Sopenharmony_ci			    le16_to_cpu(read_nvparms->hdr.status));
455562306a36Sopenharmony_ci		return -EIO;
455662306a36Sopenharmony_ci	}
455762306a36Sopenharmony_ci
455862306a36Sopenharmony_ci	memcpy(sli4->wwpn, read_nvparms->wwpn, sizeof(sli4->wwpn));
455962306a36Sopenharmony_ci	memcpy(sli4->wwnn, read_nvparms->wwnn, sizeof(sli4->wwnn));
456062306a36Sopenharmony_ci
456162306a36Sopenharmony_ci	efc_log_info(sli4, "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
456262306a36Sopenharmony_ci		     sli4->wwpn[0], sli4->wwpn[1], sli4->wwpn[2], sli4->wwpn[3],
456362306a36Sopenharmony_ci		     sli4->wwpn[4], sli4->wwpn[5], sli4->wwpn[6], sli4->wwpn[7]);
456462306a36Sopenharmony_ci	efc_log_info(sli4, "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
456562306a36Sopenharmony_ci		     sli4->wwnn[0], sli4->wwnn[1], sli4->wwnn[2], sli4->wwnn[3],
456662306a36Sopenharmony_ci		     sli4->wwnn[4], sli4->wwnn[5], sli4->wwnn[6], sli4->wwnn[7]);
456762306a36Sopenharmony_ci
456862306a36Sopenharmony_ci	return 0;
456962306a36Sopenharmony_ci}
457062306a36Sopenharmony_ci
457162306a36Sopenharmony_ciint
457262306a36Sopenharmony_cisli_setup(struct sli4 *sli4, void *os, struct pci_dev  *pdev,
457362306a36Sopenharmony_ci	  void __iomem *reg[])
457462306a36Sopenharmony_ci{
457562306a36Sopenharmony_ci	u32 intf = U32_MAX;
457662306a36Sopenharmony_ci	u32 pci_class_rev = 0;
457762306a36Sopenharmony_ci	u32 rev_id = 0;
457862306a36Sopenharmony_ci	u32 family = 0;
457962306a36Sopenharmony_ci	u32 asic_id = 0;
458062306a36Sopenharmony_ci	u32 i;
458162306a36Sopenharmony_ci	struct sli4_asic_entry_t *asic;
458262306a36Sopenharmony_ci
458362306a36Sopenharmony_ci	memset(sli4, 0, sizeof(struct sli4));
458462306a36Sopenharmony_ci
458562306a36Sopenharmony_ci	sli4->os = os;
458662306a36Sopenharmony_ci	sli4->pci = pdev;
458762306a36Sopenharmony_ci
458862306a36Sopenharmony_ci	for (i = 0; i < 6; i++)
458962306a36Sopenharmony_ci		sli4->reg[i] = reg[i];
459062306a36Sopenharmony_ci	/*
459162306a36Sopenharmony_ci	 * Read the SLI_INTF register to discover the register layout
459262306a36Sopenharmony_ci	 * and other capability information
459362306a36Sopenharmony_ci	 */
459462306a36Sopenharmony_ci	if (pci_read_config_dword(pdev, SLI4_INTF_REG, &intf))
459562306a36Sopenharmony_ci		return -EIO;
459662306a36Sopenharmony_ci
459762306a36Sopenharmony_ci	if ((intf & SLI4_INTF_VALID_MASK) != (u32)SLI4_INTF_VALID_VALUE) {
459862306a36Sopenharmony_ci		efc_log_err(sli4, "SLI_INTF is not valid\n");
459962306a36Sopenharmony_ci		return -EIO;
460062306a36Sopenharmony_ci	}
460162306a36Sopenharmony_ci
460262306a36Sopenharmony_ci	/* driver only support SLI-4 */
460362306a36Sopenharmony_ci	if ((intf & SLI4_INTF_REV_MASK) != SLI4_INTF_REV_S4) {
460462306a36Sopenharmony_ci		efc_log_err(sli4, "Unsupported SLI revision (intf=%#x)\n", intf);
460562306a36Sopenharmony_ci		return -EIO;
460662306a36Sopenharmony_ci	}
460762306a36Sopenharmony_ci
460862306a36Sopenharmony_ci	sli4->sli_family = intf & SLI4_INTF_FAMILY_MASK;
460962306a36Sopenharmony_ci
461062306a36Sopenharmony_ci	sli4->if_type = intf & SLI4_INTF_IF_TYPE_MASK;
461162306a36Sopenharmony_ci	efc_log_info(sli4, "status=%#x error1=%#x error2=%#x\n",
461262306a36Sopenharmony_ci		     sli_reg_read_status(sli4),
461362306a36Sopenharmony_ci		     sli_reg_read_err1(sli4),
461462306a36Sopenharmony_ci		     sli_reg_read_err2(sli4));
461562306a36Sopenharmony_ci
461662306a36Sopenharmony_ci	/*
461762306a36Sopenharmony_ci	 * set the ASIC type and revision
461862306a36Sopenharmony_ci	 */
461962306a36Sopenharmony_ci	if (pci_read_config_dword(pdev, PCI_CLASS_REVISION, &pci_class_rev))
462062306a36Sopenharmony_ci		return -EIO;
462162306a36Sopenharmony_ci
462262306a36Sopenharmony_ci	rev_id = pci_class_rev & 0xff;
462362306a36Sopenharmony_ci	family = sli4->sli_family;
462462306a36Sopenharmony_ci	if (family == SLI4_FAMILY_CHECK_ASIC_TYPE) {
462562306a36Sopenharmony_ci		if (!pci_read_config_dword(pdev, SLI4_ASIC_ID_REG, &asic_id))
462662306a36Sopenharmony_ci			family = asic_id & SLI4_ASIC_GEN_MASK;
462762306a36Sopenharmony_ci	}
462862306a36Sopenharmony_ci
462962306a36Sopenharmony_ci	for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table);
463062306a36Sopenharmony_ci	     i++, asic++) {
463162306a36Sopenharmony_ci		if (rev_id == asic->rev_id && family == asic->family) {
463262306a36Sopenharmony_ci			sli4->asic_type = family;
463362306a36Sopenharmony_ci			sli4->asic_rev = rev_id;
463462306a36Sopenharmony_ci			break;
463562306a36Sopenharmony_ci		}
463662306a36Sopenharmony_ci	}
463762306a36Sopenharmony_ci	/* Fail if no matching asic type/rev was found */
463862306a36Sopenharmony_ci	if (!sli4->asic_type) {
463962306a36Sopenharmony_ci		efc_log_err(sli4, "no matching asic family/rev found: %02x/%02x\n",
464062306a36Sopenharmony_ci			    family, rev_id);
464162306a36Sopenharmony_ci		return -EIO;
464262306a36Sopenharmony_ci	}
464362306a36Sopenharmony_ci
464462306a36Sopenharmony_ci	/*
464562306a36Sopenharmony_ci	 * The bootstrap mailbox is equivalent to a MQ with a single 256 byte
464662306a36Sopenharmony_ci	 * entry, a CQ with a single 16 byte entry, and no event queue.
464762306a36Sopenharmony_ci	 * Alignment must be 16 bytes as the low order address bits in the
464862306a36Sopenharmony_ci	 * address register are also control / status.
464962306a36Sopenharmony_ci	 */
465062306a36Sopenharmony_ci	sli4->bmbx.size = SLI4_BMBX_SIZE + sizeof(struct sli4_mcqe);
465162306a36Sopenharmony_ci	sli4->bmbx.virt = dma_alloc_coherent(&pdev->dev, sli4->bmbx.size,
465262306a36Sopenharmony_ci					     &sli4->bmbx.phys, GFP_KERNEL);
465362306a36Sopenharmony_ci	if (!sli4->bmbx.virt) {
465462306a36Sopenharmony_ci		memset(&sli4->bmbx, 0, sizeof(struct efc_dma));
465562306a36Sopenharmony_ci		efc_log_err(sli4, "bootstrap mailbox allocation failed\n");
465662306a36Sopenharmony_ci		return -EIO;
465762306a36Sopenharmony_ci	}
465862306a36Sopenharmony_ci
465962306a36Sopenharmony_ci	if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) {
466062306a36Sopenharmony_ci		efc_log_err(sli4, "bad alignment for bootstrap mailbox\n");
466162306a36Sopenharmony_ci		return -EIO;
466262306a36Sopenharmony_ci	}
466362306a36Sopenharmony_ci
466462306a36Sopenharmony_ci	efc_log_info(sli4, "bmbx v=%p p=0x%x %08x s=%zd\n", sli4->bmbx.virt,
466562306a36Sopenharmony_ci		     upper_32_bits(sli4->bmbx.phys),
466662306a36Sopenharmony_ci		     lower_32_bits(sli4->bmbx.phys), sli4->bmbx.size);
466762306a36Sopenharmony_ci
466862306a36Sopenharmony_ci	/* 4096 is arbitrary. What should this value actually be? */
466962306a36Sopenharmony_ci	sli4->vpd_data.size = 4096;
467062306a36Sopenharmony_ci	sli4->vpd_data.virt = dma_alloc_coherent(&pdev->dev,
467162306a36Sopenharmony_ci						 sli4->vpd_data.size,
467262306a36Sopenharmony_ci						 &sli4->vpd_data.phys,
467362306a36Sopenharmony_ci						 GFP_KERNEL);
467462306a36Sopenharmony_ci	if (!sli4->vpd_data.virt) {
467562306a36Sopenharmony_ci		memset(&sli4->vpd_data, 0, sizeof(struct efc_dma));
467662306a36Sopenharmony_ci		/* Note that failure isn't fatal in this specific case */
467762306a36Sopenharmony_ci		efc_log_info(sli4, "VPD buffer allocation failed\n");
467862306a36Sopenharmony_ci	}
467962306a36Sopenharmony_ci
468062306a36Sopenharmony_ci	if (!sli_fw_init(sli4)) {
468162306a36Sopenharmony_ci		efc_log_err(sli4, "FW initialization failed\n");
468262306a36Sopenharmony_ci		return -EIO;
468362306a36Sopenharmony_ci	}
468462306a36Sopenharmony_ci
468562306a36Sopenharmony_ci	/*
468662306a36Sopenharmony_ci	 * Set one of fcpi(initiator), fcpt(target), fcpc(combined) to true
468762306a36Sopenharmony_ci	 * in addition to any other desired features
468862306a36Sopenharmony_ci	 */
468962306a36Sopenharmony_ci	sli4->features = (SLI4_REQFEAT_IAAB | SLI4_REQFEAT_NPIV |
469062306a36Sopenharmony_ci				 SLI4_REQFEAT_DIF | SLI4_REQFEAT_VF |
469162306a36Sopenharmony_ci				 SLI4_REQFEAT_FCPC | SLI4_REQFEAT_IAAR |
469262306a36Sopenharmony_ci				 SLI4_REQFEAT_HLM | SLI4_REQFEAT_PERFH |
469362306a36Sopenharmony_ci				 SLI4_REQFEAT_RXSEQ | SLI4_REQFEAT_RXRI |
469462306a36Sopenharmony_ci				 SLI4_REQFEAT_MRQP);
469562306a36Sopenharmony_ci
469662306a36Sopenharmony_ci	/* use performance hints if available */
469762306a36Sopenharmony_ci	if (sli4->params.perf_hint)
469862306a36Sopenharmony_ci		sli4->features |= SLI4_REQFEAT_PERFH;
469962306a36Sopenharmony_ci
470062306a36Sopenharmony_ci	if (sli_request_features(sli4, &sli4->features, true))
470162306a36Sopenharmony_ci		return -EIO;
470262306a36Sopenharmony_ci
470362306a36Sopenharmony_ci	if (sli_get_config(sli4))
470462306a36Sopenharmony_ci		return -EIO;
470562306a36Sopenharmony_ci
470662306a36Sopenharmony_ci	return 0;
470762306a36Sopenharmony_ci}
470862306a36Sopenharmony_ci
470962306a36Sopenharmony_ciint
471062306a36Sopenharmony_cisli_init(struct sli4 *sli4)
471162306a36Sopenharmony_ci{
471262306a36Sopenharmony_ci	if (sli4->params.has_extents) {
471362306a36Sopenharmony_ci		efc_log_info(sli4, "extend allocation not supported\n");
471462306a36Sopenharmony_ci		return -EIO;
471562306a36Sopenharmony_ci	}
471662306a36Sopenharmony_ci
471762306a36Sopenharmony_ci	sli4->features &= (~SLI4_REQFEAT_HLM);
471862306a36Sopenharmony_ci	sli4->features &= (~SLI4_REQFEAT_RXSEQ);
471962306a36Sopenharmony_ci	sli4->features &= (~SLI4_REQFEAT_RXRI);
472062306a36Sopenharmony_ci
472162306a36Sopenharmony_ci	if (sli_request_features(sli4, &sli4->features, false))
472262306a36Sopenharmony_ci		return -EIO;
472362306a36Sopenharmony_ci
472462306a36Sopenharmony_ci	return 0;
472562306a36Sopenharmony_ci}
472662306a36Sopenharmony_ci
472762306a36Sopenharmony_ciint
472862306a36Sopenharmony_cisli_reset(struct sli4 *sli4)
472962306a36Sopenharmony_ci{
473062306a36Sopenharmony_ci	u32	i;
473162306a36Sopenharmony_ci
473262306a36Sopenharmony_ci	if (!sli_fw_init(sli4)) {
473362306a36Sopenharmony_ci		efc_log_crit(sli4, "FW initialization failed\n");
473462306a36Sopenharmony_ci		return -EIO;
473562306a36Sopenharmony_ci	}
473662306a36Sopenharmony_ci
473762306a36Sopenharmony_ci	kfree(sli4->ext[0].base);
473862306a36Sopenharmony_ci	sli4->ext[0].base = NULL;
473962306a36Sopenharmony_ci
474062306a36Sopenharmony_ci	for (i = 0; i < SLI4_RSRC_MAX; i++) {
474162306a36Sopenharmony_ci		bitmap_free(sli4->ext[i].use_map);
474262306a36Sopenharmony_ci		sli4->ext[i].use_map = NULL;
474362306a36Sopenharmony_ci		sli4->ext[i].base = NULL;
474462306a36Sopenharmony_ci	}
474562306a36Sopenharmony_ci
474662306a36Sopenharmony_ci	return sli_get_config(sli4);
474762306a36Sopenharmony_ci}
474862306a36Sopenharmony_ci
474962306a36Sopenharmony_ciint
475062306a36Sopenharmony_cisli_fw_reset(struct sli4 *sli4)
475162306a36Sopenharmony_ci{
475262306a36Sopenharmony_ci	/*
475362306a36Sopenharmony_ci	 * Firmware must be ready before issuing the reset.
475462306a36Sopenharmony_ci	 */
475562306a36Sopenharmony_ci	if (!sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC)) {
475662306a36Sopenharmony_ci		efc_log_crit(sli4, "FW status is NOT ready\n");
475762306a36Sopenharmony_ci		return -EIO;
475862306a36Sopenharmony_ci	}
475962306a36Sopenharmony_ci
476062306a36Sopenharmony_ci	/* Lancer uses PHYDEV_CONTROL */
476162306a36Sopenharmony_ci	writel(SLI4_PHYDEV_CTRL_FRST, (sli4->reg[0] + SLI4_PHYDEV_CTRL_REG));
476262306a36Sopenharmony_ci
476362306a36Sopenharmony_ci	/* wait for the FW to become ready after the reset */
476462306a36Sopenharmony_ci	if (!sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC)) {
476562306a36Sopenharmony_ci		efc_log_crit(sli4, "Failed to be ready after firmware reset\n");
476662306a36Sopenharmony_ci		return -EIO;
476762306a36Sopenharmony_ci	}
476862306a36Sopenharmony_ci	return 0;
476962306a36Sopenharmony_ci}
477062306a36Sopenharmony_ci
477162306a36Sopenharmony_civoid
477262306a36Sopenharmony_cisli_teardown(struct sli4 *sli4)
477362306a36Sopenharmony_ci{
477462306a36Sopenharmony_ci	u32 i;
477562306a36Sopenharmony_ci
477662306a36Sopenharmony_ci	kfree(sli4->ext[0].base);
477762306a36Sopenharmony_ci	sli4->ext[0].base = NULL;
477862306a36Sopenharmony_ci
477962306a36Sopenharmony_ci	for (i = 0; i < SLI4_RSRC_MAX; i++) {
478062306a36Sopenharmony_ci		sli4->ext[i].base = NULL;
478162306a36Sopenharmony_ci
478262306a36Sopenharmony_ci		bitmap_free(sli4->ext[i].use_map);
478362306a36Sopenharmony_ci		sli4->ext[i].use_map = NULL;
478462306a36Sopenharmony_ci	}
478562306a36Sopenharmony_ci
478662306a36Sopenharmony_ci	if (!sli_sliport_reset(sli4))
478762306a36Sopenharmony_ci		efc_log_err(sli4, "FW deinitialization failed\n");
478862306a36Sopenharmony_ci
478962306a36Sopenharmony_ci	dma_free_coherent(&sli4->pci->dev, sli4->vpd_data.size,
479062306a36Sopenharmony_ci			  sli4->vpd_data.virt, sli4->vpd_data.phys);
479162306a36Sopenharmony_ci	memset(&sli4->vpd_data, 0, sizeof(struct efc_dma));
479262306a36Sopenharmony_ci
479362306a36Sopenharmony_ci	dma_free_coherent(&sli4->pci->dev, sli4->bmbx.size,
479462306a36Sopenharmony_ci			  sli4->bmbx.virt, sli4->bmbx.phys);
479562306a36Sopenharmony_ci	memset(&sli4->bmbx, 0, sizeof(struct efc_dma));
479662306a36Sopenharmony_ci}
479762306a36Sopenharmony_ci
479862306a36Sopenharmony_ciint
479962306a36Sopenharmony_cisli_callback(struct sli4 *sli4, enum sli4_callback which,
480062306a36Sopenharmony_ci	     void *func, void *arg)
480162306a36Sopenharmony_ci{
480262306a36Sopenharmony_ci	if (!func) {
480362306a36Sopenharmony_ci		efc_log_err(sli4, "bad parameter sli4=%p which=%#x func=%p\n",
480462306a36Sopenharmony_ci			    sli4, which, func);
480562306a36Sopenharmony_ci		return -EIO;
480662306a36Sopenharmony_ci	}
480762306a36Sopenharmony_ci
480862306a36Sopenharmony_ci	switch (which) {
480962306a36Sopenharmony_ci	case SLI4_CB_LINK:
481062306a36Sopenharmony_ci		sli4->link = func;
481162306a36Sopenharmony_ci		sli4->link_arg = arg;
481262306a36Sopenharmony_ci		break;
481362306a36Sopenharmony_ci	default:
481462306a36Sopenharmony_ci		efc_log_info(sli4, "unknown callback %#x\n", which);
481562306a36Sopenharmony_ci		return -EIO;
481662306a36Sopenharmony_ci	}
481762306a36Sopenharmony_ci
481862306a36Sopenharmony_ci	return 0;
481962306a36Sopenharmony_ci}
482062306a36Sopenharmony_ci
482162306a36Sopenharmony_ciint
482262306a36Sopenharmony_cisli_eq_modify_delay(struct sli4 *sli4, struct sli4_queue *eq,
482362306a36Sopenharmony_ci		    u32 num_eq, u32 shift, u32 delay_mult)
482462306a36Sopenharmony_ci{
482562306a36Sopenharmony_ci	sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, eq, num_eq,
482662306a36Sopenharmony_ci				       shift, delay_mult);
482762306a36Sopenharmony_ci
482862306a36Sopenharmony_ci	if (sli_bmbx_command(sli4)) {
482962306a36Sopenharmony_ci		efc_log_crit(sli4, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n");
483062306a36Sopenharmony_ci		return -EIO;
483162306a36Sopenharmony_ci	}
483262306a36Sopenharmony_ci	if (sli_res_sli_config(sli4, sli4->bmbx.virt)) {
483362306a36Sopenharmony_ci		efc_log_err(sli4, "bad status MODIFY EQ DELAY\n");
483462306a36Sopenharmony_ci		return -EIO;
483562306a36Sopenharmony_ci	}
483662306a36Sopenharmony_ci
483762306a36Sopenharmony_ci	return 0;
483862306a36Sopenharmony_ci}
483962306a36Sopenharmony_ci
484062306a36Sopenharmony_ciint
484162306a36Sopenharmony_cisli_resource_alloc(struct sli4 *sli4, enum sli4_resource rtype,
484262306a36Sopenharmony_ci		   u32 *rid, u32 *index)
484362306a36Sopenharmony_ci{
484462306a36Sopenharmony_ci	int rc = 0;
484562306a36Sopenharmony_ci	u32 size;
484662306a36Sopenharmony_ci	u32 ext_idx;
484762306a36Sopenharmony_ci	u32 item_idx;
484862306a36Sopenharmony_ci	u32 position;
484962306a36Sopenharmony_ci
485062306a36Sopenharmony_ci	*rid = U32_MAX;
485162306a36Sopenharmony_ci	*index = U32_MAX;
485262306a36Sopenharmony_ci
485362306a36Sopenharmony_ci	switch (rtype) {
485462306a36Sopenharmony_ci	case SLI4_RSRC_VFI:
485562306a36Sopenharmony_ci	case SLI4_RSRC_VPI:
485662306a36Sopenharmony_ci	case SLI4_RSRC_RPI:
485762306a36Sopenharmony_ci	case SLI4_RSRC_XRI:
485862306a36Sopenharmony_ci		position =
485962306a36Sopenharmony_ci		find_first_zero_bit(sli4->ext[rtype].use_map,
486062306a36Sopenharmony_ci				    sli4->ext[rtype].map_size);
486162306a36Sopenharmony_ci		if (position >= sli4->ext[rtype].map_size) {
486262306a36Sopenharmony_ci			efc_log_err(sli4, "out of resource %d (alloc=%d)\n",
486362306a36Sopenharmony_ci				    rtype, sli4->ext[rtype].n_alloc);
486462306a36Sopenharmony_ci			rc = -EIO;
486562306a36Sopenharmony_ci			break;
486662306a36Sopenharmony_ci		}
486762306a36Sopenharmony_ci		set_bit(position, sli4->ext[rtype].use_map);
486862306a36Sopenharmony_ci		*index = position;
486962306a36Sopenharmony_ci
487062306a36Sopenharmony_ci		size = sli4->ext[rtype].size;
487162306a36Sopenharmony_ci
487262306a36Sopenharmony_ci		ext_idx = *index / size;
487362306a36Sopenharmony_ci		item_idx   = *index % size;
487462306a36Sopenharmony_ci
487562306a36Sopenharmony_ci		*rid = sli4->ext[rtype].base[ext_idx] + item_idx;
487662306a36Sopenharmony_ci
487762306a36Sopenharmony_ci		sli4->ext[rtype].n_alloc++;
487862306a36Sopenharmony_ci		break;
487962306a36Sopenharmony_ci	default:
488062306a36Sopenharmony_ci		rc = -EIO;
488162306a36Sopenharmony_ci	}
488262306a36Sopenharmony_ci
488362306a36Sopenharmony_ci	return rc;
488462306a36Sopenharmony_ci}
488562306a36Sopenharmony_ci
488662306a36Sopenharmony_ciint
488762306a36Sopenharmony_cisli_resource_free(struct sli4 *sli4, enum sli4_resource rtype, u32 rid)
488862306a36Sopenharmony_ci{
488962306a36Sopenharmony_ci	int rc = -EIO;
489062306a36Sopenharmony_ci	u32 x;
489162306a36Sopenharmony_ci	u32 size, *base;
489262306a36Sopenharmony_ci
489362306a36Sopenharmony_ci	switch (rtype) {
489462306a36Sopenharmony_ci	case SLI4_RSRC_VFI:
489562306a36Sopenharmony_ci	case SLI4_RSRC_VPI:
489662306a36Sopenharmony_ci	case SLI4_RSRC_RPI:
489762306a36Sopenharmony_ci	case SLI4_RSRC_XRI:
489862306a36Sopenharmony_ci		/*
489962306a36Sopenharmony_ci		 * Figure out which extent contains the resource ID. I.e. find
490062306a36Sopenharmony_ci		 * the extent such that
490162306a36Sopenharmony_ci		 *   extent->base <= resource ID < extent->base + extent->size
490262306a36Sopenharmony_ci		 */
490362306a36Sopenharmony_ci		base = sli4->ext[rtype].base;
490462306a36Sopenharmony_ci		size = sli4->ext[rtype].size;
490562306a36Sopenharmony_ci
490662306a36Sopenharmony_ci		/*
490762306a36Sopenharmony_ci		 * In the case of FW reset, this may be cleared
490862306a36Sopenharmony_ci		 * but the force_free path will still attempt to
490962306a36Sopenharmony_ci		 * free the resource. Prevent a NULL pointer access.
491062306a36Sopenharmony_ci		 */
491162306a36Sopenharmony_ci		if (!base)
491262306a36Sopenharmony_ci			break;
491362306a36Sopenharmony_ci
491462306a36Sopenharmony_ci		for (x = 0; x < sli4->ext[rtype].number; x++) {
491562306a36Sopenharmony_ci			if ((rid < base[x] || (rid >= (base[x] + size))))
491662306a36Sopenharmony_ci				continue;
491762306a36Sopenharmony_ci
491862306a36Sopenharmony_ci			rid -= base[x];
491962306a36Sopenharmony_ci			clear_bit((x * size) + rid, sli4->ext[rtype].use_map);
492062306a36Sopenharmony_ci			rc = 0;
492162306a36Sopenharmony_ci			break;
492262306a36Sopenharmony_ci		}
492362306a36Sopenharmony_ci		break;
492462306a36Sopenharmony_ci	default:
492562306a36Sopenharmony_ci		break;
492662306a36Sopenharmony_ci	}
492762306a36Sopenharmony_ci
492862306a36Sopenharmony_ci	return rc;
492962306a36Sopenharmony_ci}
493062306a36Sopenharmony_ci
493162306a36Sopenharmony_ciint
493262306a36Sopenharmony_cisli_resource_reset(struct sli4 *sli4, enum sli4_resource rtype)
493362306a36Sopenharmony_ci{
493462306a36Sopenharmony_ci	int rc = -EIO;
493562306a36Sopenharmony_ci	u32 i;
493662306a36Sopenharmony_ci
493762306a36Sopenharmony_ci	switch (rtype) {
493862306a36Sopenharmony_ci	case SLI4_RSRC_VFI:
493962306a36Sopenharmony_ci	case SLI4_RSRC_VPI:
494062306a36Sopenharmony_ci	case SLI4_RSRC_RPI:
494162306a36Sopenharmony_ci	case SLI4_RSRC_XRI:
494262306a36Sopenharmony_ci		for (i = 0; i < sli4->ext[rtype].map_size; i++)
494362306a36Sopenharmony_ci			clear_bit(i, sli4->ext[rtype].use_map);
494462306a36Sopenharmony_ci		rc = 0;
494562306a36Sopenharmony_ci		break;
494662306a36Sopenharmony_ci	default:
494762306a36Sopenharmony_ci		break;
494862306a36Sopenharmony_ci	}
494962306a36Sopenharmony_ci
495062306a36Sopenharmony_ci	return rc;
495162306a36Sopenharmony_ci}
495262306a36Sopenharmony_ci
495362306a36Sopenharmony_ciint sli_raise_ue(struct sli4 *sli4, u8 dump)
495462306a36Sopenharmony_ci{
495562306a36Sopenharmony_ci	u32 val = 0;
495662306a36Sopenharmony_ci
495762306a36Sopenharmony_ci	if (dump == SLI4_FUNC_DESC_DUMP) {
495862306a36Sopenharmony_ci		val = SLI4_PORT_CTRL_FDD | SLI4_PORT_CTRL_IP;
495962306a36Sopenharmony_ci		writel(val, (sli4->reg[0] + SLI4_PORT_CTRL_REG));
496062306a36Sopenharmony_ci	} else {
496162306a36Sopenharmony_ci		val = SLI4_PHYDEV_CTRL_FRST;
496262306a36Sopenharmony_ci
496362306a36Sopenharmony_ci		if (dump == SLI4_CHIP_LEVEL_DUMP)
496462306a36Sopenharmony_ci			val |= SLI4_PHYDEV_CTRL_DD;
496562306a36Sopenharmony_ci		writel(val, (sli4->reg[0] + SLI4_PHYDEV_CTRL_REG));
496662306a36Sopenharmony_ci	}
496762306a36Sopenharmony_ci
496862306a36Sopenharmony_ci	return 0;
496962306a36Sopenharmony_ci}
497062306a36Sopenharmony_ci
497162306a36Sopenharmony_ciint sli_dump_is_ready(struct sli4 *sli4)
497262306a36Sopenharmony_ci{
497362306a36Sopenharmony_ci	int rc = SLI4_DUMP_READY_STATUS_NOT_READY;
497462306a36Sopenharmony_ci	u32 port_val;
497562306a36Sopenharmony_ci	u32 bmbx_val;
497662306a36Sopenharmony_ci
497762306a36Sopenharmony_ci	/*
497862306a36Sopenharmony_ci	 * Ensure that the port is ready AND the mailbox is
497962306a36Sopenharmony_ci	 * ready before signaling that the dump is ready to go.
498062306a36Sopenharmony_ci	 */
498162306a36Sopenharmony_ci	port_val = sli_reg_read_status(sli4);
498262306a36Sopenharmony_ci	bmbx_val = readl(sli4->reg[0] + SLI4_BMBX_REG);
498362306a36Sopenharmony_ci
498462306a36Sopenharmony_ci	if ((bmbx_val & SLI4_BMBX_RDY) &&
498562306a36Sopenharmony_ci	    (port_val & SLI4_PORT_STATUS_RDY)) {
498662306a36Sopenharmony_ci		if (port_val & SLI4_PORT_STATUS_DIP)
498762306a36Sopenharmony_ci			rc = SLI4_DUMP_READY_STATUS_DD_PRESENT;
498862306a36Sopenharmony_ci		else if (port_val & SLI4_PORT_STATUS_FDP)
498962306a36Sopenharmony_ci			rc = SLI4_DUMP_READY_STATUS_FDB_PRESENT;
499062306a36Sopenharmony_ci	}
499162306a36Sopenharmony_ci
499262306a36Sopenharmony_ci	return rc;
499362306a36Sopenharmony_ci}
499462306a36Sopenharmony_ci
499562306a36Sopenharmony_cibool sli_reset_required(struct sli4 *sli4)
499662306a36Sopenharmony_ci{
499762306a36Sopenharmony_ci	u32 val;
499862306a36Sopenharmony_ci
499962306a36Sopenharmony_ci	val = sli_reg_read_status(sli4);
500062306a36Sopenharmony_ci	return (val & SLI4_PORT_STATUS_RN);
500162306a36Sopenharmony_ci}
500262306a36Sopenharmony_ci
500362306a36Sopenharmony_ciint
500462306a36Sopenharmony_cisli_cmd_post_sgl_pages(struct sli4 *sli4, void *buf, u16 xri,
500562306a36Sopenharmony_ci		       u32 xri_count, struct efc_dma *page0[],
500662306a36Sopenharmony_ci		       struct efc_dma *page1[], struct efc_dma *dma)
500762306a36Sopenharmony_ci{
500862306a36Sopenharmony_ci	struct sli4_rqst_post_sgl_pages *post = NULL;
500962306a36Sopenharmony_ci	u32 i;
501062306a36Sopenharmony_ci	__le32 req_len;
501162306a36Sopenharmony_ci
501262306a36Sopenharmony_ci	post = sli_config_cmd_init(sli4, buf,
501362306a36Sopenharmony_ci				   SLI4_CFG_PYLD_LENGTH(post_sgl_pages), dma);
501462306a36Sopenharmony_ci	if (!post)
501562306a36Sopenharmony_ci		return -EIO;
501662306a36Sopenharmony_ci
501762306a36Sopenharmony_ci	/* payload size calculation */
501862306a36Sopenharmony_ci	/* 4 = xri_start + xri_count */
501962306a36Sopenharmony_ci	/* xri_count = # of XRI's registered */
502062306a36Sopenharmony_ci	/* sizeof(uint64_t) = physical address size */
502162306a36Sopenharmony_ci	/* 2 = # of physical addresses per page set */
502262306a36Sopenharmony_ci	req_len = cpu_to_le32(4 + (xri_count * (sizeof(uint64_t) * 2)));
502362306a36Sopenharmony_ci	sli_cmd_fill_hdr(&post->hdr, SLI4_OPC_POST_SGL_PAGES, SLI4_SUBSYSTEM_FC,
502462306a36Sopenharmony_ci			 CMD_V0, req_len);
502562306a36Sopenharmony_ci	post->xri_start = cpu_to_le16(xri);
502662306a36Sopenharmony_ci	post->xri_count = cpu_to_le16(xri_count);
502762306a36Sopenharmony_ci
502862306a36Sopenharmony_ci	for (i = 0; i < xri_count; i++) {
502962306a36Sopenharmony_ci		post->page_set[i].page0_low  =
503062306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(page0[i]->phys));
503162306a36Sopenharmony_ci		post->page_set[i].page0_high =
503262306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(page0[i]->phys));
503362306a36Sopenharmony_ci	}
503462306a36Sopenharmony_ci
503562306a36Sopenharmony_ci	if (page1) {
503662306a36Sopenharmony_ci		for (i = 0; i < xri_count; i++) {
503762306a36Sopenharmony_ci			post->page_set[i].page1_low =
503862306a36Sopenharmony_ci				cpu_to_le32(lower_32_bits(page1[i]->phys));
503962306a36Sopenharmony_ci			post->page_set[i].page1_high =
504062306a36Sopenharmony_ci				cpu_to_le32(upper_32_bits(page1[i]->phys));
504162306a36Sopenharmony_ci		}
504262306a36Sopenharmony_ci	}
504362306a36Sopenharmony_ci
504462306a36Sopenharmony_ci	return 0;
504562306a36Sopenharmony_ci}
504662306a36Sopenharmony_ci
504762306a36Sopenharmony_ciint
504862306a36Sopenharmony_cisli_cmd_post_hdr_templates(struct sli4 *sli4, void *buf, struct efc_dma *dma,
504962306a36Sopenharmony_ci			   u16 rpi, struct efc_dma *payload_dma)
505062306a36Sopenharmony_ci{
505162306a36Sopenharmony_ci	struct sli4_rqst_post_hdr_templates *req = NULL;
505262306a36Sopenharmony_ci	uintptr_t phys = 0;
505362306a36Sopenharmony_ci	u32 i = 0;
505462306a36Sopenharmony_ci	u32 page_count, payload_size;
505562306a36Sopenharmony_ci
505662306a36Sopenharmony_ci	page_count = sli_page_count(dma->size, SLI_PAGE_SIZE);
505762306a36Sopenharmony_ci
505862306a36Sopenharmony_ci	payload_size = ((sizeof(struct sli4_rqst_post_hdr_templates) +
505962306a36Sopenharmony_ci		(page_count * SZ_DMAADDR)) - sizeof(struct sli4_rqst_hdr));
506062306a36Sopenharmony_ci
506162306a36Sopenharmony_ci	if (page_count > 16) {
506262306a36Sopenharmony_ci		/*
506362306a36Sopenharmony_ci		 * We can't fit more than 16 descriptors into an embedded mbox
506462306a36Sopenharmony_ci		 * command, it has to be non-embedded
506562306a36Sopenharmony_ci		 */
506662306a36Sopenharmony_ci		payload_dma->size = payload_size;
506762306a36Sopenharmony_ci		payload_dma->virt = dma_alloc_coherent(&sli4->pci->dev,
506862306a36Sopenharmony_ci						       payload_dma->size,
506962306a36Sopenharmony_ci					     &payload_dma->phys, GFP_KERNEL);
507062306a36Sopenharmony_ci		if (!payload_dma->virt) {
507162306a36Sopenharmony_ci			memset(payload_dma, 0, sizeof(struct efc_dma));
507262306a36Sopenharmony_ci			efc_log_err(sli4, "mbox payload memory allocation fail\n");
507362306a36Sopenharmony_ci			return -EIO;
507462306a36Sopenharmony_ci		}
507562306a36Sopenharmony_ci		req = sli_config_cmd_init(sli4, buf, payload_size, payload_dma);
507662306a36Sopenharmony_ci	} else {
507762306a36Sopenharmony_ci		req = sli_config_cmd_init(sli4, buf, payload_size, NULL);
507862306a36Sopenharmony_ci	}
507962306a36Sopenharmony_ci
508062306a36Sopenharmony_ci	if (!req)
508162306a36Sopenharmony_ci		return -EIO;
508262306a36Sopenharmony_ci
508362306a36Sopenharmony_ci	if (rpi == U16_MAX)
508462306a36Sopenharmony_ci		rpi = sli4->ext[SLI4_RSRC_RPI].base[0];
508562306a36Sopenharmony_ci
508662306a36Sopenharmony_ci	sli_cmd_fill_hdr(&req->hdr, SLI4_OPC_POST_HDR_TEMPLATES,
508762306a36Sopenharmony_ci			 SLI4_SUBSYSTEM_FC, CMD_V0,
508862306a36Sopenharmony_ci			 SLI4_RQST_PYLD_LEN(post_hdr_templates));
508962306a36Sopenharmony_ci
509062306a36Sopenharmony_ci	req->rpi_offset = cpu_to_le16(rpi);
509162306a36Sopenharmony_ci	req->page_count = cpu_to_le16(page_count);
509262306a36Sopenharmony_ci	phys = dma->phys;
509362306a36Sopenharmony_ci	for (i = 0; i < page_count; i++) {
509462306a36Sopenharmony_ci		req->page_descriptor[i].low  = cpu_to_le32(lower_32_bits(phys));
509562306a36Sopenharmony_ci		req->page_descriptor[i].high = cpu_to_le32(upper_32_bits(phys));
509662306a36Sopenharmony_ci
509762306a36Sopenharmony_ci		phys += SLI_PAGE_SIZE;
509862306a36Sopenharmony_ci	}
509962306a36Sopenharmony_ci
510062306a36Sopenharmony_ci	return 0;
510162306a36Sopenharmony_ci}
510262306a36Sopenharmony_ci
510362306a36Sopenharmony_ciu32
510462306a36Sopenharmony_cisli_fc_get_rpi_requirements(struct sli4 *sli4, u32 n_rpi)
510562306a36Sopenharmony_ci{
510662306a36Sopenharmony_ci	u32 bytes = 0;
510762306a36Sopenharmony_ci
510862306a36Sopenharmony_ci	/* Check if header templates needed */
510962306a36Sopenharmony_ci	if (sli4->params.hdr_template_req)
511062306a36Sopenharmony_ci		/* round up to a page */
511162306a36Sopenharmony_ci		bytes = round_up(n_rpi * SLI4_HDR_TEMPLATE_SIZE, SLI_PAGE_SIZE);
511262306a36Sopenharmony_ci
511362306a36Sopenharmony_ci	return bytes;
511462306a36Sopenharmony_ci}
511562306a36Sopenharmony_ci
511662306a36Sopenharmony_ciconst char *
511762306a36Sopenharmony_cisli_fc_get_status_string(u32 status)
511862306a36Sopenharmony_ci{
511962306a36Sopenharmony_ci	static struct {
512062306a36Sopenharmony_ci		u32 code;
512162306a36Sopenharmony_ci		const char *label;
512262306a36Sopenharmony_ci	} lookup[] = {
512362306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_SUCCESS,		"SUCCESS"},
512462306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE,	"FCP_RSP_FAILURE"},
512562306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_REMOTE_STOP,	"REMOTE_STOP"},
512662306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_LOCAL_REJECT,	"LOCAL_REJECT"},
512762306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_NPORT_RJT,		"NPORT_RJT"},
512862306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_FABRIC_RJT,	"FABRIC_RJT"},
512962306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_NPORT_BSY,		"NPORT_BSY"},
513062306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_FABRIC_BSY,	"FABRIC_BSY"},
513162306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_LS_RJT,		"LS_RJT"},
513262306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_CMD_REJECT,	"CMD_REJECT"},
513362306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_FCP_TGT_LENCHECK,	"FCP_TGT_LENCHECK"},
513462306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RQ_BUF_LEN_EXCEEDED, "BUF_LEN_EXCEEDED"},
513562306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_BUF_NEEDED,
513662306a36Sopenharmony_ci				"RQ_INSUFF_BUF_NEEDED"},
513762306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_FRM_DISC, "RQ_INSUFF_FRM_DESC"},
513862306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RQ_DMA_FAILURE,	"RQ_DMA_FAILURE"},
513962306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_FCP_RSP_TRUNCATE,	"FCP_RSP_TRUNCATE"},
514062306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_DI_ERROR,		"DI_ERROR"},
514162306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_BA_RJT,		"BA_RJT"},
514262306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_NEEDED,
514362306a36Sopenharmony_ci				"RQ_INSUFF_XRI_NEEDED"},
514462306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_DISC, "INSUFF_XRI_DISC"},
514562306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RX_ERROR_DETECT,	"RX_ERROR_DETECT"},
514662306a36Sopenharmony_ci		{SLI4_FC_WCQE_STATUS_RX_ABORT_REQUEST,	"RX_ABORT_REQUEST"},
514762306a36Sopenharmony_ci		};
514862306a36Sopenharmony_ci	u32 i;
514962306a36Sopenharmony_ci
515062306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(lookup); i++) {
515162306a36Sopenharmony_ci		if (status == lookup[i].code)
515262306a36Sopenharmony_ci			return lookup[i].label;
515362306a36Sopenharmony_ci	}
515462306a36Sopenharmony_ci	return "unknown";
515562306a36Sopenharmony_ci}
5156