162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is part of the Chelsio FCoE driver for Linux.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This software is available to you under a choice of one of two
762306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
862306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
962306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
1062306a36Sopenharmony_ci * OpenIB.org BSD license below:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
1362306a36Sopenharmony_ci *     without modification, are permitted provided that the following
1462306a36Sopenharmony_ci *     conditions are met:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *      - Redistributions of source code must retain the above
1762306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
1862306a36Sopenharmony_ci *        disclaimer.
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
2162306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
2262306a36Sopenharmony_ci *        disclaimer in the documentation and/or other materials
2362306a36Sopenharmony_ci *        provided with the distribution.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2662306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2762306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2862306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2962306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3062306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3162306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3262306a36Sopenharmony_ci * SOFTWARE.
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include <linux/delay.h>
3662306a36Sopenharmony_ci#include <linux/jiffies.h>
3762306a36Sopenharmony_ci#include <linux/string.h>
3862306a36Sopenharmony_ci#include <scsi/scsi_device.h>
3962306a36Sopenharmony_ci#include <scsi/scsi_transport_fc.h>
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#include "csio_hw.h"
4262306a36Sopenharmony_ci#include "csio_lnode.h"
4362306a36Sopenharmony_ci#include "csio_rnode.h"
4462306a36Sopenharmony_ci#include "csio_mb.h"
4562306a36Sopenharmony_ci#include "csio_wr.h"
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define csio_mb_is_host_owner(__owner)		((__owner) == CSIO_MBOWNER_PL)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* MB Command/Response Helpers */
5062306a36Sopenharmony_ci/*
5162306a36Sopenharmony_ci * csio_mb_fw_retval - FW return value from a mailbox response.
5262306a36Sopenharmony_ci * @mbp: Mailbox structure
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_cienum fw_retval
5662306a36Sopenharmony_cicsio_mb_fw_retval(struct csio_mb *mbp)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct fw_cmd_hdr *hdr;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	hdr = (struct fw_cmd_hdr *)(mbp->mb);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return FW_CMD_RETVAL_G(ntohl(hdr->lo));
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/*
6662306a36Sopenharmony_ci * csio_mb_hello - FW HELLO command helper
6762306a36Sopenharmony_ci * @hw: The HW structure
6862306a36Sopenharmony_ci * @mbp: Mailbox structure
6962306a36Sopenharmony_ci * @m_mbox: Master mailbox number, if any.
7062306a36Sopenharmony_ci * @a_mbox: Mailbox number for asycn notifications.
7162306a36Sopenharmony_ci * @master: Device mastership.
7262306a36Sopenharmony_ci * @cbfn: Callback, if any.
7362306a36Sopenharmony_ci *
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_civoid
7662306a36Sopenharmony_cicsio_mb_hello(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
7762306a36Sopenharmony_ci	      uint32_t m_mbox, uint32_t a_mbox, enum csio_dev_master master,
7862306a36Sopenharmony_ci	      void (*cbfn) (struct csio_hw *, struct csio_mb *))
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	struct fw_hello_cmd *cmdp = (struct fw_hello_cmd *)(mbp->mb);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	cmdp->op_to_write = htonl(FW_CMD_OP_V(FW_HELLO_CMD) |
8562306a36Sopenharmony_ci				       FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
8662306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
8762306a36Sopenharmony_ci	cmdp->err_to_clearinit = htonl(
8862306a36Sopenharmony_ci		FW_HELLO_CMD_MASTERDIS_V(master == CSIO_MASTER_CANT)	|
8962306a36Sopenharmony_ci		FW_HELLO_CMD_MASTERFORCE_V(master == CSIO_MASTER_MUST)	|
9062306a36Sopenharmony_ci		FW_HELLO_CMD_MBMASTER_V(master == CSIO_MASTER_MUST ?
9162306a36Sopenharmony_ci				m_mbox : FW_HELLO_CMD_MBMASTER_M)	|
9262306a36Sopenharmony_ci		FW_HELLO_CMD_MBASYNCNOT_V(a_mbox) |
9362306a36Sopenharmony_ci		FW_HELLO_CMD_STAGE_V(fw_hello_cmd_stage_os) |
9462306a36Sopenharmony_ci		FW_HELLO_CMD_CLEARINIT_F);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/*
9962306a36Sopenharmony_ci * csio_mb_process_hello_rsp - FW HELLO response processing helper
10062306a36Sopenharmony_ci * @hw: The HW structure
10162306a36Sopenharmony_ci * @mbp: Mailbox structure
10262306a36Sopenharmony_ci * @retval: Mailbox return value from Firmware
10362306a36Sopenharmony_ci * @state: State that the function is in.
10462306a36Sopenharmony_ci * @mpfn: Master pfn
10562306a36Sopenharmony_ci *
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_civoid
10862306a36Sopenharmony_cicsio_mb_process_hello_rsp(struct csio_hw *hw, struct csio_mb *mbp,
10962306a36Sopenharmony_ci			  enum fw_retval *retval, enum csio_dev_state *state,
11062306a36Sopenharmony_ci			  uint8_t *mpfn)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct fw_hello_cmd *rsp = (struct fw_hello_cmd *)(mbp->mb);
11362306a36Sopenharmony_ci	uint32_t value;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	*retval = FW_CMD_RETVAL_G(ntohl(rsp->retval_len16));
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (*retval == FW_SUCCESS) {
11862306a36Sopenharmony_ci		hw->fwrev = ntohl(rsp->fwrev);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		value = ntohl(rsp->err_to_clearinit);
12162306a36Sopenharmony_ci		*mpfn = FW_HELLO_CMD_MBMASTER_G(value);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci		if (value & FW_HELLO_CMD_INIT_F)
12462306a36Sopenharmony_ci			*state = CSIO_DEV_STATE_INIT;
12562306a36Sopenharmony_ci		else if (value & FW_HELLO_CMD_ERR_F)
12662306a36Sopenharmony_ci			*state = CSIO_DEV_STATE_ERR;
12762306a36Sopenharmony_ci		else
12862306a36Sopenharmony_ci			*state = CSIO_DEV_STATE_UNINIT;
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci/*
13362306a36Sopenharmony_ci * csio_mb_bye - FW BYE command helper
13462306a36Sopenharmony_ci * @hw: The HW structure
13562306a36Sopenharmony_ci * @mbp: Mailbox structure
13662306a36Sopenharmony_ci * @cbfn: Callback, if any.
13762306a36Sopenharmony_ci *
13862306a36Sopenharmony_ci */
13962306a36Sopenharmony_civoid
14062306a36Sopenharmony_cicsio_mb_bye(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
14162306a36Sopenharmony_ci	    void (*cbfn) (struct csio_hw *, struct csio_mb *))
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	struct fw_bye_cmd *cmdp = (struct fw_bye_cmd *)(mbp->mb);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	cmdp->op_to_write = htonl(FW_CMD_OP_V(FW_BYE_CMD) |
14862306a36Sopenharmony_ci				       FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
14962306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/*
15462306a36Sopenharmony_ci * csio_mb_reset - FW RESET command helper
15562306a36Sopenharmony_ci * @hw: The HW structure
15662306a36Sopenharmony_ci * @mbp: Mailbox structure
15762306a36Sopenharmony_ci * @reset: Type of reset.
15862306a36Sopenharmony_ci * @cbfn: Callback, if any.
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci */
16162306a36Sopenharmony_civoid
16262306a36Sopenharmony_cicsio_mb_reset(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
16362306a36Sopenharmony_ci	      int reset, int halt,
16462306a36Sopenharmony_ci	      void (*cbfn) (struct csio_hw *, struct csio_mb *))
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct fw_reset_cmd *cmdp = (struct fw_reset_cmd *)(mbp->mb);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	cmdp->op_to_write = htonl(FW_CMD_OP_V(FW_RESET_CMD) |
17162306a36Sopenharmony_ci				  FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
17262306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
17362306a36Sopenharmony_ci	cmdp->val = htonl(reset);
17462306a36Sopenharmony_ci	cmdp->halt_pkd = htonl(halt);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/*
17962306a36Sopenharmony_ci * csio_mb_params - FW PARAMS command helper
18062306a36Sopenharmony_ci * @hw: The HW structure
18162306a36Sopenharmony_ci * @mbp: Mailbox structure
18262306a36Sopenharmony_ci * @tmo: Command timeout.
18362306a36Sopenharmony_ci * @pf: PF number.
18462306a36Sopenharmony_ci * @vf: VF number.
18562306a36Sopenharmony_ci * @nparams: Number of parameters
18662306a36Sopenharmony_ci * @params: Parameter mnemonic array.
18762306a36Sopenharmony_ci * @val: Parameter value array.
18862306a36Sopenharmony_ci * @wr: Write/Read PARAMS.
18962306a36Sopenharmony_ci * @cbfn: Callback, if any.
19062306a36Sopenharmony_ci *
19162306a36Sopenharmony_ci */
19262306a36Sopenharmony_civoid
19362306a36Sopenharmony_cicsio_mb_params(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
19462306a36Sopenharmony_ci	       unsigned int pf, unsigned int vf, unsigned int nparams,
19562306a36Sopenharmony_ci	       const u32 *params, u32 *val, bool wr,
19662306a36Sopenharmony_ci	       void (*cbfn)(struct csio_hw *, struct csio_mb *))
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	uint32_t i;
19962306a36Sopenharmony_ci	uint32_t temp_params = 0, temp_val = 0;
20062306a36Sopenharmony_ci	struct fw_params_cmd *cmdp = (struct fw_params_cmd *)(mbp->mb);
20162306a36Sopenharmony_ci	__be32 *p = &cmdp->param[0].mnem;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_PARAMS_CMD)		|
20662306a36Sopenharmony_ci				FW_CMD_REQUEST_F			|
20762306a36Sopenharmony_ci				(wr ? FW_CMD_WRITE_F : FW_CMD_READ_F)	|
20862306a36Sopenharmony_ci				FW_PARAMS_CMD_PFN_V(pf)			|
20962306a36Sopenharmony_ci				FW_PARAMS_CMD_VFN_V(vf));
21062306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/* Write Params */
21362306a36Sopenharmony_ci	if (wr) {
21462306a36Sopenharmony_ci		while (nparams--) {
21562306a36Sopenharmony_ci			temp_params = *params++;
21662306a36Sopenharmony_ci			temp_val = *val++;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci			*p++ = htonl(temp_params);
21962306a36Sopenharmony_ci			*p++ = htonl(temp_val);
22062306a36Sopenharmony_ci		}
22162306a36Sopenharmony_ci	} else {
22262306a36Sopenharmony_ci		for (i = 0; i < nparams; i++, p += 2) {
22362306a36Sopenharmony_ci			temp_params = *params++;
22462306a36Sopenharmony_ci			*p = htonl(temp_params);
22562306a36Sopenharmony_ci		}
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci/*
23162306a36Sopenharmony_ci * csio_mb_process_read_params_rsp - FW PARAMS response processing helper
23262306a36Sopenharmony_ci * @hw: The HW structure
23362306a36Sopenharmony_ci * @mbp: Mailbox structure
23462306a36Sopenharmony_ci * @retval: Mailbox return value from Firmware
23562306a36Sopenharmony_ci * @nparams: Number of parameters
23662306a36Sopenharmony_ci * @val: Parameter value array.
23762306a36Sopenharmony_ci *
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_civoid
24062306a36Sopenharmony_cicsio_mb_process_read_params_rsp(struct csio_hw *hw, struct csio_mb *mbp,
24162306a36Sopenharmony_ci			   enum fw_retval *retval, unsigned int nparams,
24262306a36Sopenharmony_ci			   u32 *val)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	struct fw_params_cmd *rsp = (struct fw_params_cmd *)(mbp->mb);
24562306a36Sopenharmony_ci	uint32_t i;
24662306a36Sopenharmony_ci	__be32 *p = &rsp->param[0].val;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	*retval = FW_CMD_RETVAL_G(ntohl(rsp->retval_len16));
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if (*retval == FW_SUCCESS)
25162306a36Sopenharmony_ci		for (i = 0; i < nparams; i++, p += 2)
25262306a36Sopenharmony_ci			*val++ = ntohl(*p);
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/*
25662306a36Sopenharmony_ci * csio_mb_ldst - FW LDST command
25762306a36Sopenharmony_ci * @hw: The HW structure
25862306a36Sopenharmony_ci * @mbp: Mailbox structure
25962306a36Sopenharmony_ci * @tmo: timeout
26062306a36Sopenharmony_ci * @reg: register
26162306a36Sopenharmony_ci *
26262306a36Sopenharmony_ci */
26362306a36Sopenharmony_civoid
26462306a36Sopenharmony_cicsio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, int reg)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct fw_ldst_cmd *ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
26762306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, ldst_cmd, tmo, hw, NULL, 1);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/*
27062306a36Sopenharmony_ci	 * Construct and send the Firmware LDST Command to retrieve the
27162306a36Sopenharmony_ci	 * specified PCI-E Configuration Space register.
27262306a36Sopenharmony_ci	 */
27362306a36Sopenharmony_ci	ldst_cmd->op_to_addrspace =
27462306a36Sopenharmony_ci			htonl(FW_CMD_OP_V(FW_LDST_CMD)	|
27562306a36Sopenharmony_ci			FW_CMD_REQUEST_F			|
27662306a36Sopenharmony_ci			FW_CMD_READ_F			|
27762306a36Sopenharmony_ci			FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_FUNC_PCIE));
27862306a36Sopenharmony_ci	ldst_cmd->cycles_to_len16 = htonl(FW_LEN16(struct fw_ldst_cmd));
27962306a36Sopenharmony_ci	ldst_cmd->u.pcie.select_naccess = FW_LDST_CMD_NACCESS_V(1);
28062306a36Sopenharmony_ci	ldst_cmd->u.pcie.ctrl_to_fn =
28162306a36Sopenharmony_ci		(FW_LDST_CMD_LC_F | FW_LDST_CMD_FN_V(hw->pfn));
28262306a36Sopenharmony_ci	ldst_cmd->u.pcie.r = (uint8_t)reg;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci/*
28662306a36Sopenharmony_ci *
28762306a36Sopenharmony_ci * csio_mb_caps_config - FW Read/Write Capabilities command helper
28862306a36Sopenharmony_ci * @hw: The HW structure
28962306a36Sopenharmony_ci * @mbp: Mailbox structure
29062306a36Sopenharmony_ci * @wr: Write if 1, Read if 0
29162306a36Sopenharmony_ci * @init: Turn on initiator mode.
29262306a36Sopenharmony_ci * @tgt: Turn on target mode.
29362306a36Sopenharmony_ci * @cofld:  If 1, Control Offload for FCoE
29462306a36Sopenharmony_ci * @cbfn: Callback, if any.
29562306a36Sopenharmony_ci *
29662306a36Sopenharmony_ci * This helper assumes that cmdp has MB payload from a previous CAPS
29762306a36Sopenharmony_ci * read command.
29862306a36Sopenharmony_ci */
29962306a36Sopenharmony_civoid
30062306a36Sopenharmony_cicsio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
30162306a36Sopenharmony_ci		    bool wr, bool init, bool tgt, bool cofld,
30262306a36Sopenharmony_ci		    void (*cbfn) (struct csio_hw *, struct csio_mb *))
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	struct fw_caps_config_cmd *cmdp =
30562306a36Sopenharmony_ci				(struct fw_caps_config_cmd *)(mbp->mb);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, wr ? 0 : 1);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	cmdp->op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
31062306a36Sopenharmony_ci				  FW_CMD_REQUEST_F		|
31162306a36Sopenharmony_ci				  (wr ? FW_CMD_WRITE_F : FW_CMD_READ_F));
31262306a36Sopenharmony_ci	cmdp->cfvalid_to_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/* Read config */
31562306a36Sopenharmony_ci	if (!wr)
31662306a36Sopenharmony_ci		return;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* Write config */
31962306a36Sopenharmony_ci	cmdp->fcoecaps = 0;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	if (cofld)
32262306a36Sopenharmony_ci		cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_CTRL_OFLD);
32362306a36Sopenharmony_ci	if (init)
32462306a36Sopenharmony_ci		cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_INITIATOR);
32562306a36Sopenharmony_ci	if (tgt)
32662306a36Sopenharmony_ci		cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci/*
33062306a36Sopenharmony_ci * csio_mb_port- FW PORT command helper
33162306a36Sopenharmony_ci * @hw: The HW structure
33262306a36Sopenharmony_ci * @mbp: Mailbox structure
33362306a36Sopenharmony_ci * @tmo: COmmand timeout
33462306a36Sopenharmony_ci * @portid: Port ID to get/set info
33562306a36Sopenharmony_ci * @wr: Write/Read PORT information.
33662306a36Sopenharmony_ci * @fc: Flow control
33762306a36Sopenharmony_ci * @caps: Port capabilites to set.
33862306a36Sopenharmony_ci * @cbfn: Callback, if any.
33962306a36Sopenharmony_ci *
34062306a36Sopenharmony_ci */
34162306a36Sopenharmony_civoid
34262306a36Sopenharmony_cicsio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
34362306a36Sopenharmony_ci	     u8 portid, bool wr, uint32_t fc, uint16_t fw_caps,
34462306a36Sopenharmony_ci	     void (*cbfn) (struct csio_hw *, struct csio_mb *))
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn,  1);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	cmdp->op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD)		|
35162306a36Sopenharmony_ci				   FW_CMD_REQUEST_F			|
35262306a36Sopenharmony_ci				   (wr ? FW_CMD_EXEC_F : FW_CMD_READ_F)	|
35362306a36Sopenharmony_ci				   FW_PORT_CMD_PORTID_V(portid));
35462306a36Sopenharmony_ci	if (!wr) {
35562306a36Sopenharmony_ci		cmdp->action_to_len16 = htonl(
35662306a36Sopenharmony_ci			FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16
35762306a36Sopenharmony_ci			? FW_PORT_ACTION_GET_PORT_INFO
35862306a36Sopenharmony_ci			: FW_PORT_ACTION_GET_PORT_INFO32) |
35962306a36Sopenharmony_ci			FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
36062306a36Sopenharmony_ci		return;
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/* Set port */
36462306a36Sopenharmony_ci	cmdp->action_to_len16 = htonl(
36562306a36Sopenharmony_ci			FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16
36662306a36Sopenharmony_ci			? FW_PORT_ACTION_L1_CFG
36762306a36Sopenharmony_ci			: FW_PORT_ACTION_L1_CFG32) |
36862306a36Sopenharmony_ci			FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	if (fw_caps == FW_CAPS16)
37162306a36Sopenharmony_ci		cmdp->u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(fc));
37262306a36Sopenharmony_ci	else
37362306a36Sopenharmony_ci		cmdp->u.l1cfg32.rcap32 = cpu_to_be32(fc);
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci/*
37762306a36Sopenharmony_ci * csio_mb_process_read_port_rsp - FW PORT command response processing helper
37862306a36Sopenharmony_ci * @hw: The HW structure
37962306a36Sopenharmony_ci * @mbp: Mailbox structure
38062306a36Sopenharmony_ci * @retval: Mailbox return value from Firmware
38162306a36Sopenharmony_ci * @caps: port capabilities
38262306a36Sopenharmony_ci *
38362306a36Sopenharmony_ci */
38462306a36Sopenharmony_civoid
38562306a36Sopenharmony_cicsio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp,
38662306a36Sopenharmony_ci			 enum fw_retval *retval, uint16_t fw_caps,
38762306a36Sopenharmony_ci			 u32 *pcaps, u32 *acaps)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	*retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16));
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (*retval == FW_SUCCESS) {
39462306a36Sopenharmony_ci		if (fw_caps == FW_CAPS16) {
39562306a36Sopenharmony_ci			*pcaps = fwcaps16_to_caps32(ntohs(rsp->u.info.pcap));
39662306a36Sopenharmony_ci			*acaps = fwcaps16_to_caps32(ntohs(rsp->u.info.acap));
39762306a36Sopenharmony_ci		} else {
39862306a36Sopenharmony_ci			*pcaps = be32_to_cpu(rsp->u.info32.pcaps32);
39962306a36Sopenharmony_ci			*acaps = be32_to_cpu(rsp->u.info32.acaps32);
40062306a36Sopenharmony_ci		}
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci/*
40562306a36Sopenharmony_ci * csio_mb_initialize - FW INITIALIZE command helper
40662306a36Sopenharmony_ci * @hw: The HW structure
40762306a36Sopenharmony_ci * @mbp: Mailbox structure
40862306a36Sopenharmony_ci * @tmo: COmmand timeout
40962306a36Sopenharmony_ci * @cbfn: Callback, if any.
41062306a36Sopenharmony_ci *
41162306a36Sopenharmony_ci */
41262306a36Sopenharmony_civoid
41362306a36Sopenharmony_cicsio_mb_initialize(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
41462306a36Sopenharmony_ci		   void (*cbfn) (struct csio_hw *, struct csio_mb *))
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	struct fw_initialize_cmd *cmdp = (struct fw_initialize_cmd *)(mbp->mb);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	cmdp->op_to_write = htonl(FW_CMD_OP_V(FW_INITIALIZE_CMD)	|
42162306a36Sopenharmony_ci				  FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
42262306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci/*
42762306a36Sopenharmony_ci * csio_mb_iq_alloc - Initializes the mailbox to allocate an
42862306a36Sopenharmony_ci *				Ingress DMA queue in the firmware.
42962306a36Sopenharmony_ci *
43062306a36Sopenharmony_ci * @hw: The hw structure
43162306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
43262306a36Sopenharmony_ci * @priv: Private object
43362306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
43462306a36Sopenharmony_ci * @iq_params: Ingress queue params needed for allocation.
43562306a36Sopenharmony_ci * @cbfn: The call-back function
43662306a36Sopenharmony_ci *
43762306a36Sopenharmony_ci *
43862306a36Sopenharmony_ci */
43962306a36Sopenharmony_cistatic void
44062306a36Sopenharmony_cicsio_mb_iq_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
44162306a36Sopenharmony_ci		 uint32_t mb_tmo, struct csio_iq_params *iq_params,
44262306a36Sopenharmony_ci		 void (*cbfn) (struct csio_hw *, struct csio_mb *))
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD)		|
44962306a36Sopenharmony_ci				FW_CMD_REQUEST_F | FW_CMD_EXEC_F	|
45062306a36Sopenharmony_ci				FW_IQ_CMD_PFN_V(iq_params->pfn)	|
45162306a36Sopenharmony_ci				FW_IQ_CMD_VFN_V(iq_params->vfn));
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC_F		|
45462306a36Sopenharmony_ci				FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	cmdp->type_to_iqandstindex = htonl(
45762306a36Sopenharmony_ci				FW_IQ_CMD_VIID_V(iq_params->viid)	|
45862306a36Sopenharmony_ci				FW_IQ_CMD_TYPE_V(iq_params->type)	|
45962306a36Sopenharmony_ci				FW_IQ_CMD_IQASYNCH_V(iq_params->iqasynch));
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	cmdp->fl0size = htons(iq_params->fl0size);
46262306a36Sopenharmony_ci	cmdp->fl0size = htons(iq_params->fl1size);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci} /* csio_mb_iq_alloc */
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci/*
46762306a36Sopenharmony_ci * csio_mb_iq_write - Initializes the mailbox for writing into an
46862306a36Sopenharmony_ci *				Ingress DMA Queue.
46962306a36Sopenharmony_ci *
47062306a36Sopenharmony_ci * @hw: The HW structure
47162306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
47262306a36Sopenharmony_ci * @priv: Private object
47362306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
47462306a36Sopenharmony_ci * @cascaded_req: TRUE - if this request is cascased with iq-alloc request.
47562306a36Sopenharmony_ci * @iq_params: Ingress queue params needed for writing.
47662306a36Sopenharmony_ci * @cbfn: The call-back function
47762306a36Sopenharmony_ci *
47862306a36Sopenharmony_ci * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating,
47962306a36Sopenharmony_ci * because this IQ write request can be cascaded with a previous
48062306a36Sopenharmony_ci * IQ alloc request, and we dont want to over-write the bits set by
48162306a36Sopenharmony_ci * that request. This logic will work even in a non-cascaded case, since the
48262306a36Sopenharmony_ci * cmdp structure is zeroed out by CSIO_INIT_MBP.
48362306a36Sopenharmony_ci */
48462306a36Sopenharmony_cistatic void
48562306a36Sopenharmony_cicsio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
48662306a36Sopenharmony_ci		 uint32_t mb_tmo, bool cascaded_req,
48762306a36Sopenharmony_ci		 struct csio_iq_params *iq_params,
48862306a36Sopenharmony_ci		 void (*cbfn) (struct csio_hw *, struct csio_mb *))
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	uint32_t iq_start_stop = (iq_params->iq_start)	?
49362306a36Sopenharmony_ci					FW_IQ_CMD_IQSTART_F :
49462306a36Sopenharmony_ci					FW_IQ_CMD_IQSTOP_F;
49562306a36Sopenharmony_ci	int relaxed = !(hw->flags & CSIO_HWF_ROOT_NO_RELAXED_ORDERING);
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	/*
49862306a36Sopenharmony_ci	 * If this IQ write is cascaded with IQ alloc request, do not
49962306a36Sopenharmony_ci	 * re-initialize with 0's.
50062306a36Sopenharmony_ci	 *
50162306a36Sopenharmony_ci	 */
50262306a36Sopenharmony_ci	if (!cascaded_req)
50362306a36Sopenharmony_ci		CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	cmdp->op_to_vfn |= htonl(FW_CMD_OP_V(FW_IQ_CMD)		|
50662306a36Sopenharmony_ci				FW_CMD_REQUEST_F | FW_CMD_WRITE_F	|
50762306a36Sopenharmony_ci				FW_IQ_CMD_PFN_V(iq_params->pfn)	|
50862306a36Sopenharmony_ci				FW_IQ_CMD_VFN_V(iq_params->vfn));
50962306a36Sopenharmony_ci	cmdp->alloc_to_len16 |= htonl(iq_start_stop |
51062306a36Sopenharmony_ci				FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
51162306a36Sopenharmony_ci	cmdp->iqid |= htons(iq_params->iqid);
51262306a36Sopenharmony_ci	cmdp->fl0id |= htons(iq_params->fl0id);
51362306a36Sopenharmony_ci	cmdp->fl1id |= htons(iq_params->fl1id);
51462306a36Sopenharmony_ci	cmdp->type_to_iqandstindex |= htonl(
51562306a36Sopenharmony_ci			FW_IQ_CMD_IQANDST_V(iq_params->iqandst)	|
51662306a36Sopenharmony_ci			FW_IQ_CMD_IQANUS_V(iq_params->iqanus)	|
51762306a36Sopenharmony_ci			FW_IQ_CMD_IQANUD_V(iq_params->iqanud)	|
51862306a36Sopenharmony_ci			FW_IQ_CMD_IQANDSTINDEX_V(iq_params->iqandstindex));
51962306a36Sopenharmony_ci	cmdp->iqdroprss_to_iqesize |= htons(
52062306a36Sopenharmony_ci			FW_IQ_CMD_IQPCIECH_V(iq_params->iqpciech)	|
52162306a36Sopenharmony_ci			FW_IQ_CMD_IQDCAEN_V(iq_params->iqdcaen)		|
52262306a36Sopenharmony_ci			FW_IQ_CMD_IQDCACPU_V(iq_params->iqdcacpu)	|
52362306a36Sopenharmony_ci			FW_IQ_CMD_IQINTCNTTHRESH_V(iq_params->iqintcntthresh) |
52462306a36Sopenharmony_ci			FW_IQ_CMD_IQCPRIO_V(iq_params->iqcprio)		|
52562306a36Sopenharmony_ci			FW_IQ_CMD_IQESIZE_V(iq_params->iqesize));
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	cmdp->iqsize |= htons(iq_params->iqsize);
52862306a36Sopenharmony_ci	cmdp->iqaddr |= cpu_to_be64(iq_params->iqaddr);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	if (iq_params->type == 0) {
53162306a36Sopenharmony_ci		cmdp->iqns_to_fl0congen |= htonl(
53262306a36Sopenharmony_ci			FW_IQ_CMD_IQFLINTIQHSEN_V(iq_params->iqflintiqhsen)|
53362306a36Sopenharmony_ci			FW_IQ_CMD_IQFLINTCONGEN_V(iq_params->iqflintcongen));
53462306a36Sopenharmony_ci	}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (iq_params->fl0size && iq_params->fl0addr &&
53762306a36Sopenharmony_ci	    (iq_params->fl0id != 0xFFFF)) {
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		cmdp->iqns_to_fl0congen |= htonl(
54062306a36Sopenharmony_ci			FW_IQ_CMD_FL0HOSTFCMODE_V(iq_params->fl0hostfcmode)|
54162306a36Sopenharmony_ci			FW_IQ_CMD_FL0CPRIO_V(iq_params->fl0cprio)	|
54262306a36Sopenharmony_ci			FW_IQ_CMD_FL0FETCHRO_V(relaxed)			|
54362306a36Sopenharmony_ci			FW_IQ_CMD_FL0DATARO_V(relaxed)			|
54462306a36Sopenharmony_ci			FW_IQ_CMD_FL0PADEN_V(iq_params->fl0paden)	|
54562306a36Sopenharmony_ci			FW_IQ_CMD_FL0PACKEN_V(iq_params->fl0packen));
54662306a36Sopenharmony_ci		cmdp->fl0dcaen_to_fl0cidxfthresh |= htons(
54762306a36Sopenharmony_ci			FW_IQ_CMD_FL0DCAEN_V(iq_params->fl0dcaen)	|
54862306a36Sopenharmony_ci			FW_IQ_CMD_FL0DCACPU_V(iq_params->fl0dcacpu)	|
54962306a36Sopenharmony_ci			FW_IQ_CMD_FL0FBMIN_V(iq_params->fl0fbmin)	|
55062306a36Sopenharmony_ci			FW_IQ_CMD_FL0FBMAX_V(iq_params->fl0fbmax)	|
55162306a36Sopenharmony_ci			FW_IQ_CMD_FL0CIDXFTHRESH_V(iq_params->fl0cidxfthresh));
55262306a36Sopenharmony_ci		cmdp->fl0size |= htons(iq_params->fl0size);
55362306a36Sopenharmony_ci		cmdp->fl0addr |= cpu_to_be64(iq_params->fl0addr);
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci} /* csio_mb_iq_write */
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci/*
55862306a36Sopenharmony_ci * csio_mb_iq_alloc_write - Initializes the mailbox for allocating an
55962306a36Sopenharmony_ci *				Ingress DMA Queue.
56062306a36Sopenharmony_ci *
56162306a36Sopenharmony_ci * @hw: The HW structure
56262306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
56362306a36Sopenharmony_ci * @priv: Private data.
56462306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
56562306a36Sopenharmony_ci * @iq_params: Ingress queue params needed for allocation & writing.
56662306a36Sopenharmony_ci * @cbfn: The call-back function
56762306a36Sopenharmony_ci *
56862306a36Sopenharmony_ci *
56962306a36Sopenharmony_ci */
57062306a36Sopenharmony_civoid
57162306a36Sopenharmony_cicsio_mb_iq_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
57262306a36Sopenharmony_ci		       uint32_t mb_tmo, struct csio_iq_params *iq_params,
57362306a36Sopenharmony_ci		       void (*cbfn) (struct csio_hw *, struct csio_mb *))
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	csio_mb_iq_alloc(hw, mbp, priv, mb_tmo, iq_params, cbfn);
57662306a36Sopenharmony_ci	csio_mb_iq_write(hw, mbp, priv, mb_tmo, true, iq_params, cbfn);
57762306a36Sopenharmony_ci} /* csio_mb_iq_alloc_write */
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci/*
58062306a36Sopenharmony_ci * csio_mb_iq_alloc_write_rsp - Process the allocation & writing
58162306a36Sopenharmony_ci *				of ingress DMA queue mailbox's response.
58262306a36Sopenharmony_ci *
58362306a36Sopenharmony_ci * @hw: The HW structure.
58462306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize.
58562306a36Sopenharmony_ci * @retval: Firmware return value.
58662306a36Sopenharmony_ci * @iq_params: Ingress queue parameters, after allocation and write.
58762306a36Sopenharmony_ci *
58862306a36Sopenharmony_ci */
58962306a36Sopenharmony_civoid
59062306a36Sopenharmony_cicsio_mb_iq_alloc_write_rsp(struct csio_hw *hw, struct csio_mb *mbp,
59162306a36Sopenharmony_ci			   enum fw_retval *ret_val,
59262306a36Sopenharmony_ci			   struct csio_iq_params *iq_params)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	struct fw_iq_cmd *rsp = (struct fw_iq_cmd *)(mbp->mb);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	*ret_val = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16));
59762306a36Sopenharmony_ci	if (*ret_val == FW_SUCCESS) {
59862306a36Sopenharmony_ci		iq_params->physiqid = ntohs(rsp->physiqid);
59962306a36Sopenharmony_ci		iq_params->iqid = ntohs(rsp->iqid);
60062306a36Sopenharmony_ci		iq_params->fl0id = ntohs(rsp->fl0id);
60162306a36Sopenharmony_ci		iq_params->fl1id = ntohs(rsp->fl1id);
60262306a36Sopenharmony_ci	} else {
60362306a36Sopenharmony_ci		iq_params->physiqid = iq_params->iqid =
60462306a36Sopenharmony_ci		iq_params->fl0id = iq_params->fl1id = 0;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci} /* csio_mb_iq_alloc_write_rsp */
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci/*
60962306a36Sopenharmony_ci * csio_mb_iq_free - Initializes the mailbox for freeing a
61062306a36Sopenharmony_ci *				specified Ingress DMA Queue.
61162306a36Sopenharmony_ci *
61262306a36Sopenharmony_ci * @hw: The HW structure
61362306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
61462306a36Sopenharmony_ci * @priv: Private data
61562306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
61662306a36Sopenharmony_ci * @iq_params: Parameters of ingress queue, that is to be freed.
61762306a36Sopenharmony_ci * @cbfn: The call-back function
61862306a36Sopenharmony_ci *
61962306a36Sopenharmony_ci *
62062306a36Sopenharmony_ci */
62162306a36Sopenharmony_civoid
62262306a36Sopenharmony_cicsio_mb_iq_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
62362306a36Sopenharmony_ci		uint32_t mb_tmo, struct csio_iq_params *iq_params,
62462306a36Sopenharmony_ci		void (*cbfn) (struct csio_hw *, struct csio_mb *))
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD)		|
63162306a36Sopenharmony_ci				FW_CMD_REQUEST_F | FW_CMD_EXEC_F	|
63262306a36Sopenharmony_ci				FW_IQ_CMD_PFN_V(iq_params->pfn)	|
63362306a36Sopenharmony_ci				FW_IQ_CMD_VFN_V(iq_params->vfn));
63462306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_FREE_F		|
63562306a36Sopenharmony_ci				FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
63662306a36Sopenharmony_ci	cmdp->type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE_V(iq_params->type));
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	cmdp->iqid = htons(iq_params->iqid);
63962306a36Sopenharmony_ci	cmdp->fl0id = htons(iq_params->fl0id);
64062306a36Sopenharmony_ci	cmdp->fl1id = htons(iq_params->fl1id);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci} /* csio_mb_iq_free */
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci/*
64562306a36Sopenharmony_ci * csio_mb_eq_ofld_alloc - Initializes the mailbox for allocating
64662306a36Sopenharmony_ci *				an offload-egress queue.
64762306a36Sopenharmony_ci *
64862306a36Sopenharmony_ci * @hw: The HW  structure
64962306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
65062306a36Sopenharmony_ci * @priv: Private data
65162306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
65262306a36Sopenharmony_ci * @eq_ofld_params: (Offload) Egress queue parameters.
65362306a36Sopenharmony_ci * @cbfn: The call-back function
65462306a36Sopenharmony_ci *
65562306a36Sopenharmony_ci *
65662306a36Sopenharmony_ci */
65762306a36Sopenharmony_cistatic void
65862306a36Sopenharmony_cicsio_mb_eq_ofld_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
65962306a36Sopenharmony_ci		uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params,
66062306a36Sopenharmony_ci		void (*cbfn) (struct csio_hw *, struct csio_mb *))
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
66562306a36Sopenharmony_ci	cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD)		|
66662306a36Sopenharmony_ci				FW_CMD_REQUEST_F | FW_CMD_EXEC_F	|
66762306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_PFN_V(eq_ofld_params->pfn) |
66862306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_VFN_V(eq_ofld_params->vfn));
66962306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC_F	|
67062306a36Sopenharmony_ci				FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci} /* csio_mb_eq_ofld_alloc */
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci/*
67562306a36Sopenharmony_ci * csio_mb_eq_ofld_write - Initializes the mailbox for writing
67662306a36Sopenharmony_ci *				an alloacted offload-egress queue.
67762306a36Sopenharmony_ci *
67862306a36Sopenharmony_ci * @hw: The HW structure
67962306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
68062306a36Sopenharmony_ci * @priv: Private data
68162306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
68262306a36Sopenharmony_ci * @cascaded_req: TRUE - if this request is cascased with Eq-alloc request.
68362306a36Sopenharmony_ci * @eq_ofld_params: (Offload) Egress queue parameters.
68462306a36Sopenharmony_ci * @cbfn: The call-back function
68562306a36Sopenharmony_ci *
68662306a36Sopenharmony_ci *
68762306a36Sopenharmony_ci * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating,
68862306a36Sopenharmony_ci * because this EQ write request can be cascaded with a previous
68962306a36Sopenharmony_ci * EQ alloc request, and we dont want to over-write the bits set by
69062306a36Sopenharmony_ci * that request. This logic will work even in a non-cascaded case, since the
69162306a36Sopenharmony_ci * cmdp structure is zeroed out by CSIO_INIT_MBP.
69262306a36Sopenharmony_ci */
69362306a36Sopenharmony_cistatic void
69462306a36Sopenharmony_cicsio_mb_eq_ofld_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
69562306a36Sopenharmony_ci		      uint32_t mb_tmo, bool cascaded_req,
69662306a36Sopenharmony_ci		      struct csio_eq_params *eq_ofld_params,
69762306a36Sopenharmony_ci		      void (*cbfn) (struct csio_hw *, struct csio_mb *))
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	uint32_t eq_start_stop = (eq_ofld_params->eqstart)	?
70262306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_EQSTART_F :
70362306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_EQSTOP_F;
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	/*
70662306a36Sopenharmony_ci	 * If this EQ write is cascaded with EQ alloc request, do not
70762306a36Sopenharmony_ci	 * re-initialize with 0's.
70862306a36Sopenharmony_ci	 *
70962306a36Sopenharmony_ci	 */
71062306a36Sopenharmony_ci	if (!cascaded_req)
71162306a36Sopenharmony_ci		CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	cmdp->op_to_vfn |= htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD)	|
71462306a36Sopenharmony_ci				FW_CMD_REQUEST_F | FW_CMD_WRITE_F	|
71562306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_PFN_V(eq_ofld_params->pfn) |
71662306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_VFN_V(eq_ofld_params->vfn));
71762306a36Sopenharmony_ci	cmdp->alloc_to_len16 |= htonl(eq_start_stop		|
71862306a36Sopenharmony_ci				      FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	cmdp->eqid_pkd |= htonl(FW_EQ_OFLD_CMD_EQID_V(eq_ofld_params->eqid));
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	cmdp->fetchszm_to_iqid |= htonl(
72362306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_HOSTFCMODE_V(eq_ofld_params->hostfcmode)	|
72462306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_CPRIO_V(eq_ofld_params->cprio)		|
72562306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_PCIECHN_V(eq_ofld_params->pciechn)	|
72662306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_IQID_V(eq_ofld_params->iqid));
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	cmdp->dcaen_to_eqsize |= htonl(
72962306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_DCAEN_V(eq_ofld_params->dcaen)		|
73062306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_DCACPU_V(eq_ofld_params->dcacpu)		|
73162306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_FBMIN_V(eq_ofld_params->fbmin)		|
73262306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_FBMAX_V(eq_ofld_params->fbmax)		|
73362306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_CIDXFTHRESHO_V(eq_ofld_params->cidxfthresho) |
73462306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_CIDXFTHRESH_V(eq_ofld_params->cidxfthresh) |
73562306a36Sopenharmony_ci		FW_EQ_OFLD_CMD_EQSIZE_V(eq_ofld_params->eqsize));
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	cmdp->eqaddr |= cpu_to_be64(eq_ofld_params->eqaddr);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci} /* csio_mb_eq_ofld_write */
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci/*
74262306a36Sopenharmony_ci * csio_mb_eq_ofld_alloc_write - Initializes the mailbox for allocation
74362306a36Sopenharmony_ci *				writing into an Engress DMA Queue.
74462306a36Sopenharmony_ci *
74562306a36Sopenharmony_ci * @hw: The HW structure
74662306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
74762306a36Sopenharmony_ci * @priv: Private data.
74862306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
74962306a36Sopenharmony_ci * @eq_ofld_params: (Offload) Egress queue parameters.
75062306a36Sopenharmony_ci * @cbfn: The call-back function
75162306a36Sopenharmony_ci *
75262306a36Sopenharmony_ci *
75362306a36Sopenharmony_ci */
75462306a36Sopenharmony_civoid
75562306a36Sopenharmony_cicsio_mb_eq_ofld_alloc_write(struct csio_hw *hw, struct csio_mb *mbp,
75662306a36Sopenharmony_ci			    void *priv, uint32_t mb_tmo,
75762306a36Sopenharmony_ci			    struct csio_eq_params *eq_ofld_params,
75862306a36Sopenharmony_ci			    void (*cbfn) (struct csio_hw *, struct csio_mb *))
75962306a36Sopenharmony_ci{
76062306a36Sopenharmony_ci	csio_mb_eq_ofld_alloc(hw, mbp, priv, mb_tmo, eq_ofld_params, cbfn);
76162306a36Sopenharmony_ci	csio_mb_eq_ofld_write(hw, mbp, priv, mb_tmo, true,
76262306a36Sopenharmony_ci			      eq_ofld_params, cbfn);
76362306a36Sopenharmony_ci} /* csio_mb_eq_ofld_alloc_write */
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci/*
76662306a36Sopenharmony_ci * csio_mb_eq_ofld_alloc_write_rsp - Process the allocation
76762306a36Sopenharmony_ci *				& write egress DMA queue mailbox's response.
76862306a36Sopenharmony_ci *
76962306a36Sopenharmony_ci * @hw: The HW structure.
77062306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize.
77162306a36Sopenharmony_ci * @retval: Firmware return value.
77262306a36Sopenharmony_ci * @eq_ofld_params: (Offload) Egress queue parameters.
77362306a36Sopenharmony_ci *
77462306a36Sopenharmony_ci */
77562306a36Sopenharmony_civoid
77662306a36Sopenharmony_cicsio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *hw,
77762306a36Sopenharmony_ci				struct csio_mb *mbp, enum fw_retval *ret_val,
77862306a36Sopenharmony_ci				struct csio_eq_params *eq_ofld_params)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	struct fw_eq_ofld_cmd *rsp = (struct fw_eq_ofld_cmd *)(mbp->mb);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	*ret_val = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16));
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	if (*ret_val == FW_SUCCESS) {
78562306a36Sopenharmony_ci		eq_ofld_params->eqid = FW_EQ_OFLD_CMD_EQID_G(
78662306a36Sopenharmony_ci						ntohl(rsp->eqid_pkd));
78762306a36Sopenharmony_ci		eq_ofld_params->physeqid = FW_EQ_OFLD_CMD_PHYSEQID_G(
78862306a36Sopenharmony_ci						ntohl(rsp->physeqid_pkd));
78962306a36Sopenharmony_ci	} else
79062306a36Sopenharmony_ci		eq_ofld_params->eqid = 0;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci} /* csio_mb_eq_ofld_alloc_write_rsp */
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci/*
79562306a36Sopenharmony_ci * csio_mb_eq_ofld_free - Initializes the mailbox for freeing a
79662306a36Sopenharmony_ci *				specified Engress DMA Queue.
79762306a36Sopenharmony_ci *
79862306a36Sopenharmony_ci * @hw: The HW structure
79962306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
80062306a36Sopenharmony_ci * @priv: Private data area.
80162306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
80262306a36Sopenharmony_ci * @eq_ofld_params: (Offload) Egress queue parameters, that is to be freed.
80362306a36Sopenharmony_ci * @cbfn: The call-back function
80462306a36Sopenharmony_ci *
80562306a36Sopenharmony_ci *
80662306a36Sopenharmony_ci */
80762306a36Sopenharmony_civoid
80862306a36Sopenharmony_cicsio_mb_eq_ofld_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
80962306a36Sopenharmony_ci		     uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params,
81062306a36Sopenharmony_ci		     void (*cbfn) (struct csio_hw *, struct csio_mb *))
81162306a36Sopenharmony_ci{
81262306a36Sopenharmony_ci	struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD)	|
81762306a36Sopenharmony_ci				FW_CMD_REQUEST_F | FW_CMD_EXEC_F	|
81862306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_PFN_V(eq_ofld_params->pfn) |
81962306a36Sopenharmony_ci				FW_EQ_OFLD_CMD_VFN_V(eq_ofld_params->vfn));
82062306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE_F |
82162306a36Sopenharmony_ci				FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
82262306a36Sopenharmony_ci	cmdp->eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID_V(eq_ofld_params->eqid));
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci} /* csio_mb_eq_ofld_free */
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci/*
82762306a36Sopenharmony_ci * csio_write_fcoe_link_cond_init_mb - Initialize Mailbox to write FCoE link
82862306a36Sopenharmony_ci *				 condition.
82962306a36Sopenharmony_ci *
83062306a36Sopenharmony_ci * @ln: The Lnode structure
83162306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
83262306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
83362306a36Sopenharmony_ci * @cbfn: The call back function.
83462306a36Sopenharmony_ci *
83562306a36Sopenharmony_ci *
83662306a36Sopenharmony_ci */
83762306a36Sopenharmony_civoid
83862306a36Sopenharmony_cicsio_write_fcoe_link_cond_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
83962306a36Sopenharmony_ci			uint32_t mb_tmo, uint8_t port_id, uint32_t sub_opcode,
84062306a36Sopenharmony_ci			uint8_t cos, bool link_status, uint32_t fcfi,
84162306a36Sopenharmony_ci			void (*cbfn) (struct csio_hw *, struct csio_mb *))
84262306a36Sopenharmony_ci{
84362306a36Sopenharmony_ci	struct fw_fcoe_link_cmd *cmdp =
84462306a36Sopenharmony_ci				(struct fw_fcoe_link_cmd *)(mbp->mb);
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	cmdp->op_to_portid = htonl((
84962306a36Sopenharmony_ci			FW_CMD_OP_V(FW_FCOE_LINK_CMD)		|
85062306a36Sopenharmony_ci			FW_CMD_REQUEST_F				|
85162306a36Sopenharmony_ci			FW_CMD_WRITE_F				|
85262306a36Sopenharmony_ci			FW_FCOE_LINK_CMD_PORTID(port_id)));
85362306a36Sopenharmony_ci	cmdp->sub_opcode_fcfi = htonl(
85462306a36Sopenharmony_ci			FW_FCOE_LINK_CMD_SUB_OPCODE(sub_opcode)	|
85562306a36Sopenharmony_ci			FW_FCOE_LINK_CMD_FCFI(fcfi));
85662306a36Sopenharmony_ci	cmdp->lstatus = link_status;
85762306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci} /* csio_write_fcoe_link_cond_init_mb */
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci/*
86262306a36Sopenharmony_ci * csio_fcoe_read_res_info_init_mb - Initializes the mailbox for reading FCoE
86362306a36Sopenharmony_ci *				resource information(FW_GET_RES_INFO_CMD).
86462306a36Sopenharmony_ci *
86562306a36Sopenharmony_ci * @hw: The HW structure
86662306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
86762306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
86862306a36Sopenharmony_ci * @cbfn: The call-back function
86962306a36Sopenharmony_ci *
87062306a36Sopenharmony_ci *
87162306a36Sopenharmony_ci */
87262306a36Sopenharmony_civoid
87362306a36Sopenharmony_cicsio_fcoe_read_res_info_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
87462306a36Sopenharmony_ci			uint32_t mb_tmo,
87562306a36Sopenharmony_ci			void (*cbfn) (struct csio_hw *, struct csio_mb *))
87662306a36Sopenharmony_ci{
87762306a36Sopenharmony_ci	struct fw_fcoe_res_info_cmd *cmdp =
87862306a36Sopenharmony_ci			(struct fw_fcoe_res_info_cmd *)(mbp->mb);
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	cmdp->op_to_read = htonl((FW_CMD_OP_V(FW_FCOE_RES_INFO_CMD)	|
88362306a36Sopenharmony_ci				  FW_CMD_REQUEST_F			|
88462306a36Sopenharmony_ci				  FW_CMD_READ_F));
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci} /* csio_fcoe_read_res_info_init_mb */
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci/*
89162306a36Sopenharmony_ci * csio_fcoe_vnp_alloc_init_mb - Initializes the mailbox for allocating VNP
89262306a36Sopenharmony_ci *				in the firmware (FW_FCOE_VNP_CMD).
89362306a36Sopenharmony_ci *
89462306a36Sopenharmony_ci * @ln: The Lnode structure.
89562306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize.
89662306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
89762306a36Sopenharmony_ci * @fcfi: FCF Index.
89862306a36Sopenharmony_ci * @vnpi: vnpi
89962306a36Sopenharmony_ci * @iqid: iqid
90062306a36Sopenharmony_ci * @vnport_wwnn: vnport WWNN
90162306a36Sopenharmony_ci * @vnport_wwpn: vnport WWPN
90262306a36Sopenharmony_ci * @cbfn: The call-back function.
90362306a36Sopenharmony_ci *
90462306a36Sopenharmony_ci *
90562306a36Sopenharmony_ci */
90662306a36Sopenharmony_civoid
90762306a36Sopenharmony_cicsio_fcoe_vnp_alloc_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
90862306a36Sopenharmony_ci		uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, uint16_t iqid,
90962306a36Sopenharmony_ci		uint8_t vnport_wwnn[8],	uint8_t vnport_wwpn[8],
91062306a36Sopenharmony_ci		void (*cbfn) (struct csio_hw *, struct csio_mb *))
91162306a36Sopenharmony_ci{
91262306a36Sopenharmony_ci	struct fw_fcoe_vnp_cmd *cmdp =
91362306a36Sopenharmony_ci			(struct fw_fcoe_vnp_cmd *)(mbp->mb);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	cmdp->op_to_fcfi = htonl((FW_CMD_OP_V(FW_FCOE_VNP_CMD)		|
91862306a36Sopenharmony_ci				  FW_CMD_REQUEST_F			|
91962306a36Sopenharmony_ci				  FW_CMD_EXEC_F				|
92062306a36Sopenharmony_ci				  FW_FCOE_VNP_CMD_FCFI(fcfi)));
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_ALLOC		|
92362306a36Sopenharmony_ci				     FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	cmdp->iqid = htons(iqid);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	if (!wwn_to_u64(vnport_wwnn) && !wwn_to_u64(vnport_wwpn))
93062306a36Sopenharmony_ci		cmdp->gen_wwn_to_vnpi |= htonl(FW_FCOE_VNP_CMD_GEN_WWN);
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	if (vnport_wwnn)
93362306a36Sopenharmony_ci		memcpy(cmdp->vnport_wwnn, vnport_wwnn, 8);
93462306a36Sopenharmony_ci	if (vnport_wwpn)
93562306a36Sopenharmony_ci		memcpy(cmdp->vnport_wwpn, vnport_wwpn, 8);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci} /* csio_fcoe_vnp_alloc_init_mb */
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci/*
94062306a36Sopenharmony_ci * csio_fcoe_vnp_read_init_mb - Prepares VNP read cmd.
94162306a36Sopenharmony_ci * @ln: The Lnode structure.
94262306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize.
94362306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
94462306a36Sopenharmony_ci * @fcfi: FCF Index.
94562306a36Sopenharmony_ci * @vnpi: vnpi
94662306a36Sopenharmony_ci * @cbfn: The call-back handler.
94762306a36Sopenharmony_ci */
94862306a36Sopenharmony_civoid
94962306a36Sopenharmony_cicsio_fcoe_vnp_read_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
95062306a36Sopenharmony_ci		uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi,
95162306a36Sopenharmony_ci		void (*cbfn) (struct csio_hw *, struct csio_mb *))
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	struct fw_fcoe_vnp_cmd *cmdp =
95462306a36Sopenharmony_ci			(struct fw_fcoe_vnp_cmd *)(mbp->mb);
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
95762306a36Sopenharmony_ci	cmdp->op_to_fcfi = htonl(FW_CMD_OP_V(FW_FCOE_VNP_CMD)	|
95862306a36Sopenharmony_ci				 FW_CMD_REQUEST_F			|
95962306a36Sopenharmony_ci				 FW_CMD_READ_F			|
96062306a36Sopenharmony_ci				 FW_FCOE_VNP_CMD_FCFI(fcfi));
96162306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
96262306a36Sopenharmony_ci	cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci/*
96662306a36Sopenharmony_ci * csio_fcoe_vnp_free_init_mb - Initializes the mailbox for freeing an
96762306a36Sopenharmony_ci *			alloacted VNP in the firmware (FW_FCOE_VNP_CMD).
96862306a36Sopenharmony_ci *
96962306a36Sopenharmony_ci * @ln: The Lnode structure.
97062306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize.
97162306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
97262306a36Sopenharmony_ci * @fcfi: FCF flow id
97362306a36Sopenharmony_ci * @vnpi: VNP flow id
97462306a36Sopenharmony_ci * @cbfn: The call-back function.
97562306a36Sopenharmony_ci * Return: None
97662306a36Sopenharmony_ci */
97762306a36Sopenharmony_civoid
97862306a36Sopenharmony_cicsio_fcoe_vnp_free_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
97962306a36Sopenharmony_ci		uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi,
98062306a36Sopenharmony_ci		void (*cbfn) (struct csio_hw *, struct csio_mb *))
98162306a36Sopenharmony_ci{
98262306a36Sopenharmony_ci	struct fw_fcoe_vnp_cmd *cmdp =
98362306a36Sopenharmony_ci			(struct fw_fcoe_vnp_cmd *)(mbp->mb);
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	cmdp->op_to_fcfi = htonl(FW_CMD_OP_V(FW_FCOE_VNP_CMD)	|
98862306a36Sopenharmony_ci				 FW_CMD_REQUEST_F			|
98962306a36Sopenharmony_ci				 FW_CMD_EXEC_F			|
99062306a36Sopenharmony_ci				 FW_FCOE_VNP_CMD_FCFI(fcfi));
99162306a36Sopenharmony_ci	cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_FREE	|
99262306a36Sopenharmony_ci				     FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
99362306a36Sopenharmony_ci	cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
99462306a36Sopenharmony_ci}
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci/*
99762306a36Sopenharmony_ci * csio_fcoe_read_fcf_init_mb - Initializes the mailbox to read the
99862306a36Sopenharmony_ci *				FCF records.
99962306a36Sopenharmony_ci *
100062306a36Sopenharmony_ci * @ln: The Lnode structure
100162306a36Sopenharmony_ci * @mbp: Mailbox structure to initialize
100262306a36Sopenharmony_ci * @mb_tmo: Mailbox time-out period (in ms).
100362306a36Sopenharmony_ci * @fcf_params: FC-Forwarder parameters.
100462306a36Sopenharmony_ci * @cbfn: The call-back function
100562306a36Sopenharmony_ci *
100662306a36Sopenharmony_ci *
100762306a36Sopenharmony_ci */
100862306a36Sopenharmony_civoid
100962306a36Sopenharmony_cicsio_fcoe_read_fcf_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
101062306a36Sopenharmony_ci		uint32_t mb_tmo, uint32_t portid, uint32_t fcfi,
101162306a36Sopenharmony_ci		void (*cbfn) (struct csio_hw *, struct csio_mb *))
101262306a36Sopenharmony_ci{
101362306a36Sopenharmony_ci	struct fw_fcoe_fcf_cmd *cmdp =
101462306a36Sopenharmony_ci			(struct fw_fcoe_fcf_cmd *)(mbp->mb);
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	cmdp->op_to_fcfi = htonl(FW_CMD_OP_V(FW_FCOE_FCF_CMD)	|
101962306a36Sopenharmony_ci				 FW_CMD_REQUEST_F			|
102062306a36Sopenharmony_ci				 FW_CMD_READ_F			|
102162306a36Sopenharmony_ci				 FW_FCOE_FCF_CMD_FCFI(fcfi));
102262306a36Sopenharmony_ci	cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci} /* csio_fcoe_read_fcf_init_mb */
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_civoid
102762306a36Sopenharmony_cicsio_fcoe_read_portparams_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
102862306a36Sopenharmony_ci				uint32_t mb_tmo,
102962306a36Sopenharmony_ci				struct fw_fcoe_port_cmd_params *portparams,
103062306a36Sopenharmony_ci				void (*cbfn)(struct csio_hw *,
103162306a36Sopenharmony_ci					     struct csio_mb *))
103262306a36Sopenharmony_ci{
103362306a36Sopenharmony_ci	struct fw_fcoe_stats_cmd *cmdp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
103662306a36Sopenharmony_ci	mbp->mb_size = 64;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	cmdp->op_to_flowid = htonl(FW_CMD_OP_V(FW_FCOE_STATS_CMD)         |
103962306a36Sopenharmony_ci				   FW_CMD_REQUEST_F | FW_CMD_READ_F);
104062306a36Sopenharmony_ci	cmdp->free_to_len16 = htonl(FW_CMD_LEN16_V(CSIO_MAX_MB_SIZE/16));
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	cmdp->u.ctl.nstats_port = FW_FCOE_STATS_CMD_NSTATS(portparams->nstats) |
104362306a36Sopenharmony_ci				  FW_FCOE_STATS_CMD_PORT(portparams->portid);
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	cmdp->u.ctl.port_valid_ix = FW_FCOE_STATS_CMD_IX(portparams->idx)    |
104662306a36Sopenharmony_ci				    FW_FCOE_STATS_CMD_PORT_VALID;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci} /* csio_fcoe_read_portparams_init_mb */
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_civoid
105162306a36Sopenharmony_cicsio_mb_process_portparams_rsp(struct csio_hw *hw,
105262306a36Sopenharmony_ci				struct csio_mb *mbp,
105362306a36Sopenharmony_ci				enum fw_retval *retval,
105462306a36Sopenharmony_ci				struct fw_fcoe_port_cmd_params *portparams,
105562306a36Sopenharmony_ci				struct fw_fcoe_port_stats *portstats)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	struct fw_fcoe_stats_cmd *rsp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
105862306a36Sopenharmony_ci	struct fw_fcoe_port_stats stats;
105962306a36Sopenharmony_ci	uint8_t *src;
106062306a36Sopenharmony_ci	uint8_t *dst;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	*retval = FW_CMD_RETVAL_G(ntohl(rsp->free_to_len16));
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	memset(&stats, 0, sizeof(struct fw_fcoe_port_stats));
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	if (*retval == FW_SUCCESS) {
106762306a36Sopenharmony_ci		dst = (uint8_t *)(&stats) + ((portparams->idx - 1) * 8);
106862306a36Sopenharmony_ci		src = (uint8_t *)rsp + (CSIO_STATS_OFFSET * 8);
106962306a36Sopenharmony_ci		memcpy(dst, src, (portparams->nstats * 8));
107062306a36Sopenharmony_ci		if (portparams->idx == 1) {
107162306a36Sopenharmony_ci			/* Get the first 6 flits from the Mailbox */
107262306a36Sopenharmony_ci			portstats->tx_bcast_bytes = stats.tx_bcast_bytes;
107362306a36Sopenharmony_ci			portstats->tx_bcast_frames = stats.tx_bcast_frames;
107462306a36Sopenharmony_ci			portstats->tx_mcast_bytes = stats.tx_mcast_bytes;
107562306a36Sopenharmony_ci			portstats->tx_mcast_frames = stats.tx_mcast_frames;
107662306a36Sopenharmony_ci			portstats->tx_ucast_bytes = stats.tx_ucast_bytes;
107762306a36Sopenharmony_ci			portstats->tx_ucast_frames = stats.tx_ucast_frames;
107862306a36Sopenharmony_ci		}
107962306a36Sopenharmony_ci		if (portparams->idx == 7) {
108062306a36Sopenharmony_ci			/* Get the second 6 flits from the Mailbox */
108162306a36Sopenharmony_ci			portstats->tx_drop_frames = stats.tx_drop_frames;
108262306a36Sopenharmony_ci			portstats->tx_offload_bytes = stats.tx_offload_bytes;
108362306a36Sopenharmony_ci			portstats->tx_offload_frames = stats.tx_offload_frames;
108462306a36Sopenharmony_ci#if 0
108562306a36Sopenharmony_ci			portstats->rx_pf_bytes = stats.rx_pf_bytes;
108662306a36Sopenharmony_ci			portstats->rx_pf_frames	= stats.rx_pf_frames;
108762306a36Sopenharmony_ci#endif
108862306a36Sopenharmony_ci			portstats->rx_bcast_bytes = stats.rx_bcast_bytes;
108962306a36Sopenharmony_ci			portstats->rx_bcast_frames = stats.rx_bcast_frames;
109062306a36Sopenharmony_ci			portstats->rx_mcast_bytes = stats.rx_mcast_bytes;
109162306a36Sopenharmony_ci		}
109262306a36Sopenharmony_ci		if (portparams->idx == 13) {
109362306a36Sopenharmony_ci			/* Get the last 4 flits from the Mailbox */
109462306a36Sopenharmony_ci			portstats->rx_mcast_frames = stats.rx_mcast_frames;
109562306a36Sopenharmony_ci			portstats->rx_ucast_bytes = stats.rx_ucast_bytes;
109662306a36Sopenharmony_ci			portstats->rx_ucast_frames = stats.rx_ucast_frames;
109762306a36Sopenharmony_ci			portstats->rx_err_frames = stats.rx_err_frames;
109862306a36Sopenharmony_ci		}
109962306a36Sopenharmony_ci	}
110062306a36Sopenharmony_ci}
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci/* Entry points/APIs for MB module					     */
110362306a36Sopenharmony_ci/*
110462306a36Sopenharmony_ci * csio_mb_intr_enable - Enable Interrupts from mailboxes.
110562306a36Sopenharmony_ci * @hw: The HW structure
110662306a36Sopenharmony_ci *
110762306a36Sopenharmony_ci * Enables CIM interrupt bit in appropriate INT_ENABLE registers.
110862306a36Sopenharmony_ci */
110962306a36Sopenharmony_civoid
111062306a36Sopenharmony_cicsio_mb_intr_enable(struct csio_hw *hw)
111162306a36Sopenharmony_ci{
111262306a36Sopenharmony_ci	csio_wr_reg32(hw, MBMSGRDYINTEN_F, MYPF_REG(CIM_PF_HOST_INT_ENABLE_A));
111362306a36Sopenharmony_ci	csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE_A));
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci/*
111762306a36Sopenharmony_ci * csio_mb_intr_disable - Disable Interrupts from mailboxes.
111862306a36Sopenharmony_ci * @hw: The HW structure
111962306a36Sopenharmony_ci *
112062306a36Sopenharmony_ci * Disable bit in HostInterruptEnable CIM register.
112162306a36Sopenharmony_ci */
112262306a36Sopenharmony_civoid
112362306a36Sopenharmony_cicsio_mb_intr_disable(struct csio_hw *hw)
112462306a36Sopenharmony_ci{
112562306a36Sopenharmony_ci	csio_wr_reg32(hw, MBMSGRDYINTEN_V(0),
112662306a36Sopenharmony_ci		      MYPF_REG(CIM_PF_HOST_INT_ENABLE_A));
112762306a36Sopenharmony_ci	csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE_A));
112862306a36Sopenharmony_ci}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_cistatic void
113162306a36Sopenharmony_cicsio_mb_dump_fw_dbg(struct csio_hw *hw, __be64 *cmd)
113262306a36Sopenharmony_ci{
113362306a36Sopenharmony_ci	struct fw_debug_cmd *dbg = (struct fw_debug_cmd *)cmd;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	if ((FW_DEBUG_CMD_TYPE_G(ntohl(dbg->op_type))) == 1) {
113662306a36Sopenharmony_ci		csio_info(hw, "FW print message:\n");
113762306a36Sopenharmony_ci		csio_info(hw, "\tdebug->dprtstridx = %d\n",
113862306a36Sopenharmony_ci			    ntohs(dbg->u.prt.dprtstridx));
113962306a36Sopenharmony_ci		csio_info(hw, "\tdebug->dprtstrparam0 = 0x%x\n",
114062306a36Sopenharmony_ci			    ntohl(dbg->u.prt.dprtstrparam0));
114162306a36Sopenharmony_ci		csio_info(hw, "\tdebug->dprtstrparam1 = 0x%x\n",
114262306a36Sopenharmony_ci			    ntohl(dbg->u.prt.dprtstrparam1));
114362306a36Sopenharmony_ci		csio_info(hw, "\tdebug->dprtstrparam2 = 0x%x\n",
114462306a36Sopenharmony_ci			    ntohl(dbg->u.prt.dprtstrparam2));
114562306a36Sopenharmony_ci		csio_info(hw, "\tdebug->dprtstrparam3 = 0x%x\n",
114662306a36Sopenharmony_ci			    ntohl(dbg->u.prt.dprtstrparam3));
114762306a36Sopenharmony_ci	} else {
114862306a36Sopenharmony_ci		/* This is a FW assertion */
114962306a36Sopenharmony_ci		csio_fatal(hw, "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
115062306a36Sopenharmony_ci			    dbg->u.assert.filename_0_7,
115162306a36Sopenharmony_ci			    ntohl(dbg->u.assert.line),
115262306a36Sopenharmony_ci			    ntohl(dbg->u.assert.x),
115362306a36Sopenharmony_ci			    ntohl(dbg->u.assert.y));
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cistatic void
115862306a36Sopenharmony_cicsio_mb_debug_cmd_handler(struct csio_hw *hw)
115962306a36Sopenharmony_ci{
116062306a36Sopenharmony_ci	int i;
116162306a36Sopenharmony_ci	__be64 cmd[CSIO_MB_MAX_REGS];
116262306a36Sopenharmony_ci	uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL_A);
116362306a36Sopenharmony_ci	uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA_A);
116462306a36Sopenharmony_ci	int size = sizeof(struct fw_debug_cmd);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	/* Copy mailbox data */
116762306a36Sopenharmony_ci	for (i = 0; i < size; i += 8)
116862306a36Sopenharmony_ci		cmd[i / 8] = cpu_to_be64(csio_rd_reg64(hw, data_reg + i));
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	csio_mb_dump_fw_dbg(hw, cmd);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	/* Notify FW of mailbox by setting owner as UP */
117362306a36Sopenharmony_ci	csio_wr_reg32(hw, MBMSGVALID_F | MBINTREQ_F |
117462306a36Sopenharmony_ci		      MBOWNER_V(CSIO_MBOWNER_FW), ctl_reg);
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	csio_rd_reg32(hw, ctl_reg);
117762306a36Sopenharmony_ci	wmb();
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci/*
118162306a36Sopenharmony_ci * csio_mb_issue - generic routine for issuing Mailbox commands.
118262306a36Sopenharmony_ci * @hw: The HW structure
118362306a36Sopenharmony_ci * @mbp: Mailbox command to issue
118462306a36Sopenharmony_ci *
118562306a36Sopenharmony_ci *  Caller should hold hw lock across this call.
118662306a36Sopenharmony_ci */
118762306a36Sopenharmony_ciint
118862306a36Sopenharmony_cicsio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp)
118962306a36Sopenharmony_ci{
119062306a36Sopenharmony_ci	uint32_t owner, ctl;
119162306a36Sopenharmony_ci	int i;
119262306a36Sopenharmony_ci	uint32_t ii;
119362306a36Sopenharmony_ci	__be64 *cmd = mbp->mb;
119462306a36Sopenharmony_ci	__be64 hdr;
119562306a36Sopenharmony_ci	struct csio_mbm	*mbm = &hw->mbm;
119662306a36Sopenharmony_ci	uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL_A);
119762306a36Sopenharmony_ci	uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA_A);
119862306a36Sopenharmony_ci	int size = mbp->mb_size;
119962306a36Sopenharmony_ci	int rv = -EINVAL;
120062306a36Sopenharmony_ci	struct fw_cmd_hdr *fw_hdr;
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	/* Determine mode */
120362306a36Sopenharmony_ci	if (mbp->mb_cbfn == NULL) {
120462306a36Sopenharmony_ci		/* Need to issue/get results in the same context */
120562306a36Sopenharmony_ci		if (mbp->tmo < CSIO_MB_POLL_FREQ) {
120662306a36Sopenharmony_ci			csio_err(hw, "Invalid tmo: 0x%x\n", mbp->tmo);
120762306a36Sopenharmony_ci			goto error_out;
120862306a36Sopenharmony_ci		}
120962306a36Sopenharmony_ci	} else if (!csio_is_host_intr_enabled(hw) ||
121062306a36Sopenharmony_ci		   !csio_is_hw_intr_enabled(hw)) {
121162306a36Sopenharmony_ci		csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n",
121262306a36Sopenharmony_ci			 *((uint8_t *)mbp->mb));
121362306a36Sopenharmony_ci		goto error_out;
121462306a36Sopenharmony_ci	}
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	if (mbm->mcurrent != NULL) {
121762306a36Sopenharmony_ci		/* Queue mbox cmd, if another mbox cmd is active */
121862306a36Sopenharmony_ci		if (mbp->mb_cbfn == NULL) {
121962306a36Sopenharmony_ci			rv = -EBUSY;
122062306a36Sopenharmony_ci			csio_dbg(hw, "Couldn't own Mailbox %x op:0x%x\n",
122162306a36Sopenharmony_ci				    hw->pfn, *((uint8_t *)mbp->mb));
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci			goto error_out;
122462306a36Sopenharmony_ci		} else {
122562306a36Sopenharmony_ci			list_add_tail(&mbp->list, &mbm->req_q);
122662306a36Sopenharmony_ci			CSIO_INC_STATS(mbm, n_activeq);
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci			return 0;
122962306a36Sopenharmony_ci		}
123062306a36Sopenharmony_ci	}
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	/* Now get ownership of mailbox */
123362306a36Sopenharmony_ci	owner = MBOWNER_G(csio_rd_reg32(hw, ctl_reg));
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	if (!csio_mb_is_host_owner(owner)) {
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci		for (i = 0; (owner == CSIO_MBOWNER_NONE) && (i < 3); i++)
123862306a36Sopenharmony_ci			owner = MBOWNER_G(csio_rd_reg32(hw, ctl_reg));
123962306a36Sopenharmony_ci		/*
124062306a36Sopenharmony_ci		 * Mailbox unavailable. In immediate mode, fail the command.
124162306a36Sopenharmony_ci		 * In other modes, enqueue the request.
124262306a36Sopenharmony_ci		 */
124362306a36Sopenharmony_ci		if (!csio_mb_is_host_owner(owner)) {
124462306a36Sopenharmony_ci			if (mbp->mb_cbfn == NULL) {
124562306a36Sopenharmony_ci				rv = owner ? -EBUSY : -ETIMEDOUT;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci				csio_dbg(hw,
124862306a36Sopenharmony_ci					 "Couldn't own Mailbox %x op:0x%x "
124962306a36Sopenharmony_ci					 "owner:%x\n",
125062306a36Sopenharmony_ci					 hw->pfn, *((uint8_t *)mbp->mb), owner);
125162306a36Sopenharmony_ci				goto error_out;
125262306a36Sopenharmony_ci			} else {
125362306a36Sopenharmony_ci				if (mbm->mcurrent == NULL) {
125462306a36Sopenharmony_ci					csio_err(hw,
125562306a36Sopenharmony_ci						 "Couldn't own Mailbox %x "
125662306a36Sopenharmony_ci						 "op:0x%x owner:%x\n",
125762306a36Sopenharmony_ci						 hw->pfn, *((uint8_t *)mbp->mb),
125862306a36Sopenharmony_ci						 owner);
125962306a36Sopenharmony_ci					csio_err(hw,
126062306a36Sopenharmony_ci						 "No outstanding driver"
126162306a36Sopenharmony_ci						 " mailbox as well\n");
126262306a36Sopenharmony_ci					goto error_out;
126362306a36Sopenharmony_ci				}
126462306a36Sopenharmony_ci			}
126562306a36Sopenharmony_ci		}
126662306a36Sopenharmony_ci	}
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	/* Mailbox is available, copy mailbox data into it */
126962306a36Sopenharmony_ci	for (i = 0; i < size; i += 8) {
127062306a36Sopenharmony_ci		csio_wr_reg64(hw, be64_to_cpu(*cmd), data_reg + i);
127162306a36Sopenharmony_ci		cmd++;
127262306a36Sopenharmony_ci	}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	CSIO_DUMP_MB(hw, hw->pfn, data_reg);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	/* Start completion timers in non-immediate modes and notify FW */
127762306a36Sopenharmony_ci	if (mbp->mb_cbfn != NULL) {
127862306a36Sopenharmony_ci		mbm->mcurrent = mbp;
127962306a36Sopenharmony_ci		mod_timer(&mbm->timer, jiffies + msecs_to_jiffies(mbp->tmo));
128062306a36Sopenharmony_ci		csio_wr_reg32(hw, MBMSGVALID_F | MBINTREQ_F |
128162306a36Sopenharmony_ci			      MBOWNER_V(CSIO_MBOWNER_FW), ctl_reg);
128262306a36Sopenharmony_ci	} else
128362306a36Sopenharmony_ci		csio_wr_reg32(hw, MBMSGVALID_F | MBOWNER_V(CSIO_MBOWNER_FW),
128462306a36Sopenharmony_ci			      ctl_reg);
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	/* Flush posted writes */
128762306a36Sopenharmony_ci	csio_rd_reg32(hw, ctl_reg);
128862306a36Sopenharmony_ci	wmb();
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	CSIO_INC_STATS(mbm, n_req);
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	if (mbp->mb_cbfn)
129362306a36Sopenharmony_ci		return 0;
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	/* Poll for completion in immediate mode */
129662306a36Sopenharmony_ci	cmd = mbp->mb;
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	for (ii = 0; ii < mbp->tmo; ii += CSIO_MB_POLL_FREQ) {
129962306a36Sopenharmony_ci		mdelay(CSIO_MB_POLL_FREQ);
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci		/* Check for response */
130262306a36Sopenharmony_ci		ctl = csio_rd_reg32(hw, ctl_reg);
130362306a36Sopenharmony_ci		if (csio_mb_is_host_owner(MBOWNER_G(ctl))) {
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci			if (!(ctl & MBMSGVALID_F)) {
130662306a36Sopenharmony_ci				csio_wr_reg32(hw, 0, ctl_reg);
130762306a36Sopenharmony_ci				continue;
130862306a36Sopenharmony_ci			}
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci			CSIO_DUMP_MB(hw, hw->pfn, data_reg);
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci			hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
131362306a36Sopenharmony_ci			fw_hdr = (struct fw_cmd_hdr *)&hdr;
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci			switch (FW_CMD_OP_G(ntohl(fw_hdr->hi))) {
131662306a36Sopenharmony_ci			case FW_DEBUG_CMD:
131762306a36Sopenharmony_ci				csio_mb_debug_cmd_handler(hw);
131862306a36Sopenharmony_ci				continue;
131962306a36Sopenharmony_ci			}
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci			/* Copy response */
132262306a36Sopenharmony_ci			for (i = 0; i < size; i += 8)
132362306a36Sopenharmony_ci				*cmd++ = cpu_to_be64(csio_rd_reg64
132462306a36Sopenharmony_ci							  (hw, data_reg + i));
132562306a36Sopenharmony_ci			csio_wr_reg32(hw, 0, ctl_reg);
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci			if (csio_mb_fw_retval(mbp) != FW_SUCCESS)
132862306a36Sopenharmony_ci				CSIO_INC_STATS(mbm, n_err);
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci			CSIO_INC_STATS(mbm, n_rsp);
133162306a36Sopenharmony_ci			return 0;
133262306a36Sopenharmony_ci		}
133362306a36Sopenharmony_ci	}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	CSIO_INC_STATS(mbm, n_tmo);
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	csio_err(hw, "Mailbox %x op:0x%x timed out!\n",
133862306a36Sopenharmony_ci		 hw->pfn, *((uint8_t *)cmd));
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	return -ETIMEDOUT;
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_cierror_out:
134362306a36Sopenharmony_ci	CSIO_INC_STATS(mbm, n_err);
134462306a36Sopenharmony_ci	return rv;
134562306a36Sopenharmony_ci}
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci/*
134862306a36Sopenharmony_ci * csio_mb_completions - Completion handler for Mailbox commands
134962306a36Sopenharmony_ci * @hw: The HW structure
135062306a36Sopenharmony_ci * @cbfn_q: Completion queue.
135162306a36Sopenharmony_ci *
135262306a36Sopenharmony_ci */
135362306a36Sopenharmony_civoid
135462306a36Sopenharmony_cicsio_mb_completions(struct csio_hw *hw, struct list_head *cbfn_q)
135562306a36Sopenharmony_ci{
135662306a36Sopenharmony_ci	struct csio_mb *mbp;
135762306a36Sopenharmony_ci	struct csio_mbm *mbm = &hw->mbm;
135862306a36Sopenharmony_ci	enum fw_retval rv;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	while (!list_empty(cbfn_q)) {
136162306a36Sopenharmony_ci		mbp = list_first_entry(cbfn_q, struct csio_mb, list);
136262306a36Sopenharmony_ci		list_del_init(&mbp->list);
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci		rv = csio_mb_fw_retval(mbp);
136562306a36Sopenharmony_ci		if ((rv != FW_SUCCESS) && (rv != FW_HOSTERROR))
136662306a36Sopenharmony_ci			CSIO_INC_STATS(mbm, n_err);
136762306a36Sopenharmony_ci		else if (rv != FW_HOSTERROR)
136862306a36Sopenharmony_ci			CSIO_INC_STATS(mbm, n_rsp);
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci		if (mbp->mb_cbfn)
137162306a36Sopenharmony_ci			mbp->mb_cbfn(hw, mbp);
137262306a36Sopenharmony_ci	}
137362306a36Sopenharmony_ci}
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_cistatic void
137662306a36Sopenharmony_cicsio_mb_portmod_changed(struct csio_hw *hw, uint8_t port_id)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	static char *mod_str[] = {
137962306a36Sopenharmony_ci		NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM"
138062306a36Sopenharmony_ci	};
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	struct csio_pport *port = &hw->pport[port_id];
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	if (port->mod_type == FW_PORT_MOD_TYPE_NONE)
138562306a36Sopenharmony_ci		csio_info(hw, "Port:%d - port module unplugged\n", port_id);
138662306a36Sopenharmony_ci	else if (port->mod_type < ARRAY_SIZE(mod_str))
138762306a36Sopenharmony_ci		csio_info(hw, "Port:%d - %s port module inserted\n", port_id,
138862306a36Sopenharmony_ci			  mod_str[port->mod_type]);
138962306a36Sopenharmony_ci	else if (port->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
139062306a36Sopenharmony_ci		csio_info(hw,
139162306a36Sopenharmony_ci			  "Port:%d - unsupported optical port module "
139262306a36Sopenharmony_ci			  "inserted\n", port_id);
139362306a36Sopenharmony_ci	else if (port->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
139462306a36Sopenharmony_ci		csio_info(hw,
139562306a36Sopenharmony_ci			  "Port:%d - unknown port module inserted, forcing "
139662306a36Sopenharmony_ci			  "TWINAX\n", port_id);
139762306a36Sopenharmony_ci	else if (port->mod_type == FW_PORT_MOD_TYPE_ERROR)
139862306a36Sopenharmony_ci		csio_info(hw, "Port:%d - transceiver module error\n", port_id);
139962306a36Sopenharmony_ci	else
140062306a36Sopenharmony_ci		csio_info(hw, "Port:%d - unknown module type %d inserted\n",
140162306a36Sopenharmony_ci			  port_id, port->mod_type);
140262306a36Sopenharmony_ci}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ciint
140562306a36Sopenharmony_cicsio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
140662306a36Sopenharmony_ci{
140762306a36Sopenharmony_ci	uint8_t opcode = *(uint8_t *)cmd;
140862306a36Sopenharmony_ci	struct fw_port_cmd *pcmd;
140962306a36Sopenharmony_ci	uint8_t port_id;
141062306a36Sopenharmony_ci	uint32_t link_status;
141162306a36Sopenharmony_ci	uint16_t action;
141262306a36Sopenharmony_ci	uint8_t mod_type;
141362306a36Sopenharmony_ci	fw_port_cap32_t linkattr;
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	if (opcode == FW_PORT_CMD) {
141662306a36Sopenharmony_ci		pcmd = (struct fw_port_cmd *)cmd;
141762306a36Sopenharmony_ci		port_id = FW_PORT_CMD_PORTID_G(
141862306a36Sopenharmony_ci				ntohl(pcmd->op_to_portid));
141962306a36Sopenharmony_ci		action = FW_PORT_CMD_ACTION_G(
142062306a36Sopenharmony_ci				ntohl(pcmd->action_to_len16));
142162306a36Sopenharmony_ci		if (action != FW_PORT_ACTION_GET_PORT_INFO &&
142262306a36Sopenharmony_ci		    action != FW_PORT_ACTION_GET_PORT_INFO32) {
142362306a36Sopenharmony_ci			csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n",
142462306a36Sopenharmony_ci				action);
142562306a36Sopenharmony_ci			return -EINVAL;
142662306a36Sopenharmony_ci		}
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci		if (action == FW_PORT_ACTION_GET_PORT_INFO) {
142962306a36Sopenharmony_ci			link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
143062306a36Sopenharmony_ci			mod_type = FW_PORT_CMD_MODTYPE_G(link_status);
143162306a36Sopenharmony_ci			linkattr = lstatus_to_fwcap(link_status);
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci			hw->pport[port_id].link_status =
143462306a36Sopenharmony_ci				FW_PORT_CMD_LSTATUS_G(link_status);
143562306a36Sopenharmony_ci		} else {
143662306a36Sopenharmony_ci			link_status =
143762306a36Sopenharmony_ci				ntohl(pcmd->u.info32.lstatus32_to_cbllen32);
143862306a36Sopenharmony_ci			mod_type = FW_PORT_CMD_MODTYPE32_G(link_status);
143962306a36Sopenharmony_ci			linkattr = ntohl(pcmd->u.info32.linkattr32);
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci			hw->pport[port_id].link_status =
144262306a36Sopenharmony_ci				FW_PORT_CMD_LSTATUS32_G(link_status);
144362306a36Sopenharmony_ci		}
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci		hw->pport[port_id].link_speed = fwcap_to_fwspeed(linkattr);
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci		csio_info(hw, "Port:%x - LINK %s\n", port_id,
144862306a36Sopenharmony_ci			hw->pport[port_id].link_status ? "UP" : "DOWN");
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci		if (mod_type != hw->pport[port_id].mod_type) {
145162306a36Sopenharmony_ci			hw->pport[port_id].mod_type = mod_type;
145262306a36Sopenharmony_ci			csio_mb_portmod_changed(hw, port_id);
145362306a36Sopenharmony_ci		}
145462306a36Sopenharmony_ci	} else if (opcode == FW_DEBUG_CMD) {
145562306a36Sopenharmony_ci		csio_mb_dump_fw_dbg(hw, cmd);
145662306a36Sopenharmony_ci	} else {
145762306a36Sopenharmony_ci		csio_dbg(hw, "Gen MB can't handle op:0x%x on evtq.\n", opcode);
145862306a36Sopenharmony_ci		return -EINVAL;
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	return 0;
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci/*
146562306a36Sopenharmony_ci * csio_mb_isr_handler - Handle mailboxes related interrupts.
146662306a36Sopenharmony_ci * @hw: The HW structure
146762306a36Sopenharmony_ci *
146862306a36Sopenharmony_ci * Called from the ISR to handle Mailbox related interrupts.
146962306a36Sopenharmony_ci * HW Lock should be held across this call.
147062306a36Sopenharmony_ci */
147162306a36Sopenharmony_ciint
147262306a36Sopenharmony_cicsio_mb_isr_handler(struct csio_hw *hw)
147362306a36Sopenharmony_ci{
147462306a36Sopenharmony_ci	struct csio_mbm		*mbm = &hw->mbm;
147562306a36Sopenharmony_ci	struct csio_mb		*mbp =  mbm->mcurrent;
147662306a36Sopenharmony_ci	__be64			*cmd;
147762306a36Sopenharmony_ci	uint32_t		ctl, cim_cause, pl_cause;
147862306a36Sopenharmony_ci	int			i;
147962306a36Sopenharmony_ci	uint32_t	ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL_A);
148062306a36Sopenharmony_ci	uint32_t	data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA_A);
148162306a36Sopenharmony_ci	int			size;
148262306a36Sopenharmony_ci	__be64			hdr;
148362306a36Sopenharmony_ci	struct fw_cmd_hdr	*fw_hdr;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	pl_cause = csio_rd_reg32(hw, MYPF_REG(PL_PF_INT_CAUSE_A));
148662306a36Sopenharmony_ci	cim_cause = csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_CAUSE_A));
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	if (!(pl_cause & PFCIM_F) || !(cim_cause & MBMSGRDYINT_F)) {
148962306a36Sopenharmony_ci		CSIO_INC_STATS(hw, n_mbint_unexp);
149062306a36Sopenharmony_ci		return -EINVAL;
149162306a36Sopenharmony_ci	}
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_ci	/*
149462306a36Sopenharmony_ci	 * The cause registers below HAVE to be cleared in the SAME
149562306a36Sopenharmony_ci	 * order as below: The low level cause register followed by
149662306a36Sopenharmony_ci	 * the upper level cause register. In other words, CIM-cause
149762306a36Sopenharmony_ci	 * first followed by PL-Cause next.
149862306a36Sopenharmony_ci	 */
149962306a36Sopenharmony_ci	csio_wr_reg32(hw, MBMSGRDYINT_F, MYPF_REG(CIM_PF_HOST_INT_CAUSE_A));
150062306a36Sopenharmony_ci	csio_wr_reg32(hw, PFCIM_F, MYPF_REG(PL_PF_INT_CAUSE_A));
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	ctl = csio_rd_reg32(hw, ctl_reg);
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	if (csio_mb_is_host_owner(MBOWNER_G(ctl))) {
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci		CSIO_DUMP_MB(hw, hw->pfn, data_reg);
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_ci		if (!(ctl & MBMSGVALID_F)) {
150962306a36Sopenharmony_ci			csio_warn(hw,
151062306a36Sopenharmony_ci				  "Stray mailbox interrupt recvd,"
151162306a36Sopenharmony_ci				  " mailbox data not valid\n");
151262306a36Sopenharmony_ci			csio_wr_reg32(hw, 0, ctl_reg);
151362306a36Sopenharmony_ci			/* Flush */
151462306a36Sopenharmony_ci			csio_rd_reg32(hw, ctl_reg);
151562306a36Sopenharmony_ci			return -EINVAL;
151662306a36Sopenharmony_ci		}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci		hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
151962306a36Sopenharmony_ci		fw_hdr = (struct fw_cmd_hdr *)&hdr;
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci		switch (FW_CMD_OP_G(ntohl(fw_hdr->hi))) {
152262306a36Sopenharmony_ci		case FW_DEBUG_CMD:
152362306a36Sopenharmony_ci			csio_mb_debug_cmd_handler(hw);
152462306a36Sopenharmony_ci			return -EINVAL;
152562306a36Sopenharmony_ci#if 0
152662306a36Sopenharmony_ci		case FW_ERROR_CMD:
152762306a36Sopenharmony_ci		case FW_INITIALIZE_CMD: /* When we are not master */
152862306a36Sopenharmony_ci#endif
152962306a36Sopenharmony_ci		}
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci		CSIO_ASSERT(mbp != NULL);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci		cmd = mbp->mb;
153462306a36Sopenharmony_ci		size = mbp->mb_size;
153562306a36Sopenharmony_ci		/* Get response */
153662306a36Sopenharmony_ci		for (i = 0; i < size; i += 8)
153762306a36Sopenharmony_ci			*cmd++ = cpu_to_be64(csio_rd_reg64
153862306a36Sopenharmony_ci						  (hw, data_reg + i));
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci		csio_wr_reg32(hw, 0, ctl_reg);
154162306a36Sopenharmony_ci		/* Flush */
154262306a36Sopenharmony_ci		csio_rd_reg32(hw, ctl_reg);
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_ci		mbm->mcurrent = NULL;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci		/* Add completion to tail of cbfn queue */
154762306a36Sopenharmony_ci		list_add_tail(&mbp->list, &mbm->cbfn_q);
154862306a36Sopenharmony_ci		CSIO_INC_STATS(mbm, n_cbfnq);
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci		/*
155162306a36Sopenharmony_ci		 * Enqueue event to EventQ. Events processing happens
155262306a36Sopenharmony_ci		 * in Event worker thread context
155362306a36Sopenharmony_ci		 */
155462306a36Sopenharmony_ci		if (csio_enqueue_evt(hw, CSIO_EVT_MBX, mbp, sizeof(mbp)))
155562306a36Sopenharmony_ci			CSIO_INC_STATS(hw, n_evt_drop);
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci		return 0;
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	} else {
156062306a36Sopenharmony_ci		/*
156162306a36Sopenharmony_ci		 * We can get here if mailbox MSIX vector is shared,
156262306a36Sopenharmony_ci		 * or in INTx case. Or a stray interrupt.
156362306a36Sopenharmony_ci		 */
156462306a36Sopenharmony_ci		csio_dbg(hw, "Host not owner, no mailbox interrupt\n");
156562306a36Sopenharmony_ci		CSIO_INC_STATS(hw, n_int_stray);
156662306a36Sopenharmony_ci		return -EINVAL;
156762306a36Sopenharmony_ci	}
156862306a36Sopenharmony_ci}
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci/*
157162306a36Sopenharmony_ci * csio_mb_tmo_handler - Timeout handler
157262306a36Sopenharmony_ci * @hw: The HW structure
157362306a36Sopenharmony_ci *
157462306a36Sopenharmony_ci */
157562306a36Sopenharmony_cistruct csio_mb *
157662306a36Sopenharmony_cicsio_mb_tmo_handler(struct csio_hw *hw)
157762306a36Sopenharmony_ci{
157862306a36Sopenharmony_ci	struct csio_mbm *mbm = &hw->mbm;
157962306a36Sopenharmony_ci	struct csio_mb *mbp =  mbm->mcurrent;
158062306a36Sopenharmony_ci	struct fw_cmd_hdr *fw_hdr;
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	/*
158362306a36Sopenharmony_ci	 * Could be a race b/w the completion handler and the timer
158462306a36Sopenharmony_ci	 * and the completion handler won that race.
158562306a36Sopenharmony_ci	 */
158662306a36Sopenharmony_ci	if (mbp == NULL) {
158762306a36Sopenharmony_ci		CSIO_DB_ASSERT(0);
158862306a36Sopenharmony_ci		return NULL;
158962306a36Sopenharmony_ci	}
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	fw_hdr = (struct fw_cmd_hdr *)(mbp->mb);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	csio_dbg(hw, "Mailbox num:%x op:0x%x timed out\n", hw->pfn,
159462306a36Sopenharmony_ci		    FW_CMD_OP_G(ntohl(fw_hdr->hi)));
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	mbm->mcurrent = NULL;
159762306a36Sopenharmony_ci	CSIO_INC_STATS(mbm, n_tmo);
159862306a36Sopenharmony_ci	fw_hdr->lo = htonl(FW_CMD_RETVAL_V(FW_ETIMEDOUT));
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	return mbp;
160162306a36Sopenharmony_ci}
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci/*
160462306a36Sopenharmony_ci * csio_mb_cancel_all - Cancel all waiting commands.
160562306a36Sopenharmony_ci * @hw: The HW structure
160662306a36Sopenharmony_ci * @cbfn_q: The callback queue.
160762306a36Sopenharmony_ci *
160862306a36Sopenharmony_ci * Caller should hold hw lock across this call.
160962306a36Sopenharmony_ci */
161062306a36Sopenharmony_civoid
161162306a36Sopenharmony_cicsio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q)
161262306a36Sopenharmony_ci{
161362306a36Sopenharmony_ci	struct csio_mb *mbp;
161462306a36Sopenharmony_ci	struct csio_mbm *mbm = &hw->mbm;
161562306a36Sopenharmony_ci	struct fw_cmd_hdr *hdr;
161662306a36Sopenharmony_ci	struct list_head *tmp;
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	if (mbm->mcurrent) {
161962306a36Sopenharmony_ci		mbp = mbm->mcurrent;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci		/* Stop mailbox completion timer */
162262306a36Sopenharmony_ci		del_timer_sync(&mbm->timer);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci		/* Add completion to tail of cbfn queue */
162562306a36Sopenharmony_ci		list_add_tail(&mbp->list, cbfn_q);
162662306a36Sopenharmony_ci		mbm->mcurrent = NULL;
162762306a36Sopenharmony_ci	}
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	if (!list_empty(&mbm->req_q)) {
163062306a36Sopenharmony_ci		list_splice_tail_init(&mbm->req_q, cbfn_q);
163162306a36Sopenharmony_ci		mbm->stats.n_activeq = 0;
163262306a36Sopenharmony_ci	}
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	if (!list_empty(&mbm->cbfn_q)) {
163562306a36Sopenharmony_ci		list_splice_tail_init(&mbm->cbfn_q, cbfn_q);
163662306a36Sopenharmony_ci		mbm->stats.n_cbfnq = 0;
163762306a36Sopenharmony_ci	}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	if (list_empty(cbfn_q))
164062306a36Sopenharmony_ci		return;
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	list_for_each(tmp, cbfn_q) {
164362306a36Sopenharmony_ci		mbp = (struct csio_mb *)tmp;
164462306a36Sopenharmony_ci		hdr = (struct fw_cmd_hdr *)(mbp->mb);
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci		csio_dbg(hw, "Cancelling pending mailbox num %x op:%x\n",
164762306a36Sopenharmony_ci			    hw->pfn, FW_CMD_OP_G(ntohl(hdr->hi)));
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci		CSIO_INC_STATS(mbm, n_cancel);
165062306a36Sopenharmony_ci		hdr->lo = htonl(FW_CMD_RETVAL_V(FW_HOSTERROR));
165162306a36Sopenharmony_ci	}
165262306a36Sopenharmony_ci}
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci/*
165562306a36Sopenharmony_ci * csio_mbm_init - Initialize Mailbox module
165662306a36Sopenharmony_ci * @mbm: Mailbox module
165762306a36Sopenharmony_ci * @hw: The HW structure
165862306a36Sopenharmony_ci * @timer: Timing function for interrupting mailboxes
165962306a36Sopenharmony_ci *
166062306a36Sopenharmony_ci * Initialize timer and the request/response queues.
166162306a36Sopenharmony_ci */
166262306a36Sopenharmony_ciint
166362306a36Sopenharmony_cicsio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw,
166462306a36Sopenharmony_ci	      void (*timer_fn)(struct timer_list *))
166562306a36Sopenharmony_ci{
166662306a36Sopenharmony_ci	mbm->hw = hw;
166762306a36Sopenharmony_ci	timer_setup(&mbm->timer, timer_fn, 0);
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	INIT_LIST_HEAD(&mbm->req_q);
167062306a36Sopenharmony_ci	INIT_LIST_HEAD(&mbm->cbfn_q);
167162306a36Sopenharmony_ci	csio_set_mb_intr_idx(mbm, -1);
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	return 0;
167462306a36Sopenharmony_ci}
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci/*
167762306a36Sopenharmony_ci * csio_mbm_exit - Uninitialize mailbox module
167862306a36Sopenharmony_ci * @mbm: Mailbox module
167962306a36Sopenharmony_ci *
168062306a36Sopenharmony_ci * Stop timer.
168162306a36Sopenharmony_ci */
168262306a36Sopenharmony_civoid
168362306a36Sopenharmony_cicsio_mbm_exit(struct csio_mbm *mbm)
168462306a36Sopenharmony_ci{
168562306a36Sopenharmony_ci	del_timer_sync(&mbm->timer);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	CSIO_DB_ASSERT(mbm->mcurrent == NULL);
168862306a36Sopenharmony_ci	CSIO_DB_ASSERT(list_empty(&mbm->req_q));
168962306a36Sopenharmony_ci	CSIO_DB_ASSERT(list_empty(&mbm->cbfn_q));
169062306a36Sopenharmony_ci}
1691