// SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2017 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * Contact Information: * linux-drivers@broadcom.com
*/
/* * beiscsi_mccq_compl_wait()- Process completion in MCC CQ * @phba: Driver private structure * @tag: Tag for the MBX Command * @wrb: the WRB used for the MBX Command * @mbx_cmd_mem: ptr to memory allocated for MBX Cmd * * Waits for MBX completion with the passed TAG. * * return * Success: 0 * Failure: Non-Zero
**/ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, unsignedint tag, struct be_mcc_wrb **wrb, struct be_dma_mem *mbx_cmd_mem)
{ int rc = 0;
if (!tag || tag > MAX_MCC_CMD) {
__beiscsi_log(phba, KERN_ERR, "BC_%d : invalid tag %u\n", tag); return -EINVAL;
}
if (beiscsi_hba_in_error(phba)) {
clear_bit(MCC_TAG_STATE_RUNNING,
&phba->ctrl.ptag_state[tag].tag_state); return -EIO;
}
/* wait for the mccq completion */
rc = wait_event_interruptible_timeout(phba->ctrl.mcc_wait[tag],
phba->ctrl.mcc_tag_status[tag],
msecs_to_jiffies(
BEISCSI_HOST_MBX_TIMEOUT)); /** * Return EIO if port is being disabled. Associated DMA memory, if any, * is freed by the caller. When port goes offline, MCCQ is cleaned up * so does WRB.
*/ if (!test_bit(BEISCSI_HBA_ONLINE, &phba->state)) {
clear_bit(MCC_TAG_STATE_RUNNING,
&phba->ctrl.ptag_state[tag].tag_state); return -EIO;
}
/** * If MBOX cmd timeout expired, tag and resource allocated * for cmd is not freed until FW returns completion.
*/ if (rc <= 0) { struct be_dma_mem *tag_mem;
/** * PCI/DMA memory allocated and posted in non-embedded mode * will have mbx_cmd_mem != NULL. * Save virtual and bus addresses for the command so that it * can be freed later.
**/
tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; if (mbx_cmd_mem) {
tag_mem->size = mbx_cmd_mem->size;
tag_mem->va = mbx_cmd_mem->va;
tag_mem->dma = mbx_cmd_mem->dma;
} else
tag_mem->size = 0;
/* first make tag_mem_state visible to all */
wmb();
set_bit(MCC_TAG_STATE_TIMEOUT,
&phba->ctrl.ptag_state[tag].tag_state);
/* * beiscsi_process_mbox_compl()- Check the MBX completion status * @ctrl: Function specific MBX data structure * @compl: Completion status of MBX Command * * Check for the MBX completion status when BMBX method used * * return * Success: Zero * Failure: Non-Zero
**/ staticint beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, struct be_mcc_compl *compl)
{ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); struct be_cmd_req_hdr *hdr = embedded_payload(wrb);
u16 compl_status, extd_status;
/** * To check if valid bit is set, check the entire word as we don't know * the endianness of the data (old entry is host endian while a new * entry is little endian)
*/ if (!compl->flags) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, "BC_%d : BMBX busy, no completion\n"); return -EBUSY;
}
compl->flags = le32_to_cpu(compl->flags);
WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
/** * Just swap the status to host endian; * mcc tag is opaquely copied from mcc_wrb.
*/
be_dws_le_to_cpu(compl, 4);
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
CQE_STATUS_COMPL_MASK;
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
CQE_STATUS_EXTD_MASK; /* Need to reset the entire word that houses the valid bit */
compl->flags = 0;
phba->port_speed = evt->port_speed; /** * Check logical link status in ASYNC event. * This has been newly introduced in SKH-R Firmware 10.0.338.45.
**/ if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) {
set_bit(BEISCSI_HBA_LINK_UP, &phba->state); if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state))
beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE);
__beiscsi_log(phba, KERN_ERR, "BC_%d : Link Up on Port %d tag 0x%x\n",
evt->physical_port, evt->event_tag);
} else {
clear_bit(BEISCSI_HBA_LINK_UP, &phba->state);
__beiscsi_log(phba, KERN_ERR, "BC_%d : Link Down on Port %d tag 0x%x\n",
evt->physical_port, evt->event_tag);
iscsi_host_for_each_session(phba->shost,
beiscsi_session_fail);
}
}
staticchar *beiscsi_port_misconf_event_msg[] = { "Physical Link is functional.", "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", "Optics of two types installed - Remove one optic or install matching pair of optics.", "Incompatible optics - Replace with compatible optics for card to function.", "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", "Uncertified optics - Replace with Avago Certified optics to enable link operation."
};
if (state >= ARRAY_SIZE(beiscsi_port_misconf_event_msg)) { /* fw is reporting a state we don't know, log and return */
__beiscsi_log(phba, KERN_ERR, "BC_%d : Port %c: Unrecognized optic state 0x%x\n",
phba->port_name, async_sli->event_data1); return;
}
if (ASYNC_SLI_LINK_EFFECT_VALID(le)) { /* log link effect for unqualified-4, uncertified-5 optics */ if (state > 3)
msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ? " Link is non-operational." : " Link is operational."; /* 1 - info */ if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1)
sev = KERN_INFO; /* 2 - error */ if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2)
sev = KERN_ERR;
}
if (old_state != phba->optic_state)
__beiscsi_log(phba, sev, "BC_%d : Port %c: %s%s\n",
phba->port_name,
beiscsi_port_misconf_event_msg[state],
!msg ? "" : msg);
}
set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state);
val |= mccq->id & DB_MCCQ_RING_ID_MASK;
val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; /* make request available for DMA */
wmb();
iowrite32(val, phba->db_va + DB_MCCQ_OFFSET);
}
/* * be_mbox_db_ready_poll()- Check ready status * @ctrl: Function specific MBX data structure * * Check for the ready status of FW to send BMBX * commands to adapter. * * return * Success: 0 * Failure: Non-Zero
**/ staticint be_mbox_db_ready_poll(struct be_ctrl_info *ctrl)
{ /* wait 30s for generic non-flash MBOX operation */ #define BEISCSI_MBX_RDY_BIT_TIMEOUT 30000 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsignedlong timeout;
u32 ready;
/* * This BMBX busy wait path is used during init only. * For the commands executed during init, 5s should suffice.
*/
timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); do { if (beiscsi_hba_in_error(phba)) return -EIO;
ready = ioread32(db); if (ready == 0xffffffff) return -EIO;
ready &= MPU_MAILBOX_DB_RDY_MASK; if (ready) return 0;
if (time_after(jiffies, timeout)) break; /* 1ms sleep is enough in most cases */
schedule_timeout_uninterruptible(msecs_to_jiffies(1));
} while (!ready);
if (temp_num_pages == 0xff)
req->num_pages = temp_num_pages;
status = be_mbox_notify(ctrl); if (status) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BC_%d : FW CMD to map iscsi frags failed.\n");
goto error;
}
} while (num_pages > 0);
error:
mutex_unlock(&ctrl->mbox_lock); if (status != 0)
beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); return status;
}
/** * be_cmd_set_vlan()- Configure VLAN paramters on the adapter * @phba: device priv structure instance * @vlan_tag: TAG to be set * * Set the VLAN_TAG for the adapter or Disable VLAN on adapter * * returns * TAG for the MBX Cmd
* **/ int be_cmd_set_vlan(struct beiscsi_hba *phba,
uint16_t vlan_tag)
{ unsignedint tag; struct be_mcc_wrb *wrb; struct be_cmd_set_vlan_req *req; struct be_ctrl_info *ctrl = &phba->ctrl;
if (mutex_lock_interruptible(&ctrl->mbox_lock)) return 0;
wrb = alloc_mcc_wrb(phba, &tag); if (!wrb) {
mutex_unlock(&ctrl->mbox_lock); return 0;
}
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BG_%d : Firmware Version of CMD : %s\n" "Firmware Version is : %s\n" "Developer Build, not performing version check...\n",
resp->params.hba_attribs
.flashrom_version_string,
resp->params.hba_attribs.
firmware_version_string);
/** * beiscsi_get_fw_config()- Get the FW config for the function * @ctrl: ptr to Ctrl Info * @phba: ptr to the dev priv structure * * Get the FW config and resources available for the function. * The resources are created based on the count received here. * * return * Success: 0 * Failure: Non-Zero Value
**/ int beiscsi_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba)
{ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct be_fw_cfg *pfw_cfg = embedded_payload(wrb);
uint32_t cid_count, icd_count; int status = -EINVAL;
uint8_t ulp_num = 0;
if (be_mbox_notify(ctrl)) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BG_%d : Failed in beiscsi_get_fw_config\n"); goto fail_init;
}
/* FW response formats depend on port id */
phba->fw_config.phys_port = pfw_cfg->phys_port; if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BG_%d : invalid physical port id %d\n",
phba->fw_config.phys_port); goto fail_init;
}
/* populate and check FW config against min and max values */ if (!is_chip_be2_be3r(phba)) {
phba->fw_config.eqid_count = pfw_cfg->eqid_count;
phba->fw_config.cqid_count = pfw_cfg->cqid_count; if (phba->fw_config.eqid_count == 0 ||
phba->fw_config.eqid_count > 2048) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BG_%d : invalid EQ count %d\n",
phba->fw_config.eqid_count); goto fail_init;
} if (phba->fw_config.cqid_count == 0 ||
phba->fw_config.cqid_count > 4096) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BG_%d : invalid CQ count %d\n",
phba->fw_config.cqid_count); goto fail_init;
}
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BG_%d : EQ_Count : %d CQ_Count : %d\n",
phba->fw_config.eqid_count,
phba->fw_config.cqid_count);
}
/** * Check on which all ULP iSCSI Protocol is loaded. * Set the Bit for those ULP. This set flag is used * at all places in the code to check on which ULP * iSCSi Protocol is loaded
**/ for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { if (pfw_cfg->ulp[ulp_num].ulp_mode &
BEISCSI_ULP_ISCSI_INI_MODE) {
set_bit(ulp_num, &phba->fw_config.ulp_supported);
/* Get the CID, ICD and Chain count for each ULP */
phba->fw_config.iscsi_cid_start[ulp_num] =
pfw_cfg->ulp[ulp_num].sq_base;
phba->fw_config.iscsi_cid_count[ulp_num] =
pfw_cfg->ulp[ulp_num].sq_count;
/** * Check FW is dual ULP aware i.e. can handle either * of the protocols.
*/
phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
BEISCSI_FUNC_DUA_MODE);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BG_%d : DUA Mode : 0x%x\n",
phba->fw_config.dual_ulp_aware);
/* all set, continue using this FW config */
status = 0;
fail_init:
mutex_unlock(&ctrl->mbox_lock); return status;
}
/** * beiscsi_get_port_name()- Get port name for the function * @ctrl: ptr to Ctrl Info * @phba: ptr to the dev priv structure * * Get the alphanumeric character for port *
**/ int beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba)
{ int ret = 0; struct be_mcc_wrb *wrb; struct be_cmd_get_port_name *ioctl;
status = be_mbox_notify(ctrl); if (status)
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BC_%d : special WRB message failed\n");
mutex_unlock(&ctrl->mbox_lock); return status;
}
int beiscsi_init_sliport(struct beiscsi_hba *phba)
{ int status;
/* check POST stage before talking to FW */
status = beiscsi_check_fw_rdy(phba); if (!status) return -EIO;
/* clear all error states after checking FW rdy */
phba->state &= ~BEISCSI_HBA_IN_ERR;
/* check again UER support */
phba->state &= ~BEISCSI_HBA_UER_SUPP;
/* * SLI COMMON_FUNCTION_RESET completion is indicated by BMBX RDY bit. * It should clean up any stale info in FW for this fn.
*/
status = beiscsi_cmd_function_reset(phba); if (status) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BC_%d : SLI Function Reset failed\n"); return status;
}
/* indicate driver is loading */ return beiscsi_cmd_special_wrb(&phba->ctrl, 1);
}
/** * beiscsi_cmd_iscsi_cleanup()- Inform FW to cleanup EP data structures. * @phba: pointer to dev priv structure * @ulp: ULP number. * * return * Success: 0 * Failure: Non-Zero Value
**/ int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsignedshort ulp)
{ struct be_ctrl_info *ctrl = &phba->ctrl; struct iscsi_cleanup_req_v1 *req_v1; struct iscsi_cleanup_req *req;
u16 hdr_ring_id, data_ring_id; struct be_mcc_wrb *wrb; int status;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.