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

[SCSI] lpfc: NPIV: add NPIV support on top of SLI-3



NPIV support is added to the driver.  It utilizes the interfaces of
the fc transport for the creation and deletion of vports. Within the
driver, a new Scsi_Host is created for each NPIV instance, and is
paired with a new instance of a FC port.  This allows N FC Port
elements to share a single Adapter.

Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent ed957684
Loading
Loading
Loading
Loading
+3 −2
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                                                  *
# *                                                                 *
@@ -27,4 +27,5 @@ endif
obj-$(CONFIG_SCSI_LPFC) := lpfc.o

lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o	\
	lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o
	lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \
	lpfc_vport.o
+111 −45
Original line number Diff line number Diff line
@@ -34,6 +34,17 @@ struct lpfc_sli2_slim;
#define LPFC_IOCB_LIST_CNT	2250	/* list of IOCBs for fast-path usage. */
#define LPFC_Q_RAMP_UP_INTERVAL 120     /* lun q_depth ramp up interval */

/*
 * Following time intervals are used of adjusting SCSI device
 * queue depths when there are driver resource error or Firmware
 * resource error.
 */
#define QUEUE_RAMP_DOWN_INTERVAL	(1 * HZ)   /* 1 Second */
#define QUEUE_RAMP_UP_INTERVAL		(300 * HZ) /* 5 minutes */

/* Number of exchanges reserved for discovery to complete */
#define LPFC_DISC_IOCB_BUFF_COUNT 20

/* Define macros for 64 bit support */
#define putPaddrLow(addr)    ((uint32_t) (0xffffffff & (u64)(addr)))
#define putPaddrHigh(addr)   ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
@@ -97,6 +108,29 @@ typedef struct lpfc_vpd {
		uint32_t sli2FwRev;
		uint8_t sli2FwName[16];
	} rev;
	struct {
#ifdef __BIG_ENDIAN_BITFIELD
		uint32_t rsvd2  :24;  /* Reserved                             */
		uint32_t cmv	: 1;  /* Configure Max VPIs                   */
		uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
		uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
		uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
		uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
		uint32_t cerbm	: 1;  /* Configure Enhanced Receive Buf Mgmt  */
		uint32_t cmx	: 1;  /* Configure Max XRIs                   */
		uint32_t cmr	: 1;  /* Configure Max RPIs                   */
#else	/*  __LITTLE_ENDIAN */
		uint32_t cmr	: 1;  /* Configure Max RPIs                   */
		uint32_t cmx	: 1;  /* Configure Max XRIs                   */
		uint32_t cerbm	: 1;  /* Configure Enhanced Receive Buf Mgmt  */
		uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
		uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
		uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
		uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
		uint32_t cmv	: 1;  /* Configure Max VPIs                   */
		uint32_t rsvd2  :24;  /* Reserved                             */
#endif
	} sli3Feat;
} lpfc_vpd_t;

struct lpfc_scsi_buf;
@@ -129,6 +163,7 @@ struct lpfc_stats {
	uint32_t elsRcvRPS;
	uint32_t elsRcvRPL;
	uint32_t elsXmitFLOGI;
	uint32_t elsXmitFDISC;
	uint32_t elsXmitPLOGI;
	uint32_t elsXmitPRLI;
	uint32_t elsXmitADISC;
@@ -174,17 +209,20 @@ struct lpfc_sysfs_mbox {

struct lpfc_hba;


enum discovery_state {
	LPFC_STATE_UNKNOWN   =  0,    /* HBA state is unknown */
	LPFC_VPORT_UNKNOWN     =  0,    /* vport state is unknown */
	LPFC_VPORT_FAILED      =  1,    /* vport has failed */
	LPFC_LOCAL_CFG_LINK    =  6,    /* local NPORT Id configured */
	LPFC_FLOGI             =  7,    /* FLOGI sent to Fabric */
	LPFC_FABRIC_CFG_LINK =  8,    /* Fabric assigned NPORT Id
	LPFC_FDISC             =  8,    /* FDISC sent for vport */
	LPFC_FABRIC_CFG_LINK   =  9,    /* Fabric assigned NPORT Id
				         * configured */
	LPFC_NS_REG          =  9,    /* Register with NameServer */
	LPFC_NS_QRY          =  10,   /* Query NameServer for NPort ID list */
	LPFC_BUILD_DISC_LIST =  11,   /* Build ADISC and PLOGI lists for
	LPFC_NS_REG            =  10,   /* Register with NameServer */
	LPFC_NS_QRY            =  11,   /* Query NameServer for NPort ID list */
	LPFC_BUILD_DISC_LIST   =  12,   /* Build ADISC and PLOGI lists for
				         * device authentication / discovery */
	LPFC_DISC_AUTH       =  12,   /* Processing ADISC list */
	LPFC_DISC_AUTH         =  13,   /* Processing ADISC list */
	LPFC_VPORT_READY       =  32,
};

@@ -195,8 +233,9 @@ enum hba_state {
	LPFC_INIT_MBX_CMDS   =   3,   /* Initialize HBA with mbox commands */
	LPFC_LINK_DOWN       =   4,   /* HBA initialized, link is down */
	LPFC_LINK_UP         =   5,   /* Link is up  - issue READ_LA */
	LPFC_CLEAR_LA        =  13,   /* authentication cmplt - issue
	LPFC_CLEAR_LA        =   6,   /* authentication cmplt - issue
				       * CLEAR_LA */
	LPFC_HBA_READY       =  32,
	LPFC_HBA_ERROR       =  -1
};

@@ -209,6 +248,7 @@ struct lpfc_vport {
#define LPFC_FABRIC_PORT 3
	enum discovery_state port_state;

	uint16_t vpi;

	uint32_t fc_flag;	/* FC flags */
/* Several of these flags are HBA centric and should be moved to
@@ -224,11 +264,14 @@ struct lpfc_vport {
#define FC_OFFLINE_MODE         0x80	 /* Interface is offline for diag */
#define FC_FABRIC               0x100	 /* We are fabric attached */
#define FC_ESTABLISH_LINK       0x200	 /* Reestablish Link */
#define FC_RSCN_DISCOVERY       0x400	/* Authenticate all devices after RSCN*/
#define FC_RSCN_DISCOVERY       0x400	 /* Auth all devices after RSCN */
#define FC_SCSI_SCAN_TMO        0x4000	 /* scsi scan timer running */
#define FC_ABORT_DISCOVERY      0x8000	 /* we want to abort discovery */
#define FC_NDISC_ACTIVE         0x10000	 /* NPort discovery active */
#define FC_BYPASSED_MODE        0x20000	 /* NPort is in bypassed mode */
#define FC_RFF_NOT_SUPPORTED    0x40000	 /* RFF_ID was rejected by switch */
#define FC_VPORT_NEEDS_REG_VPI	0x80000  /* Needs to have its vpi registered */
#define FC_RSCN_DEFERRED	0x100000 /* A deferred RSCN being processed */

	struct list_head fc_nodes;

@@ -269,6 +312,9 @@ struct lpfc_vport {
#define WORKER_ELS_TMO                 0x2	/* ELS timeout */
#define WORKER_MBOX_TMO                0x4	/* MBOX timeout */
#define WORKER_FDMI_TMO                0x8	/* FDMI timeout */
#define WORKER_FABRIC_BLOCK_TMO        0x10	/* fabric block timout */
#define WORKER_RAMP_DOWN_QUEUE    0x20	/* Decrease Q depth */
#define WORKER_RAMP_UP_QUEUE      0x40	/* Increase Q depth */

	struct timer_list fc_fdmitmo;
	struct timer_list els_tmofunc;
@@ -278,10 +324,10 @@ struct lpfc_vport {
	uint8_t load_flag;
#define FC_LOADING		0x1	/* HBA in process of loading drvr */
#define FC_UNLOADING		0x2	/* HBA in process of unloading drvr */

	char  *vname;		        /* Application assigned name */
	struct fc_vport *fc_vport;
};


struct hbq_s {
	uint16_t entry_count;	  /* Current number of HBQ slots */
	uint32_t next_hbqPutIdx;  /* Index to next HBQ slot to use */
@@ -289,7 +335,9 @@ struct hbq_s {
	uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */
};

#define MAX_HBQS  16
#define LPFC_MAX_HBQS  16
/* this matches the possition in the lpfc_hbq_defs array */
#define LPFC_ELS_HBQ	0

struct lpfc_hba {
	struct lpfc_sli sli;
@@ -297,25 +345,28 @@ struct lpfc_hba {
	uint32_t sli3_options;		/* Mask of enabled SLI3 options */
#define LPFC_SLI3_ENABLED 	 0x01
#define LPFC_SLI3_HBQ_ENABLED	 0x02
#define LPFC_SLI3_INB_ENABLED	0x04
#define LPFC_SLI3_NPIV_ENABLED	 0x04
#define LPFC_SLI3_VPORT_TEARDOWN 0x08
	uint32_t iocb_cmd_size;
	uint32_t iocb_rsp_size;

	enum hba_state link_state;
	uint32_t link_flag;	/* link state flags */
#define LS_LOOPBACK_MODE        0x40000	/* NPort is in Loopback mode */
#define LS_LOOPBACK_MODE      0x1 	/* NPort is in Loopback mode */
					/* This flag is set while issuing */
					/* INIT_LINK mailbox command */
#define LS_IGNORE_ERATT         0x80000	/* intr handler should ignore ERATT */
#define LS_NPIV_FAB_SUPPORTED 0x2	/* Fabric supports NPIV */
#define LS_IGNORE_ERATT       0x3	/* intr handler should ignore ERATT */

	struct lpfc_sli2_slim *slim2p;
	struct lpfc_dmabuf hbqslimp;

	dma_addr_t slim2p_mapping;


	uint16_t pci_cfg_value;

	uint8_t work_found;
#define LPFC_MAX_WORKER_ITERATION  4

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

@@ -355,6 +406,8 @@ struct lpfc_hba {
	uint32_t cfg_nodev_tmo;
	uint32_t cfg_devloss_tmo;
	uint32_t cfg_hba_queue_depth;
	uint32_t cfg_peer_port_login;
	uint32_t cfg_vport_restrict_login;
	uint32_t cfg_fcp_class;
	uint32_t cfg_use_adisc;
	uint32_t cfg_ack0;
@@ -391,11 +444,9 @@ struct lpfc_hba {
	wait_queue_head_t    *work_wait;
	struct task_struct   *worker_thread;

	struct   hbq_dmabuf *hbq_buffer_pool;
	uint32_t hbq_buffer_count;
	uint32_t hbq_buff_count; 	/* Current hbq buffers */
	struct list_head hbq_buffer_list;
	uint32_t hbq_count;	        /* Count of configured HBQs */
	struct hbq_s hbqs[MAX_HBQS];    /* local copy of hbq indicies  */
	struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies  */

	unsigned long pci_bar0_map;     /* Physical address for PCI BAR0 */
	unsigned long pci_bar2_map;     /* Physical address for PCI BAR2 */
@@ -413,7 +464,7 @@ struct lpfc_hba {

	struct lpfc_hgp __iomem *host_gp; /* Host side get/put pointers */
	uint32_t __iomem  *hbq_put;     /* Address in SLIM to HBQ put ptrs */
	uint32_t __iomem  *hbq_get;     /* Address in SLIM to HBQ get ptrs */
	uint32_t          *hbq_get;     /* Host mem address of HBQ get ptrs */

	int brd_no;			/* FC board number */

@@ -464,6 +515,22 @@ struct lpfc_hba {
	struct fc_host_statistics link_stats;
	struct list_head port_list;
	struct lpfc_vport *pport; /* physical lpfc_vport pointer */
	uint16_t max_vpi;	/* Maximum virtual nports */
	uint16_t vpi_cnt;	/* Nport count */
#define LPFC_MAX_VPI 100  /* Max number of VPorts supported */
	unsigned long *vpi_bmask; /* vpi allocation table */

	/* Data structure used by fabric iocb scheduler */
	struct list_head fabric_iocb_list;
	atomic_t fabric_iocb_count;
	struct timer_list fabric_block_timer;
	unsigned long bit_flags;
#define	FABRIC_COMANDS_BLOCKED	0
	atomic_t num_rsrc_err;
	atomic_t num_cmd_success;
	unsigned long last_rsrc_error_time;
	unsigned long last_ramp_down_time;
	unsigned long last_ramp_up_time;
};

static inline struct Scsi_Host *
@@ -485,10 +552,9 @@ static inline int
lpfc_is_link_up(struct lpfc_hba *phba)
{
	return  phba->link_state == LPFC_LINK_UP ||
		phba->link_state == LPFC_CLEAR_LA;
		phba->link_state == LPFC_CLEAR_LA ||
		phba->link_state == LPFC_HBA_READY;
}



#define FC_REG_DUMP_EVENT	0x10	/* Register for Dump events */
+295 −13
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include "lpfc_version.h"
#include "lpfc_compat.h"
#include "lpfc_crtn.h"
#include "lpfc_vport.h"

#define LPFC_DEF_DEVLOSS_TMO 30
#define LPFC_MIN_DEVLOSS_TMO 1
@@ -139,7 +140,7 @@ lpfc_fwrev_show(struct class_device *cdev, char *buf)
	char fwrev[32];

	lpfc_decode_firmware_rev(phba, fwrev, 1);
	return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
	return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
}

static ssize_t
@@ -178,10 +179,11 @@ lpfc_state_show(struct class_device *cdev, char *buf)
	case LPFC_INIT_MBX_CMDS:
	case LPFC_LINK_DOWN:
	case LPFC_HBA_ERROR:
		len += snprintf(buf + len, PAGE_SIZE-len, "Link Down");
		len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
		break;
	case LPFC_LINK_UP:
	case LPFC_CLEAR_LA:
	case LPFC_HBA_READY:
		len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");

		switch (vport->port_state) {
@@ -190,8 +192,9 @@ lpfc_state_show(struct class_device *cdev, char *buf)
			break;
		case LPFC_LOCAL_CFG_LINK:
			len += snprintf(buf + len, PAGE_SIZE-len,
					"configuring\n");
					"Configuring Link\n");
			break;
		case LPFC_FDISC:
		case LPFC_FLOGI:
		case LPFC_FABRIC_CFG_LINK:
		case LPFC_NS_REG:
@@ -205,7 +208,11 @@ lpfc_state_show(struct class_device *cdev, char *buf)
			len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
			break;

		case LPFC_STATE_UNKNOWN:
		case LPFC_VPORT_FAILED:
			len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n");
			break;

		case LPFC_VPORT_UNKNOWN:
			len += snprintf(buf + len, PAGE_SIZE - len,
					"Unknown\n");
			break;
@@ -432,6 +439,151 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
		return -EIO;
}

static ssize_t
lpfc_max_vpi_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;

	return snprintf(buf, PAGE_SIZE, "%d\n", phba->max_vpi);
}

static ssize_t
lpfc_used_vpi_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;

	/* Don't count the physical port */
	return snprintf(buf, PAGE_SIZE, "%d\n", phba->vpi_cnt-1);
}

int
lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri,
	uint32_t *axri, uint32_t *mrpi, uint32_t *arpi)
{
	struct lpfc_sli   *psli = &phba->sli;
	LPFC_MBOXQ_t *pmboxq;
	MAILBOX_t *pmb;
	int rc = 0;

	/*
	 * prevent udev from issuing mailbox commands until the port is
	 * configured.
	 */
	if (phba->link_state < LPFC_LINK_DOWN ||
	    !phba->mbox_mem_pool ||
	    (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
		return 0;

	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
		return 0;

	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
	if (!pmboxq)
		return 0;
	memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));

	pmb = &pmboxq->mb;
	pmb->mbxCommand = MBX_READ_CONFIG;
	pmb->mbxOwner = OWN_HOST;
	pmboxq->context1 = NULL;

	if ((phba->pport->fc_flag & FC_OFFLINE_MODE) ||
		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
		rc = MBX_NOT_FINISHED;
	else
		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);

	if (rc != MBX_SUCCESS) {
		if (rc == MBX_TIMEOUT)
			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
		else
			mempool_free(pmboxq, phba->mbox_mem_pool);
		return 0;
	}

	if (mrpi)
		*mrpi = pmb->un.varRdConfig.max_rpi;
	if (arpi)
		*arpi = pmb->un.varRdConfig.avail_rpi;
	if (mxri)
		*mxri = pmb->un.varRdConfig.max_xri;
	if (axri)
		*axri = pmb->un.varRdConfig.avail_xri;

	mempool_free(pmboxq, phba->mbox_mem_pool);
	return 1;
}

static ssize_t
lpfc_max_rpi_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;
	uint32_t cnt;

	if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL))
		return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
	return snprintf(buf, PAGE_SIZE, "Unknown\n");
}

static ssize_t
lpfc_used_rpi_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;
	uint32_t cnt, acnt;

	if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt))
		return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
	return snprintf(buf, PAGE_SIZE, "Unknown\n");
}

static ssize_t
lpfc_max_xri_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;
	uint32_t cnt;

	if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL))
		return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
	return snprintf(buf, PAGE_SIZE, "Unknown\n");
}

static ssize_t
lpfc_used_xri_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;
	uint32_t cnt, acnt;

	if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL))
		return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
	return snprintf(buf, PAGE_SIZE, "Unknown\n");
}

static ssize_t
lpfc_npiv_info_show(struct class_device *cdev, char *buf)
{
	struct Scsi_Host  *shost = class_to_shost(cdev);
	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
	struct lpfc_hba   *phba = vport->phba;

	if (!(phba->max_vpi))
		return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
	if (vport->port_type == LPFC_PHYSICAL_PORT)
		return snprintf(buf, PAGE_SIZE, "NPIV Physical\n");
	return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
}

static ssize_t
lpfc_poll_show(struct class_device *cdev, char *buf)
{
@@ -640,6 +792,13 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
			 lpfc_board_mode_show, lpfc_board_mode_store);
static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);


static char *lpfc_soft_wwn_key = "C99G71SL8032A";
@@ -829,6 +988,17 @@ 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);

int  lpfc_sli_mode = 0;
module_param(lpfc_sli_mode, int, 0);
MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
		 " 0 - auto (SLI-3 if supported),"
		 " 2 - select SLI-2 even on SLI-3 capable HBAs,"
		 " 3 - select SLI-3");

int  lpfc_npiv_enable = 0;
module_param(lpfc_npiv_enable, int, 0);
MODULE_PARM_DESC(lpfc_npiv_enable, "Enable NPIV functionality");

/*
# 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.
@@ -984,6 +1154,33 @@ LPFC_ATTR_R(lun_queue_depth, 30, 1, 128,
LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,
	    "Max number of FCP commands we can queue to a lpfc HBA");

/*
# peer_port_login:  This parameter allows/prevents logins
# between peer ports hosted on the same physical port.
# When this parameter is set 0 peer ports of same physical port
# are not allowed to login to each other.
# When this parameter is set 1 peer ports of same physical port
# are allowed to login to each other.
# Default value of this parameter is 0.
*/
LPFC_ATTR_R(peer_port_login, 0, 0, 1,
	    "Allow peer ports on the same physical port to login to each "
	    "other.");

/*
# vport_restrict_login:  This parameter allows/prevents logins
# between Virtual Ports and remote initiators.
# When this parameter is not set (0) Virtual Ports will accept PLOGIs from
# other initiators and will attempt to PLOGI all remote ports.
# When this parameter is set (1) Virtual Ports will reject PLOGIs from
# remote ports and will not attempt to PLOGI to other initiators.
# This parameter does not restrict to the physical port.
# This parameter does not restrict logins to Fabric resident remote ports.
# Default value of this parameter is 1.
*/
LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1,
	    "Restrict virtual ports login to remote initiators.");

/*
# Some disk devices have a "select ID" or "select Target" capability.
# From a protocol standpoint "select ID" usually means select the
@@ -1127,6 +1324,7 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");



struct class_device_attribute *lpfc_hba_attrs[] = {
	&class_device_attr_info,
	&class_device_attr_serialnum,
@@ -1143,6 +1341,8 @@ struct class_device_attribute *lpfc_hba_attrs[] = {
	&class_device_attr_lpfc_log_verbose,
	&class_device_attr_lpfc_lun_queue_depth,
	&class_device_attr_lpfc_hba_queue_depth,
	&class_device_attr_lpfc_peer_port_login,
	&class_device_attr_lpfc_vport_restrict_login,
	&class_device_attr_lpfc_nodev_tmo,
	&class_device_attr_lpfc_devloss_tmo,
	&class_device_attr_lpfc_fcp_class,
@@ -1161,6 +1361,13 @@ struct class_device_attribute *lpfc_hba_attrs[] = {
	&class_device_attr_nport_evt_cnt,
	&class_device_attr_management_version,
	&class_device_attr_board_mode,
	&class_device_attr_max_vpi,
	&class_device_attr_used_vpi,
	&class_device_attr_max_rpi,
	&class_device_attr_used_rpi,
	&class_device_attr_max_xri,
	&class_device_attr_used_xri,
	&class_device_attr_npiv_info,
	&class_device_attr_issue_reset,
	&class_device_attr_lpfc_poll,
	&class_device_attr_lpfc_poll_tmo,
@@ -1406,6 +1613,8 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
			return -EPERM;
		}

		phba->sysfs_mbox.mbox->vport = vport;

		if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
			sysfs_mbox_idle(phba);
			spin_unlock_irq(&phba->hbalock);
@@ -1527,7 +1736,9 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)

	spin_lock_irq(shost->host_lock);

	if (lpfc_is_link_up(phba)) {
	if (vport->port_type == LPFC_NPIV_PORT) {
		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
	} else if (lpfc_is_link_up(phba)) {
		if (phba->fc_topology == TOPOLOGY_LOOP) {
			if (vport->fc_flag & FC_PUBLIC_LOOP)
				fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
@@ -1563,6 +1774,7 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
			break;
		case LPFC_LINK_UP:
		case LPFC_CLEAR_LA:
		case LPFC_HBA_READY:
			/* Links up, beyond this port_type reports state */
			fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
			break;
@@ -1644,8 +1856,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
	unsigned long seconds;
	int rc = 0;

				/* prevent udev from issuing mailbox commands
				 * until the port is configured.
	/*
	 * prevent udev from issuing mailbox commands until the port is
	 * configured.
	 */
	if (phba->link_state < LPFC_LINK_DOWN ||
	    !phba->mbox_mem_pool ||
@@ -1664,6 +1877,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
	pmb->mbxCommand = MBX_READ_STATUS;
	pmb->mbxOwner = OWN_HOST;
	pmboxq->context1 = NULL;
	pmboxq->vport = vport;

	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
@@ -1690,6 +1904,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
	pmb->mbxCommand = MBX_READ_LNK_STAT;
	pmb->mbxOwner = OWN_HOST;
	pmboxq->context1 = NULL;
	pmboxq->vport = vport;

	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
@@ -1769,6 +1984,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
	pmb->mbxOwner = OWN_HOST;
	pmb->un.varWords[0] = 0x1; /* reset request */
	pmboxq->context1 = NULL;
	pmboxq->vport = vport;

	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
@@ -1788,6 +2004,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
	pmb->mbxCommand = MBX_READ_LNK_STAT;
	pmb->mbxOwner = OWN_HOST;
	pmboxq->context1 = NULL;
	pmboxq->vport = vport;

	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
@@ -1950,6 +2167,69 @@ struct fc_function_template lpfc_transport_functions = {
	.issue_fc_host_lip = lpfc_issue_lip,
	.dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
	.terminate_rport_io = lpfc_terminate_rport_io,

	.vport_create = lpfc_vport_create,
	.vport_delete = lpfc_vport_delete,
	.dd_fcvport_size = sizeof(struct lpfc_vport *),
};

struct fc_function_template lpfc_vport_transport_functions = {
	/* fixed attributes the driver supports */
	.show_host_node_name = 1,
	.show_host_port_name = 1,
	.show_host_supported_classes = 1,
	.show_host_supported_fc4s = 1,
	.show_host_supported_speeds = 1,
	.show_host_maxframe_size = 1,

	/* dynamic attributes the driver supports */
	.get_host_port_id = lpfc_get_host_port_id,
	.show_host_port_id = 1,

	.get_host_port_type = lpfc_get_host_port_type,
	.show_host_port_type = 1,

	.get_host_port_state = lpfc_get_host_port_state,
	.show_host_port_state = 1,

	/* active_fc4s is shown but doesn't change (thus no get function) */
	.show_host_active_fc4s = 1,

	.get_host_speed = lpfc_get_host_speed,
	.show_host_speed = 1,

	.get_host_fabric_name = lpfc_get_host_fabric_name,
	.show_host_fabric_name = 1,

	/*
	 * The LPFC driver treats linkdown handling as target loss events
	 * so there are no sysfs handlers for link_down_tmo.
	 */

	.get_fc_host_stats = lpfc_get_stats,
	.reset_fc_host_stats = lpfc_reset_stats,

	.dd_fcrport_size = sizeof(struct lpfc_rport_data),
	.show_rport_maxframe_size = 1,
	.show_rport_supported_classes = 1,

	.set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
	.show_rport_dev_loss_tmo = 1,

	.get_starget_port_id  = lpfc_get_starget_port_id,
	.show_starget_port_id = 1,

	.get_starget_node_name = lpfc_get_starget_node_name,
	.show_starget_node_name = 1,

	.get_starget_port_name = lpfc_get_starget_port_name,
	.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,

	.vport_disable = lpfc_vport_disable,
};

void
@@ -1972,6 +2252,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
	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_peer_port_login_init(phba, lpfc_peer_port_login);
	lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login);
	lpfc_use_msi_init(phba, lpfc_use_msi);
	lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
	lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
Loading