Commit d1d5ca88 authored by Jitendra Bhivare's avatar Jitendra Bhivare Committed by Martin K. Petersen

scsi: be2iscsi: Add TPE recovery feature

After UE is detected, check for recoverable error by reading
SLIPORT SEMAPHORE register. If transient parity error i.e. 0xExxx
then schedule recovery work on driver wq.

FLag this error to prevent any transactions for the duration of ue2rp to
restart polling. After that, if FW becomes ready then recover port.

Wake up processes in wq before going offline.
Wait for process to execute before cleaning up.
Signed-off-by: default avatarJitendra Bhivare <jitendra.bhivare@broadcom.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f79929de
......@@ -21,6 +21,78 @@
#include "be.h"
#include "be_mgmt.h"
/* UE Status Low CSR */
static const char * const desc_ue_status_low[] = {
"CEV",
"CTX",
"DBUF",
"ERX",
"Host",
"MPU",
"NDMA",
"PTC ",
"RDMA ",
"RXF ",
"RXIPS ",
"RXULP0 ",
"RXULP1 ",
"RXULP2 ",
"TIM ",
"TPOST ",
"TPRE ",
"TXIPS ",
"TXULP0 ",
"TXULP1 ",
"UC ",
"WDMA ",
"TXULP2 ",
"HOST1 ",
"P0_OB_LINK ",
"P1_OB_LINK ",
"HOST_GPIO ",
"MBOX ",
"AXGMAC0",
"AXGMAC1",
"JTAG",
"MPU_INTPEND"
};
/* UE Status High CSR */
static const char * const desc_ue_status_hi[] = {
"LPCMEMHOST",
"MGMT_MAC",
"PCS0ONLINE",
"MPU_IRAM",
"PCS1ONLINE",
"PCTL0",
"PCTL1",
"PMEM",
"RR",
"TXPB",
"RXPP",
"XAUI",
"TXP",
"ARM",
"IPC",
"HOST2",
"HOST3",
"HOST4",
"HOST5",
"HOST6",
"HOST7",
"HOST8",
"HOST9",
"NETC",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown"
};
struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba,
unsigned int *ref_tag)
{
......@@ -185,6 +257,16 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba,
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
......@@ -538,7 +620,6 @@ static int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl)
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BC_%d : FW Timed Out\n");
set_bit(BEISCSI_HBA_FW_TIMEOUT, &phba->state);
beiscsi_ue_detect(phba);
return -EBUSY;
}
......@@ -1584,6 +1665,12 @@ int beiscsi_init_sliport(struct beiscsi_hba *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.
......@@ -1647,3 +1734,87 @@ int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp)
mutex_unlock(&ctrl->mbox_lock);
return status;
}
/*
* beiscsi_detect_ue()- Detect Unrecoverable Error on adapter
* @phba: Driver priv structure
*
* Read registers linked to UE and check for the UE status
**/
int beiscsi_detect_ue(struct beiscsi_hba *phba)
{
uint32_t ue_mask_hi = 0, ue_mask_lo = 0;
uint32_t ue_hi = 0, ue_lo = 0;
uint8_t i = 0;
int ret = 0;
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_LOW, &ue_lo);
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_MASK_LOW,
&ue_mask_lo);
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_HIGH,
&ue_hi);
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_MASK_HI,
&ue_mask_hi);
ue_lo = (ue_lo & ~ue_mask_lo);
ue_hi = (ue_hi & ~ue_mask_hi);
if (ue_lo || ue_hi) {
set_bit(BEISCSI_HBA_IN_UE, &phba->state);
__beiscsi_log(phba, KERN_ERR,
"BC_%d : HBA error detected\n");
ret = 1;
}
if (ue_lo) {
for (i = 0; ue_lo; ue_lo >>= 1, i++) {
if (ue_lo & 1)
__beiscsi_log(phba, KERN_ERR,
"BC_%d : UE_LOW %s bit set\n",
desc_ue_status_low[i]);
}
}
if (ue_hi) {
for (i = 0; ue_hi; ue_hi >>= 1, i++) {
if (ue_hi & 1)
__beiscsi_log(phba, KERN_ERR,
"BC_%d : UE_HIGH %s bit set\n",
desc_ue_status_hi[i]);
}
}
return ret;
}
/*
* beiscsi_detect_tpe()- Detect Transient Parity Error on adapter
* @phba: Driver priv structure
*
* Read SLIPORT SEMAPHORE register to check for UER
*
**/
int beiscsi_detect_tpe(struct beiscsi_hba *phba)
{
u32 post, status;
int ret = 0;
post = beiscsi_get_post_stage(phba);
status = post & POST_STAGE_MASK;
if ((status & POST_ERR_RECOVERY_CODE_MASK) ==
POST_STAGE_RECOVERABLE_ERR) {
set_bit(BEISCSI_HBA_IN_TPE, &phba->state);
__beiscsi_log(phba, KERN_INFO,
"BC_%d : HBA error recoverable: 0x%x\n", post);
ret = 1;
} else {
__beiscsi_log(phba, KERN_INFO,
"BC_%d : HBA in UE: 0x%x\n", post);
}
return ret;
}
......@@ -770,6 +770,10 @@ int beiscsi_init_sliport(struct beiscsi_hba *phba);
int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num);
int beiscsi_detect_ue(struct beiscsi_hba *phba);
int beiscsi_detect_tpe(struct beiscsi_hba *phba);
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *eq, int eq_delay);
......
......@@ -58,7 +58,7 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
beiscsi_ep = ep->dd_data;
phba = beiscsi_ep->phba;
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
return NULL;
......@@ -444,7 +444,7 @@ int beiscsi_iface_set_param(struct Scsi_Host *shost,
uint32_t rm_len = dt_len;
int ret;
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
return -EBUSY;
......@@ -587,7 +587,7 @@ int beiscsi_iface_get_param(struct iscsi_iface *iface,
if (param_type != ISCSI_NET_PARAM)
return 0;
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
return -EBUSY;
......@@ -797,7 +797,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
struct beiscsi_hba *phba = iscsi_host_priv(shost);
int status = 0;
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
return -EBUSY;
......@@ -945,7 +945,7 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
return -EBUSY;
......@@ -1175,7 +1175,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
}
phba = iscsi_host_priv(shost);
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
ret = -EIO;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
......@@ -1335,7 +1335,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
}
if (beiscsi_hba_in_error(phba)) {
if (!beiscsi_hba_is_online(phba)) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : HBA in error 0x%lx\n", phba->state);
goto free_ep;
......
This diff is collapsed.
......@@ -393,7 +393,7 @@ struct beiscsi_hba {
} fw_config;
unsigned long state;
#define BEISCSI_HBA_RUNNING 0
#define BEISCSI_HBA_ONLINE 0
#define BEISCSI_HBA_LINK_UP 1
#define BEISCSI_HBA_BOOT_FOUND 2
#define BEISCSI_HBA_BOOT_WORK 3
......@@ -417,6 +417,7 @@ struct beiscsi_hba {
/* check for UE every 1000ms */
#define BEISCSI_UE_DETECT_INTERVAL 1000
u32 ue2rp;
struct delayed_work recover_port;
bool mac_addr_set;
u8 mac_address[ETH_ALEN];
......@@ -455,6 +456,9 @@ struct beiscsi_hba {
};
#define beiscsi_hba_in_error(phba) ((phba)->state & BEISCSI_HBA_IN_ERR)
#define beiscsi_hba_is_online(phba) \
(!beiscsi_hba_in_error((phba)) && \
test_bit(BEISCSI_HBA_ONLINE, &phba->state))
struct beiscsi_session {
struct pci_pool *bhs_pool;
......
......@@ -24,134 +24,6 @@
#include "be_iscsi.h"
#include "be_main.h"
/* UE Status Low CSR */
static const char * const desc_ue_status_low[] = {
"CEV",
"CTX",
"DBUF",
"ERX",
"Host",
"MPU",
"NDMA",
"PTC ",
"RDMA ",
"RXF ",
"RXIPS ",
"RXULP0 ",
"RXULP1 ",
"RXULP2 ",
"TIM ",
"TPOST ",
"TPRE ",
"TXIPS ",
"TXULP0 ",
"TXULP1 ",
"UC ",
"WDMA ",
"TXULP2 ",
"HOST1 ",
"P0_OB_LINK ",
"P1_OB_LINK ",
"HOST_GPIO ",
"MBOX ",
"AXGMAC0",
"AXGMAC1",
"JTAG",
"MPU_INTPEND"
};
/* UE Status High CSR */
static const char * const desc_ue_status_hi[] = {
"LPCMEMHOST",
"MGMT_MAC",
"PCS0ONLINE",
"MPU_IRAM",
"PCS1ONLINE",
"PCTL0",
"PCTL1",
"PMEM",
"RR",
"TXPB",
"RXPP",
"XAUI",
"TXP",
"ARM",
"IPC",
"HOST2",
"HOST3",
"HOST4",
"HOST5",
"HOST6",
"HOST7",
"HOST8",
"HOST9",
"NETC",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown"
};
/*
* beiscsi_ue_detect()- Detect Unrecoverable Error on adapter
* @phba: Driver priv structure
*
* Read registers linked to UE and check for the UE status
**/
void beiscsi_ue_detect(struct beiscsi_hba *phba)
{
uint32_t ue_hi = 0, ue_lo = 0;
uint32_t ue_mask_hi = 0, ue_mask_lo = 0;
uint8_t i = 0;
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_LOW, &ue_lo);
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_MASK_LOW,
&ue_mask_lo);
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_HIGH,
&ue_hi);
pci_read_config_dword(phba->pcidev,
PCICFG_UE_STATUS_MASK_HI,
&ue_mask_hi);
ue_lo = (ue_lo & ~ue_mask_lo);
ue_hi = (ue_hi & ~ue_mask_hi);
if (ue_lo || ue_hi) {
set_bit(BEISCSI_HBA_IN_UE, &phba->state);
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : HBA error detected\n");
}
if (ue_lo) {
for (i = 0; ue_lo; ue_lo >>= 1, i++) {
if (ue_lo & 1)
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG,
"BG_%d : UE_LOW %s bit set\n",
desc_ue_status_low[i]);
}
}
if (ue_hi) {
for (i = 0; ue_hi; ue_hi >>= 1, i++) {
if (ue_hi & 1)
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG,
"BG_%d : UE_HIGH %s bit set\n",
desc_ue_status_hi[i]);
}
}
}
int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *set_eqd,
int num)
......
......@@ -329,7 +329,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle,
struct hwi_wrb_context *pwrb_context);
void beiscsi_ue_detect(struct beiscsi_hba *phba);
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *, int num);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment