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