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

Commit c01f3208 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.1.10 : Add support for dev_loss_tmo_callbk and fast_io_fail_tmo_callbk



Add support for new dev_loss_tmo callback
  Goodness is that it removes code for a parallel nodev timer that
  existed in the driver
Add support for the new fast_io_fail callback

Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 0f29b966
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -285,6 +285,7 @@ struct lpfc_hba {
	uint32_t cfg_log_verbose;
	uint32_t cfg_lun_queue_depth;
	uint32_t cfg_nodev_tmo;
	uint32_t cfg_devloss_tmo;
	uint32_t cfg_hba_queue_depth;
	uint32_t cfg_fcp_class;
	uint32_t cfg_use_adisc;
@@ -303,6 +304,8 @@ struct lpfc_hba {
	uint32_t cfg_sg_seg_cnt;
	uint32_t cfg_sg_dma_buf_size;

	uint32_t dev_loss_tmo_changed;

	lpfc_vpd_t vpd;		/* vital product data */

	struct Scsi_Host *host;
+127 −28
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@
#include "lpfc_compat.h"
#include "lpfc_crtn.h"

#define LPFC_DEF_DEVLOSS_TMO 30
#define LPFC_MIN_DEVLOSS_TMO 1
#define LPFC_MAX_DEVLOSS_TMO 255

static void
lpfc_jedec_to_ascii(int incr, char hdw[])
@@ -558,6 +561,123 @@ MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
			 lpfc_poll_show, lpfc_poll_store);

/*
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
# until the timer expires. Value range is [0,255]. Default value is 30.
*/
static int lpfc_nodev_tmo = LPFC_DEF_DEVLOSS_TMO;
static int lpfc_devloss_tmo = LPFC_DEF_DEVLOSS_TMO;
module_param(lpfc_nodev_tmo, int, 0);
MODULE_PARM_DESC(lpfc_nodev_tmo,
		 "Seconds driver will hold I/O waiting "
		 "for a device to come back");
static ssize_t
lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host *host = class_to_shost(cdev);
	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
	int val = 0;
	val = phba->cfg_devloss_tmo;
	return snprintf(buf, PAGE_SIZE, "%d\n",
			phba->cfg_devloss_tmo);
}

static int
lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val)
{
	static int warned;
	if (phba->cfg_devloss_tmo !=  LPFC_DEF_DEVLOSS_TMO) {
		phba->cfg_nodev_tmo = phba->cfg_devloss_tmo;
		if (!warned && val != LPFC_DEF_DEVLOSS_TMO) {
			warned = 1;
			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
					"%d:0402 Ignoring nodev_tmo module "
					"parameter because devloss_tmo is"
					" set.\n",
					phba->brd_no);
		}
		return 0;
	}

	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
		phba->cfg_nodev_tmo = val;
		phba->cfg_devloss_tmo = val;
		return 0;
	}
	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
			"%d:0400 lpfc_nodev_tmo attribute cannot be set to %d, "
			"allowed range is [%d, %d]\n",
			phba->brd_no, val,
			LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);
	phba->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO;
	return -EINVAL;
}

static int
lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
{
	if (phba->dev_loss_tmo_changed ||
		(lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) {
		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
				"%d:0401 Ignoring change to nodev_tmo "
				"because devloss_tmo is set.\n",
				phba->brd_no);
		return 0;
	}

	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
		phba->cfg_nodev_tmo = val;
		phba->cfg_devloss_tmo = val;
		return 0;
	}

	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
			"%d:0403 lpfc_nodev_tmo attribute cannot be set to %d, "
			"allowed range is [%d, %d]\n",
			phba->brd_no, val, LPFC_MIN_DEVLOSS_TMO,
			LPFC_MAX_DEVLOSS_TMO);
	return -EINVAL;
}

lpfc_param_store(nodev_tmo)

static CLASS_DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,
			 lpfc_nodev_tmo_show, lpfc_nodev_tmo_store);

/*
# lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that
# disappear until the timer expires. Value range is [0,255]. Default
# value is 30.
*/
module_param(lpfc_devloss_tmo, int, 0);
MODULE_PARM_DESC(lpfc_devloss_tmo,
		 "Seconds driver will hold I/O waiting "
		 "for a device to come back");
