Skip to content

Commit

Permalink
[SCSI] zfcp: provide support for NPIV
Browse files Browse the repository at this point in the history
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: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Maxim Shchetynin authored and James Bottomley committed Sep 19, 2005
1 parent 8a36e45 commit aef4a98
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 140 deletions.
11 changes: 10 additions & 1 deletion drivers/s390/scsi/zfcp_dbf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 11 additions & 2 deletions drivers/s390/scsi/zfcp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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 | \
Expand Down Expand Up @@ -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 */
Expand Down
95 changes: 87 additions & 8 deletions drivers/s390/scsi/zfcp_erp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down Expand Up @@ -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;

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;
}

/* do 'exchange configuration data' */
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
if (retval == ZFCP_ERP_FAILED)
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;

/* start the desired number of Status Reads */
retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
return retval;
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}

/*
Expand Down Expand Up @@ -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:
*
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion drivers/s390/scsi/zfcp_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
Loading

0 comments on commit aef4a98

Please sign in to comment.