18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2017 Broadcom. All Rights Reserved. 48c2ecf20Sopenharmony_ci * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Contact Information: 78c2ecf20Sopenharmony_ci * linux-drivers@broadcom.com 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <scsi/iscsi_proto.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "be_main.h" 138c2ecf20Sopenharmony_ci#include "be.h" 148c2ecf20Sopenharmony_ci#include "be_mgmt.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* UE Status Low CSR */ 178c2ecf20Sopenharmony_cistatic const char * const desc_ue_status_low[] = { 188c2ecf20Sopenharmony_ci "CEV", 198c2ecf20Sopenharmony_ci "CTX", 208c2ecf20Sopenharmony_ci "DBUF", 218c2ecf20Sopenharmony_ci "ERX", 228c2ecf20Sopenharmony_ci "Host", 238c2ecf20Sopenharmony_ci "MPU", 248c2ecf20Sopenharmony_ci "NDMA", 258c2ecf20Sopenharmony_ci "PTC ", 268c2ecf20Sopenharmony_ci "RDMA ", 278c2ecf20Sopenharmony_ci "RXF ", 288c2ecf20Sopenharmony_ci "RXIPS ", 298c2ecf20Sopenharmony_ci "RXULP0 ", 308c2ecf20Sopenharmony_ci "RXULP1 ", 318c2ecf20Sopenharmony_ci "RXULP2 ", 328c2ecf20Sopenharmony_ci "TIM ", 338c2ecf20Sopenharmony_ci "TPOST ", 348c2ecf20Sopenharmony_ci "TPRE ", 358c2ecf20Sopenharmony_ci "TXIPS ", 368c2ecf20Sopenharmony_ci "TXULP0 ", 378c2ecf20Sopenharmony_ci "TXULP1 ", 388c2ecf20Sopenharmony_ci "UC ", 398c2ecf20Sopenharmony_ci "WDMA ", 408c2ecf20Sopenharmony_ci "TXULP2 ", 418c2ecf20Sopenharmony_ci "HOST1 ", 428c2ecf20Sopenharmony_ci "P0_OB_LINK ", 438c2ecf20Sopenharmony_ci "P1_OB_LINK ", 448c2ecf20Sopenharmony_ci "HOST_GPIO ", 458c2ecf20Sopenharmony_ci "MBOX ", 468c2ecf20Sopenharmony_ci "AXGMAC0", 478c2ecf20Sopenharmony_ci "AXGMAC1", 488c2ecf20Sopenharmony_ci "JTAG", 498c2ecf20Sopenharmony_ci "MPU_INTPEND" 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* UE Status High CSR */ 538c2ecf20Sopenharmony_cistatic const char * const desc_ue_status_hi[] = { 548c2ecf20Sopenharmony_ci "LPCMEMHOST", 558c2ecf20Sopenharmony_ci "MGMT_MAC", 568c2ecf20Sopenharmony_ci "PCS0ONLINE", 578c2ecf20Sopenharmony_ci "MPU_IRAM", 588c2ecf20Sopenharmony_ci "PCS1ONLINE", 598c2ecf20Sopenharmony_ci "PCTL0", 608c2ecf20Sopenharmony_ci "PCTL1", 618c2ecf20Sopenharmony_ci "PMEM", 628c2ecf20Sopenharmony_ci "RR", 638c2ecf20Sopenharmony_ci "TXPB", 648c2ecf20Sopenharmony_ci "RXPP", 658c2ecf20Sopenharmony_ci "XAUI", 668c2ecf20Sopenharmony_ci "TXP", 678c2ecf20Sopenharmony_ci "ARM", 688c2ecf20Sopenharmony_ci "IPC", 698c2ecf20Sopenharmony_ci "HOST2", 708c2ecf20Sopenharmony_ci "HOST3", 718c2ecf20Sopenharmony_ci "HOST4", 728c2ecf20Sopenharmony_ci "HOST5", 738c2ecf20Sopenharmony_ci "HOST6", 748c2ecf20Sopenharmony_ci "HOST7", 758c2ecf20Sopenharmony_ci "HOST8", 768c2ecf20Sopenharmony_ci "HOST9", 778c2ecf20Sopenharmony_ci "NETC", 788c2ecf20Sopenharmony_ci "Unknown", 798c2ecf20Sopenharmony_ci "Unknown", 808c2ecf20Sopenharmony_ci "Unknown", 818c2ecf20Sopenharmony_ci "Unknown", 828c2ecf20Sopenharmony_ci "Unknown", 838c2ecf20Sopenharmony_ci "Unknown", 848c2ecf20Sopenharmony_ci "Unknown", 858c2ecf20Sopenharmony_ci "Unknown" 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistruct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, 898c2ecf20Sopenharmony_ci unsigned int *ref_tag) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; 928c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = NULL; 938c2ecf20Sopenharmony_ci unsigned int tag; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci spin_lock(&phba->ctrl.mcc_lock); 968c2ecf20Sopenharmony_ci if (mccq->used == mccq->len) { 978c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | 988c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 998c2ecf20Sopenharmony_ci "BC_%d : MCC queue full: WRB used %u tag avail %u\n", 1008c2ecf20Sopenharmony_ci mccq->used, phba->ctrl.mcc_tag_available); 1018c2ecf20Sopenharmony_ci goto alloc_failed; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (!phba->ctrl.mcc_tag_available) 1058c2ecf20Sopenharmony_ci goto alloc_failed; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; 1088c2ecf20Sopenharmony_ci if (!tag) { 1098c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | 1108c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 1118c2ecf20Sopenharmony_ci "BC_%d : MCC tag 0 allocated: tag avail %u alloc index %u\n", 1128c2ecf20Sopenharmony_ci phba->ctrl.mcc_tag_available, 1138c2ecf20Sopenharmony_ci phba->ctrl.mcc_alloc_index); 1148c2ecf20Sopenharmony_ci goto alloc_failed; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* return this tag for further reference */ 1188c2ecf20Sopenharmony_ci *ref_tag = tag; 1198c2ecf20Sopenharmony_ci phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; 1208c2ecf20Sopenharmony_ci phba->ctrl.mcc_tag_status[tag] = 0; 1218c2ecf20Sopenharmony_ci phba->ctrl.ptag_state[tag].tag_state = 0; 1228c2ecf20Sopenharmony_ci phba->ctrl.ptag_state[tag].cbfn = NULL; 1238c2ecf20Sopenharmony_ci phba->ctrl.mcc_tag_available--; 1248c2ecf20Sopenharmony_ci if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) 1258c2ecf20Sopenharmony_ci phba->ctrl.mcc_alloc_index = 0; 1268c2ecf20Sopenharmony_ci else 1278c2ecf20Sopenharmony_ci phba->ctrl.mcc_alloc_index++; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci wrb = queue_head_node(mccq); 1308c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 1318c2ecf20Sopenharmony_ci wrb->tag0 = tag; 1328c2ecf20Sopenharmony_ci wrb->tag0 |= (mccq->head << MCC_Q_WRB_IDX_SHIFT) & MCC_Q_WRB_IDX_MASK; 1338c2ecf20Sopenharmony_ci queue_head_inc(mccq); 1348c2ecf20Sopenharmony_ci mccq->used++; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cialloc_failed: 1378c2ecf20Sopenharmony_ci spin_unlock(&phba->ctrl.mcc_lock); 1388c2ecf20Sopenharmony_ci return wrb; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_civoid free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct be_queue_info *mccq = &ctrl->mcc_obj.q; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci spin_lock(&ctrl->mcc_lock); 1468c2ecf20Sopenharmony_ci tag = tag & MCC_Q_CMD_TAG_MASK; 1478c2ecf20Sopenharmony_ci ctrl->mcc_tag[ctrl->mcc_free_index] = tag; 1488c2ecf20Sopenharmony_ci if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) 1498c2ecf20Sopenharmony_ci ctrl->mcc_free_index = 0; 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci ctrl->mcc_free_index++; 1528c2ecf20Sopenharmony_ci ctrl->mcc_tag_available++; 1538c2ecf20Sopenharmony_ci mccq->used--; 1548c2ecf20Sopenharmony_ci spin_unlock(&ctrl->mcc_lock); 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/* 1588c2ecf20Sopenharmony_ci * beiscsi_mcc_compl_status - Return the status of MCC completion 1598c2ecf20Sopenharmony_ci * @phba: Driver private structure 1608c2ecf20Sopenharmony_ci * @tag: Tag for the MBX Command 1618c2ecf20Sopenharmony_ci * @wrb: the WRB used for the MBX Command 1628c2ecf20Sopenharmony_ci * @mbx_cmd_mem: ptr to memory allocated for MBX Cmd 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci * return 1658c2ecf20Sopenharmony_ci * Success: 0 1668c2ecf20Sopenharmony_ci * Failure: Non-Zero 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_ciint __beiscsi_mcc_compl_status(struct beiscsi_hba *phba, 1698c2ecf20Sopenharmony_ci unsigned int tag, 1708c2ecf20Sopenharmony_ci struct be_mcc_wrb **wrb, 1718c2ecf20Sopenharmony_ci struct be_dma_mem *mbx_cmd_mem) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; 1748c2ecf20Sopenharmony_ci uint16_t status = 0, addl_status = 0, wrb_num = 0; 1758c2ecf20Sopenharmony_ci struct be_cmd_resp_hdr *mbx_resp_hdr; 1768c2ecf20Sopenharmony_ci struct be_cmd_req_hdr *mbx_hdr; 1778c2ecf20Sopenharmony_ci struct be_mcc_wrb *temp_wrb; 1788c2ecf20Sopenharmony_ci uint32_t mcc_tag_status; 1798c2ecf20Sopenharmony_ci int rc = 0; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci mcc_tag_status = phba->ctrl.mcc_tag_status[tag]; 1828c2ecf20Sopenharmony_ci status = (mcc_tag_status & CQE_STATUS_MASK); 1838c2ecf20Sopenharmony_ci addl_status = ((mcc_tag_status & CQE_STATUS_ADDL_MASK) >> 1848c2ecf20Sopenharmony_ci CQE_STATUS_ADDL_SHIFT); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (mbx_cmd_mem) { 1878c2ecf20Sopenharmony_ci mbx_hdr = (struct be_cmd_req_hdr *)mbx_cmd_mem->va; 1888c2ecf20Sopenharmony_ci } else { 1898c2ecf20Sopenharmony_ci wrb_num = (mcc_tag_status & CQE_STATUS_WRB_MASK) >> 1908c2ecf20Sopenharmony_ci CQE_STATUS_WRB_SHIFT; 1918c2ecf20Sopenharmony_ci temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); 1928c2ecf20Sopenharmony_ci mbx_hdr = embedded_payload(temp_wrb); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (wrb) 1958c2ecf20Sopenharmony_ci *wrb = temp_wrb; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (status || addl_status) { 1998c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, 2008c2ecf20Sopenharmony_ci BEISCSI_LOG_INIT | BEISCSI_LOG_EH | 2018c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG, 2028c2ecf20Sopenharmony_ci "BC_%d : MBX Cmd Failed for Subsys : %d Opcode : %d with Status : %d and Extd_Status : %d\n", 2038c2ecf20Sopenharmony_ci mbx_hdr->subsystem, mbx_hdr->opcode, 2048c2ecf20Sopenharmony_ci status, addl_status); 2058c2ecf20Sopenharmony_ci rc = -EIO; 2068c2ecf20Sopenharmony_ci if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { 2078c2ecf20Sopenharmony_ci mbx_resp_hdr = (struct be_cmd_resp_hdr *)mbx_hdr; 2088c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, 2098c2ecf20Sopenharmony_ci BEISCSI_LOG_INIT | BEISCSI_LOG_EH | 2108c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG, 2118c2ecf20Sopenharmony_ci "BC_%d : Insufficient Buffer Error Resp_Len : %d Actual_Resp_Len : %d\n", 2128c2ecf20Sopenharmony_ci mbx_resp_hdr->response_length, 2138c2ecf20Sopenharmony_ci mbx_resp_hdr->actual_resp_len); 2148c2ecf20Sopenharmony_ci rc = -EAGAIN; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return rc; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci/* 2228c2ecf20Sopenharmony_ci * beiscsi_mccq_compl_wait()- Process completion in MCC CQ 2238c2ecf20Sopenharmony_ci * @phba: Driver private structure 2248c2ecf20Sopenharmony_ci * @tag: Tag for the MBX Command 2258c2ecf20Sopenharmony_ci * @wrb: the WRB used for the MBX Command 2268c2ecf20Sopenharmony_ci * @mbx_cmd_mem: ptr to memory allocated for MBX Cmd 2278c2ecf20Sopenharmony_ci * 2288c2ecf20Sopenharmony_ci * Waits for MBX completion with the passed TAG. 2298c2ecf20Sopenharmony_ci * 2308c2ecf20Sopenharmony_ci * return 2318c2ecf20Sopenharmony_ci * Success: 0 2328c2ecf20Sopenharmony_ci * Failure: Non-Zero 2338c2ecf20Sopenharmony_ci **/ 2348c2ecf20Sopenharmony_ciint beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, 2358c2ecf20Sopenharmony_ci unsigned int tag, 2368c2ecf20Sopenharmony_ci struct be_mcc_wrb **wrb, 2378c2ecf20Sopenharmony_ci struct be_dma_mem *mbx_cmd_mem) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci int rc = 0; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (!tag || tag > MAX_MCC_CMD) { 2428c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 2438c2ecf20Sopenharmony_ci "BC_%d : invalid tag %u\n", tag); 2448c2ecf20Sopenharmony_ci return -EINVAL; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (beiscsi_hba_in_error(phba)) { 2488c2ecf20Sopenharmony_ci clear_bit(MCC_TAG_STATE_RUNNING, 2498c2ecf20Sopenharmony_ci &phba->ctrl.ptag_state[tag].tag_state); 2508c2ecf20Sopenharmony_ci return -EIO; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* wait for the mccq completion */ 2548c2ecf20Sopenharmony_ci rc = wait_event_interruptible_timeout(phba->ctrl.mcc_wait[tag], 2558c2ecf20Sopenharmony_ci phba->ctrl.mcc_tag_status[tag], 2568c2ecf20Sopenharmony_ci msecs_to_jiffies( 2578c2ecf20Sopenharmony_ci BEISCSI_HOST_MBX_TIMEOUT)); 2588c2ecf20Sopenharmony_ci /** 2598c2ecf20Sopenharmony_ci * Return EIO if port is being disabled. Associated DMA memory, if any, 2608c2ecf20Sopenharmony_ci * is freed by the caller. When port goes offline, MCCQ is cleaned up 2618c2ecf20Sopenharmony_ci * so does WRB. 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ci if (!test_bit(BEISCSI_HBA_ONLINE, &phba->state)) { 2648c2ecf20Sopenharmony_ci clear_bit(MCC_TAG_STATE_RUNNING, 2658c2ecf20Sopenharmony_ci &phba->ctrl.ptag_state[tag].tag_state); 2668c2ecf20Sopenharmony_ci return -EIO; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /** 2708c2ecf20Sopenharmony_ci * If MBOX cmd timeout expired, tag and resource allocated 2718c2ecf20Sopenharmony_ci * for cmd is not freed until FW returns completion. 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci if (rc <= 0) { 2748c2ecf20Sopenharmony_ci struct be_dma_mem *tag_mem; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /** 2778c2ecf20Sopenharmony_ci * PCI/DMA memory allocated and posted in non-embedded mode 2788c2ecf20Sopenharmony_ci * will have mbx_cmd_mem != NULL. 2798c2ecf20Sopenharmony_ci * Save virtual and bus addresses for the command so that it 2808c2ecf20Sopenharmony_ci * can be freed later. 2818c2ecf20Sopenharmony_ci **/ 2828c2ecf20Sopenharmony_ci tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; 2838c2ecf20Sopenharmony_ci if (mbx_cmd_mem) { 2848c2ecf20Sopenharmony_ci tag_mem->size = mbx_cmd_mem->size; 2858c2ecf20Sopenharmony_ci tag_mem->va = mbx_cmd_mem->va; 2868c2ecf20Sopenharmony_ci tag_mem->dma = mbx_cmd_mem->dma; 2878c2ecf20Sopenharmony_ci } else 2888c2ecf20Sopenharmony_ci tag_mem->size = 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* first make tag_mem_state visible to all */ 2918c2ecf20Sopenharmony_ci wmb(); 2928c2ecf20Sopenharmony_ci set_bit(MCC_TAG_STATE_TIMEOUT, 2938c2ecf20Sopenharmony_ci &phba->ctrl.ptag_state[tag].tag_state); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 2968c2ecf20Sopenharmony_ci BEISCSI_LOG_INIT | BEISCSI_LOG_EH | 2978c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG, 2988c2ecf20Sopenharmony_ci "BC_%d : MBX Cmd Completion timed out\n"); 2998c2ecf20Sopenharmony_ci return -EBUSY; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci rc = __beiscsi_mcc_compl_status(phba, tag, wrb, mbx_cmd_mem); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci free_mcc_wrb(&phba->ctrl, tag); 3058c2ecf20Sopenharmony_ci return rc; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/* 3098c2ecf20Sopenharmony_ci * beiscsi_process_mbox_compl()- Check the MBX completion status 3108c2ecf20Sopenharmony_ci * @ctrl: Function specific MBX data structure 3118c2ecf20Sopenharmony_ci * @compl: Completion status of MBX Command 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * Check for the MBX completion status when BMBX method used 3148c2ecf20Sopenharmony_ci * 3158c2ecf20Sopenharmony_ci * return 3168c2ecf20Sopenharmony_ci * Success: Zero 3178c2ecf20Sopenharmony_ci * Failure: Non-Zero 3188c2ecf20Sopenharmony_ci **/ 3198c2ecf20Sopenharmony_cistatic int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, 3208c2ecf20Sopenharmony_ci struct be_mcc_compl *compl) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 3238c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 3248c2ecf20Sopenharmony_ci struct be_cmd_req_hdr *hdr = embedded_payload(wrb); 3258c2ecf20Sopenharmony_ci u16 compl_status, extd_status; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /** 3288c2ecf20Sopenharmony_ci * To check if valid bit is set, check the entire word as we don't know 3298c2ecf20Sopenharmony_ci * the endianness of the data (old entry is host endian while a new 3308c2ecf20Sopenharmony_ci * entry is little endian) 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_ci if (!compl->flags) { 3338c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 3348c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 3358c2ecf20Sopenharmony_ci "BC_%d : BMBX busy, no completion\n"); 3368c2ecf20Sopenharmony_ci return -EBUSY; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci compl->flags = le32_to_cpu(compl->flags); 3398c2ecf20Sopenharmony_ci WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /** 3428c2ecf20Sopenharmony_ci * Just swap the status to host endian; 3438c2ecf20Sopenharmony_ci * mcc tag is opaquely copied from mcc_wrb. 3448c2ecf20Sopenharmony_ci */ 3458c2ecf20Sopenharmony_ci be_dws_le_to_cpu(compl, 4); 3468c2ecf20Sopenharmony_ci compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & 3478c2ecf20Sopenharmony_ci CQE_STATUS_COMPL_MASK; 3488c2ecf20Sopenharmony_ci extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & 3498c2ecf20Sopenharmony_ci CQE_STATUS_EXTD_MASK; 3508c2ecf20Sopenharmony_ci /* Need to reset the entire word that houses the valid bit */ 3518c2ecf20Sopenharmony_ci compl->flags = 0; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci if (compl_status == MCC_STATUS_SUCCESS) 3548c2ecf20Sopenharmony_ci return 0; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 3578c2ecf20Sopenharmony_ci "BC_%d : error in cmd completion: Subsystem : %d Opcode : %d status(compl/extd)=%d/%d\n", 3588c2ecf20Sopenharmony_ci hdr->subsystem, hdr->opcode, compl_status, extd_status); 3598c2ecf20Sopenharmony_ci return compl_status; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic void beiscsi_process_async_link(struct beiscsi_hba *phba, 3638c2ecf20Sopenharmony_ci struct be_mcc_compl *compl) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci struct be_async_event_link_state *evt; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci evt = (struct be_async_event_link_state *)compl; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci phba->port_speed = evt->port_speed; 3708c2ecf20Sopenharmony_ci /** 3718c2ecf20Sopenharmony_ci * Check logical link status in ASYNC event. 3728c2ecf20Sopenharmony_ci * This has been newly introduced in SKH-R Firmware 10.0.338.45. 3738c2ecf20Sopenharmony_ci **/ 3748c2ecf20Sopenharmony_ci if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { 3758c2ecf20Sopenharmony_ci set_bit(BEISCSI_HBA_LINK_UP, &phba->state); 3768c2ecf20Sopenharmony_ci if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state)) 3778c2ecf20Sopenharmony_ci beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE); 3788c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 3798c2ecf20Sopenharmony_ci "BC_%d : Link Up on Port %d tag 0x%x\n", 3808c2ecf20Sopenharmony_ci evt->physical_port, evt->event_tag); 3818c2ecf20Sopenharmony_ci } else { 3828c2ecf20Sopenharmony_ci clear_bit(BEISCSI_HBA_LINK_UP, &phba->state); 3838c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 3848c2ecf20Sopenharmony_ci "BC_%d : Link Down on Port %d tag 0x%x\n", 3858c2ecf20Sopenharmony_ci evt->physical_port, evt->event_tag); 3868c2ecf20Sopenharmony_ci iscsi_host_for_each_session(phba->shost, 3878c2ecf20Sopenharmony_ci beiscsi_session_fail); 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic char *beiscsi_port_misconf_event_msg[] = { 3928c2ecf20Sopenharmony_ci "Physical Link is functional.", 3938c2ecf20Sopenharmony_ci "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", 3948c2ecf20Sopenharmony_ci "Optics of two types installed - Remove one optic or install matching pair of optics.", 3958c2ecf20Sopenharmony_ci "Incompatible optics - Replace with compatible optics for card to function.", 3968c2ecf20Sopenharmony_ci "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", 3978c2ecf20Sopenharmony_ci "Uncertified optics - Replace with Avago Certified optics to enable link operation." 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic void beiscsi_process_async_sli(struct beiscsi_hba *phba, 4018c2ecf20Sopenharmony_ci struct be_mcc_compl *compl) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci struct be_async_event_sli *async_sli; 4048c2ecf20Sopenharmony_ci u8 evt_type, state, old_state, le; 4058c2ecf20Sopenharmony_ci char *sev = KERN_WARNING; 4068c2ecf20Sopenharmony_ci char *msg = NULL; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci evt_type = compl->flags >> ASYNC_TRAILER_EVENT_TYPE_SHIFT; 4098c2ecf20Sopenharmony_ci evt_type &= ASYNC_TRAILER_EVENT_TYPE_MASK; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* processing only MISCONFIGURED physical port event */ 4128c2ecf20Sopenharmony_ci if (evt_type != ASYNC_SLI_EVENT_TYPE_MISCONFIGURED) 4138c2ecf20Sopenharmony_ci return; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci async_sli = (struct be_async_event_sli *)compl; 4168c2ecf20Sopenharmony_ci state = async_sli->event_data1 >> 4178c2ecf20Sopenharmony_ci (phba->fw_config.phys_port * 8) & 0xff; 4188c2ecf20Sopenharmony_ci le = async_sli->event_data2 >> 4198c2ecf20Sopenharmony_ci (phba->fw_config.phys_port * 8) & 0xff; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci old_state = phba->optic_state; 4228c2ecf20Sopenharmony_ci phba->optic_state = state; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci if (state >= ARRAY_SIZE(beiscsi_port_misconf_event_msg)) { 4258c2ecf20Sopenharmony_ci /* fw is reporting a state we don't know, log and return */ 4268c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 4278c2ecf20Sopenharmony_ci "BC_%d : Port %c: Unrecognized optic state 0x%x\n", 4288c2ecf20Sopenharmony_ci phba->port_name, async_sli->event_data1); 4298c2ecf20Sopenharmony_ci return; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci if (ASYNC_SLI_LINK_EFFECT_VALID(le)) { 4338c2ecf20Sopenharmony_ci /* log link effect for unqualified-4, uncertified-5 optics */ 4348c2ecf20Sopenharmony_ci if (state > 3) 4358c2ecf20Sopenharmony_ci msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ? 4368c2ecf20Sopenharmony_ci " Link is non-operational." : 4378c2ecf20Sopenharmony_ci " Link is operational."; 4388c2ecf20Sopenharmony_ci /* 1 - info */ 4398c2ecf20Sopenharmony_ci if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1) 4408c2ecf20Sopenharmony_ci sev = KERN_INFO; 4418c2ecf20Sopenharmony_ci /* 2 - error */ 4428c2ecf20Sopenharmony_ci if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2) 4438c2ecf20Sopenharmony_ci sev = KERN_ERR; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if (old_state != phba->optic_state) 4478c2ecf20Sopenharmony_ci __beiscsi_log(phba, sev, "BC_%d : Port %c: %s%s\n", 4488c2ecf20Sopenharmony_ci phba->port_name, 4498c2ecf20Sopenharmony_ci beiscsi_port_misconf_event_msg[state], 4508c2ecf20Sopenharmony_ci !msg ? "" : msg); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_civoid beiscsi_process_async_event(struct beiscsi_hba *phba, 4548c2ecf20Sopenharmony_ci struct be_mcc_compl *compl) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci char *sev = KERN_INFO; 4578c2ecf20Sopenharmony_ci u8 evt_code; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* interpret flags as an async trailer */ 4608c2ecf20Sopenharmony_ci evt_code = compl->flags >> ASYNC_TRAILER_EVENT_CODE_SHIFT; 4618c2ecf20Sopenharmony_ci evt_code &= ASYNC_TRAILER_EVENT_CODE_MASK; 4628c2ecf20Sopenharmony_ci switch (evt_code) { 4638c2ecf20Sopenharmony_ci case ASYNC_EVENT_CODE_LINK_STATE: 4648c2ecf20Sopenharmony_ci beiscsi_process_async_link(phba, compl); 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci case ASYNC_EVENT_CODE_ISCSI: 4678c2ecf20Sopenharmony_ci if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state)) 4688c2ecf20Sopenharmony_ci beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE); 4698c2ecf20Sopenharmony_ci sev = KERN_ERR; 4708c2ecf20Sopenharmony_ci break; 4718c2ecf20Sopenharmony_ci case ASYNC_EVENT_CODE_SLI: 4728c2ecf20Sopenharmony_ci beiscsi_process_async_sli(phba, compl); 4738c2ecf20Sopenharmony_ci break; 4748c2ecf20Sopenharmony_ci default: 4758c2ecf20Sopenharmony_ci /* event not registered */ 4768c2ecf20Sopenharmony_ci sev = KERN_ERR; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci beiscsi_log(phba, sev, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 4808c2ecf20Sopenharmony_ci "BC_%d : ASYNC Event %x: status 0x%08x flags 0x%08x\n", 4818c2ecf20Sopenharmony_ci evt_code, compl->status, compl->flags); 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ciint beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, 4858c2ecf20Sopenharmony_ci struct be_mcc_compl *compl) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 4888c2ecf20Sopenharmony_ci u16 compl_status, extd_status; 4898c2ecf20Sopenharmony_ci struct be_dma_mem *tag_mem; 4908c2ecf20Sopenharmony_ci unsigned int tag, wrb_idx; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci be_dws_le_to_cpu(compl, 4); 4938c2ecf20Sopenharmony_ci tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); 4948c2ecf20Sopenharmony_ci wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (!test_bit(MCC_TAG_STATE_RUNNING, 4978c2ecf20Sopenharmony_ci &ctrl->ptag_state[tag].tag_state)) { 4988c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX | 4998c2ecf20Sopenharmony_ci BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 5008c2ecf20Sopenharmony_ci "BC_%d : MBX cmd completed but not posted\n"); 5018c2ecf20Sopenharmony_ci return 0; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci /* end MCC with this tag */ 5058c2ecf20Sopenharmony_ci clear_bit(MCC_TAG_STATE_RUNNING, &ctrl->ptag_state[tag].tag_state); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci if (test_bit(MCC_TAG_STATE_TIMEOUT, &ctrl->ptag_state[tag].tag_state)) { 5088c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, 5098c2ecf20Sopenharmony_ci BEISCSI_LOG_MBOX | BEISCSI_LOG_INIT | 5108c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG, 5118c2ecf20Sopenharmony_ci "BC_%d : MBX Completion for timeout Command from FW\n"); 5128c2ecf20Sopenharmony_ci /** 5138c2ecf20Sopenharmony_ci * Check for the size before freeing resource. 5148c2ecf20Sopenharmony_ci * Only for non-embedded cmd, PCI resource is allocated. 5158c2ecf20Sopenharmony_ci **/ 5168c2ecf20Sopenharmony_ci tag_mem = &ctrl->ptag_state[tag].tag_mem_state; 5178c2ecf20Sopenharmony_ci if (tag_mem->size) { 5188c2ecf20Sopenharmony_ci dma_free_coherent(&ctrl->pdev->dev, tag_mem->size, 5198c2ecf20Sopenharmony_ci tag_mem->va, tag_mem->dma); 5208c2ecf20Sopenharmony_ci tag_mem->size = 0; 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci free_mcc_wrb(ctrl, tag); 5238c2ecf20Sopenharmony_ci return 0; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & 5278c2ecf20Sopenharmony_ci CQE_STATUS_COMPL_MASK; 5288c2ecf20Sopenharmony_ci extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & 5298c2ecf20Sopenharmony_ci CQE_STATUS_EXTD_MASK; 5308c2ecf20Sopenharmony_ci /* The ctrl.mcc_tag_status[tag] is filled with 5318c2ecf20Sopenharmony_ci * [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status, 5328c2ecf20Sopenharmony_ci * [7:0] = compl_status 5338c2ecf20Sopenharmony_ci */ 5348c2ecf20Sopenharmony_ci ctrl->mcc_tag_status[tag] = CQE_VALID_MASK; 5358c2ecf20Sopenharmony_ci ctrl->mcc_tag_status[tag] |= (wrb_idx << CQE_STATUS_WRB_SHIFT); 5368c2ecf20Sopenharmony_ci ctrl->mcc_tag_status[tag] |= (extd_status << CQE_STATUS_ADDL_SHIFT) & 5378c2ecf20Sopenharmony_ci CQE_STATUS_ADDL_MASK; 5388c2ecf20Sopenharmony_ci ctrl->mcc_tag_status[tag] |= (compl_status & CQE_STATUS_MASK); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (test_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state)) { 5418c2ecf20Sopenharmony_ci if (ctrl->ptag_state[tag].cbfn) 5428c2ecf20Sopenharmony_ci ctrl->ptag_state[tag].cbfn(phba, tag); 5438c2ecf20Sopenharmony_ci else 5448c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 5458c2ecf20Sopenharmony_ci "BC_%d : MBX ASYNC command with no callback\n"); 5468c2ecf20Sopenharmony_ci free_mcc_wrb(ctrl, tag); 5478c2ecf20Sopenharmony_ci return 0; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (test_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state)) { 5518c2ecf20Sopenharmony_ci /* just check completion status and free wrb */ 5528c2ecf20Sopenharmony_ci __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); 5538c2ecf20Sopenharmony_ci free_mcc_wrb(ctrl, tag); 5548c2ecf20Sopenharmony_ci return 0; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci wake_up_interruptible(&ctrl->mcc_wait[tag]); 5588c2ecf20Sopenharmony_ci return 0; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_civoid be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; 5648c2ecf20Sopenharmony_ci u32 val = 0; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); 5678c2ecf20Sopenharmony_ci val |= mccq->id & DB_MCCQ_RING_ID_MASK; 5688c2ecf20Sopenharmony_ci val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; 5698c2ecf20Sopenharmony_ci /* make request available for DMA */ 5708c2ecf20Sopenharmony_ci wmb(); 5718c2ecf20Sopenharmony_ci iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci/* 5758c2ecf20Sopenharmony_ci * be_mbox_db_ready_poll()- Check ready status 5768c2ecf20Sopenharmony_ci * @ctrl: Function specific MBX data structure 5778c2ecf20Sopenharmony_ci * 5788c2ecf20Sopenharmony_ci * Check for the ready status of FW to send BMBX 5798c2ecf20Sopenharmony_ci * commands to adapter. 5808c2ecf20Sopenharmony_ci * 5818c2ecf20Sopenharmony_ci * return 5828c2ecf20Sopenharmony_ci * Success: 0 5838c2ecf20Sopenharmony_ci * Failure: Non-Zero 5848c2ecf20Sopenharmony_ci **/ 5858c2ecf20Sopenharmony_cistatic int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci /* wait 30s for generic non-flash MBOX operation */ 5888c2ecf20Sopenharmony_ci#define BEISCSI_MBX_RDY_BIT_TIMEOUT 30000 5898c2ecf20Sopenharmony_ci void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; 5908c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 5918c2ecf20Sopenharmony_ci unsigned long timeout; 5928c2ecf20Sopenharmony_ci u32 ready; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci /* 5958c2ecf20Sopenharmony_ci * This BMBX busy wait path is used during init only. 5968c2ecf20Sopenharmony_ci * For the commands executed during init, 5s should suffice. 5978c2ecf20Sopenharmony_ci */ 5988c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); 5998c2ecf20Sopenharmony_ci do { 6008c2ecf20Sopenharmony_ci if (beiscsi_hba_in_error(phba)) 6018c2ecf20Sopenharmony_ci return -EIO; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci ready = ioread32(db); 6048c2ecf20Sopenharmony_ci if (ready == 0xffffffff) 6058c2ecf20Sopenharmony_ci return -EIO; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci ready &= MPU_MAILBOX_DB_RDY_MASK; 6088c2ecf20Sopenharmony_ci if (ready) 6098c2ecf20Sopenharmony_ci return 0; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci if (time_after(jiffies, timeout)) 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci /* 1ms sleep is enough in most cases */ 6148c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(msecs_to_jiffies(1)); 6158c2ecf20Sopenharmony_ci } while (!ready); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 6188c2ecf20Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 6198c2ecf20Sopenharmony_ci "BC_%d : FW Timed Out\n"); 6208c2ecf20Sopenharmony_ci set_bit(BEISCSI_HBA_FW_TIMEOUT, &phba->state); 6218c2ecf20Sopenharmony_ci return -EBUSY; 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci/* 6258c2ecf20Sopenharmony_ci * be_mbox_notify: Notify adapter of new BMBX command 6268c2ecf20Sopenharmony_ci * @ctrl: Function specific MBX data structure 6278c2ecf20Sopenharmony_ci * 6288c2ecf20Sopenharmony_ci * Ring doorbell to inform adapter of a BMBX command 6298c2ecf20Sopenharmony_ci * to process 6308c2ecf20Sopenharmony_ci * 6318c2ecf20Sopenharmony_ci * return 6328c2ecf20Sopenharmony_ci * Success: 0 6338c2ecf20Sopenharmony_ci * Failure: Non-Zero 6348c2ecf20Sopenharmony_ci **/ 6358c2ecf20Sopenharmony_cistatic int be_mbox_notify(struct be_ctrl_info *ctrl) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci int status; 6388c2ecf20Sopenharmony_ci u32 val = 0; 6398c2ecf20Sopenharmony_ci void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; 6408c2ecf20Sopenharmony_ci struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; 6418c2ecf20Sopenharmony_ci struct be_mcc_mailbox *mbox = mbox_mem->va; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci status = be_mbox_db_ready_poll(ctrl); 6448c2ecf20Sopenharmony_ci if (status) 6458c2ecf20Sopenharmony_ci return status; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci val &= ~MPU_MAILBOX_DB_RDY_MASK; 6488c2ecf20Sopenharmony_ci val |= MPU_MAILBOX_DB_HI_MASK; 6498c2ecf20Sopenharmony_ci val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; 6508c2ecf20Sopenharmony_ci iowrite32(val, db); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci status = be_mbox_db_ready_poll(ctrl); 6538c2ecf20Sopenharmony_ci if (status) 6548c2ecf20Sopenharmony_ci return status; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci val = 0; 6578c2ecf20Sopenharmony_ci val &= ~MPU_MAILBOX_DB_RDY_MASK; 6588c2ecf20Sopenharmony_ci val &= ~MPU_MAILBOX_DB_HI_MASK; 6598c2ecf20Sopenharmony_ci val |= (u32) (mbox_mem->dma >> 4) << 2; 6608c2ecf20Sopenharmony_ci iowrite32(val, db); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci status = be_mbox_db_ready_poll(ctrl); 6638c2ecf20Sopenharmony_ci if (status) 6648c2ecf20Sopenharmony_ci return status; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* RDY is set; small delay before CQE read. */ 6678c2ecf20Sopenharmony_ci udelay(1); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci status = beiscsi_process_mbox_compl(ctrl, &mbox->compl); 6708c2ecf20Sopenharmony_ci return status; 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_civoid be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, u32 payload_len, 6748c2ecf20Sopenharmony_ci bool embedded, u8 sge_cnt) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci if (embedded) 6778c2ecf20Sopenharmony_ci wrb->emb_sgecnt_special |= MCC_WRB_EMBEDDED_MASK; 6788c2ecf20Sopenharmony_ci else 6798c2ecf20Sopenharmony_ci wrb->emb_sgecnt_special |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << 6808c2ecf20Sopenharmony_ci MCC_WRB_SGE_CNT_SHIFT; 6818c2ecf20Sopenharmony_ci wrb->payload_length = payload_len; 6828c2ecf20Sopenharmony_ci be_dws_cpu_to_le(wrb, 8); 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_civoid be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, 6868c2ecf20Sopenharmony_ci u8 subsystem, u8 opcode, u32 cmd_len) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci req_hdr->opcode = opcode; 6898c2ecf20Sopenharmony_ci req_hdr->subsystem = subsystem; 6908c2ecf20Sopenharmony_ci req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); 6918c2ecf20Sopenharmony_ci req_hdr->timeout = BEISCSI_FW_MBX_TIMEOUT; 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, 6958c2ecf20Sopenharmony_ci struct be_dma_mem *mem) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci int i, buf_pages; 6988c2ecf20Sopenharmony_ci u64 dma = (u64) mem->dma; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); 7018c2ecf20Sopenharmony_ci for (i = 0; i < buf_pages; i++) { 7028c2ecf20Sopenharmony_ci pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); 7038c2ecf20Sopenharmony_ci pages[i].hi = cpu_to_le32(upper_32_bits(dma)); 7048c2ecf20Sopenharmony_ci dma += PAGE_SIZE_4K; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic u32 eq_delay_to_mult(u32 usec_delay) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci#define MAX_INTR_RATE 651042 7118c2ecf20Sopenharmony_ci const u32 round = 10; 7128c2ecf20Sopenharmony_ci u32 multiplier; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (usec_delay == 0) 7158c2ecf20Sopenharmony_ci multiplier = 0; 7168c2ecf20Sopenharmony_ci else { 7178c2ecf20Sopenharmony_ci u32 interrupt_rate = 1000000 / usec_delay; 7188c2ecf20Sopenharmony_ci if (interrupt_rate == 0) 7198c2ecf20Sopenharmony_ci multiplier = 1023; 7208c2ecf20Sopenharmony_ci else { 7218c2ecf20Sopenharmony_ci multiplier = (MAX_INTR_RATE - interrupt_rate) * round; 7228c2ecf20Sopenharmony_ci multiplier /= interrupt_rate; 7238c2ecf20Sopenharmony_ci multiplier = (multiplier + round / 2) / round; 7248c2ecf20Sopenharmony_ci multiplier = min(multiplier, (u32) 1023); 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci return multiplier; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_cistruct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ciint beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, 7368c2ecf20Sopenharmony_ci struct be_queue_info *eq, int eq_delay) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 7398c2ecf20Sopenharmony_ci struct be_cmd_req_eq_create *req = embedded_payload(wrb); 7408c2ecf20Sopenharmony_ci struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); 7418c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem = &eq->dma_mem; 7428c2ecf20Sopenharmony_ci int status; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 7458c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 7508c2ecf20Sopenharmony_ci OPCODE_COMMON_EQ_CREATE, sizeof(*req)); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_eq_context, func, req->context, 7558c2ecf20Sopenharmony_ci PCI_FUNC(ctrl->pdev->devfn)); 7568c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); 7578c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); 7588c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_eq_context, count, req->context, 7598c2ecf20Sopenharmony_ci __ilog2_u32(eq->len / 256)); 7608c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, 7618c2ecf20Sopenharmony_ci eq_delay_to_mult(eq_delay)); 7628c2ecf20Sopenharmony_ci be_dws_cpu_to_le(req->context, sizeof(req->context)); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 7678c2ecf20Sopenharmony_ci if (!status) { 7688c2ecf20Sopenharmony_ci eq->id = le16_to_cpu(resp->eq_id); 7698c2ecf20Sopenharmony_ci eq->created = true; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 7728c2ecf20Sopenharmony_ci return status; 7738c2ecf20Sopenharmony_ci} 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ciint beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, 7768c2ecf20Sopenharmony_ci struct be_queue_info *cq, struct be_queue_info *eq, 7778c2ecf20Sopenharmony_ci bool sol_evts, bool no_delay, int coalesce_wm) 7788c2ecf20Sopenharmony_ci{ 7798c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 7808c2ecf20Sopenharmony_ci struct be_cmd_req_cq_create *req = embedded_payload(wrb); 7818c2ecf20Sopenharmony_ci struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); 7828c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 7838c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem = &cq->dma_mem; 7848c2ecf20Sopenharmony_ci void *ctxt = &req->context; 7858c2ecf20Sopenharmony_ci int status; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 7888c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 7938c2ecf20Sopenharmony_ci OPCODE_COMMON_CQ_CREATE, sizeof(*req)); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); 7968c2ecf20Sopenharmony_ci if (is_chip_be2_be3r(phba)) { 7978c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, coalescwm, 7988c2ecf20Sopenharmony_ci ctxt, coalesce_wm); 7998c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); 8008c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, count, ctxt, 8018c2ecf20Sopenharmony_ci __ilog2_u32(cq->len / 256)); 8028c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); 8038c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); 8048c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); 8058c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); 8068c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); 8078c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context, func, ctxt, 8088c2ecf20Sopenharmony_ci PCI_FUNC(ctrl->pdev->devfn)); 8098c2ecf20Sopenharmony_ci } else { 8108c2ecf20Sopenharmony_ci req->hdr.version = MBX_CMD_VER2; 8118c2ecf20Sopenharmony_ci req->page_size = 1; 8128c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, 8138c2ecf20Sopenharmony_ci ctxt, coalesce_wm); 8148c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, 8158c2ecf20Sopenharmony_ci ctxt, no_delay); 8168c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, 8178c2ecf20Sopenharmony_ci __ilog2_u32(cq->len / 256)); 8188c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); 8198c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); 8208c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); 8218c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1); 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci be_dws_cpu_to_le(ctxt, sizeof(req->context)); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 8298c2ecf20Sopenharmony_ci if (!status) { 8308c2ecf20Sopenharmony_ci cq->id = le16_to_cpu(resp->cq_id); 8318c2ecf20Sopenharmony_ci cq->created = true; 8328c2ecf20Sopenharmony_ci } else 8338c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 8348c2ecf20Sopenharmony_ci "BC_%d : In be_cmd_cq_create, status=ox%08x\n", 8358c2ecf20Sopenharmony_ci status); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci return status; 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_cistatic u32 be_encoded_q_len(int q_len) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci u32 len_encoded = fls(q_len); /* log2(len) + 1 */ 8458c2ecf20Sopenharmony_ci if (len_encoded == 16) 8468c2ecf20Sopenharmony_ci len_encoded = 0; 8478c2ecf20Sopenharmony_ci return len_encoded; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ciint beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, 8518c2ecf20Sopenharmony_ci struct be_queue_info *mccq, 8528c2ecf20Sopenharmony_ci struct be_queue_info *cq) 8538c2ecf20Sopenharmony_ci{ 8548c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb; 8558c2ecf20Sopenharmony_ci struct be_cmd_req_mcc_create_ext *req; 8568c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem = &mccq->dma_mem; 8578c2ecf20Sopenharmony_ci struct be_ctrl_info *ctrl; 8588c2ecf20Sopenharmony_ci void *ctxt; 8598c2ecf20Sopenharmony_ci int status; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci mutex_lock(&phba->ctrl.mbox_lock); 8628c2ecf20Sopenharmony_ci ctrl = &phba->ctrl; 8638c2ecf20Sopenharmony_ci wrb = wrb_from_mbox(&ctrl->mbox_mem); 8648c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 8658c2ecf20Sopenharmony_ci req = embedded_payload(wrb); 8668c2ecf20Sopenharmony_ci ctxt = &req->context; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 8718c2ecf20Sopenharmony_ci OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req)); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 8748c2ecf20Sopenharmony_ci req->async_evt_bitmap = 1 << ASYNC_EVENT_CODE_LINK_STATE; 8758c2ecf20Sopenharmony_ci req->async_evt_bitmap |= 1 << ASYNC_EVENT_CODE_ISCSI; 8768c2ecf20Sopenharmony_ci req->async_evt_bitmap |= 1 << ASYNC_EVENT_CODE_SLI; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, 8798c2ecf20Sopenharmony_ci PCI_FUNC(phba->pcidev->devfn)); 8808c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); 8818c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, 8828c2ecf20Sopenharmony_ci be_encoded_q_len(mccq->len)); 8838c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci be_dws_cpu_to_le(ctxt, sizeof(req->context)); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 8908c2ecf20Sopenharmony_ci if (!status) { 8918c2ecf20Sopenharmony_ci struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); 8928c2ecf20Sopenharmony_ci mccq->id = le16_to_cpu(resp->id); 8938c2ecf20Sopenharmony_ci mccq->created = true; 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci mutex_unlock(&phba->ctrl.mbox_lock); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci return status; 8988c2ecf20Sopenharmony_ci} 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ciint beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, 9018c2ecf20Sopenharmony_ci int queue_type) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 9048c2ecf20Sopenharmony_ci struct be_cmd_req_q_destroy *req = embedded_payload(wrb); 9058c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 9068c2ecf20Sopenharmony_ci u8 subsys = 0, opcode = 0; 9078c2ecf20Sopenharmony_ci int status; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 9108c2ecf20Sopenharmony_ci "BC_%d : In beiscsi_cmd_q_destroy " 9118c2ecf20Sopenharmony_ci "queue_type : %d\n", queue_type); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 9148c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 9158c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci switch (queue_type) { 9188c2ecf20Sopenharmony_ci case QTYPE_EQ: 9198c2ecf20Sopenharmony_ci subsys = CMD_SUBSYSTEM_COMMON; 9208c2ecf20Sopenharmony_ci opcode = OPCODE_COMMON_EQ_DESTROY; 9218c2ecf20Sopenharmony_ci break; 9228c2ecf20Sopenharmony_ci case QTYPE_CQ: 9238c2ecf20Sopenharmony_ci subsys = CMD_SUBSYSTEM_COMMON; 9248c2ecf20Sopenharmony_ci opcode = OPCODE_COMMON_CQ_DESTROY; 9258c2ecf20Sopenharmony_ci break; 9268c2ecf20Sopenharmony_ci case QTYPE_MCCQ: 9278c2ecf20Sopenharmony_ci subsys = CMD_SUBSYSTEM_COMMON; 9288c2ecf20Sopenharmony_ci opcode = OPCODE_COMMON_MCC_DESTROY; 9298c2ecf20Sopenharmony_ci break; 9308c2ecf20Sopenharmony_ci case QTYPE_WRBQ: 9318c2ecf20Sopenharmony_ci subsys = CMD_SUBSYSTEM_ISCSI; 9328c2ecf20Sopenharmony_ci opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY; 9338c2ecf20Sopenharmony_ci break; 9348c2ecf20Sopenharmony_ci case QTYPE_DPDUQ: 9358c2ecf20Sopenharmony_ci subsys = CMD_SUBSYSTEM_ISCSI; 9368c2ecf20Sopenharmony_ci opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY; 9378c2ecf20Sopenharmony_ci break; 9388c2ecf20Sopenharmony_ci case QTYPE_SGL: 9398c2ecf20Sopenharmony_ci subsys = CMD_SUBSYSTEM_ISCSI; 9408c2ecf20Sopenharmony_ci opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES; 9418c2ecf20Sopenharmony_ci break; 9428c2ecf20Sopenharmony_ci default: 9438c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 9448c2ecf20Sopenharmony_ci BUG(); 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); 9478c2ecf20Sopenharmony_ci if (queue_type != QTYPE_SGL) 9488c2ecf20Sopenharmony_ci req->id = cpu_to_le16(q->id); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 9538c2ecf20Sopenharmony_ci return status; 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci/** 9578c2ecf20Sopenharmony_ci * be_cmd_create_default_pdu_queue()- Create DEFQ for the adapter 9588c2ecf20Sopenharmony_ci * @ctrl: ptr to ctrl_info 9598c2ecf20Sopenharmony_ci * @cq: Completion Queue 9608c2ecf20Sopenharmony_ci * @dq: Default Queue 9618c2ecf20Sopenharmony_ci * @length: ring size 9628c2ecf20Sopenharmony_ci * @entry_size: size of each entry in DEFQ 9638c2ecf20Sopenharmony_ci * @is_header: Header or Data DEFQ 9648c2ecf20Sopenharmony_ci * @ulp_num: Bind to which ULP 9658c2ecf20Sopenharmony_ci * 9668c2ecf20Sopenharmony_ci * Create HDR/Data DEFQ for the passed ULP. Unsol PDU are posted 9678c2ecf20Sopenharmony_ci * on this queue by the FW 9688c2ecf20Sopenharmony_ci * 9698c2ecf20Sopenharmony_ci * return 9708c2ecf20Sopenharmony_ci * Success: 0 9718c2ecf20Sopenharmony_ci * Failure: Non-Zero Value 9728c2ecf20Sopenharmony_ci * 9738c2ecf20Sopenharmony_ci **/ 9748c2ecf20Sopenharmony_ciint be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, 9758c2ecf20Sopenharmony_ci struct be_queue_info *cq, 9768c2ecf20Sopenharmony_ci struct be_queue_info *dq, int length, 9778c2ecf20Sopenharmony_ci int entry_size, uint8_t is_header, 9788c2ecf20Sopenharmony_ci uint8_t ulp_num) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 9818c2ecf20Sopenharmony_ci struct be_defq_create_req *req = embedded_payload(wrb); 9828c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem = &dq->dma_mem; 9838c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 9848c2ecf20Sopenharmony_ci void *ctxt = &req->context; 9858c2ecf20Sopenharmony_ci int status; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 9888c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 9938c2ecf20Sopenharmony_ci OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 9968c2ecf20Sopenharmony_ci if (phba->fw_config.dual_ulp_aware) { 9978c2ecf20Sopenharmony_ci req->ulp_num = ulp_num; 9988c2ecf20Sopenharmony_ci req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT); 9998c2ecf20Sopenharmony_ci req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT); 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci if (is_chip_be2_be3r(phba)) { 10038c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_be_default_pdu_context, 10048c2ecf20Sopenharmony_ci rx_pdid, ctxt, 0); 10058c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_be_default_pdu_context, 10068c2ecf20Sopenharmony_ci rx_pdid_valid, ctxt, 1); 10078c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_be_default_pdu_context, 10088c2ecf20Sopenharmony_ci pci_func_id, ctxt, PCI_FUNC(ctrl->pdev->devfn)); 10098c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_be_default_pdu_context, 10108c2ecf20Sopenharmony_ci ring_size, ctxt, 10118c2ecf20Sopenharmony_ci be_encoded_q_len(length / 10128c2ecf20Sopenharmony_ci sizeof(struct phys_addr))); 10138c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_be_default_pdu_context, 10148c2ecf20Sopenharmony_ci default_buffer_size, ctxt, entry_size); 10158c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_be_default_pdu_context, 10168c2ecf20Sopenharmony_ci cq_id_recv, ctxt, cq->id); 10178c2ecf20Sopenharmony_ci } else { 10188c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_default_pdu_context_ext, 10198c2ecf20Sopenharmony_ci rx_pdid, ctxt, 0); 10208c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_default_pdu_context_ext, 10218c2ecf20Sopenharmony_ci rx_pdid_valid, ctxt, 1); 10228c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_default_pdu_context_ext, 10238c2ecf20Sopenharmony_ci ring_size, ctxt, 10248c2ecf20Sopenharmony_ci be_encoded_q_len(length / 10258c2ecf20Sopenharmony_ci sizeof(struct phys_addr))); 10268c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_default_pdu_context_ext, 10278c2ecf20Sopenharmony_ci default_buffer_size, ctxt, entry_size); 10288c2ecf20Sopenharmony_ci AMAP_SET_BITS(struct amap_default_pdu_context_ext, 10298c2ecf20Sopenharmony_ci cq_id_recv, ctxt, cq->id); 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci be_dws_cpu_to_le(ctxt, sizeof(req->context)); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 10378c2ecf20Sopenharmony_ci if (!status) { 10388c2ecf20Sopenharmony_ci struct be_ring *defq_ring; 10398c2ecf20Sopenharmony_ci struct be_defq_create_resp *resp = embedded_payload(wrb); 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci dq->id = le16_to_cpu(resp->id); 10428c2ecf20Sopenharmony_ci dq->created = true; 10438c2ecf20Sopenharmony_ci if (is_header) 10448c2ecf20Sopenharmony_ci defq_ring = &phba->phwi_ctrlr->default_pdu_hdr[ulp_num]; 10458c2ecf20Sopenharmony_ci else 10468c2ecf20Sopenharmony_ci defq_ring = &phba->phwi_ctrlr-> 10478c2ecf20Sopenharmony_ci default_pdu_data[ulp_num]; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci defq_ring->id = dq->id; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci if (!phba->fw_config.dual_ulp_aware) { 10528c2ecf20Sopenharmony_ci defq_ring->ulp_num = BEISCSI_ULP0; 10538c2ecf20Sopenharmony_ci defq_ring->doorbell_offset = DB_RXULP0_OFFSET; 10548c2ecf20Sopenharmony_ci } else { 10558c2ecf20Sopenharmony_ci defq_ring->ulp_num = resp->ulp_num; 10568c2ecf20Sopenharmony_ci defq_ring->doorbell_offset = resp->doorbell_offset; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci return status; 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci/** 10658c2ecf20Sopenharmony_ci * be_cmd_wrbq_create()- Create WRBQ 10668c2ecf20Sopenharmony_ci * @ctrl: ptr to ctrl_info 10678c2ecf20Sopenharmony_ci * @q_mem: memory details for the queue 10688c2ecf20Sopenharmony_ci * @wrbq: queue info 10698c2ecf20Sopenharmony_ci * @pwrb_context: ptr to wrb_context 10708c2ecf20Sopenharmony_ci * @ulp_num: ULP on which the WRBQ is to be created 10718c2ecf20Sopenharmony_ci * 10728c2ecf20Sopenharmony_ci * Create WRBQ on the passed ULP_NUM. 10738c2ecf20Sopenharmony_ci * 10748c2ecf20Sopenharmony_ci **/ 10758c2ecf20Sopenharmony_ciint be_cmd_wrbq_create(struct be_ctrl_info *ctrl, 10768c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem, 10778c2ecf20Sopenharmony_ci struct be_queue_info *wrbq, 10788c2ecf20Sopenharmony_ci struct hwi_wrb_context *pwrb_context, 10798c2ecf20Sopenharmony_ci uint8_t ulp_num) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 10828c2ecf20Sopenharmony_ci struct be_wrbq_create_req *req = embedded_payload(wrb); 10838c2ecf20Sopenharmony_ci struct be_wrbq_create_resp *resp = embedded_payload(wrb); 10848c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 10858c2ecf20Sopenharmony_ci int status; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 10888c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 10938c2ecf20Sopenharmony_ci OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req)); 10948c2ecf20Sopenharmony_ci req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci if (phba->fw_config.dual_ulp_aware) { 10978c2ecf20Sopenharmony_ci req->ulp_num = ulp_num; 10988c2ecf20Sopenharmony_ci req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT); 10998c2ecf20Sopenharmony_ci req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT); 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 11058c2ecf20Sopenharmony_ci if (!status) { 11068c2ecf20Sopenharmony_ci wrbq->id = le16_to_cpu(resp->cid); 11078c2ecf20Sopenharmony_ci wrbq->created = true; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci pwrb_context->cid = wrbq->id; 11108c2ecf20Sopenharmony_ci if (!phba->fw_config.dual_ulp_aware) { 11118c2ecf20Sopenharmony_ci pwrb_context->doorbell_offset = DB_TXULP0_OFFSET; 11128c2ecf20Sopenharmony_ci pwrb_context->ulp_num = BEISCSI_ULP0; 11138c2ecf20Sopenharmony_ci } else { 11148c2ecf20Sopenharmony_ci pwrb_context->ulp_num = resp->ulp_num; 11158c2ecf20Sopenharmony_ci pwrb_context->doorbell_offset = resp->doorbell_offset; 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 11198c2ecf20Sopenharmony_ci return status; 11208c2ecf20Sopenharmony_ci} 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ciint be_cmd_iscsi_post_template_hdr(struct be_ctrl_info *ctrl, 11238c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 11268c2ecf20Sopenharmony_ci struct be_post_template_pages_req *req = embedded_payload(wrb); 11278c2ecf20Sopenharmony_ci int status; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 11328c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 11338c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 11348c2ecf20Sopenharmony_ci OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS, 11358c2ecf20Sopenharmony_ci sizeof(*req)); 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); 11388c2ecf20Sopenharmony_ci req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI; 11398c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 11428c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 11438c2ecf20Sopenharmony_ci return status; 11448c2ecf20Sopenharmony_ci} 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ciint be_cmd_iscsi_remove_template_hdr(struct be_ctrl_info *ctrl) 11478c2ecf20Sopenharmony_ci{ 11488c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 11498c2ecf20Sopenharmony_ci struct be_remove_template_pages_req *req = embedded_payload(wrb); 11508c2ecf20Sopenharmony_ci int status; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 11558c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 11568c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 11578c2ecf20Sopenharmony_ci OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS, 11588c2ecf20Sopenharmony_ci sizeof(*req)); 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 11638c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 11648c2ecf20Sopenharmony_ci return status; 11658c2ecf20Sopenharmony_ci} 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ciint be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, 11688c2ecf20Sopenharmony_ci struct be_dma_mem *q_mem, 11698c2ecf20Sopenharmony_ci u32 page_offset, u32 num_pages) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 11728c2ecf20Sopenharmony_ci struct be_post_sgl_pages_req *req = embedded_payload(wrb); 11738c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 11748c2ecf20Sopenharmony_ci int status; 11758c2ecf20Sopenharmony_ci unsigned int curr_pages; 11768c2ecf20Sopenharmony_ci u32 internal_page_offset = 0; 11778c2ecf20Sopenharmony_ci u32 temp_num_pages = num_pages; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci if (num_pages == 0xff) 11808c2ecf20Sopenharmony_ci num_pages = 1; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 11838c2ecf20Sopenharmony_ci do { 11848c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 11858c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 11868c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 11878c2ecf20Sopenharmony_ci OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES, 11888c2ecf20Sopenharmony_ci sizeof(*req)); 11898c2ecf20Sopenharmony_ci curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req, 11908c2ecf20Sopenharmony_ci pages); 11918c2ecf20Sopenharmony_ci req->num_pages = min(num_pages, curr_pages); 11928c2ecf20Sopenharmony_ci req->page_offset = page_offset; 11938c2ecf20Sopenharmony_ci be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem); 11948c2ecf20Sopenharmony_ci q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE); 11958c2ecf20Sopenharmony_ci internal_page_offset += req->num_pages; 11968c2ecf20Sopenharmony_ci page_offset += req->num_pages; 11978c2ecf20Sopenharmony_ci num_pages -= req->num_pages; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci if (temp_num_pages == 0xff) 12008c2ecf20Sopenharmony_ci req->num_pages = temp_num_pages; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 12038c2ecf20Sopenharmony_ci if (status) { 12048c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 12058c2ecf20Sopenharmony_ci "BC_%d : FW CMD to map iscsi frags failed.\n"); 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci goto error; 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci } while (num_pages > 0); 12108c2ecf20Sopenharmony_cierror: 12118c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 12128c2ecf20Sopenharmony_ci if (status != 0) 12138c2ecf20Sopenharmony_ci beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); 12148c2ecf20Sopenharmony_ci return status; 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci/** 12188c2ecf20Sopenharmony_ci * be_cmd_set_vlan()- Configure VLAN paramters on the adapter 12198c2ecf20Sopenharmony_ci * @phba: device priv structure instance 12208c2ecf20Sopenharmony_ci * @vlan_tag: TAG to be set 12218c2ecf20Sopenharmony_ci * 12228c2ecf20Sopenharmony_ci * Set the VLAN_TAG for the adapter or Disable VLAN on adapter 12238c2ecf20Sopenharmony_ci * 12248c2ecf20Sopenharmony_ci * returns 12258c2ecf20Sopenharmony_ci * TAG for the MBX Cmd 12268c2ecf20Sopenharmony_ci * **/ 12278c2ecf20Sopenharmony_ciint be_cmd_set_vlan(struct beiscsi_hba *phba, 12288c2ecf20Sopenharmony_ci uint16_t vlan_tag) 12298c2ecf20Sopenharmony_ci{ 12308c2ecf20Sopenharmony_ci unsigned int tag; 12318c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb; 12328c2ecf20Sopenharmony_ci struct be_cmd_set_vlan_req *req; 12338c2ecf20Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&ctrl->mbox_lock)) 12368c2ecf20Sopenharmony_ci return 0; 12378c2ecf20Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 12388c2ecf20Sopenharmony_ci if (!wrb) { 12398c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 12408c2ecf20Sopenharmony_ci return 0; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci req = embedded_payload(wrb); 12448c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*wrb), true, 0); 12458c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 12468c2ecf20Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_SET_VLAN, 12478c2ecf20Sopenharmony_ci sizeof(*req)); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci req->interface_hndl = phba->interface_handle; 12508c2ecf20Sopenharmony_ci req->vlan_priority = vlan_tag; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci be_mcc_notify(phba, tag); 12538c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci return tag; 12568c2ecf20Sopenharmony_ci} 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ciint beiscsi_check_supported_fw(struct be_ctrl_info *ctrl, 12598c2ecf20Sopenharmony_ci struct beiscsi_hba *phba) 12608c2ecf20Sopenharmony_ci{ 12618c2ecf20Sopenharmony_ci struct be_dma_mem nonemb_cmd; 12628c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 12638c2ecf20Sopenharmony_ci struct be_mgmt_controller_attributes *req; 12648c2ecf20Sopenharmony_ci struct be_sge *sge = nonembedded_sgl(wrb); 12658c2ecf20Sopenharmony_ci int status = 0; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci nonemb_cmd.va = dma_alloc_coherent(&ctrl->pdev->dev, 12688c2ecf20Sopenharmony_ci sizeof(struct be_mgmt_controller_attributes), 12698c2ecf20Sopenharmony_ci &nonemb_cmd.dma, GFP_KERNEL); 12708c2ecf20Sopenharmony_ci if (nonemb_cmd.va == NULL) { 12718c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 12728c2ecf20Sopenharmony_ci "BG_%d : dma_alloc_coherent failed in %s\n", 12738c2ecf20Sopenharmony_ci __func__); 12748c2ecf20Sopenharmony_ci return -ENOMEM; 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); 12778c2ecf20Sopenharmony_ci req = nonemb_cmd.va; 12788c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 12798c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 12808c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 12818c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 12828c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 12838c2ecf20Sopenharmony_ci OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); 12848c2ecf20Sopenharmony_ci sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); 12858c2ecf20Sopenharmony_ci sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); 12868c2ecf20Sopenharmony_ci sge->len = cpu_to_le32(nonemb_cmd.size); 12878c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 12888c2ecf20Sopenharmony_ci if (!status) { 12898c2ecf20Sopenharmony_ci struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 12928c2ecf20Sopenharmony_ci "BG_%d : Firmware Version of CMD : %s\n" 12938c2ecf20Sopenharmony_ci "Firmware Version is : %s\n" 12948c2ecf20Sopenharmony_ci "Developer Build, not performing version check...\n", 12958c2ecf20Sopenharmony_ci resp->params.hba_attribs 12968c2ecf20Sopenharmony_ci .flashrom_version_string, 12978c2ecf20Sopenharmony_ci resp->params.hba_attribs. 12988c2ecf20Sopenharmony_ci firmware_version_string); 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci phba->fw_config.iscsi_features = 13018c2ecf20Sopenharmony_ci resp->params.hba_attribs.iscsi_features; 13028c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 13038c2ecf20Sopenharmony_ci "BM_%d : phba->fw_config.iscsi_features = %d\n", 13048c2ecf20Sopenharmony_ci phba->fw_config.iscsi_features); 13058c2ecf20Sopenharmony_ci memcpy(phba->fw_ver_str, resp->params.hba_attribs. 13068c2ecf20Sopenharmony_ci firmware_version_string, BEISCSI_VER_STRLEN); 13078c2ecf20Sopenharmony_ci } else 13088c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 13098c2ecf20Sopenharmony_ci "BG_%d : Failed in beiscsi_check_supported_fw\n"); 13108c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 13118c2ecf20Sopenharmony_ci if (nonemb_cmd.va) 13128c2ecf20Sopenharmony_ci dma_free_coherent(&ctrl->pdev->dev, nonemb_cmd.size, 13138c2ecf20Sopenharmony_ci nonemb_cmd.va, nonemb_cmd.dma); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci return status; 13168c2ecf20Sopenharmony_ci} 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci/** 13198c2ecf20Sopenharmony_ci * beiscsi_get_fw_config()- Get the FW config for the function 13208c2ecf20Sopenharmony_ci * @ctrl: ptr to Ctrl Info 13218c2ecf20Sopenharmony_ci * @phba: ptr to the dev priv structure 13228c2ecf20Sopenharmony_ci * 13238c2ecf20Sopenharmony_ci * Get the FW config and resources available for the function. 13248c2ecf20Sopenharmony_ci * The resources are created based on the count received here. 13258c2ecf20Sopenharmony_ci * 13268c2ecf20Sopenharmony_ci * return 13278c2ecf20Sopenharmony_ci * Success: 0 13288c2ecf20Sopenharmony_ci * Failure: Non-Zero Value 13298c2ecf20Sopenharmony_ci **/ 13308c2ecf20Sopenharmony_ciint beiscsi_get_fw_config(struct be_ctrl_info *ctrl, 13318c2ecf20Sopenharmony_ci struct beiscsi_hba *phba) 13328c2ecf20Sopenharmony_ci{ 13338c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 13348c2ecf20Sopenharmony_ci struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); 13358c2ecf20Sopenharmony_ci uint32_t cid_count, icd_count; 13368c2ecf20Sopenharmony_ci int status = -EINVAL; 13378c2ecf20Sopenharmony_ci uint8_t ulp_num = 0; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 13408c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 13418c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, 13448c2ecf20Sopenharmony_ci OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, 13458c2ecf20Sopenharmony_ci EMBED_MBX_MAX_PAYLOAD_SIZE); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci if (be_mbox_notify(ctrl)) { 13488c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 13498c2ecf20Sopenharmony_ci "BG_%d : Failed in beiscsi_get_fw_config\n"); 13508c2ecf20Sopenharmony_ci goto fail_init; 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci /* FW response formats depend on port id */ 13548c2ecf20Sopenharmony_ci phba->fw_config.phys_port = pfw_cfg->phys_port; 13558c2ecf20Sopenharmony_ci if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { 13568c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 13578c2ecf20Sopenharmony_ci "BG_%d : invalid physical port id %d\n", 13588c2ecf20Sopenharmony_ci phba->fw_config.phys_port); 13598c2ecf20Sopenharmony_ci goto fail_init; 13608c2ecf20Sopenharmony_ci } 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci /* populate and check FW config against min and max values */ 13638c2ecf20Sopenharmony_ci if (!is_chip_be2_be3r(phba)) { 13648c2ecf20Sopenharmony_ci phba->fw_config.eqid_count = pfw_cfg->eqid_count; 13658c2ecf20Sopenharmony_ci phba->fw_config.cqid_count = pfw_cfg->cqid_count; 13668c2ecf20Sopenharmony_ci if (phba->fw_config.eqid_count == 0 || 13678c2ecf20Sopenharmony_ci phba->fw_config.eqid_count > 2048) { 13688c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 13698c2ecf20Sopenharmony_ci "BG_%d : invalid EQ count %d\n", 13708c2ecf20Sopenharmony_ci phba->fw_config.eqid_count); 13718c2ecf20Sopenharmony_ci goto fail_init; 13728c2ecf20Sopenharmony_ci } 13738c2ecf20Sopenharmony_ci if (phba->fw_config.cqid_count == 0 || 13748c2ecf20Sopenharmony_ci phba->fw_config.cqid_count > 4096) { 13758c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 13768c2ecf20Sopenharmony_ci "BG_%d : invalid CQ count %d\n", 13778c2ecf20Sopenharmony_ci phba->fw_config.cqid_count); 13788c2ecf20Sopenharmony_ci goto fail_init; 13798c2ecf20Sopenharmony_ci } 13808c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 13818c2ecf20Sopenharmony_ci "BG_%d : EQ_Count : %d CQ_Count : %d\n", 13828c2ecf20Sopenharmony_ci phba->fw_config.eqid_count, 13838c2ecf20Sopenharmony_ci phba->fw_config.cqid_count); 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci /** 13878c2ecf20Sopenharmony_ci * Check on which all ULP iSCSI Protocol is loaded. 13888c2ecf20Sopenharmony_ci * Set the Bit for those ULP. This set flag is used 13898c2ecf20Sopenharmony_ci * at all places in the code to check on which ULP 13908c2ecf20Sopenharmony_ci * iSCSi Protocol is loaded 13918c2ecf20Sopenharmony_ci **/ 13928c2ecf20Sopenharmony_ci for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 13938c2ecf20Sopenharmony_ci if (pfw_cfg->ulp[ulp_num].ulp_mode & 13948c2ecf20Sopenharmony_ci BEISCSI_ULP_ISCSI_INI_MODE) { 13958c2ecf20Sopenharmony_ci set_bit(ulp_num, &phba->fw_config.ulp_supported); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci /* Get the CID, ICD and Chain count for each ULP */ 13988c2ecf20Sopenharmony_ci phba->fw_config.iscsi_cid_start[ulp_num] = 13998c2ecf20Sopenharmony_ci pfw_cfg->ulp[ulp_num].sq_base; 14008c2ecf20Sopenharmony_ci phba->fw_config.iscsi_cid_count[ulp_num] = 14018c2ecf20Sopenharmony_ci pfw_cfg->ulp[ulp_num].sq_count; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci phba->fw_config.iscsi_icd_start[ulp_num] = 14048c2ecf20Sopenharmony_ci pfw_cfg->ulp[ulp_num].icd_base; 14058c2ecf20Sopenharmony_ci phba->fw_config.iscsi_icd_count[ulp_num] = 14068c2ecf20Sopenharmony_ci pfw_cfg->ulp[ulp_num].icd_count; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci phba->fw_config.iscsi_chain_start[ulp_num] = 14098c2ecf20Sopenharmony_ci pfw_cfg->chain_icd[ulp_num].chain_base; 14108c2ecf20Sopenharmony_ci phba->fw_config.iscsi_chain_count[ulp_num] = 14118c2ecf20Sopenharmony_ci pfw_cfg->chain_icd[ulp_num].chain_count; 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 14148c2ecf20Sopenharmony_ci "BG_%d : Function loaded on ULP : %d\n" 14158c2ecf20Sopenharmony_ci "\tiscsi_cid_count : %d\n" 14168c2ecf20Sopenharmony_ci "\tiscsi_cid_start : %d\n" 14178c2ecf20Sopenharmony_ci "\t iscsi_icd_count : %d\n" 14188c2ecf20Sopenharmony_ci "\t iscsi_icd_start : %d\n", 14198c2ecf20Sopenharmony_ci ulp_num, 14208c2ecf20Sopenharmony_ci phba->fw_config. 14218c2ecf20Sopenharmony_ci iscsi_cid_count[ulp_num], 14228c2ecf20Sopenharmony_ci phba->fw_config. 14238c2ecf20Sopenharmony_ci iscsi_cid_start[ulp_num], 14248c2ecf20Sopenharmony_ci phba->fw_config. 14258c2ecf20Sopenharmony_ci iscsi_icd_count[ulp_num], 14268c2ecf20Sopenharmony_ci phba->fw_config. 14278c2ecf20Sopenharmony_ci iscsi_icd_start[ulp_num]); 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci if (phba->fw_config.ulp_supported == 0) { 14328c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 14338c2ecf20Sopenharmony_ci "BG_%d : iSCSI initiator mode not set: ULP0 %x ULP1 %x\n", 14348c2ecf20Sopenharmony_ci pfw_cfg->ulp[BEISCSI_ULP0].ulp_mode, 14358c2ecf20Sopenharmony_ci pfw_cfg->ulp[BEISCSI_ULP1].ulp_mode); 14368c2ecf20Sopenharmony_ci goto fail_init; 14378c2ecf20Sopenharmony_ci } 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci /** 14408c2ecf20Sopenharmony_ci * ICD is shared among ULPs. Use icd_count of any one loaded ULP 14418c2ecf20Sopenharmony_ci **/ 14428c2ecf20Sopenharmony_ci for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) 14438c2ecf20Sopenharmony_ci if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) 14448c2ecf20Sopenharmony_ci break; 14458c2ecf20Sopenharmony_ci icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; 14468c2ecf20Sopenharmony_ci if (icd_count == 0 || icd_count > 65536) { 14478c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 14488c2ecf20Sopenharmony_ci "BG_%d: invalid ICD count %d\n", icd_count); 14498c2ecf20Sopenharmony_ci goto fail_init; 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) + 14538c2ecf20Sopenharmony_ci BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1); 14548c2ecf20Sopenharmony_ci if (cid_count == 0 || cid_count > 4096) { 14558c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 14568c2ecf20Sopenharmony_ci "BG_%d: invalid CID count %d\n", cid_count); 14578c2ecf20Sopenharmony_ci goto fail_init; 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci /** 14618c2ecf20Sopenharmony_ci * Check FW is dual ULP aware i.e. can handle either 14628c2ecf20Sopenharmony_ci * of the protocols. 14638c2ecf20Sopenharmony_ci */ 14648c2ecf20Sopenharmony_ci phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode & 14658c2ecf20Sopenharmony_ci BEISCSI_FUNC_DUA_MODE); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 14688c2ecf20Sopenharmony_ci "BG_%d : DUA Mode : 0x%x\n", 14698c2ecf20Sopenharmony_ci phba->fw_config.dual_ulp_aware); 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci /* all set, continue using this FW config */ 14728c2ecf20Sopenharmony_ci status = 0; 14738c2ecf20Sopenharmony_cifail_init: 14748c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 14758c2ecf20Sopenharmony_ci return status; 14768c2ecf20Sopenharmony_ci} 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci/** 14798c2ecf20Sopenharmony_ci * beiscsi_get_port_name()- Get port name for the function 14808c2ecf20Sopenharmony_ci * @ctrl: ptr to Ctrl Info 14818c2ecf20Sopenharmony_ci * @phba: ptr to the dev priv structure 14828c2ecf20Sopenharmony_ci * 14838c2ecf20Sopenharmony_ci * Get the alphanumeric character for port 14848c2ecf20Sopenharmony_ci * 14858c2ecf20Sopenharmony_ci **/ 14868c2ecf20Sopenharmony_ciint beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) 14878c2ecf20Sopenharmony_ci{ 14888c2ecf20Sopenharmony_ci int ret = 0; 14898c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb; 14908c2ecf20Sopenharmony_ci struct be_cmd_get_port_name *ioctl; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 14938c2ecf20Sopenharmony_ci wrb = wrb_from_mbox(&ctrl->mbox_mem); 14948c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 14958c2ecf20Sopenharmony_ci ioctl = embedded_payload(wrb); 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0); 14988c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON, 14998c2ecf20Sopenharmony_ci OPCODE_COMMON_GET_PORT_NAME, 15008c2ecf20Sopenharmony_ci EMBED_MBX_MAX_PAYLOAD_SIZE); 15018c2ecf20Sopenharmony_ci ret = be_mbox_notify(ctrl); 15028c2ecf20Sopenharmony_ci phba->port_name = 0; 15038c2ecf20Sopenharmony_ci if (!ret) { 15048c2ecf20Sopenharmony_ci phba->port_name = ioctl->p.resp.port_names >> 15058c2ecf20Sopenharmony_ci (phba->fw_config.phys_port * 8) & 0xff; 15068c2ecf20Sopenharmony_ci } else { 15078c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 15088c2ecf20Sopenharmony_ci "BG_%d : GET_PORT_NAME ret 0x%x status 0x%x\n", 15098c2ecf20Sopenharmony_ci ret, ioctl->h.resp_hdr.status); 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (phba->port_name == 0) 15138c2ecf20Sopenharmony_ci phba->port_name = '?'; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 15168c2ecf20Sopenharmony_ci return ret; 15178c2ecf20Sopenharmony_ci} 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ciint beiscsi_set_host_data(struct beiscsi_hba *phba) 15208c2ecf20Sopenharmony_ci{ 15218c2ecf20Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 15228c2ecf20Sopenharmony_ci struct be_cmd_set_host_data *ioctl; 15238c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb; 15248c2ecf20Sopenharmony_ci int ret = 0; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci if (is_chip_be2_be3r(phba)) 15278c2ecf20Sopenharmony_ci return ret; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 15308c2ecf20Sopenharmony_ci wrb = wrb_from_mbox(&ctrl->mbox_mem); 15318c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 15328c2ecf20Sopenharmony_ci ioctl = embedded_payload(wrb); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0); 15358c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON, 15368c2ecf20Sopenharmony_ci OPCODE_COMMON_SET_HOST_DATA, 15378c2ecf20Sopenharmony_ci EMBED_MBX_MAX_PAYLOAD_SIZE); 15388c2ecf20Sopenharmony_ci ioctl->param.req.param_id = BE_CMD_SET_HOST_PARAM_ID; 15398c2ecf20Sopenharmony_ci ioctl->param.req.param_len = 15408c2ecf20Sopenharmony_ci snprintf((char *)ioctl->param.req.param_data, 15418c2ecf20Sopenharmony_ci sizeof(ioctl->param.req.param_data), 15428c2ecf20Sopenharmony_ci "Linux iSCSI v%s", BUILD_STR); 15438c2ecf20Sopenharmony_ci ioctl->param.req.param_len = ALIGN(ioctl->param.req.param_len + 1, 4); 15448c2ecf20Sopenharmony_ci if (ioctl->param.req.param_len > BE_CMD_MAX_DRV_VERSION) 15458c2ecf20Sopenharmony_ci ioctl->param.req.param_len = BE_CMD_MAX_DRV_VERSION; 15468c2ecf20Sopenharmony_ci ret = be_mbox_notify(ctrl); 15478c2ecf20Sopenharmony_ci if (!ret) { 15488c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 15498c2ecf20Sopenharmony_ci "BG_%d : HBA set host driver version\n"); 15508c2ecf20Sopenharmony_ci } else { 15518c2ecf20Sopenharmony_ci /** 15528c2ecf20Sopenharmony_ci * Check "MCC_STATUS_INVALID_LENGTH" for SKH. 15538c2ecf20Sopenharmony_ci * Older FW versions return this error. 15548c2ecf20Sopenharmony_ci */ 15558c2ecf20Sopenharmony_ci if (ret == MCC_STATUS_ILLEGAL_REQUEST || 15568c2ecf20Sopenharmony_ci ret == MCC_STATUS_INVALID_LENGTH) 15578c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_INFO, 15588c2ecf20Sopenharmony_ci "BG_%d : HBA failed to set host driver version\n"); 15598c2ecf20Sopenharmony_ci } 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 15628c2ecf20Sopenharmony_ci return ret; 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ciint beiscsi_set_uer_feature(struct beiscsi_hba *phba) 15668c2ecf20Sopenharmony_ci{ 15678c2ecf20Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 15688c2ecf20Sopenharmony_ci struct be_cmd_set_features *ioctl; 15698c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb; 15708c2ecf20Sopenharmony_ci int ret = 0; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 15738c2ecf20Sopenharmony_ci wrb = wrb_from_mbox(&ctrl->mbox_mem); 15748c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 15758c2ecf20Sopenharmony_ci ioctl = embedded_payload(wrb); 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0); 15788c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON, 15798c2ecf20Sopenharmony_ci OPCODE_COMMON_SET_FEATURES, 15808c2ecf20Sopenharmony_ci EMBED_MBX_MAX_PAYLOAD_SIZE); 15818c2ecf20Sopenharmony_ci ioctl->feature = BE_CMD_SET_FEATURE_UER; 15828c2ecf20Sopenharmony_ci ioctl->param_len = sizeof(ioctl->param.req); 15838c2ecf20Sopenharmony_ci ioctl->param.req.uer = BE_CMD_UER_SUPP_BIT; 15848c2ecf20Sopenharmony_ci ret = be_mbox_notify(ctrl); 15858c2ecf20Sopenharmony_ci if (!ret) { 15868c2ecf20Sopenharmony_ci phba->ue2rp = ioctl->param.resp.ue2rp; 15878c2ecf20Sopenharmony_ci set_bit(BEISCSI_HBA_UER_SUPP, &phba->state); 15888c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 15898c2ecf20Sopenharmony_ci "BG_%d : HBA error recovery supported\n"); 15908c2ecf20Sopenharmony_ci } else { 15918c2ecf20Sopenharmony_ci /** 15928c2ecf20Sopenharmony_ci * Check "MCC_STATUS_INVALID_LENGTH" for SKH. 15938c2ecf20Sopenharmony_ci * Older FW versions return this error. 15948c2ecf20Sopenharmony_ci */ 15958c2ecf20Sopenharmony_ci if (ret == MCC_STATUS_ILLEGAL_REQUEST || 15968c2ecf20Sopenharmony_ci ret == MCC_STATUS_INVALID_LENGTH) 15978c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_INFO, 15988c2ecf20Sopenharmony_ci "BG_%d : HBA error recovery not supported\n"); 15998c2ecf20Sopenharmony_ci } 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 16028c2ecf20Sopenharmony_ci return ret; 16038c2ecf20Sopenharmony_ci} 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_cistatic u32 beiscsi_get_post_stage(struct beiscsi_hba *phba) 16068c2ecf20Sopenharmony_ci{ 16078c2ecf20Sopenharmony_ci u32 sem; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci if (is_chip_be2_be3r(phba)) 16108c2ecf20Sopenharmony_ci sem = ioread32(phba->csr_va + SLIPORT_SEMAPHORE_OFFSET_BEx); 16118c2ecf20Sopenharmony_ci else 16128c2ecf20Sopenharmony_ci pci_read_config_dword(phba->pcidev, 16138c2ecf20Sopenharmony_ci SLIPORT_SEMAPHORE_OFFSET_SH, &sem); 16148c2ecf20Sopenharmony_ci return sem; 16158c2ecf20Sopenharmony_ci} 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ciint beiscsi_check_fw_rdy(struct beiscsi_hba *phba) 16188c2ecf20Sopenharmony_ci{ 16198c2ecf20Sopenharmony_ci u32 loop, post, rdy = 0; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci loop = 1000; 16228c2ecf20Sopenharmony_ci while (loop--) { 16238c2ecf20Sopenharmony_ci post = beiscsi_get_post_stage(phba); 16248c2ecf20Sopenharmony_ci if (post & POST_ERROR_BIT) 16258c2ecf20Sopenharmony_ci break; 16268c2ecf20Sopenharmony_ci if ((post & POST_STAGE_MASK) == POST_STAGE_ARMFW_RDY) { 16278c2ecf20Sopenharmony_ci rdy = 1; 16288c2ecf20Sopenharmony_ci break; 16298c2ecf20Sopenharmony_ci } 16308c2ecf20Sopenharmony_ci msleep(60); 16318c2ecf20Sopenharmony_ci } 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci if (!rdy) { 16348c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 16358c2ecf20Sopenharmony_ci "BC_%d : FW not ready 0x%x\n", post); 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci return rdy; 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ciint beiscsi_cmd_function_reset(struct beiscsi_hba *phba) 16428c2ecf20Sopenharmony_ci{ 16438c2ecf20Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 16448c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 16458c2ecf20Sopenharmony_ci struct be_post_sgl_pages_req *req; 16468c2ecf20Sopenharmony_ci int status; 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci req = embedded_payload(wrb); 16518c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 16528c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 16538c2ecf20Sopenharmony_ci OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); 16548c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 16578c2ecf20Sopenharmony_ci return status; 16588c2ecf20Sopenharmony_ci} 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ciint beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load) 16618c2ecf20Sopenharmony_ci{ 16628c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 16638c2ecf20Sopenharmony_ci struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); 16648c2ecf20Sopenharmony_ci u8 *endian_check; 16658c2ecf20Sopenharmony_ci int status; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 16688c2ecf20Sopenharmony_ci memset(wrb, 0, sizeof(*wrb)); 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci endian_check = (u8 *) wrb; 16718c2ecf20Sopenharmony_ci if (load) { 16728c2ecf20Sopenharmony_ci /* to start communicating */ 16738c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16748c2ecf20Sopenharmony_ci *endian_check++ = 0x12; 16758c2ecf20Sopenharmony_ci *endian_check++ = 0x34; 16768c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16778c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16788c2ecf20Sopenharmony_ci *endian_check++ = 0x56; 16798c2ecf20Sopenharmony_ci *endian_check++ = 0x78; 16808c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16818c2ecf20Sopenharmony_ci } else { 16828c2ecf20Sopenharmony_ci /* to stop communicating */ 16838c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16848c2ecf20Sopenharmony_ci *endian_check++ = 0xAA; 16858c2ecf20Sopenharmony_ci *endian_check++ = 0xBB; 16868c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16878c2ecf20Sopenharmony_ci *endian_check++ = 0xFF; 16888c2ecf20Sopenharmony_ci *endian_check++ = 0xCC; 16898c2ecf20Sopenharmony_ci *endian_check++ = 0xDD; 16908c2ecf20Sopenharmony_ci *endian_check = 0xFF; 16918c2ecf20Sopenharmony_ci } 16928c2ecf20Sopenharmony_ci be_dws_cpu_to_le(wrb, sizeof(*wrb)); 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 16958c2ecf20Sopenharmony_ci if (status) 16968c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 16978c2ecf20Sopenharmony_ci "BC_%d : special WRB message failed\n"); 16988c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 16998c2ecf20Sopenharmony_ci return status; 17008c2ecf20Sopenharmony_ci} 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ciint beiscsi_init_sliport(struct beiscsi_hba *phba) 17038c2ecf20Sopenharmony_ci{ 17048c2ecf20Sopenharmony_ci int status; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci /* check POST stage before talking to FW */ 17078c2ecf20Sopenharmony_ci status = beiscsi_check_fw_rdy(phba); 17088c2ecf20Sopenharmony_ci if (!status) 17098c2ecf20Sopenharmony_ci return -EIO; 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci /* clear all error states after checking FW rdy */ 17128c2ecf20Sopenharmony_ci phba->state &= ~BEISCSI_HBA_IN_ERR; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci /* check again UER support */ 17158c2ecf20Sopenharmony_ci phba->state &= ~BEISCSI_HBA_UER_SUPP; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci /* 17188c2ecf20Sopenharmony_ci * SLI COMMON_FUNCTION_RESET completion is indicated by BMBX RDY bit. 17198c2ecf20Sopenharmony_ci * It should clean up any stale info in FW for this fn. 17208c2ecf20Sopenharmony_ci */ 17218c2ecf20Sopenharmony_ci status = beiscsi_cmd_function_reset(phba); 17228c2ecf20Sopenharmony_ci if (status) { 17238c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 17248c2ecf20Sopenharmony_ci "BC_%d : SLI Function Reset failed\n"); 17258c2ecf20Sopenharmony_ci return status; 17268c2ecf20Sopenharmony_ci } 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci /* indicate driver is loading */ 17298c2ecf20Sopenharmony_ci return beiscsi_cmd_special_wrb(&phba->ctrl, 1); 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci/** 17338c2ecf20Sopenharmony_ci * beiscsi_cmd_iscsi_cleanup()- Inform FW to cleanup EP data structures. 17348c2ecf20Sopenharmony_ci * @phba: pointer to dev priv structure 17358c2ecf20Sopenharmony_ci * @ulp: ULP number. 17368c2ecf20Sopenharmony_ci * 17378c2ecf20Sopenharmony_ci * return 17388c2ecf20Sopenharmony_ci * Success: 0 17398c2ecf20Sopenharmony_ci * Failure: Non-Zero Value 17408c2ecf20Sopenharmony_ci **/ 17418c2ecf20Sopenharmony_ciint beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp) 17428c2ecf20Sopenharmony_ci{ 17438c2ecf20Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 17448c2ecf20Sopenharmony_ci struct iscsi_cleanup_req_v1 *req_v1; 17458c2ecf20Sopenharmony_ci struct iscsi_cleanup_req *req; 17468c2ecf20Sopenharmony_ci u16 hdr_ring_id, data_ring_id; 17478c2ecf20Sopenharmony_ci struct be_mcc_wrb *wrb; 17488c2ecf20Sopenharmony_ci int status; 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 17518c2ecf20Sopenharmony_ci wrb = wrb_from_mbox(&ctrl->mbox_mem); 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci hdr_ring_id = HWI_GET_DEF_HDRQ_ID(phba, ulp); 17548c2ecf20Sopenharmony_ci data_ring_id = HWI_GET_DEF_BUFQ_ID(phba, ulp); 17558c2ecf20Sopenharmony_ci if (is_chip_be2_be3r(phba)) { 17568c2ecf20Sopenharmony_ci req = embedded_payload(wrb); 17578c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 17588c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 17598c2ecf20Sopenharmony_ci OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); 17608c2ecf20Sopenharmony_ci req->chute = (1 << ulp); 17618c2ecf20Sopenharmony_ci /* BE2/BE3 FW creates 8-bit ring id */ 17628c2ecf20Sopenharmony_ci req->hdr_ring_id = hdr_ring_id; 17638c2ecf20Sopenharmony_ci req->data_ring_id = data_ring_id; 17648c2ecf20Sopenharmony_ci } else { 17658c2ecf20Sopenharmony_ci req_v1 = embedded_payload(wrb); 17668c2ecf20Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req_v1), true, 0); 17678c2ecf20Sopenharmony_ci be_cmd_hdr_prepare(&req_v1->hdr, CMD_SUBSYSTEM_ISCSI, 17688c2ecf20Sopenharmony_ci OPCODE_COMMON_ISCSI_CLEANUP, 17698c2ecf20Sopenharmony_ci sizeof(*req_v1)); 17708c2ecf20Sopenharmony_ci req_v1->hdr.version = 1; 17718c2ecf20Sopenharmony_ci req_v1->chute = (1 << ulp); 17728c2ecf20Sopenharmony_ci req_v1->hdr_ring_id = cpu_to_le16(hdr_ring_id); 17738c2ecf20Sopenharmony_ci req_v1->data_ring_id = cpu_to_le16(data_ring_id); 17748c2ecf20Sopenharmony_ci } 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci status = be_mbox_notify(ctrl); 17778c2ecf20Sopenharmony_ci if (status) 17788c2ecf20Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, 17798c2ecf20Sopenharmony_ci "BG_%d : %s failed %d\n", __func__, ulp); 17808c2ecf20Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 17818c2ecf20Sopenharmony_ci return status; 17828c2ecf20Sopenharmony_ci} 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci/* 17858c2ecf20Sopenharmony_ci * beiscsi_detect_ue()- Detect Unrecoverable Error on adapter 17868c2ecf20Sopenharmony_ci * @phba: Driver priv structure 17878c2ecf20Sopenharmony_ci * 17888c2ecf20Sopenharmony_ci * Read registers linked to UE and check for the UE status 17898c2ecf20Sopenharmony_ci **/ 17908c2ecf20Sopenharmony_ciint beiscsi_detect_ue(struct beiscsi_hba *phba) 17918c2ecf20Sopenharmony_ci{ 17928c2ecf20Sopenharmony_ci uint32_t ue_mask_hi = 0, ue_mask_lo = 0; 17938c2ecf20Sopenharmony_ci uint32_t ue_hi = 0, ue_lo = 0; 17948c2ecf20Sopenharmony_ci uint8_t i = 0; 17958c2ecf20Sopenharmony_ci int ret = 0; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci pci_read_config_dword(phba->pcidev, 17988c2ecf20Sopenharmony_ci PCICFG_UE_STATUS_LOW, &ue_lo); 17998c2ecf20Sopenharmony_ci pci_read_config_dword(phba->pcidev, 18008c2ecf20Sopenharmony_ci PCICFG_UE_STATUS_MASK_LOW, 18018c2ecf20Sopenharmony_ci &ue_mask_lo); 18028c2ecf20Sopenharmony_ci pci_read_config_dword(phba->pcidev, 18038c2ecf20Sopenharmony_ci PCICFG_UE_STATUS_HIGH, 18048c2ecf20Sopenharmony_ci &ue_hi); 18058c2ecf20Sopenharmony_ci pci_read_config_dword(phba->pcidev, 18068c2ecf20Sopenharmony_ci PCICFG_UE_STATUS_MASK_HI, 18078c2ecf20Sopenharmony_ci &ue_mask_hi); 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci ue_lo = (ue_lo & ~ue_mask_lo); 18108c2ecf20Sopenharmony_ci ue_hi = (ue_hi & ~ue_mask_hi); 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci if (ue_lo || ue_hi) { 18148c2ecf20Sopenharmony_ci set_bit(BEISCSI_HBA_IN_UE, &phba->state); 18158c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 18168c2ecf20Sopenharmony_ci "BC_%d : HBA error detected\n"); 18178c2ecf20Sopenharmony_ci ret = 1; 18188c2ecf20Sopenharmony_ci } 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci if (ue_lo) { 18218c2ecf20Sopenharmony_ci for (i = 0; ue_lo; ue_lo >>= 1, i++) { 18228c2ecf20Sopenharmony_ci if (ue_lo & 1) 18238c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 18248c2ecf20Sopenharmony_ci "BC_%d : UE_LOW %s bit set\n", 18258c2ecf20Sopenharmony_ci desc_ue_status_low[i]); 18268c2ecf20Sopenharmony_ci } 18278c2ecf20Sopenharmony_ci } 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci if (ue_hi) { 18308c2ecf20Sopenharmony_ci for (i = 0; ue_hi; ue_hi >>= 1, i++) { 18318c2ecf20Sopenharmony_ci if (ue_hi & 1) 18328c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 18338c2ecf20Sopenharmony_ci "BC_%d : UE_HIGH %s bit set\n", 18348c2ecf20Sopenharmony_ci desc_ue_status_hi[i]); 18358c2ecf20Sopenharmony_ci } 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci return ret; 18388c2ecf20Sopenharmony_ci} 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci/* 18418c2ecf20Sopenharmony_ci * beiscsi_detect_tpe()- Detect Transient Parity Error on adapter 18428c2ecf20Sopenharmony_ci * @phba: Driver priv structure 18438c2ecf20Sopenharmony_ci * 18448c2ecf20Sopenharmony_ci * Read SLIPORT SEMAPHORE register to check for UER 18458c2ecf20Sopenharmony_ci * 18468c2ecf20Sopenharmony_ci **/ 18478c2ecf20Sopenharmony_ciint beiscsi_detect_tpe(struct beiscsi_hba *phba) 18488c2ecf20Sopenharmony_ci{ 18498c2ecf20Sopenharmony_ci u32 post, status; 18508c2ecf20Sopenharmony_ci int ret = 0; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci post = beiscsi_get_post_stage(phba); 18538c2ecf20Sopenharmony_ci status = post & POST_STAGE_MASK; 18548c2ecf20Sopenharmony_ci if ((status & POST_ERR_RECOVERY_CODE_MASK) == 18558c2ecf20Sopenharmony_ci POST_STAGE_RECOVERABLE_ERR) { 18568c2ecf20Sopenharmony_ci set_bit(BEISCSI_HBA_IN_TPE, &phba->state); 18578c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_INFO, 18588c2ecf20Sopenharmony_ci "BC_%d : HBA error recoverable: 0x%x\n", post); 18598c2ecf20Sopenharmony_ci ret = 1; 18608c2ecf20Sopenharmony_ci } else { 18618c2ecf20Sopenharmony_ci __beiscsi_log(phba, KERN_INFO, 18628c2ecf20Sopenharmony_ci "BC_%d : HBA in UE: 0x%x\n", post); 18638c2ecf20Sopenharmony_ci } 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci return ret; 18668c2ecf20Sopenharmony_ci} 1867