lpfc_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO,
		LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO)
lpfc_param_show(devloss_tmo)
static int
lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val)
{
	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
		phba->cfg_nodev_tmo = val;
		phba->cfg_devloss_tmo = val;
		phba->dev_loss_tmo_changed = 1;
		return 0;
	}

	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
			"%d:0404 lpfc_devloss_tmo attribute cannot be set to"
			" %d, allowed range is [%d, %d]\n",
			phba->brd_no, val, LPFC_MIN_DEVLOSS_TMO,
			LPFC_MAX_DEVLOSS_TMO);
	return -EINVAL;
}

lpfc_param_store(devloss_tmo)
static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,
	lpfc_devloss_tmo_show, lpfc_devloss_tmo_store);

/*
# lpfc_log_verbose: Only turn this flag on if you are willing to risk being
# deluged with LOTS of information.
@@ -616,14 +736,6 @@ LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,
LPFC_ATTR_R(scan_down, 1, 0, 1,
	     "Start scanning for devices from highest ALPA to lowest");

/*
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
# until the timer expires. Value range is [0,255]. Default value is 30.
# NOTE: this MUST be less then the SCSI Layer command timeout - 1.
*/
LPFC_ATTR_RW(nodev_tmo, 30, 0, 255,
	     "Seconds driver will hold I/O waiting for a device to come back");

/*
# lpfc_topology:  link topology for init link
#            0x0  = attempt loop mode then point-to-point
@@ -737,6 +849,7 @@ struct class_device_attribute *lpfc_host_attrs[] = {
	&class_device_attr_lpfc_lun_queue_depth,
	&class_device_attr_lpfc_hba_queue_depth,
	&class_device_attr_lpfc_nodev_tmo,
	&class_device_attr_lpfc_devloss_tmo,
	&class_device_attr_lpfc_fcp_class,
	&class_device_attr_lpfc_use_adisc,
	&class_device_attr_lpfc_ack0,
@@ -1449,28 +1562,13 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
	fc_starget_port_name(starget) = port_name;
}

static void
lpfc_get_rport_loss_tmo(struct fc_rport *rport)
{
	/*
	 * Return the driver's global value for device loss timeout plus
	 * five seconds to allow the driver's nodev timer to run.
	 */
	rport->dev_loss_tmo = lpfc_nodev_tmo + 5;
}

static void
lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{
	/*
	 * The driver doesn't have a per-target timeout setting.  Set
	 * this value globally. lpfc_nodev_tmo should be greater then 0.
	 */
	if (timeout)
		lpfc_nodev_tmo = timeout;
		rport->dev_loss_tmo = timeout;
	else
		lpfc_nodev_tmo = 1;
	rport->dev_loss_tmo = lpfc_nodev_tmo + 5;
		rport->dev_loss_tmo = 1;
}


@@ -1532,7 +1630,6 @@ struct fc_function_template lpfc_transport_functions = {
	.show_rport_maxframe_size = 1,
	.show_rport_supported_classes = 1,

	.get_rport_dev_loss_tmo = lpfc_get_rport_loss_tmo,
	.set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
	.show_rport_dev_loss_tmo = 1,

@@ -1546,6 +1643,8 @@ struct fc_function_template lpfc_transport_functions = {
	.show_starget_port_name = 1,

	.issue_fc_host_lip = lpfc_issue_lip,
	.dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
	.terminate_rport_io = lpfc_terminate_rport_io,
};

void
@@ -1561,13 +1660,13 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
	lpfc_ack0_init(phba, lpfc_ack0);
	lpfc_topology_init(phba, lpfc_topology);
	lpfc_scan_down_init(phba, lpfc_scan_down);
	lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
	lpfc_link_speed_init(phba, lpfc_link_speed);
	lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
	lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
	lpfc_max_luns_init(phba, lpfc_max_luns);
	lpfc_poll_tmo_init(phba, lpfc_poll_tmo);

	lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
	lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
	phba->cfg_poll = lpfc_poll;

	/*
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
 * included with this package.                                     *
 *******************************************************************/

struct fc_rport;
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
@@ -200,6 +201,8 @@ extern struct scsi_host_template lpfc_template;
extern struct fc_function_template lpfc_transport_functions;

void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp);
void lpfc_terminate_rport_io(struct fc_rport *);
void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);

#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
#define HBA_EVENT_RSCN                   5
+0 −25
Original line number Diff line number Diff line
@@ -324,7 +324,6 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
	struct lpfc_sli_ct_request *Response =
		(struct lpfc_sli_ct_request *) mp->virt;
	struct lpfc_nodelist *ndlp = NULL;
	struct lpfc_nodelist *next_ndlp;
	struct lpfc_dmabuf *mlast, *next_mp;
	uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
	uint32_t Did;
@@ -399,30 +398,6 @@ nsout1:
 	 * current driver state.
 	 */
	if (phba->hba_state == LPFC_HBA_READY) {

		/*
		 * Switch ports that connect a loop of multiple targets need
		 * special consideration.  The driver wants to unregister the
		 * rpi only on the target that was pulled from the loop.  On
		 * RSCN, the driver wants to rediscover an NPort only if the
		 * driver flagged it as NLP_NPR_2B_DISC.  Provided adisc is
		 * not enabled and the NPort is not capable of retransmissions
		 * (FC Tape) prevent timing races with the scsi error handler by
		 * unregistering the Nport's RPI.  This action causes all
		 * outstanding IO to flush back to the midlayer.
		 */
		list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
					 nlp_listp) {
			if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
			    (lpfc_rscn_payload_check(phba, ndlp->nlp_DID))) {
				if ((phba->cfg_use_adisc == 0) &&
				    !(ndlp->nlp_fcp_info &
				      NLP_FCP_2_DEVICE)) {
					lpfc_unreg_rpi(phba, ndlp);
					ndlp->nlp_flag &= ~NLP_NPR_ADISC;
				}
			}
		}
		lpfc_els_flush_rscn(phba);
		spin_lock_irq(phba->host->host_lock);
		phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
+1 −5
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@

/* worker thread events */
enum lpfc_work_type {
	LPFC_EVT_NODEV_TMO,
	LPFC_EVT_ONLINE,
	LPFC_EVT_OFFLINE,
	LPFC_EVT_WARM_START,
@@ -74,11 +73,9 @@ struct lpfc_nodelist {
#define NLP_FCP_2_DEVICE   0x10			/* FCP-2 device */

	struct timer_list   nlp_delayfunc;	/* Used for delayed ELS cmds */
	struct timer_list   nlp_tmofunc;	/* Used for nodev tmo */
	struct fc_rport *rport;			/* Corresponding FC transport
						   port structure */
	struct lpfc_hba      *nlp_phba;
	struct lpfc_work_evt nodev_timeout_evt;
	struct lpfc_work_evt els_retry_evt;
	unsigned long last_ramp_up_time;        /* jiffy of last ramp up */
	unsigned long last_q_full_time;		/* jiffy of last queue full */
@@ -102,7 +99,6 @@ struct lpfc_nodelist {
#define NLP_LOGO_SND       0x100	/* sent LOGO request for this entry */
#define NLP_RNID_SND       0x400	/* sent RNID request for this entry */
#define NLP_ELS_SND_MASK   0x7e0	/* sent ELS request for this entry */
#define NLP_NODEV_TMO      0x10000	/* nodev timeout is running for node */
#define NLP_DELAY_TMO      0x20000	/* delay timeout is running for node */
#define NLP_NPR_2B_DISC    0x40000	/* node is included in num_disc_nodes */
#define NLP_RCV_PLOGI      0x80000	/* Rcv'ed PLOGI from remote system */
@@ -169,7 +165,7 @@ struct lpfc_nodelist {
 */
/*
 * For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped
 * lists will receive a DEVICE_RECOVERY event. If the linkdown or nodev timers
 * lists will receive a DEVICE_RECOVERY event. If the linkdown or devloss timers
 * expire, all effected nodes will receive a DEVICE_RM event.
 */
/*
Loading