scsi: be2iscsi: Fix POST check and reset sequence
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>
This commit is contained in:

committed by
Martin K. Petersen

parent
480195c267
commit
4d2ee1e688
@@ -21,35 +21,6 @@
|
||||
#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)
|
||||
{
|
||||
@@ -769,87 +740,6 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
|
||||
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)
|
||||
@@ -1293,25 +1183,6 @@ error:
|
||||
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
|
||||
@@ -1653,3 +1524,124 @@ int beiscsi_set_uer_feature(struct beiscsi_hba *phba)
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user