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