SLIPORT FUNCTION_RESET does not reset the chip.
So POST status needs to be checked before issuing FUNCTION_RESET.
The completion of FUNCTION_RESET is indicated in BMBX Rdy bit.
be_cmd_fw_initialize too needs to be done before issuing any cmd to FW.
be_cmd_fw_initialize is renamed as beiscsi_cmd_special_wrb.
Rearrange and rename few functions in init and cleanup path.
Signed-off-by: Jitendra Bhivare <jitendra.bhivare@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
#include "be.h"
#include "be_mgmt.h"
-int be_chk_reset_complete(struct beiscsi_hba *phba)
-{
- unsigned int num_loop;
- u8 *mpu_sem = 0;
- u32 status;
-
- num_loop = 1000;
- mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
- msleep(5000);
-
- while (num_loop) {
- status = readl((void *)mpu_sem);
-
- if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000)
- break;
- msleep(60);
- num_loop--;
- }
-
- if ((status & 0x80000000) || (!num_loop)) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BC_%d : Failed in be_chk_reset_complete"
- "status = 0x%x\n", status);
- return -EIO;
- }
-
- return 0;
-}
-
struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba,
unsigned int *ref_tag)
{
return status;
}
-/**
- * be_cmd_fw_initialize()- Initialize FW
- * @ctrl: Pointer to function control structure
- *
- * Send FW initialize pattern for the function.
- *
- * return
- * Success: 0
- * Failure: Non-Zero value
- **/
-int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
-{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
- struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
- int status;
- u8 *endian_check;
-
- mutex_lock(&ctrl->mbox_lock);
- memset(wrb, 0, sizeof(*wrb));
-
- endian_check = (u8 *) wrb;
- *endian_check++ = 0xFF;
- *endian_check++ = 0x12;
- *endian_check++ = 0x34;
- *endian_check++ = 0xFF;
- *endian_check++ = 0xFF;
- *endian_check++ = 0x56;
- *endian_check++ = 0x78;
- *endian_check++ = 0xFF;
- be_dws_cpu_to_le(wrb, sizeof(*wrb));
-
- status = be_mbox_notify(ctrl);
- if (status)
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BC_%d : be_cmd_fw_initialize Failed\n");
-
- mutex_unlock(&ctrl->mbox_lock);
- return status;
-}
-
-/**
- * be_cmd_fw_uninit()- Uinitialize FW
- * @ctrl: Pointer to function control structure
- *
- * Send FW uninitialize pattern for the function
- *
- * return
- * Success: 0
- * Failure: Non-Zero value
- **/
-int be_cmd_fw_uninit(struct be_ctrl_info *ctrl)
-{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
- struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
- int status;
- u8 *endian_check;
-
- mutex_lock(&ctrl->mbox_lock);
- memset(wrb, 0, sizeof(*wrb));
-
- endian_check = (u8 *) wrb;
- *endian_check++ = 0xFF;
- *endian_check++ = 0xAA;
- *endian_check++ = 0xBB;
- *endian_check++ = 0xFF;
- *endian_check++ = 0xFF;
- *endian_check++ = 0xCC;
- *endian_check++ = 0xDD;
- *endian_check = 0xFF;
-
- be_dws_cpu_to_le(wrb, sizeof(*wrb));
-
- status = be_mbox_notify(ctrl);
- if (status)
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BC_%d : be_cmd_fw_uninit Failed\n");
-
- mutex_unlock(&ctrl->mbox_lock);
- return status;
-}
-
int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *cq, struct be_queue_info *eq,
bool sol_evts, bool no_delay, int coalesce_wm)
return status;
}
-int beiscsi_cmd_reset_function(struct beiscsi_hba *phba)
-{
- struct be_ctrl_info *ctrl = &phba->ctrl;
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
- struct be_post_sgl_pages_req *req = embedded_payload(wrb);
- int status;
-
- mutex_lock(&ctrl->mbox_lock);
-
- req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
- status = be_mbox_notify(ctrl);
-
- mutex_unlock(&ctrl->mbox_lock);
- return status;
-}
-
/**
* be_cmd_set_vlan()- Configure VLAN paramters on the adapter
* @phba: device priv structure instance
mutex_unlock(&ctrl->mbox_lock);
return ret;
}
+
+static u32 beiscsi_get_post_stage(struct beiscsi_hba *phba)
+{
+ u32 sem;
+
+ if (is_chip_be2_be3r(phba))
+ sem = ioread32(phba->csr_va + SLIPORT_SEMAPHORE_OFFSET_BEx);
+ else
+ pci_read_config_dword(phba->pcidev,
+ SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
+ return sem;
+}
+
+int beiscsi_check_fw_rdy(struct beiscsi_hba *phba)
+{
+ u32 loop, post, rdy = 0;
+
+ loop = 1000;
+ while (loop--) {
+ post = beiscsi_get_post_stage(phba);
+ if (post & POST_ERROR_BIT)
+ break;
+ if ((post & POST_STAGE_MASK) == POST_STAGE_ARMFW_RDY) {
+ rdy = 1;
+ break;
+ }
+ msleep(60);
+ }
+
+ if (!rdy) {
+ __beiscsi_log(phba, KERN_ERR,
+ "BC_%d : FW not ready 0x%x\n", post);
+ }
+
+ return rdy;
+}
+
+static int beiscsi_cmd_function_reset(struct beiscsi_hba *phba)
+{
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_post_sgl_pages_req *req = embedded_payload(wrb);
+ int status;
+
+ mutex_lock(&ctrl->mbox_lock);
+
+ req = embedded_payload(wrb);
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+ status = be_mbox_notify(ctrl);
+
+ mutex_unlock(&ctrl->mbox_lock);
+ return status;
+}
+
+int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load)
+{
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+ u8 *endian_check;
+ int status;
+
+ mutex_lock(&ctrl->mbox_lock);
+ memset(wrb, 0, sizeof(*wrb));
+
+ endian_check = (u8 *) wrb;
+ if (load) {
+ /* to start communicating */
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0x12;
+ *endian_check++ = 0x34;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0x56;
+ *endian_check++ = 0x78;
+ *endian_check++ = 0xFF;
+ } else {
+ /* to stop communicating */
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xAA;
+ *endian_check++ = 0xBB;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xFF;
+ *endian_check++ = 0xCC;
+ *endian_check++ = 0xDD;
+ *endian_check = 0xFF;
+ }
+ be_dws_cpu_to_le(wrb, sizeof(*wrb));
+
+ 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;
+
+ /*
+ * 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);
+}
#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */
#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */
-/********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET 0xac
-#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK 0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT 31
+/********** MPU semphore: used for SH & BE ******************/
+#define SLIPORT_SOFTRESET_OFFSET 0x5c /* CSR BAR offset */
+#define SLIPORT_SEMAPHORE_OFFSET_BEx 0xac /* CSR BAR offset */
+#define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 /* PCI-CFG offset */
+#define POST_STAGE_MASK 0x0000FFFF
+#define POST_ERROR_BIT 0x80000000
+#define POST_ERR_RECOVERY_CODE_MASK 0xF000
+
+/* Soft Reset register masks */
+#define SLIPORT_SOFTRESET_SR_MASK 0x00000080 /* SR bit */
+
+/* MPU semphore POST stage values */
+#define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */
+#define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */
+#define POST_STAGE_BE_RESET 0x3 /* Host wants to reset chip */
+#define POST_STAGE_ARMFW_RDY 0xC000 /* FW is done with POST */
+#define POST_STAGE_RECOVERABLE_ERR 0xE000 /* Recoverable err detected */
/********** MCC door bell ************/
#define DB_MCCQ_OFFSET 0x140
/* Number of entries posted */
#define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */
-/* MPU semphore POST stage values */
-#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */
-
/**
* When the async bit of mcc_compl is set, the last 4 bytes of
* mcc_compl is interpreted as follows:
} param;
} __packed;
+int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load);
+
+int beiscsi_check_fw_rdy(struct beiscsi_hba *phba);
+
+int beiscsi_init_sliport(struct beiscsi_hba *phba);
+
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *eq, int eq_delay);
struct be_mcc_wrb **wrb,
struct be_dma_mem *mbx_cmd_mem);
/*ISCSI Functuions */
-int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
-int be_cmd_fw_uninit(struct be_ctrl_info *ctrl);
-
struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag);
void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag);
struct be_dma_mem *q_mem, u32 page_offset,
u32 num_pages);
-int beiscsi_cmd_reset_function(struct beiscsi_hba *phba);
-
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
struct be_queue_info *wrbq,
struct hwi_wrb_context *pwrb_context,
* the cxn
*/
-int be_chk_reset_complete(struct beiscsi_hba *phba);
-
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
bool embedded, u8 sge_cnt);
}
}
-static void hwi_cleanup(struct beiscsi_hba *phba)
+static void hwi_cleanup_port(struct beiscsi_hba *phba)
{
struct be_queue_info *q;
struct be_ctrl_info *ctrl = &phba->ctrl;
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
}
}
- be_cmd_fw_uninit(ctrl);
+ /* last communication, indicate driver is unloading */
+ beiscsi_cmd_special_wrb(&phba->ctrl, 0);
}
static int be_mcc_queues_create(struct beiscsi_hba *phba,
phwi_context->max_eqd = 128;
phwi_context->min_eqd = 0;
phwi_context->cur_eqd = 0;
- be_cmd_fw_initialize(&phba->ctrl);
- /* set optic state to unknown */
+ /* set port optic state to unknown */
phba->optic_state = 0xff;
status = beiscsi_create_eqs(phba, phwi_context);
error:
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : hwi_init_port failed");
- hwi_cleanup(phba);
+ hwi_cleanup_port(phba);
return status;
}
return ret;
do_cleanup_ctrlr:
- hwi_cleanup(phba);
+ hwi_cleanup_port(phba);
return ret;
}
}
}
-static void beiscsi_clean_port(struct beiscsi_hba *phba)
+static void beiscsi_cleanup_port(struct beiscsi_hba *phba)
{
int mgmt_status, ulp_num;
struct ulp_cid_info *ptr_cid_info = NULL;
}
hwi_purge_eq(phba);
- hwi_cleanup(phba);
+ hwi_cleanup_port(phba);
kfree(phba->io_sgl_hndl_base);
kfree(phba->eh_sgl_hndl_base);
kfree(phba->ep_array);
/* PCI_ERR is set then check if driver is not unloading */
if (test_bit(BEISCSI_HBA_RUNNING, &phba->state) &&
test_bit(BEISCSI_HBA_PCI_ERR, &phba->state)) {
- hwi_cleanup(phba);
+ hwi_cleanup_port(phba);
return;
}
destroy_workqueue(phba->wq);
- beiscsi_clean_port(phba);
+ beiscsi_cleanup_port(phba);
beiscsi_free_mem(phba);
beiscsi_unmap_pci_function(phba);
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- /* Wait for the CHIP Reset to complete */
- status = be_chk_reset_complete(phba);
- if (!status) {
+ status = beiscsi_check_fw_rdy(phba);
+ if (status) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
"BM_%d : EEH Reset Completed\n");
} else {
static void beiscsi_eeh_resume(struct pci_dev *pdev)
{
- int ret = 0, i;
+ int ret, i;
struct be_eq_obj *pbe_eq;
struct beiscsi_hba *phba = NULL;
struct hwi_controller *phwi_ctrlr;
phba->num_cpus = 1;
}
- ret = beiscsi_cmd_reset_function(phba);
- if (ret) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BM_%d : Reset Failed\n");
- goto ret_err;
- }
-
- ret = be_chk_reset_complete(phba);
- if (ret) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BM_%d : Failed to get out of reset.\n");
+ ret = beiscsi_init_sliport(phba);
+ if (ret)
goto ret_err;
- }
beiscsi_get_params(phba);
phba->shost->max_id = phba->params.cxns_per_ctrl;
ret = be_ctrl_init(phba, pcidev);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BM_%d : beiscsi_dev_probe-"
- "Failed in be_ctrl_init\n");
+ "BM_%d : be_ctrl_init failed\n");
goto hba_free;
}
- set_bit(BEISCSI_HBA_RUNNING, &phba->state);
- /*
- * FUNCTION_RESET should clean up any stale info in FW for this fn
- */
- ret = beiscsi_cmd_reset_function(phba);
- if (ret) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BM_%d : Reset Failed\n");
- goto hba_free;
- }
- ret = be_chk_reset_complete(phba);
- if (ret) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
- "BM_%d : Failed to get out of reset.\n");
+ ret = beiscsi_init_sliport(phba);
+ if (ret)
goto hba_free;
- }
+ set_bit(BEISCSI_HBA_RUNNING, &phba->state);
spin_lock_init(&phba->io_sgl_lock);
spin_lock_init(&phba->mgmt_sgl_lock);
spin_lock_init(&phba->async_pdu_lock);
irq_poll_disable(&pbe_eq->iopoll);
}
free_twq:
- beiscsi_clean_port(phba);
+ beiscsi_cleanup_port(phba);
beiscsi_free_mem(phba);
free_port:
pci_free_consistent(phba->pcidev,
#define BEISCSI_MAX_FRAGS_INIT 192
#define BE_NUM_MSIX_ENTRIES 1
-#define MPU_EP_CONTROL 0
-#define MPU_EP_SEMAPHORE 0xac
-#define BE2_SOFT_RESET 0x5c
-#define BE2_PCI_ONLINE0 0xb0
-#define BE2_PCI_ONLINE1 0xb4
-#define BE2_SET_RESET 0x80
-#define BE2_MPU_IRAM_ONLINE 0x00000080
-
#define BE_SENSE_INFO_SIZE 258
#define BE_ISCSI_PDU_HEADER_SIZE 64
#define BE_MIN_MEM_SIZE 16384