Commit 7a158003 authored by John Soni Jose's avatar John Soni Jose Committed by James Bottomley
Browse files

[SCSI] be2iscsi: Fix Unrecoverable Error Detection



Driver periodically checks adapter state,is up fine or not.
Based on the value updates the internal structures of driver.

Signed-off-by: default avatarJohn Soni Jose <sony.john-n@emulex.com>
Signed-off-by: default avatarJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent e175defe
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -157,6 +157,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
	struct be_cmd_req_hdr *ioctl_hdr;
	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;

	if (beiscsi_error(phba))
		return -EIO;

	/* wait for the mccq completion */
	rc = wait_event_interruptible_timeout(
				phba->ctrl.mcc_wait[tag],
@@ -423,7 +426,7 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba)
{
	int i, status;
	for (i = 0; i < mcc_timeout; i++) {
		if (phba->fw_timeout)
		if (beiscsi_error(phba))
			return -EIO;

		status = beiscsi_process_mcc(phba);
@@ -439,6 +442,7 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba)
			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
			    "BC_%d : FW Timed Out\n");
		phba->fw_timeout = true;
		beiscsi_ue_detect(phba);
		return -EBUSY;
	}
	return 0;
@@ -479,7 +483,8 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
	u32 ready;

	do {
		if (phba->fw_timeout)

		if (beiscsi_error(phba))
			return -EIO;

		ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
@@ -491,6 +496,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
				    "BC_%d : FW Timed Out\n");
			phba->fw_timeout = true;
			beiscsi_ue_detect(phba);
			return -EBUSY;
		}

+26 −0
Original line number Diff line number Diff line
@@ -4717,6 +4717,8 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba)
			    phba->ctrl.mbox_mem_alloced.size,
			    phba->ctrl.mbox_mem_alloced.va,
			    phba->ctrl.mbox_mem_alloced.dma);

	cancel_delayed_work_sync(&phba->beiscsi_hw_check_task);
}

static void beiscsi_remove(struct pci_dev *pcidev)
@@ -4769,6 +4771,25 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba)
	return;
}

/*
 * beiscsi_hw_health_check()- Check adapter health
 * @work: work item to check HW health
 *
 * Check if adapter in an unrecoverable state or not.
 **/
static void
beiscsi_hw_health_check(struct work_struct *work)
{
	struct beiscsi_hba *phba =
		container_of(work, struct beiscsi_hba,
			     beiscsi_hw_check_task.work);

	beiscsi_ue_detect(phba);

	schedule_delayed_work(&phba->beiscsi_hw_check_task,
			      msecs_to_jiffies(1000));
}

static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
				const struct pci_device_id *id)
{
@@ -4892,6 +4913,8 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
		goto free_twq;
	}

	INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task,
			  beiscsi_hw_health_check);

	phwi_ctrlr = phba->phwi_ctrlr;
	phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -4941,6 +4964,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
			    "iSCSI boot info.\n");

	beiscsi_create_def_ifaces(phba);
	schedule_delayed_work(&phba->beiscsi_hw_check_task,
			      msecs_to_jiffies(1000));

	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
		    "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
	return 0;
+5 −0
Original line number Diff line number Diff line
@@ -750,6 +750,11 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);

void beiscsi_process_all_cqs(struct work_struct *work);

static inline bool beiscsi_error(struct beiscsi_hba *phba)
{
	return phba->ue_detected || phba->fw_timeout;
}

struct pdu_nop_out {
	u32 dw[12];
};
+132 −0
Original line number Diff line number Diff line
@@ -22,6 +22,138 @@
#include <scsi/scsi_bsg_iscsi.h>
#include "be_mgmt.h"
#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_detec()- 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;

	if (phba->ue_detected)
		return;

	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) {
		phba->ue_detected = true;
		beiscsi_log(phba, KERN_ERR,
			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
			    "BG_%d : Error detected on the adapter\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]);
		}
	}
}

/**
 * mgmt_reopen_session()- Reopen a session based on reopen_type
+7 −0
Original line number Diff line number Diff line
@@ -30,6 +30,12 @@
#define IP_V6_LEN	16
#define IP_V4_LEN	4

/* UE Status and Mask register */
#define PCICFG_UE_STATUS_LOW            0xA0
#define PCICFG_UE_STATUS_HIGH           0xA4
#define PCICFG_UE_STATUS_MASK_LOW       0xA8
#define PCICFG_UE_STATUS_MASK_HI        0xAC

/**
 * Pseudo amap definition in which each bit of the actual structure is defined
 * as a byte: used to calculate offset/shift/mask of each field
@@ -314,5 +320,6 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,

void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
			     struct wrb_handle *pwrb_handle);
void beiscsi_ue_detect(struct beiscsi_hba *phba);

#endif