* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $"
-
#include "zfcp_ext.h"
static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *);
zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
struct fsf_link_down_info *link_down)
{
+ if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status))
+ return;
+
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
+
+ if (link_down == NULL) {
+ zfcp_erp_adapter_reopen(adapter, 0);
+ return;
+ }
+
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
ZFCP_LOG_NORMAL("The local link to adapter %s is down "
link_down->explanation_code,
link_down->vendor_specific_code);
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status)) {
- atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status);
- switch (link_down->error_code) {
- case FSF_PSQ_LINK_NO_LIGHT:
- case FSF_PSQ_LINK_WRAP_PLUG:
- case FSF_PSQ_LINK_NO_FCP:
- case FSF_PSQ_LINK_FIRMWARE_UPDATE:
- zfcp_erp_adapter_reopen(adapter, 0);
- break;
- default:
- zfcp_erp_adapter_failed(adapter);
- }
+ switch (link_down->error_code) {
+ case FSF_PSQ_LINK_NO_LIGHT:
+ case FSF_PSQ_LINK_WRAP_PLUG:
+ case FSF_PSQ_LINK_NO_FCP:
+ case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+ zfcp_erp_adapter_reopen(adapter, 0);
+ break;
+ default:
+ zfcp_erp_adapter_failed(adapter);
}
}
case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter,
+ (struct fsf_link_down_info *)
+ &status_buffer->payload);
break;
case FSF_STATUS_READ_SUB_FDISC_FAILED:
ZFCP_LOG_INFO("Local link to adapter %s is down "
"due to failed FDISC login\n",
- zfcp_get_busid_by_adapter(adapter));
+ zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter,
+ (struct fsf_link_down_info *)
+ &status_buffer->payload);
break;
case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
ZFCP_LOG_INFO("Local link to adapter %s is down "
"due to firmware update on adapter\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter, NULL);
break;
default:
ZFCP_LOG_INFO("Local link to adapter %s is down "
"due to unknown reason\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter, NULL);
};
- zfcp_fsf_link_down_info_eval(adapter,
- (struct fsf_link_down_info *) &status_buffer->payload);
break;
case FSF_STATUS_READ_LINK_UP:
ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. "
- "Restarting operations on this adapter\n",
- zfcp_get_busid_by_adapter(adapter));
+ "Restarting operations on this adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
/* All ports should be marked as ready to run again */
zfcp_erp_modify_adapter_status(adapter,
ZFCP_STATUS_COMMON_RUNNING,
| ZFCP_STATUS_COMMON_ERP_FAILED);
break;
+ case FSF_STATUS_READ_NOTIFICATION_LOST:
+ ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "
+ "adapter %s%s%s%s%s%s%s%s%s\n",
+ zfcp_get_busid_by_adapter(adapter),
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_INCOMING_ELS) ?
+ ", incoming ELS" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_SENSE_DATA) ?
+ ", sense data" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_LINK_STATUS) ?
+ ", link status change" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_PORT_CLOSED) ?
+ ", port close" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?
+ ", bit error exception" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED) ?
+ ", ACT update" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_HARDENED) ?
+ ", ACT hardening" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?
+ ", adapter feature change" : "");
+
+ if (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED)
+ zfcp_erp_adapter_access_changed(adapter);
+ break;
+
case FSF_STATUS_READ_CFDC_UPDATED:
ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
erp_action->fsf_req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_CFDC |
FSF_FEATURE_LUN_SHARING |
+ FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
/* start QDIO request for this FSF request */
fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
fc_host_speed(shost) = bottom->fc_link_speed;
fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
- adapter->fc_topology = bottom->fc_topology;
adapter->hydra_version = bottom->adapter_type;
- if (adapter->physical_wwpn == 0)
- adapter->physical_wwpn = fc_host_port_name(shost);
- if (adapter->physical_s_id == 0)
- adapter->physical_s_id = fc_host_port_id(shost);
+ if (fc_host_permanent_port_name(shost) == -1)
+ fc_host_permanent_port_name(shost) =
+ fc_host_port_name(shost);
+ if (bottom->fc_topology == FSF_TOPO_P2P) {
+ adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
+ adapter->peer_wwpn = bottom->plogi_payload.wwpn;
+ adapter->peer_wwnn = bottom->plogi_payload.wwnn;
+ fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+ } else if (bottom->fc_topology == FSF_TOPO_FABRIC)
+ fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+ else if (bottom->fc_topology == FSF_TOPO_AL)
+ fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+ else
+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
} else {
fc_host_node_name(shost) = 0;
fc_host_port_name(shost) = 0;
fc_host_port_id(shost) = 0;
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
- adapter->fc_topology = 0;
+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
adapter->hydra_version = 0;
}
- if (adapter->fc_topology == FSF_TOPO_P2P) {
- adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
- adapter->peer_wwpn = bottom->plogi_payload.wwpn;
- adapter->peer_wwnn = bottom->plogi_payload.wwnn;
- }
-
if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
adapter->hardware_version = bottom->hardware_version;
memcpy(fc_host_serial_number(shost), bottom->serial_number,
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
return -EIO;
- switch (adapter->fc_topology) {
- case FSF_TOPO_P2P:
+ switch (fc_host_port_type(adapter->scsi_host)) {
+ case FC_PORTTYPE_PTP:
ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
"configuration detected at adapter %s\n"
"Peer WWNN 0x%016llx, "
debug_text_event(fsf_req->adapter->erp_dbf, 0,
"top-p-to-p");
break;
- case FSF_TOPO_AL:
+ case FC_PORTTYPE_NLPORT:
ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
"topology detected at adapter %s "
"unsupported, shutting down adapter\n",
"top-al");
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
- case FSF_TOPO_FABRIC:
+ case FC_PORTTYPE_NPORT:
ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
"network detected at adapter %s.\n",
zfcp_get_busid_by_adapter(adapter));
"of a type known to the zfcp "
"driver, shutting down adapter\n",
zfcp_get_busid_by_adapter(adapter));
- adapter->fc_topology = FSF_TOPO_ERROR;
debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"unknown-topo");
zfcp_erp_adapter_shutdown(adapter, 0);
return -EOPNOTSUPP;
}
- timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
- if (!timer)
- return -ENOMEM;
-
/* setup new FSF request */
retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
- 0, 0, &lock_flags, &fsf_req);
+ erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0,
+ 0, &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Out of resources. Could not create an "
"exchange port data request for"
zfcp_get_busid_by_adapter(adapter));
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
- goto out;
- }
-
- if (erp_action) {
- erp_action->fsf_req = fsf_req;
- fsf_req->erp_action = erp_action;
+ return retval;
}
if (data)
- fsf_req->data = (unsigned long) data;
+ fsf_req->data = (unsigned long) data;
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+ if (erp_action) {
+ erp_action->fsf_req = fsf_req;
+ fsf_req->erp_action = erp_action;
+ timer = &erp_action->timer;
+ } else {
+ timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
+ if (!timer) {
+ write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+ lock_flags);
+ zfcp_fsf_req_free(fsf_req);
+ return -ENOMEM;
+ }
+ init_timer(timer);
+ timer->function = zfcp_fsf_request_timeout_handler;
+ timer->data = (unsigned long) adapter;
+ timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+ }
retval = zfcp_fsf_req_send(fsf_req, timer);
if (retval) {
zfcp_fsf_req_free(fsf_req);
if (erp_action)
erp_action->fsf_req = NULL;
+ else
+ kfree(timer);
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
- goto out;
+ return retval;
}
- ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n",
- zfcp_get_busid_by_adapter(adapter));
-
- write_unlock_irqrestore(&adapter->request_queue.queue_lock,
- lock_flags);
+ write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
- wait_event(fsf_req->completion_wq,
- fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- del_timer_sync(timer);
- zfcp_fsf_req_free(fsf_req);
- out:
- kfree(timer);
+ if (!erp_action) {
+ wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ del_timer_sync(timer);
+ zfcp_fsf_req_free(fsf_req);
+ kfree(timer);
+ }
return retval;
}
data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
if (data)
memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
- adapter->physical_wwpn = bottom->wwpn;
- adapter->physical_s_id = bottom->fc_port_id;
- } else {
- adapter->physical_wwpn = fc_host_port_name(shost);
- adapter->physical_s_id = fc_host_port_id(shost);
- }
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ fc_host_permanent_port_name(shost) = bottom->wwpn;
+ else
+ fc_host_permanent_port_name(shost) =
+ fc_host_port_name(shost);
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ fc_host_supported_speeds(shost) = bottom->supported_speed;
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: