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

Commit aef4a983 authored by Maxim Shchetynin's avatar Maxim Shchetynin Committed by James Bottomley
Browse files

[SCSI] zfcp: provide support for NPIV



N_Port ID Virtualization (NPIV) allows a single FCP port to appear as
multiple, distinct ports providing separate port identification. NPIV
is supported by FC HBAs on System z9. zfcp was adapted to support this
new feature.

Signed-off-by: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 8a36e453
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -279,9 +279,18 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
			break;

		case FSF_STATUS_READ_LINK_DOWN:
			rec->type.status.payload_size = sizeof(u64);
			switch (status_buffer->status_subtype) {
			case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
			case FSF_STATUS_READ_SUB_FDISC_FAILED:
				rec->type.status.payload_size =
					sizeof(struct fsf_link_down_info);
			}
			break;

		case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
			rec->type.status.payload_size =
			    ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
			break;
		}
		memcpy(&rec->type.status.payload,
		       &status_buffer->payload, rec->type.status.payload_size);
+11 −2
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@
/********************* GENERAL DEFINES *********************************/

/* zfcp version number, it consists of major, minor, and patch-level number */
#define ZFCP_VERSION		"4.4.0"
#define ZFCP_VERSION		"4.5.0"

/**
 * zfcp_sg_to_address - determine kernel address from struct scatterlist
@@ -154,6 +154,11 @@ typedef u32 scsi_lun_t;
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP	100
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES	7

/* Retry 5 times every 2 second, then every minute */
#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES	5
#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP	200
#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP	6000

/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);

@@ -638,6 +643,7 @@ do { \
#define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL	0x00000080
#define ZFCP_STATUS_ADAPTER_ERP_PENDING		0x00000100
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED	0x00000200
#define ZFCP_STATUS_ADAPTER_XPORT_OK		0x00000800

#define ZFCP_STATUS_ADAPTER_SCSI_UP			\
		(ZFCP_STATUS_COMMON_UNBLOCKED |	\
@@ -915,13 +921,16 @@ struct zfcp_adapter {
	wwn_t			peer_wwnn;	   /* P2P peer WWNN */
	wwn_t			peer_wwpn;	   /* P2P peer WWPN */
	fc_id_t			peer_d_id;	   /* P2P peer D_ID */
	wwn_t			physical_wwpn;     /* WWPN of physical port */
	fc_id_t			physical_s_id;     /* local FC port ID */
	struct ccw_device       *ccw_device;	   /* S/390 ccw device */
	u8			fc_service_class;
	u32			fc_topology;	   /* FC topology */
	u32			fc_link_speed;	   /* FC interface speed */
	u32			hydra_version;	   /* Hydra version */
	u32			fsf_lic_version;
        u32			supported_features;/* of FCP channel */
	u32			adapter_features;  /* FCP channel features */
	u32			connection_features; /* host connection features */
        u32			hardware_version;  /* of FCP channel */
        u8			serial_number[32]; /* of hardware */
	struct Scsi_Host	*scsi_host;	   /* Pointer to mid-layer */
+87 −8
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf_statusread(
	struct zfcp_erp_action *);

@@ -2258,16 +2259,21 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
static int
zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
	int retval;
	int xconfig, xport;

	/* do 'exchange configuration data' */
	retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
	if (retval == ZFCP_ERP_FAILED)
		return retval;
	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
			     &erp_action->adapter->status)) {
		zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
		atomic_set(&erp_action->adapter->erp_counter, 0);
		return ZFCP_ERP_FAILED;
	}

	/* start the desired number of Status Reads */
	retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
	return retval;
	xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
	xport   = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
	if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED))
		return ZFCP_ERP_FAILED;

	return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}

/*
@@ -2350,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
	return retval;
}

static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{
	int retval = ZFCP_ERP_SUCCEEDED;
	int retries;
	int sleep;
	struct zfcp_adapter *adapter = erp_action->adapter;

	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);

	for (retries = 0; ; retries++) {
		ZFCP_LOG_DEBUG("Doing exchange port data\n");
		zfcp_erp_action_to_running(erp_action);
		zfcp_erp_timeout_init(erp_action);
		if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) {
			retval = ZFCP_ERP_FAILED;
			debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
			ZFCP_LOG_INFO("error: initiation of exchange of "
				      "port data failed for adapter %s\n",
				      zfcp_get_busid_by_adapter(adapter));
			break;
		}
		debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
		ZFCP_LOG_DEBUG("Xchange underway\n");

		/*
		 * Why this works:
		 * Both the normal completion handler as well as the timeout
		 * handler will do an 'up' when the 'exchange port data'
		 * request completes or times out. Thus, the signal to go on
		 * won't be lost utilizing this semaphore.
		 * Furthermore, this 'adapter_reopen' action is
		 * guaranteed to be the only action being there (highest action
		 * which prevents other actions from being created).
		 * Resulting from that, the wake signal recognized here
		 * _must_ be the one belonging to the 'exchange port
		 * data' request.
		 */
		down(&adapter->erp_ready_sem);
		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
			ZFCP_LOG_INFO("error: exchange of port data "
				      "for adapter %s timed out\n",
				      zfcp_get_busid_by_adapter(adapter));
			break;
		}

		if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
				      &adapter->status))
			break;

		ZFCP_LOG_DEBUG("host connection still initialising... "
			       "waiting and retrying...\n");
		/* sleep a little bit before retry */
		sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ?
				ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP :
				ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
		msleep(jiffies_to_msecs(sleep));
	}

	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
			     &adapter->status)) {
		ZFCP_LOG_INFO("error: exchange of port data for "
			      "adapter %s failed\n",
			      zfcp_get_busid_by_adapter(adapter));
		retval = ZFCP_ERP_FAILED;
	}

	return retval;
}

/*
 * function:	
 *
@@ -3599,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
	struct zfcp_port *port;
	unsigned long flags;

	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
		return;

	debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
	debug_event(adapter->erp_dbf, 3, &adapter->name, 8);

+2 −1
Original line number Diff line number Diff line
@@ -96,7 +96,8 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
extern int  zfcp_fsf_close_unit(struct zfcp_erp_action *);

extern int  zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
extern int  zfcp_fsf_exchange_port_data(struct zfcp_adapter *,
extern int  zfcp_fsf_exchange_port_data(struct zfcp_erp_action *,
					struct zfcp_adapter *,
					struct fsf_qtcb_bottom_port *);
extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
				  u32, u32, struct zfcp_sg_list *);
+214 −116

File changed.

Preview size limit exceeded, changes collapsed.

Loading