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

[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
......@@ -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);
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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 *);
......
This diff is collapsed.
......@@ -140,9 +140,18 @@
#define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004
/* FSF status qualifier (most significant 4 bytes), local link down */
#define FSF_PSQ_LINK_NOLIGHT 0x00000004
#define FSF_PSQ_LINK_WRAPPLUG 0x00000008
#define FSF_PSQ_LINK_NOFCP 0x00000010
#define FSF_PSQ_LINK_NO_LIGHT 0x00000004
#define FSF_PSQ_LINK_WRAP_PLUG 0x00000008
#define FSF_PSQ_LINK_NO_FCP 0x00000010
#define FSF_PSQ_LINK_FIRMWARE_UPDATE 0x00000020
#define FSF_PSQ_LINK_INVALID_WWPN 0x00000100
#define FSF_PSQ_LINK_NO_NPIV_SUPPORT 0x00000200
#define FSF_PSQ_LINK_NO_FCP_RESOURCES 0x00000400
#define FSF_PSQ_LINK_NO_FABRIC_RESOURCES 0x00000800
#define FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE 0x00001000
#define FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED 0x00002000
#define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED 0x00004000
#define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT 0x00008000
/* payload size in status read buffer */
#define FSF_STATUS_READ_PAYLOAD_SIZE 4032
......@@ -155,15 +164,21 @@
#define FSF_STATUS_READ_INCOMING_ELS 0x00000002
#define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003
#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004
#define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */
#define FSF_STATUS_READ_LINK_DOWN 0x00000005
#define FSF_STATUS_READ_LINK_UP 0x00000006
#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C
/* status subtypes in status read buffer */
#define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001
#define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002
/* status subtypes for link down */
#define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000
#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001
#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002
/* status subtypes for CFDC */
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
......@@ -194,11 +209,15 @@
#define FSF_QTCB_LOG_SIZE 1024
/* channel features */
#define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001
#define FSF_FEATURE_CFDC 0x00000002
#define FSF_FEATURE_LUN_SHARING 0x00000004
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
/* host connection features */
#define FSF_FEATURE_NPIV_MODE 0x00000001
#define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002
/* option */
#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001
......@@ -306,16 +325,23 @@ struct fsf_qual_sequence_error {
u32 res1[3];
} __attribute__ ((packed));
struct fsf_qual_locallink_error {
u32 code;
u32 res1[3];
struct fsf_link_down_info {
u32 error_code;
u32 res1;
u8 res2[2];
u8 primary_status;
u8 ioerr_code;
u8 action_code;
u8 reason_code;
u8 explanation_code;
u8 vendor_specific_code;
} __attribute__ ((packed));
union fsf_prot_status_qual {
u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)];
struct fsf_qual_version_error version_error;
struct fsf_qual_sequence_error sequence_error;
struct fsf_qual_locallink_error locallink_error;
struct fsf_link_down_info link_down_info;
} __attribute__ ((packed));
struct fsf_qtcb_prefix {
......@@ -335,6 +361,7 @@ union fsf_status_qual {
u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)];
u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)];
struct fsf_queue_designator fsf_queue_designator;
struct fsf_link_down_info link_down_info;
} __attribute__ ((packed));
struct fsf_qtcb_header {
......@@ -409,8 +436,8 @@ struct fsf_qtcb_bottom_config {
u32 low_qtcb_version;
u32 max_qtcb_size;
u32 max_data_transfer_size;
u32 supported_features;
u8 res1[4];
u32 adapter_features;
u32 connection_features;
u32 fc_topology;
u32 fc_link_speed;
u32 adapter_type;
......@@ -428,7 +455,7 @@ struct fsf_qtcb_bottom_config {
} __attribute__ ((packed));
struct fsf_qtcb_bottom_port {
u8 res1[8];
u64 wwpn;
u32 fc_port_id;
u32 port_type;
u32 port_state;
......
......@@ -68,6 +68,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed);
......@@ -261,6 +263,8 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_peer_wwnn.attr,
&dev_attr_peer_wwpn.attr,
&dev_attr_peer_d_id.attr,
&dev_attr_physical_wwpn.attr,
&dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.attr,
&dev_attr_fc_link_speed.attr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment