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