Commit 41415862 authored by Jamie Wellnitz's avatar Jamie Wellnitz Committed by James Bottomley
Browse files

[SCSI] lpfc 8.1.2: Add ERROR and WARM_START modes for diagnostic purposes.



Add ERROR and WARM_START modes for diagnostic purposes.

Signed-off-by: default avatarJamie Wellnitz <Jamie.Wellnitz@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent d9d959c4
Loading
Loading
Loading
Loading
+18 −16
Original line number Diff line number Diff line
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
 * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
 * www.emulex.com                                                  *
 * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -175,25 +175,27 @@ struct lpfc_hba {
	uint16_t pci_cfg_value;

	struct semaphore hba_can_block;
	uint32_t hba_state;

#define LPFC_INIT_START           1	/* Initial state after board reset */
#define LPFC_INIT_MBX_CMDS        2	/* Initialize HBA with mbox commands */
#define LPFC_LINK_DOWN            3	/* HBA initialized, link is down */
#define LPFC_LINK_UP              4	/* Link is up  - issue READ_LA */
#define LPFC_LOCAL_CFG_LINK       5	/* local NPORT Id configured */
#define LPFC_FLOGI                6	/* FLOGI sent to Fabric */
#define LPFC_FABRIC_CFG_LINK      7	/* Fabric assigned NPORT Id
	int32_t hba_state;

#define LPFC_STATE_UNKNOWN        0    /* HBA state is unknown */
#define LPFC_WARM_START           1    /* HBA state after selective reset */
#define LPFC_INIT_START           2    /* Initial state after board reset */
#define LPFC_INIT_MBX_CMDS        3    /* Initialize HBA with mbox commands */
#define LPFC_LINK_DOWN            4    /* HBA initialized, link is down */
#define LPFC_LINK_UP              5    /* Link is up  - issue READ_LA */
#define LPFC_LOCAL_CFG_LINK       6    /* local NPORT Id configured */
#define LPFC_FLOGI                7    /* FLOGI sent to Fabric */
#define LPFC_FABRIC_CFG_LINK      8    /* Fabric assigned NPORT Id
					   configured */
#define LPFC_NS_REG               8	/* Register with NameServer */
#define LPFC_NS_QRY               9	/* Query NameServer for NPort ID list */
#define LPFC_BUILD_DISC_LIST      10	/* Build ADISC and PLOGI lists for
#define LPFC_NS_REG               9	/* Register with NameServer */
#define LPFC_NS_QRY               10	/* Query NameServer for NPort ID list */
#define LPFC_BUILD_DISC_LIST      11	/* Build ADISC and PLOGI lists for
					 * device authentication / discovery */
#define LPFC_DISC_AUTH            11	/* Processing ADISC list */
#define LPFC_CLEAR_LA             12	/* authentication cmplt - issue
#define LPFC_DISC_AUTH            12	/* Processing ADISC list */
#define LPFC_CLEAR_LA             13	/* authentication cmplt - issue
					   CLEAR_LA */
#define LPFC_HBA_READY            32
#define LPFC_HBA_ERROR            0xff
#define LPFC_HBA_ERROR            -1

	uint8_t fc_linkspeed;	/* Link speed after last READ_LA */

+63 −1
Original line number Diff line number Diff line
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
 * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
 * www.emulex.com                                                  *
 * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -149,6 +149,8 @@ lpfc_state_show(struct class_device *cdev, char *buf)
	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
	int len = 0;
	switch (phba->hba_state) {
	case LPFC_STATE_UNKNOWN:
	case LPFC_WARM_START:
	case LPFC_INIT_START:
	case LPFC_INIT_MBX_CMDS:
	case LPFC_LINK_DOWN:
@@ -278,6 +280,58 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
		return -EIO;
}

static ssize_t
lpfc_board_mode_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host *host = class_to_shost(cdev);
	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
	char  * state;

	if (phba->hba_state == LPFC_HBA_ERROR)
		state = "error";
	else if (phba->hba_state == LPFC_WARM_START)
		state = "warm start";
	else if (phba->hba_state == LPFC_INIT_START)
		state = "offline";
	else
		state = "online";

	return snprintf(buf, PAGE_SIZE, "%s\n", state);
}

static ssize_t
lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
{
	struct Scsi_Host *host = class_to_shost(cdev);
	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
	struct completion online_compl;
	int status=0;

	init_completion(&online_compl);

	if(strncmp(buf, "online", sizeof("online") - 1) == 0)
		lpfc_workq_post_event(phba, &status, &online_compl,
				      LPFC_EVT_ONLINE);
	else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
		lpfc_workq_post_event(phba, &status, &online_compl,
				      LPFC_EVT_OFFLINE);
	else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
		lpfc_workq_post_event(phba, &status, &online_compl,
				      LPFC_EVT_WARM_START);
 	else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
		lpfc_workq_post_event(phba, &status, &online_compl,
				      LPFC_EVT_KILL);
	else
		return -EINVAL;

	wait_for_completion(&online_compl);

	if (!status)
		return strlen(buf);
	else
		return -EIO;
}

static ssize_t
lpfc_poll_show(struct class_device *cdev, char *buf)
{
@@ -480,6 +534,8 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
			 NULL);
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
			 lpfc_board_online_show, lpfc_board_online_store);
