|
@@ -373,90 +373,146 @@ int mgmt_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 *req = embedded_payload(wrb);
|
|
|
- int status = 0;
|
|
|
+ struct be_fw_cfg *pfw_cfg = embedded_payload(wrb);
|
|
|
+ uint32_t cid_count, icd_count;
|
|
|
+ int status = -EINVAL;
|
|
|
+ uint8_t ulp_num = 0;
|
|
|
|
|
|
mutex_lock(&ctrl->mbox_lock);
|
|
|
memset(wrb, 0, sizeof(*wrb));
|
|
|
+ be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0);
|
|
|
|
|
|
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
|
|
-
|
|
|
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
|
|
+ be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON,
|
|
|
OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
|
|
|
EMBED_MBX_MAX_PAYLOAD_SIZE);
|
|
|
- status = be_mbox_notify(ctrl);
|
|
|
- if (!status) {
|
|
|
- uint8_t ulp_num = 0;
|
|
|
- struct be_fw_cfg *pfw_cfg;
|
|
|
- pfw_cfg = req;
|
|
|
|
|
|
- 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 (be_mbox_notify(ctrl)) {
|
|
|
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
|
|
|
+ "BG_%d : Failed in mgmt_get_fw_config\n");
|
|
|
+ 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,
|
|
|
+ /* 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);
|
|
|
+ }
|
|
|
|
|
|
- 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);
|
|
|
-
|
|
|
- phba->fw_config.phys_port = pfw_cfg->phys_port;
|
|
|
- for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
|
|
|
- if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
|
|
|
-
|
|
|
- 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;
|
|
|
-
|
|
|
- phba->fw_config.iscsi_icd_start[ulp_num] =
|
|
|
- pfw_cfg->ulp[ulp_num].icd_base;
|
|
|
- phba->fw_config.iscsi_icd_count[ulp_num] =
|
|
|
- pfw_cfg->ulp[ulp_num].icd_count;
|
|
|
-
|
|
|
- phba->fw_config.iscsi_chain_start[ulp_num] =
|
|
|
- pfw_cfg->chain_icd[ulp_num].chain_base;
|
|
|
- phba->fw_config.iscsi_chain_count[ulp_num] =
|
|
|
- pfw_cfg->chain_icd[ulp_num].chain_count;
|
|
|
-
|
|
|
- beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
|
|
|
- "BG_%d : Function loaded on ULP : %d\n"
|
|
|
- "\tiscsi_cid_count : %d\n"
|
|
|
- "\tiscsi_cid_start : %d\n"
|
|
|
- "\t iscsi_icd_count : %d\n"
|
|
|
- "\t iscsi_icd_start : %d\n",
|
|
|
- ulp_num,
|
|
|
- phba->fw_config.
|
|
|
- iscsi_cid_count[ulp_num],
|
|
|
- phba->fw_config.
|
|
|
- iscsi_cid_start[ulp_num],
|
|
|
- phba->fw_config.
|
|
|
- iscsi_icd_count[ulp_num],
|
|
|
- phba->fw_config.
|
|
|
- iscsi_icd_start[ulp_num]);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 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;
|
|
|
+
|
|
|
+ phba->fw_config.iscsi_icd_start[ulp_num] =
|
|
|
+ pfw_cfg->ulp[ulp_num].icd_base;
|
|
|
+ phba->fw_config.iscsi_icd_count[ulp_num] =
|
|
|
+ pfw_cfg->ulp[ulp_num].icd_count;
|
|
|
+
|
|
|
+ phba->fw_config.iscsi_chain_start[ulp_num] =
|
|
|
+ pfw_cfg->chain_icd[ulp_num].chain_base;
|
|
|
+ phba->fw_config.iscsi_chain_count[ulp_num] =
|
|
|
+ pfw_cfg->chain_icd[ulp_num].chain_count;
|
|
|
+
|
|
|
+ beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
|
|
|
+ "BG_%d : Function loaded on ULP : %d\n"
|
|
|
+ "\tiscsi_cid_count : %d\n"
|
|
|
+ "\tiscsi_cid_start : %d\n"
|
|
|
+ "\t iscsi_icd_count : %d\n"
|
|
|
+ "\t iscsi_icd_start : %d\n",
|
|
|
+ ulp_num,
|
|
|
+ phba->fw_config.
|
|
|
+ iscsi_cid_count[ulp_num],
|
|
|
+ phba->fw_config.
|
|
|
+ iscsi_cid_start[ulp_num],
|
|
|
+ phba->fw_config.
|
|
|
+ iscsi_icd_count[ulp_num],
|
|
|
+ phba->fw_config.
|
|
|
+ iscsi_icd_start[ulp_num]);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
|
|
|
- BEISCSI_FUNC_DUA_MODE);
|
|
|
+ if (phba->fw_config.ulp_supported == 0) {
|
|
|
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
|
|
|
+ "BG_%d : iSCSI initiator mode not set: ULP0 %x ULP1 %x\n",
|
|
|
+ pfw_cfg->ulp[BEISCSI_ULP0].ulp_mode,
|
|
|
+ pfw_cfg->ulp[BEISCSI_ULP1].ulp_mode);
|
|
|
+ goto fail_init;
|
|
|
+ }
|
|
|
|
|
|
- beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
|
|
|
- "BG_%d : DUA Mode : 0x%x\n",
|
|
|
- phba->fw_config.dual_ulp_aware);
|
|
|
+ /**
|
|
|
+ * ICD is shared among ULPs. Use icd_count of any one loaded ULP
|
|
|
+ **/
|
|
|
+ for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
|
|
|
+ if (test_bit(ulp_num, &phba->fw_config.ulp_supported))
|
|
|
+ break;
|
|
|
+ icd_count = phba->fw_config.iscsi_icd_count[ulp_num];
|
|
|
+ if (icd_count == 0 || icd_count > 65536) {
|
|
|
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
|
|
|
+ "BG_%d: invalid ICD count %d\n", icd_count);
|
|
|
+ goto fail_init;
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+ cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) +
|
|
|
+ BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1);
|
|
|
+ if (cid_count == 0 || cid_count > 4096) {
|
|
|
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
|
|
|
- "BG_%d : Failed in mgmt_get_fw_config\n");
|
|
|
- status = -EINVAL;
|
|
|
+ "BG_%d: invalid CID count %d\n", cid_count);
|
|
|
+ goto fail_init;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 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;
|
|
|
}
|