* Wolfgang Taphorn
* Stefan Bader <stefan.bader@de.ibm.com>
* Heiko Carstens <heiko.carstens@de.ibm.com>
+ * Andreas Herrmann <aherrman@de.ibm.com>
+ * Volker Sameske <sameske@de.ibm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_FSF_C_REVISION "$Revision: 1.65 $"
+#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $"
#include "zfcp_ext.h"
zfcp_fsf_exchange_config_data_handler(fsf_req);
break;
- case FSF_QTCB_EXCHANGE_PORT_DATA :
+ case FSF_QTCB_EXCHANGE_PORT_DATA:
ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_PORT_DATA\n");
zfcp_fsf_exchange_port_data_handler(fsf_req);
break;
- case FSF_QTCB_SEND_ELS :
+ case FSF_QTCB_SEND_ELS:
ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n");
zfcp_fsf_send_els_handler(fsf_req);
break;
zfcp_fsf_incoming_els(fsf_req);
break;
+ case FSF_STATUS_READ_SENSE_DATA_AVAIL:
+ ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_SENSE_DATA_AVAIL\n");
+ debug_text_event(adapter->erp_dbf, 3, "unsol_sense:");
+ ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer,
+ sizeof(struct fsf_status_read_buffer));
+ break;
+
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_BIT_ERROR_THRESHOLD\n");
debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:");
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
| ZFCP_STATUS_COMMON_ERP_FAILED);
-
break;
case FSF_STATUS_READ_CFDC_UPDATED:
debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_erp_adapter_access_changed(adapter);
break;
case FSF_STATUS_READ_CFDC_HARDENED:
| ZFCP_STATUS_FSFREQ_RETRY;
break;
+ case FSF_LUN_BOXED:
+ ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
+ ZFCP_LOG_INFO(
+ "unit 0x%016Lx on port 0x%016Lx on adapter %s needs "
+ "to be reopened\n",
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+ debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
+ zfcp_erp_unit_reopen(unit, 0);
+ zfcp_cmd_dbf_event_fsf("unitbox", new_fsf_req,
+ &new_fsf_req->qtcb->header.fsf_status_qual,
+ sizeof(union fsf_status_qual));
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ | ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+
case FSF_ADAPTER_STATUS_AVAILABLE:
/* 2 */
ZFCP_LOG_FLAGS(0, "FSF_ADAPTER_STATUS_AVAILABLE\n");
header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support;
- if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
- /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
goto skip_fsfstatus;
- }
/* evaluate FSF status in QTCB */
switch (header->fsf_status) {
- case FSF_GOOD :
+ case FSF_GOOD:
ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
retval = 0;
break;
- case FSF_SERVICE_CLASS_NOT_SUPPORTED :
+ case FSF_SERVICE_CLASS_NOT_SUPPORTED:
ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
if (adapter->fc_service_class <= 3) {
ZFCP_LOG_INFO("error: adapter %s does not support fc "
}
/* stop operation for this adapter */
debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
- zfcp_erp_adapter_shutdown(port->adapter, 0);
+ zfcp_erp_adapter_shutdown(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
- case FSF_ADAPTER_STATUS_AVAILABLE :
+ case FSF_ADAPTER_STATUS_AVAILABLE:
ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]){
- case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE :
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* reopening link to port */
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
zfcp_test_link(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
- case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED :
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
case FSF_ACCESS_DENIED:
ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
- ZFCP_LOG_NORMAL("Access denied, cannot send generic command "
- "to port 0x%016Lx on adapter %s\n", port->wwpn,
- zfcp_get_busid_by_port(port));
+ ZFCP_LOG_NORMAL("access denied, cannot send generic service "
+ "command (adapter %s, port d_id=0x%08x)\n",
+ zfcp_get_busid_by_port(port), port->d_id);
for (counter = 0; counter < 2; counter++) {
subtable = header->fsf_status_qual.halfword[counter * 2];
rule = header->fsf_status_qual.halfword[counter * 2 + 1];
break;
}
}
- debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+ debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+ zfcp_erp_port_access_denied(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
- case FSF_GENERIC_COMMAND_REJECTED :
+ case FSF_GENERIC_COMMAND_REJECTED:
ZFCP_LOG_FLAGS(2, "FSF_GENERIC_COMMAND_REJECTED\n");
- ZFCP_LOG_INFO("warning: The port 0x%016Lx on adapter %s has "
- "rejected a generic services command.\n",
- port->wwpn, zfcp_get_busid_by_port(port));
+ ZFCP_LOG_INFO("generic service command rejected "
+ "(adapter %s, port d_id=0x%08x)\n",
+ zfcp_get_busid_by_port(port), port->d_id);
ZFCP_LOG_INFO("status qualifier:\n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
(char *) &header->fsf_status_qual,
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
- case FSF_PORT_HANDLE_NOT_VALID :
+ case FSF_PORT_HANDLE_NOT_VALID:
ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port "
"0x%016Lx on adapter %s invalid. This may "
(char *) &header->fsf_status_qual,
sizeof (union fsf_status_qual));
debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv");
- zfcp_erp_adapter_reopen(port->adapter, 0);
+ zfcp_erp_adapter_reopen(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
- case FSF_PORT_BOXED :
+ case FSF_PORT_BOXED:
ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
- ZFCP_LOG_INFO("The remote port 0x%016Lx on adapter %s "
- "needs to be reopened\n",
- port->wwpn, zfcp_get_busid_by_port(port));
+ ZFCP_LOG_INFO("port needs to be reopened "
+ "(adapter %s, port d_id=0x%08x)\n",
+ zfcp_get_busid_by_port(port), port->d_id);
debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
zfcp_erp_port_reopen(port, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
| ZFCP_STATUS_FSFREQ_RETRY;
break;
- default :
+ /* following states should never occure, all cases avoided
+ in zfcp_fsf_send_ct - but who knows ... */
+ case FSF_PAYLOAD_SIZE_MISMATCH:
+ ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n");
+ ZFCP_LOG_INFO("payload size mismatch (adapter: %s, "
+ "req_buf_length=%d, resp_buf_length=%d)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ bottom->req_buf_length, bottom->resp_buf_length);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_REQUEST_SIZE_TOO_LARGE:
+ ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n");
+ ZFCP_LOG_INFO("request size too large (adapter: %s, "
+ "req_buf_length=%d)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ bottom->req_buf_length);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_RESPONSE_SIZE_TOO_LARGE:
+ ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n");
+ ZFCP_LOG_INFO("response size too large (adapter: %s, "
+ "resp_buf_length=%d)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ bottom->resp_buf_length);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SBAL_MISMATCH:
+ ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n");
+ ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "
+ "resp_buf_length=%d)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ bottom->req_buf_length, bottom->resp_buf_length);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+ default:
ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
"(debug info 0x%x)\n", header->fsf_status);
debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:");
{
volatile struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *fsf_req;
- struct zfcp_port *port;
+ fc_id_t d_id;
struct zfcp_adapter *adapter;
unsigned long lock_flags;
int bytes;
int ret = 0;
- port = els->port;
- adapter = port->adapter;
+ d_id = els->d_id;
+ adapter = els->adapter;
ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
- ZFCP_WAIT_FOR_SBAL|ZFCP_REQ_AUTO_CLEANUP,
+ ZFCP_REQ_AUTO_CLEANUP,
NULL, &lock_flags, &fsf_req);
if (ret < 0) {
ZFCP_LOG_INFO("error: creation of ELS request failed "
"(adapter %s, port d_id: 0x%08x)\n",
- zfcp_get_busid_by_adapter(adapter), port->d_id);
+ zfcp_get_busid_by_adapter(adapter), d_id);
goto failed_req;
}
if (bytes <= 0) {
ZFCP_LOG_INFO("error: creation of ELS request failed "
"(adapter %s, port d_id: 0x%08x)\n",
- zfcp_get_busid_by_adapter(adapter),
- port->d_id);
+ zfcp_get_busid_by_adapter(adapter), d_id);
if (bytes == 0) {
ret = -ENOMEM;
} else {
if (bytes <= 0) {
ZFCP_LOG_INFO("error: creation of ELS request failed "
"(adapter %s, port d_id: 0x%08x)\n",
- zfcp_get_busid_by_adapter(adapter),
- port->d_id);
+ zfcp_get_busid_by_adapter(adapter), d_id);
if (bytes == 0) {
ret = -ENOMEM;
} else {
ZFCP_LOG_INFO("error: microcode does not support chained SBALs"
", ELS request too big (adapter %s, "
"port d_id: 0x%08x)\n",
- zfcp_get_busid_by_adapter(adapter), port->d_id);
+ zfcp_get_busid_by_adapter(adapter), d_id);
ret = -EOPNOTSUPP;
goto failed_send;
}
/* settings in QTCB */
- fsf_req->qtcb->bottom.support.d_id = port->d_id;
+ fsf_req->qtcb->bottom.support.d_id = d_id;
fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT;
fsf_req->data.send_els = els;
ret = zfcp_fsf_req_send(fsf_req, els->timer);
if (ret) {
ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
- "(adapter %s, port 0x%016Lx)\n",
- zfcp_get_busid_by_adapter(adapter), port->wwpn);
+ "(adapter %s, port d_id: 0x%08x)\n",
+ zfcp_get_busid_by_adapter(adapter), d_id);
goto failed_send;
}
- ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port 0x%016Lx)\n",
- zfcp_get_busid_by_adapter(adapter), port->wwpn);
+ ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: "
+ "0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id);
goto out;
failed_send:
static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_adapter *adapter;
+ fc_id_t d_id;
struct zfcp_port *port;
struct fsf_qtcb_header *header;
struct fsf_qtcb_bottom_support *bottom;
int retval = -EINVAL;
u16 subtable, rule, counter;
- adapter = fsf_req->adapter;
send_els = fsf_req->data.send_els;
- port = send_els->port;
+ adapter = send_els->adapter;
+ d_id = send_els->d_id;
header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support;
if (adapter->fc_service_class <= 3) {
ZFCP_LOG_INFO("error: adapter %s does "
"not support fibrechannel class %d.\n",
- zfcp_get_busid_by_port(port),
+ zfcp_get_busid_by_adapter(adapter),
adapter->fc_service_class);
} else {
ZFCP_LOG_INFO("bug: The fibrechannel class at "
"adapter %s is invalid. "
"(debug info %d)\n",
- zfcp_get_busid_by_port(port),
+ zfcp_get_busid_by_adapter(adapter),
adapter->fc_service_class);
}
/* stop operation for this adapter */
debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
- zfcp_erp_adapter_shutdown(port->adapter, 0);
+ zfcp_erp_adapter_shutdown(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]){
- case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
- if (send_els->ls_code != ZFCP_LS_ADISC)
- zfcp_test_link(port);
+ if (send_els->ls_code != ZFCP_LS_ADISC) {
+ read_lock(&zfcp_data.config_lock);
+ port = zfcp_get_port_by_did(adapter, d_id);
+ if (port)
+ zfcp_test_link(port);
+ read_unlock(&zfcp_data.config_lock);
+ }
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
- }
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
- /* ERP strategy will escalate */
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
retval =
ZFCP_LOG_FLAGS(2, "FSF_ELS_COMMAND_REJECTED\n");
ZFCP_LOG_INFO("ELS has been rejected because command filter "
"prohibited sending "
- "(adapter: %s, wwpn=0x%016Lx)\n",
- zfcp_get_busid_by_port(port), port->wwpn);
+ "(adapter: %s, port d_id: 0x%08x)\n",
+ zfcp_get_busid_by_adapter(adapter), d_id);
break;
"ELS request size and ELS response size must be either "
"both 0, or both greater than 0 "
"(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n",
- zfcp_get_busid_by_port(port),
+ zfcp_get_busid_by_adapter(adapter),
bottom->req_buf_length,
bottom->resp_buf_length);
break;
"exceeds the size of the buffers "
"that have been allocated for ELS request data "
"(adapter: %s, req_buf_length=%d)\n",
- zfcp_get_busid_by_port(port),
+ zfcp_get_busid_by_adapter(adapter),
bottom->req_buf_length);
break;
"exceeds the size of the buffers "
"that have been allocated for ELS response data "
"(adapter: %s, resp_buf_length=%d)\n",
- zfcp_get_busid_by_port(port),
+ zfcp_get_busid_by_adapter(adapter),
bottom->resp_buf_length);
break;
+ case FSF_SBAL_MISMATCH:
+ /* should never occure, avoided in zfcp_fsf_send_els */
+ ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n");
+ ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "
+ "resp_buf_length=%d)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ bottom->req_buf_length, bottom->resp_buf_length);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
case FSF_ACCESS_DENIED:
ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
- ZFCP_LOG_NORMAL("Access denied, cannot send ELS "
- "(adapter: %s, wwpn=0x%016Lx)\n",
- zfcp_get_busid_by_port(port), port->wwpn);
+ ZFCP_LOG_NORMAL("access denied, cannot send ELS command "
+ "(adapter %s, port d_id=0x%08x)\n",
+ zfcp_get_busid_by_adapter(adapter), d_id);
for (counter = 0; counter < 2; counter++) {
subtable = header->fsf_status_qual.halfword[counter * 2];
rule = header->fsf_status_qual.halfword[counter * 2 + 1];
}
}
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+ read_lock(&zfcp_data.config_lock);
+ port = zfcp_get_port_by_did(adapter, d_id);
+ if (port != NULL)
+ zfcp_erp_port_access_denied(port);
+ read_unlock(&zfcp_data.config_lock);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
ZFCP_LOG_NORMAL(
"bug: An unknown FSF Status was presented "
"(adapter: %s, fsf_status=0x%08x)\n",
- zfcp_get_busid_by_port(port),
+ zfcp_get_busid_by_adapter(adapter),
header->fsf_status);
debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval");
debug_exception(adapter->erp_dbf, 0,
erp_action->fsf_req->erp_action = erp_action;
erp_action->fsf_req->qtcb->bottom.config.feature_selection =
- FSF_FEATURE_CFDC;
+ (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING);
/* start QDIO request for this FSF request */
retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
return;
switch (fsf_req->qtcb->header.fsf_status) {
- case FSF_GOOD :
+ case FSF_GOOD:
ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
bottom = &fsf_req->qtcb->bottom.port;
memcpy(data, bottom, sizeof(*data));
ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx "
"on adapter %s\n",
- port->wwpn, zfcp_get_busid_by_port(port));
+ port->wwpn, zfcp_get_busid_by_port(port));
for (counter = 0; counter < 2; counter++) {
subtable = header->fsf_status_qual.halfword[counter * 2];
rule = header->fsf_status_qual.halfword[counter * 2 + 1];
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
- zfcp_erp_port_failed(port);
+ zfcp_erp_port_access_denied(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
break;
+ case FSF_UNKNOWN_OP_SUBTYPE:
+ /* should never occure, subtype not set in zfcp_fsf_open_port */
+ ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
+ ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, "
+ "op_subtype=0x%x)\n",
+ zfcp_get_busid_by_port(port),
+ fsf_req->qtcb->bottom.support.operation_subtype);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
default:
ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
"(debug info 0x%x)\n",
case FSF_ACCESS_DENIED:
ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot close "
- "physical port 0x%016Lx on "
- "adapter %s\n", port->wwpn,
- zfcp_get_busid_by_port(port));
+ "physical port 0x%016Lx on adapter %s\n",
+ port->wwpn, zfcp_get_busid_by_port(port));
for (counter = 0; counter < 2; counter++) {
subtable = header->fsf_status_qual.halfword[counter * 2];
rule = header->fsf_status_qual.halfword[counter * 2 + 1];
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+ zfcp_erp_port_access_denied(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
erp_action->port->handle;
erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
erp_action->unit->fcp_lun;
+ erp_action->fsf_req->qtcb->bottom.support.option =
+ FSF_OPEN_LUN_SUPPRESS_BOXING;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
erp_action->fsf_req->data.open_unit.unit = erp_action->unit;
erp_action->fsf_req->erp_action = erp_action;
struct zfcp_unit *unit;
struct fsf_qtcb_header *header;
struct fsf_qtcb_bottom_support *bottom;
+ struct fsf_queue_designator *queue_designator;
u16 subtable, rule, counter;
+ u32 allowed, exclusive, readwrite;
- adapter = fsf_req->adapter;
unit = fsf_req->data.open_unit.unit;
- header = &fsf_req->qtcb->header;
- bottom = &fsf_req->qtcb->bottom.support;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't change unit status in our bookkeeping */
goto skip_fsfstatus;
}
+ adapter = fsf_req->adapter;
+ header = &fsf_req->qtcb->header;
+ bottom = &fsf_req->qtcb->bottom.support;
+ queue_designator = &header->fsf_status_qual.fsf_queue_designator;
+
+ allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED;
+ exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE;
+ readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER;
+
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
+ ZFCP_STATUS_UNIT_SHARED |
+ ZFCP_STATUS_UNIT_READONLY,
+ &unit->status);
+
/* evaluate FSF status in QTCB */
switch (header->fsf_status) {
}
}
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
- zfcp_erp_unit_failed(unit);
+ zfcp_erp_unit_access_denied(unit);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
ZFCP_STATUS_FSFREQ_RETRY;
break;
- case FSF_LUN_SHARING_VIOLATION :
+ case FSF_LUN_SHARING_VIOLATION:
ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n");
if (header->fsf_status_qual.word[0] != 0) {
ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port "
"with WWPN 0x%Lx "
"connected to the adapter %s "
- "is already in use in LPAR%d\n",
+ "is already in use in LPAR%d, CSS%d\n",
unit->fcp_lun,
unit->port->wwpn,
zfcp_get_busid_by_unit(unit),
- header->fsf_status_qual.fsf_queue_designator.hla);
+ queue_designator->hla,
+ queue_designator->cssid);
} else {
subtable = header->fsf_status_qual.halfword[4];
rule = header->fsf_status_qual.halfword[5];
sizeof (union fsf_status_qual));
debug_text_event(adapter->erp_dbf, 2,
"fsf_s_l_sh_vio");
- zfcp_erp_unit_failed(unit);
+ zfcp_erp_unit_access_denied(unit);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
unit->handle);
/* mark unit as open */
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
+
+ if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){
+ if (!exclusive)
+ atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
+ &unit->status);
+
+ if (!readwrite) {
+ atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
+ &unit->status);
+ ZFCP_LOG_NORMAL("read-only access for unit "
+ "(adapter %s, wwpn=0x%016Lx, "
+ "fcp_lun=0x%016Lx)\n",
+ zfcp_get_busid_by_unit(unit),
+ unit->port->wwpn,
+ unit->fcp_lun);
+ }
+
+ if (exclusive && !readwrite) {
+ ZFCP_LOG_NORMAL("exclusive access of read-only "
+ "unit not supported\n");
+ zfcp_erp_unit_failed(unit);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ zfcp_erp_unit_shutdown(unit, 0);
+ } else if (!exclusive && readwrite) {
+ ZFCP_LOG_NORMAL("shared access of read-write "
+ "unit not supported\n");
+ zfcp_erp_unit_failed(unit);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ zfcp_erp_unit_shutdown(unit, 0);
+ }
+ }
+
retval = 0;
break;
break;
}
- skip_fsfstatus:
+ skip_fsfstatus:
atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status);
return retval;
}
unsigned long lock_flags;
int real_bytes = 0;
int retval = 0;
+ int mask;
/* setup new FSF request */
retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
/* set FCP_LUN in FCP_CMND IU in QTCB */
fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
+ mask = ZFCP_STATUS_UNIT_READONLY | ZFCP_STATUS_UNIT_SHARED;
+
/* set task attributes in FCP_CMND IU in QTCB */
- if (likely(scsi_cmnd->device->simple_tags)) {
+ if (likely((scsi_cmnd->device->simple_tags) ||
+ (atomic_test_mask(mask, &unit->status))))
fcp_cmnd_iu->task_attribute = SIMPLE_Q;
- ZFCP_LOG_TRACE("setting SIMPLE_Q task attribute\n");
- } else {
+ else
fcp_cmnd_iu->task_attribute = UNTAGGED;
- ZFCP_LOG_TRACE("setting UNTAGGED task attribute\n");
- }
/* set additional length of FCP_CDB in FCP_CMND IU in QTCB, if needed */
if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH)) {
}
}
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+ zfcp_erp_unit_access_denied(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_LUN_BOXED:
ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
- ZFCP_LOG_NORMAL(
- "unit 0x%016Lx on port 0x%016Lx on adapter %s needs "
- "to be reopened\n",
- unit->fcp_lun, unit->port->wwpn,
- zfcp_get_busid_by_unit(unit));
+ ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, "
+ "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
+ zfcp_get_busid_by_unit(unit),
+ unit->port->wwpn, unit->fcp_lun);
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
zfcp_erp_unit_reopen(unit, 0);
zfcp_cmd_dbf_event_fsf("unitbox", fsf_req,
- &header->fsf_status_qual,
- sizeof(union fsf_status_qual));
+ &header->fsf_status_qual,
+ sizeof(union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
| ZFCP_STATUS_FSFREQ_RETRY;
break;
/* check for underrun */
if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
- ZFCP_LOG_DEBUG("A data underrun was detected for a command. "
- "unit 0x%016Lx, port 0x%016Lx, adapter %s. "
- "The response data length is "
- "%d, the original length was %d.\n",
- unit->fcp_lun,
- unit->port->wwpn,
- zfcp_get_busid_by_unit(unit),
- fcp_rsp_iu->fcp_resid,
- (int) zfcp_get_fcp_dl(fcp_cmnd_iu));
- /*
- * It may not have been possible to send all data and the
- * underrun on send may already be in scpnt->resid, so it's add
- * not equals in the below statement.
- */
- scpnt->resid += fcp_rsp_iu->fcp_resid;
- ZFCP_LOG_TRACE("scpnt->resid=0x%x\n", scpnt->resid);
+ ZFCP_LOG_INFO("A data underrun was detected for a command. "
+ "unit 0x%016Lx, port 0x%016Lx, adapter %s. "
+ "The response data length is "
+ "%d, the original length was %d.\n",
+ unit->fcp_lun,
+ unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit),
+ fcp_rsp_iu->fcp_resid,
+ (int) zfcp_get_fcp_dl(fcp_cmnd_iu));
+
+ scpnt->resid = fcp_rsp_iu->fcp_resid;
+ if (scpnt->request_bufflen - scpnt->resid < scpnt->underflow)
+ scpnt->result |= DID_ERROR << 16;
}
skip_fsfstatus:
* -EOPNOTSUPP - The FCP adapter does not have Control File support
* -EINVAL - Invalid direction specified
* -ENOMEM - Insufficient memory
- * -EPERM - Cannot create FSF request or or place it in QDIO queue
+ * -EPERM - Cannot create FSF request or place it in QDIO queue
*/
int
zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *fsf_req;
struct fsf_qtcb_bottom_support *bottom;
volatile struct qdio_buffer_element *sbale;
+ struct timer_list *timer;
unsigned long lock_flags;
int req_flags = 0;
int direction;
int retval = 0;
if (!(adapter->supported_features & FSF_FEATURE_CFDC)) {
- ZFCP_LOG_INFO(
- "Adapter %s does not support control file\n",
- zfcp_get_busid_by_adapter(adapter));
+ ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n",
+ zfcp_get_busid_by_adapter(adapter));
retval = -EOPNOTSUPP;
- goto no_cfdc_support;
+ goto out;
}
switch (fsf_command) {
default:
ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command);
- goto invalid_command;
+ retval = -EINVAL;
+ goto out;
}
+ timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+ if (!timer) {
+ retval = -ENOMEM;
+ goto out;
+ }
+
retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags,
NULL, &lock_flags, &fsf_req);
if (retval < 0) {
"adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
retval = -EPERM;
- goto out;
+ goto unlock_queue_lock;
}
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
"SBALS for an FSF request to the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
retval = -ENOMEM;
- goto sbals_failed;
+ goto free_fsf_req;
}
- } else {
+ } else
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- }
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ 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 < 0) {
- ZFCP_LOG_INFO(
- "error: Could not send FSF request to the adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
+ ZFCP_LOG_INFO("initiation of cfdc up/download failed"
+ "(adapter %s)\n",
+ zfcp_get_busid_by_adapter(adapter));
retval = -EPERM;
- goto queue_failed;
+ goto free_fsf_req;
}
+ write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
- ZFCP_LOG_NORMAL(
- "Control file %s FSF request has been sent to the adapter %s\n",
- fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ?
+ ZFCP_LOG_NORMAL("Control file %s FSF request has been sent to the "
+ "adapter %s\n",
+ fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ?
"download" : "upload",
- zfcp_get_busid_by_adapter(adapter));
+ zfcp_get_busid_by_adapter(adapter));
- *fsf_req_ptr = fsf_req;
+ wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- goto out;
+ *fsf_req_ptr = fsf_req;
+ del_timer_sync(timer);
+ goto free_timer;
-sbals_failed:
-queue_failed:
+ free_fsf_req:
zfcp_fsf_req_free(fsf_req);
-
-out:
+ unlock_queue_lock:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
-
-invalid_command:
-no_cfdc_support:
+ free_timer:
+ kfree(timer);
+ out:
return retval;
}
case FSF_UNKNOWN_OP_SUBTYPE:
ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
- ZFCP_LOG_NORMAL(
- "Invalid operation subtype 0x%x has been specified "
- "in QTCB bottom sent to the adapter %s\n",
- bottom->operation_subtype,
- zfcp_get_busid_by_adapter(adapter));
+ ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, "
+ "op_subtype=0x%x)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ bottom->operation_subtype);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
retval = -EINVAL;
break;
ZFCP_SBAL_TIMEOUT);
if (ret < 0)
return ret;
+ if (!ret)
+ return -EIO;
} else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1))
return -EIO;
* timer might be expired (absolutely unlikely)
*/
if (timer)
- del_timer_sync(timer);
+ del_timer(timer);
write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
list_del(&fsf_req->list);
write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);