Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+172 −1
Original line number Diff line number Diff line
@@ -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;
}
+4 −0
Original line number Diff line number Diff line
@@ -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);

+7 −7
Original line number Diff line number Diff line
@@ -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;
+444 −295

File changed.

Preview size limit exceeded, changes collapsed.

+5 −1
Original line number Diff line number Diff line
@@ -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;
Loading