static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
			 lpfc_board_mode_show, lpfc_board_mode_store);

static int lpfc_poll = 0;
module_param(lpfc_poll, int, 0);
@@ -674,6 +730,7 @@ struct class_device_attribute *lpfc_host_attrs[] = {
	&class_device_attr_nport_evt_cnt,
	&class_device_attr_management_version,
	&class_device_attr_board_online,
	&class_device_attr_board_mode,
	&class_device_attr_lpfc_poll,
	&class_device_attr_lpfc_poll_tmo,
	NULL,
@@ -883,8 +940,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
		case MBX_DUMP_MEMORY:
		case MBX_DOWN_LOAD:
		case MBX_UPDATE_CFG:
		case MBX_KILL_BOARD:
		case MBX_LOAD_AREA:
		case MBX_LOAD_EXP_ROM:
		case MBX_BEACON:
		case MBX_DEL_LD_ENTRY:
			break;
		case MBX_READ_SPARM64:
		case MBX_READ_LA:
@@ -1042,6 +1102,8 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
	else {
		switch (phba->hba_state) {
		case LPFC_STATE_UNKNOWN:
		case LPFC_WARM_START:
		case LPFC_INIT_START:
		case LPFC_INIT_MBX_CMDS:
		case LPFC_LINK_DOWN:
+8 −1
Original line number Diff line number Diff line
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
 * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
 * www.emulex.com                                                  *
 *                                                                 *
@@ -107,6 +107,7 @@ void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
int lpfc_config_port_prep(struct lpfc_hba *);
int lpfc_config_port_post(struct lpfc_hba *);
int lpfc_hba_down_prep(struct lpfc_hba *);
int lpfc_hba_down_post(struct lpfc_hba *);
void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
@@ -123,6 +124,7 @@ irqreturn_t lpfc_intr_handler(int, void *, struct pt_regs *);
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);

@@ -135,6 +137,11 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);

int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_brdreset(struct lpfc_hba *);
int lpfc_sli_brdrestart(struct lpfc_hba *);
int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
+12 −6
Original line number Diff line number Diff line
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
 * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
 * www.emulex.com                                                  *
 *                                                                 *
@@ -28,18 +28,24 @@
 * This is used by Fibre Channel protocol to support FCP.
 */

/* worker thread events */
enum lpfc_work_type {
	LPFC_EVT_NODEV_TMO,
	LPFC_EVT_ONLINE,
	LPFC_EVT_OFFLINE,
	LPFC_EVT_WARM_START,
	LPFC_EVT_KILL,
	LPFC_EVT_ELS_RETRY,
};

/* structure used to queue event to the discovery tasklet */
struct lpfc_work_evt {
	struct list_head      evt_listp;
	void                * evt_arg1;
	void                * evt_arg2;
	uint32_t              evt;
	enum lpfc_work_type   evt;
};

#define LPFC_EVT_NODEV_TMO	0x1
#define LPFC_EVT_ONLINE		0x2
#define LPFC_EVT_OFFLINE	0x3
#define LPFC_EVT_ELS_RETRY	0x4

struct lpfc_nodelist {
	struct list_head nlp_listp;
+29 −3
Original line number Diff line number Diff line
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
 * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
 * www.emulex.com                                                  *
 * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -120,11 +120,33 @@ lpfc_work_list_done(struct lpfc_hba * phba)
			free_evt = 0;
			break;
		case LPFC_EVT_ONLINE:
			if (phba->hba_state < LPFC_LINK_DOWN)
				*(int *)(evtp->evt_arg1)  = lpfc_online(phba);
			else
				*(int *)(evtp->evt_arg1)  = 0;
			complete((struct completion *)(evtp->evt_arg2));
			break;
		case LPFC_EVT_OFFLINE:
			*(int *)(evtp->evt_arg1)  = lpfc_offline(phba);
			if (phba->hba_state >= LPFC_LINK_DOWN)
				lpfc_offline(phba);
			lpfc_sli_brdrestart(phba);
			*(int *)(evtp->evt_arg1) =
				lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY);
			complete((struct completion *)(evtp->evt_arg2));
			break;
		case LPFC_EVT_WARM_START:
			if (phba->hba_state >= LPFC_LINK_DOWN)
				lpfc_offline(phba);
			lpfc_sli_brdreset(phba);
			lpfc_hba_down_post(phba);
			*(int *)(evtp->evt_arg1) =
				lpfc_sli_brdready(phba, HS_MBRDY);
			complete((struct completion *)(evtp->evt_arg2));
			break;
		case LPFC_EVT_KILL:
			if (phba->hba_state >= LPFC_LINK_DOWN)
				lpfc_offline(phba);
			*(int *)(evtp->evt_arg1)  = lpfc_sli_brdkill(phba);
			complete((struct completion *)(evtp->evt_arg2));
			break;
		}
@@ -287,6 +309,10 @@ lpfc_linkdown(struct lpfc_hba * phba)
	LPFC_MBOXQ_t     *mb;
	int               rc, i;

	if (phba->hba_state == LPFC_LINK_DOWN) {
		return 0;
	}

	psli = &phba->sli;

	/* sysfs or selective reset may call this routine to clean up */
Loading