Commit be3a4d39 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: zfcp host adapter

From: Heiko Carstens <heiko.carstens@de.ibm.com>
From: Andreas Herrmann <aherrman@de.ibm.com>
From: Maxim Shchetynin <maxim@de.ibm.com>

zfcp host adapter changes:
 - Use predefined macro to create in_recovery sysfs attributes.
 - Add function to check CT_IU response.
 - Fix handling of rejected ELS commands.
 - Change return value of zfcp_fsf_req_sbal_get to -ERESTARTSYS in some cases.
 - Return proper error code if control file upload/download failed.
 - Remove dead code.
 - Avoid sparse warnings.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9a1ac79c
......@@ -29,7 +29,7 @@
*/
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_AUX_REVISION "$Revision: 1.115 $"
#define ZFCP_AUX_REVISION "$Revision: 1.121 $"
#include "zfcp_ext.h"
......@@ -48,10 +48,10 @@ static void zfcp_ns_gid_pn_handler(unsigned long);
static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
static inline int zfcp_sg_list_free(struct zfcp_sg_list *);
static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *,
size_t);
static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *,
size_t);
static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
void __user *, size_t);
static inline int zfcp_sg_list_copy_to_user(void __user *,
struct zfcp_sg_list *, size_t);
static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *,
unsigned int, unsigned long);
......@@ -95,7 +95,7 @@ MODULE_PARM_DESC(device, "specify initial device");
module_param(loglevel, uint, 0);
MODULE_PARM_DESC(loglevel,
"log levels, 8 nibbles: "
"(unassigned) ERP QDIO DIO Config FSF SCSI Other, "
"(unassigned) FC ERP QDIO CIO Config FSF SCSI Other, "
"levels: 0=none 1=normal 2=devel 3=trace");
#ifdef ZFCP_PRINT_FLAGS
......@@ -382,7 +382,7 @@ static int
zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
unsigned int command, unsigned long buffer)
{
struct zfcp_cfdc_sense_data sense_data, *sense_data_user;
struct zfcp_cfdc_sense_data sense_data, __user *sense_data_user;
struct zfcp_adapter *adapter = NULL;
struct zfcp_fsf_req *fsf_req = NULL;
struct zfcp_sg_list *sg_list = NULL;
......@@ -403,7 +403,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
goto out;
}
if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) {
if ((sense_data_user = (void __user *) buffer) == NULL) {
ZFCP_LOG_INFO("sense data record is required\n");
retval = -EINVAL;
goto out;
......@@ -520,6 +520,12 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
wait_event(fsf_req->completion_wq,
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
(fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
retval = -ENXIO;
goto out;
}
sense_data.fsf_status = fsf_req->qtcb->header.fsf_status;
memcpy(&sense_data.fsf_status_qual,
&fsf_req->qtcb->header.fsf_status_qual,
......@@ -637,7 +643,8 @@ zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
* -EFAULT - Memory I/O operation fault
*/
static inline int
zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
void __user *user_buffer,
size_t size)
{
struct scatterlist *sg;
......@@ -671,7 +678,8 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
* -EFAULT - Memory I/O operation fault
*/
static inline int
zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list,
zfcp_sg_list_copy_to_user(void __user *user_buffer,
struct zfcp_sg_list *sg_list,
size_t size)
{
struct scatterlist *sg;
......@@ -1646,15 +1654,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
ct_iu_req = zfcp_sg_to_address(ct->req);
ct_iu_resp = zfcp_sg_to_address(ct->resp);
if (ct_iu_resp->header.revision != ZFCP_CT_REVISION)
goto failed;
if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE)
goto failed;
if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER)
goto failed;
if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS)
goto failed;
if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
if (zfcp_check_ct_response(&ct_iu_resp->header)) {
/* FIXME: do we need some specific erp entry points */
atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
goto failed;
......@@ -1675,7 +1675,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
goto out;
failed:
failed:
ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn "
"0x%016Lx for adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port));
......@@ -1690,4 +1690,169 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
return;
}
/* reject CT_IU reason codes acc. to FC-GS-4 */
static const struct zfcp_rc_entry zfcp_ct_rc[] = {
{0x01, "invalid command code"},
{0x02, "invalid version level"},
{0x03, "logical error"},
{0x04, "invalid CT_IU size"},
{0x05, "logical busy"},
{0x07, "protocol error"},
{0x09, "unable to perform command request"},
{0x0b, "command not supported"},
{0x0d, "server not available"},
{0x0e, "session could not be established"},
{0xff, "vendor specific error"},
{0, NULL},
};
/* LS_RJT reason codes acc. to FC-FS */
static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = {
{0x01, "invalid LS_Command code"},
{0x03, "logical error"},
{0x05, "logical busy"},
{0x07, "protocol error"},
{0x09, "unable to perform command request"},
{0x0b, "command not supported"},
{0x0e, "command already in progress"},
{0xff, "vendor specific error"},
{0, NULL},
};
/* reject reason codes according to FC-PH/FC-FS */
static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = {
{0x01, "invalid D_ID"},
{0x02, "invalid S_ID"},
{0x03, "Nx_Port not available, temporary"},
{0x04, "Nx_Port not available, permament"},
{0x05, "class not supported"},
{0x06, "delimiter usage error"},
{0x07, "TYPE not supported"},
{0x08, "invalid Link_Control"},
{0x09, "invalid R_CTL field"},
{0x0a, "invalid F_CTL field"},
{0x0b, "invalid OX_ID"},
{0x0c, "invalid RX_ID"},
{0x0d, "invalid SEQ_ID"},
{0x0e, "invalid DF_CTL"},
{0x0f, "invalid SEQ_CNT"},
{0x10, "invalid parameter field"},
{0x11, "exchange error"},
{0x12, "protocol error"},
{0x13, "incorrect length"},
{0x14, "unsupported ACK"},
{0x15, "class of service not supported by entity at FFFFFE"},
{0x16, "login required"},
{0x17, "excessive sequences attempted"},
{0x18, "unable to establish exchange"},
{0x1a, "fabric path not available"},
{0x1b, "invalid VC_ID (class 4)"},
{0x1c, "invalid CS_CTL field"},
{0x1d, "insufficient resources for VC (class 4)"},
{0x1f, "invalid class of service"},
{0x20, "preemption request rejected"},
{0x21, "preemption not enabled"},
{0x22, "multicast error"},
{0x23, "multicast error terminate"},
{0x24, "process login required"},
{0xff, "vendor specific reject"},
{0, NULL},
};
/**
* zfcp_rc_description - return description for given reaon code
* @code: reason code
* @rc_table: table of reason codes and descriptions
*/
static inline const char *
zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table)
{
const char *descr = "unknown reason code";
do {
if (code == rc_table->code) {
descr = rc_table->description;
break;
}
rc_table++;
} while (rc_table->code && rc_table->description);
return descr;
}
/**
* zfcp_check_ct_response - evaluate reason code for CT_IU
* @rjt: response payload to an CT_IU request
* Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code
*/
int
zfcp_check_ct_response(struct ct_hdr *rjt)
{
if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT)
return 0;
if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) {
ZFCP_LOG_NORMAL("error: invalid Generic Service command/"
"response code (0x%04hx)\n",
rjt->cmd_rsp_code);
return 1;
}
ZFCP_LOG_INFO("Generic Service command rejected\n");
ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n",
zfcp_rc_description(rjt->reason_code, zfcp_ct_rc),
(u32) rjt->reason_code, (u32) rjt->reason_code_expl,
(u32) rjt->vendor_unique);
return 1;
}
/**
* zfcp_print_els_rjt - print reject parameter and description for ELS reject
* @rjt_par: reject parameter acc. to FC-PH/FC-FS
* @rc_table: table of reason codes and descriptions
*/
static inline void
zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,
const struct zfcp_rc_entry *rc_table)
{
ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n",
zfcp_rc_description(rjt_par->reason_code, rc_table),
(u32) rjt_par->action, (u32) rjt_par->reason_code,
(u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique);
}
/**
* zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject
* @sq: status qualifier word
* @rjt_par: reject parameter as described in FC-PH and FC-FS
* Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else
*/
int
zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par)
{
int ret = -EIO;
if (sq == FSF_IOSTAT_NPORT_RJT) {
ZFCP_LOG_INFO("ELS rejected (P_RJT)\n");
zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);
/* invalid d_id */
if (rjt_par->reason_code == 0x01)
ret = -EREMCHG;
} else if (sq == FSF_IOSTAT_FABRIC_RJT) {
ZFCP_LOG_INFO("ELS rejected (F_RJT)\n");
zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);
/* invalid d_id */
if (rjt_par->reason_code == 0x01)
ret = -EREMCHG;
} else if (sq == FSF_IOSTAT_LS_RJT) {
ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n");
zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc);
ret = -EREMOTEIO;
} else
ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq);
return ret;
}
#undef ZFCP_LOG_AREA
......@@ -33,7 +33,7 @@
#define ZFCP_DEF_H
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_DEF_REVISION "$Revision: 1.81 $"
#define ZFCP_DEF_REVISION "$Revision: 1.83 $"
/*************************** INCLUDES *****************************************/
......@@ -296,10 +296,8 @@ struct fcp_logo {
#define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED 0x0B
#define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR 0xFF
struct zfcp_ls_rjt {
u8 code;
u8 field[3];
u8 reserved;
struct zfcp_ls_rjt_par {
u8 action;
u8 reason_code;
u8 reason_expl;
u8 vendor_unique;
......@@ -423,6 +421,11 @@ struct zfcp_ls_rnid_acc {
specific_id;
} __attribute__((packed));
struct zfcp_rc_entry {
u8 code;
const char *description;
};
/*
* FC-GS-2 stuff
*/
......@@ -431,9 +434,9 @@ struct zfcp_ls_rnid_acc {
#define ZFCP_CT_NAME_SERVER 0x02
#define ZFCP_CT_SYNCHRONOUS 0x00
#define ZFCP_CT_GID_PN 0x0121
#define ZFCP_CT_GA_NXT 0x0100
#define ZFCP_CT_MAX_SIZE 0x1020
#define ZFCP_CT_ACCEPT 0x8002
#define ZFCP_CT_REJECT 0x8001
/*
* FC-GS-4 stuff
......@@ -851,7 +854,7 @@ struct zfcp_gid_pn_data {
struct zfcp_port *port;
};
typedef int (*zfcp_send_els_handler_t)(unsigned long);
typedef void (*zfcp_send_els_handler_t)(unsigned long);
/* used to pass parameters to zfcp_send_els() */
/* ToDo merge send_ct() and send_els() and corresponding structs */
......
......@@ -31,12 +31,12 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_ERP_REVISION "$Revision: 1.61 $"
#define ZFCP_ERP_REVISION "$Revision: 1.62 $"
#include "zfcp_ext.h"
static int zfcp_els(struct zfcp_port *, u8);
static int zfcp_els_handler(unsigned long);
static void zfcp_els_handler(unsigned long);
static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
......@@ -324,6 +324,7 @@ zfcp_els(struct zfcp_port *port, u8 ls_code)
send_els->completion = NULL;
req = zfcp_sg_to_address(send_els->req);
memset(req, 0, PAGE_SIZE);
*(u32*)req = 0;
*(u8*)req = ls_code;
......@@ -412,109 +413,40 @@ zfcp_els(struct zfcp_port *port, u8 ls_code)
}
/*
* function: zfcp_els_handler
*
* purpose: Handler for all kind of ELSs
*
* returns: 0 - Operation completed successfuly
* -ENXIO - ELS has been rejected
* -EPERM - Port forced reopen failed
/**
* zfcp_els_handler - handler for ELS commands
* @data: pointer to struct zfcp_send_els
* If ELS failed (LS_RJT or timed out) forced reopen of the port is triggered.
*/
int
void
zfcp_els_handler(unsigned long data)
{
struct zfcp_send_els *send_els = (struct zfcp_send_els*)data;
struct zfcp_port *port = send_els->port;
struct zfcp_ls_rjt *rjt;
struct zfcp_ls_rtv_acc *rtv;
struct zfcp_ls_rls_acc *rls;
struct zfcp_ls_pdisc_acc *pdisc;
struct zfcp_ls_adisc_acc *adisc;
void *req, *resp;
u8 req_code, resp_code;
int retval = 0;
u8 req_code;
/* request rejected or timed out */
if (send_els->status != 0) {
ZFCP_LOG_NORMAL("ELS request timed out, force physical port "
"reopen of port 0x%016Lx on adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port));
debug_text_event(port->adapter->erp_dbf, 3, "forcreop");
retval = zfcp_erp_port_forced_reopen(port, 0);
if (retval != 0) {
if (zfcp_erp_port_forced_reopen(port, 0))
ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
"on adapter %s failed\n", port->wwpn,
zfcp_get_busid_by_port(port));
retval = -EPERM;
}
goto skip_fsfstatus;
goto out;
}
req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset);
resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset);
req = zfcp_sg_to_address(send_els->req);
resp = zfcp_sg_to_address(send_els->resp);
req_code = *(u8*)req;
resp_code = *(u8*)resp;
switch (resp_code) {
case ZFCP_LS_RJT:
rjt = (struct zfcp_ls_rjt*)resp;
switch (rjt->reason_code) {
case ZFCP_LS_RJT_INVALID_COMMAND_CODE:
ZFCP_LOG_INFO("invalid LS command code "
"(wwpn=0x%016Lx, command=0x%02x)\n",
port->wwpn, req_code);
break;
case ZFCP_LS_RJT_LOGICAL_ERROR:
ZFCP_LOG_INFO("logical error (wwpn=0x%016Lx, "
"reason_expl=0x%02x)\n",
port->wwpn, rjt->reason_expl);
break;
case ZFCP_LS_RJT_LOGICAL_BUSY:
ZFCP_LOG_INFO("logical busy (wwpn=0x%016Lx, "
"reason_expl=0x%02x)\n",
port->wwpn, rjt->reason_expl);
break;
case ZFCP_LS_RJT_PROTOCOL_ERROR:
ZFCP_LOG_INFO("protocol error (wwpn=0x%016Lx, "
"reason_expl=0x%02x)\n",
port->wwpn, rjt->reason_expl);
break;
case ZFCP_LS_RJT_UNABLE_TO_PERFORM:
ZFCP_LOG_INFO("unable to perform command requested "
"(wwpn=0x%016Lx, reason_expl=0x%02x)\n",
port->wwpn, rjt->reason_expl);
break;
case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED:
ZFCP_LOG_INFO("command not supported (wwpn=0x%016Lx, "
"command=0x%02x)\n",
port->wwpn, req_code);
break;
case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR:
ZFCP_LOG_INFO("vendor specific error (wwpn=0x%016Lx, "
"vendor_unique=0x%02x)\n",
port->wwpn, rjt->vendor_unique);
break;
default:
ZFCP_LOG_NORMAL("ELS rejected by remote port 0x%016Lx "
"on adapter %s (reason_code=0x%02x)\n",
port->wwpn,
zfcp_get_busid_by_port(port),
rjt->reason_code);
}
retval = -ENXIO;
break;
case ZFCP_LS_ACC:
switch (req_code) {
case ZFCP_LS_RTV:
......@@ -568,29 +500,12 @@ zfcp_els_handler(unsigned long data)
port->wwnn = adisc->wwnn;
break;
}
break;
default:
ZFCP_LOG_NORMAL("unknown payload code 0x%02x received for "
"request 0x%02x to d_id 0x%08x, reopen needed "
"for port 0x%016Lx on adapter %s\n", resp_code,
req_code, port->d_id, port->wwpn,
zfcp_get_busid_by_port(port));
retval = zfcp_erp_port_forced_reopen(port, 0);
if (retval != 0) {
ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx on "
"adapter %s failed\n", port->wwpn,
zfcp_get_busid_by_port(port));
retval = -EPERM;
}
}
skip_fsfstatus:
out:
__free_pages(send_els->req->page, 0);
kfree(send_els->req);
kfree(send_els->resp);
return retval;
kfree(send_els);
}
......
......@@ -31,7 +31,7 @@
#ifndef ZFCP_EXT_H
#define ZFCP_EXT_H
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_EXT_REVISION "$Revision: 1.51 $"
#define ZFCP_EXT_REVISION "$Revision: 1.53 $"
#include "zfcp_def.h"
......@@ -117,9 +117,11 @@ extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
unsigned long, struct zfcp_adapter *, struct zfcp_unit *, int);
/******************************** FCP ****************************************/
/******************************* FC/FCP **************************************/
extern int zfcp_nameserver_enqueue(struct zfcp_adapter *);
extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
extern int zfcp_check_ct_response(struct ct_hdr *);
extern int zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *);
/******************************* SCSI ****************************************/
extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
......
......@@ -29,7 +29,7 @@
*/
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_FSF_C_REVISION "$Revision: 1.55 $"
#define ZFCP_FSF_C_REVISION "$Revision: 1.59 $"
#include "zfcp_ext.h"
......@@ -48,7 +48,7 @@ static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *);
static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *);
static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *);
static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *);
static inline int zfcp_fsf_req_create_sbal_check(
static inline int zfcp_fsf_req_sbal_check(
unsigned long *, struct zfcp_qdio_queue *, int);
static inline int zfcp_use_one_sbal(
struct scatterlist *, int, struct scatterlist *, int);
......@@ -79,10 +79,9 @@ static u32 fsf_qtcb_type[] = {
};
static const char zfcp_act_subtable_type[5][8] = {
{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
"unknown", "OS", "WWPN", "DID", "LUN"
};
/****************************************************************/
/*************** FSF related Functions *************************/
/****************************************************************/
......@@ -1863,6 +1862,10 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
/* ERP strategy will escalate */
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
retval =
zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
(struct zfcp_ls_rjt_par *)
&header->fsf_status_qual.word[2]);
break;
case FSF_SQ_RETRY_IF_POSSIBLE:
ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
......@@ -1971,8 +1974,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
if (send_els->handler != 0)
send_els->handler(send_els->handler_data);
kfree(send_els);
return retval;
}
......@@ -4157,87 +4158,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
}
skip_fsfstatus:
#if 0
/*
* This nasty chop at the problem is not working anymore
* as we do not adjust the retry count anylonger in order
* to have a number of retries that avoids I/O errors.
* The manipulation of the retry count has been removed
* in favour of a safe tape device handling. We must not
* sent SCSI commands more than once to a device if no
* retries are permitted by the high level driver. Generally
* speaking, it was a mess to change retry counts. So it is
* fine that this sort of workaround is gone.
* Then, we had to face a certain number of immediate retries in case of
* busy and queue full conditions (see below).
* This is not acceptable
* for the latter. Queue full conditions are used
* by devices to indicate to a host that the host can rely
* on the completion (or timeout) of at least one outstanding
* command as a suggested trigger for command retries.
* Busy conditions require a different trigger since
* no commands are outstanding for that initiator from the
* devices perspective.
* The drawback of mapping a queue full condition to a
* busy condition is the chance of wasting all retries prior
* to the time when the device indicates that a command
* rejected due to a queue full condition should be re-driven.
* This case would lead to unnecessary I/O errors that
* have to be considered fatal if for example ext3's
* journaling would be torpedoed by such an avoidable
* I/O error.
* So, what issues are there with not mapping a queue-full
* condition to a busy condition?
* Due to the 'exclusive LUN'
* policy enforced by the zSeries FCP channel, this
* Linux instance is the only initiator with regard to
* this adapter. It is safe to rely on the information
* 'don't disturb me now ... and btw. no other commands
* pending for you' (= queue full) sent by the LU,
* since no other Linux can use this LUN via this adapter
* at the same time. If there is a potential race
* introduced by the FCP channel by not inhibiting Linux A
* to give up a LU with commands pending while Linux B
* grabs this LU and sends commands - thus providing
* an exploit at the 'exclusive LUN' policy - then this
* issue has to be considered a hardware problem. It should
* be tracked as such if it really occurs. Even if the
* FCP Channel spec. begs exploiters to wait for the
* completion of all request sent to a LU prior to
* closing this LU connection.
* This spec. statement in conjunction with
* the 'exclusive LUN' policy is not consistent design.
* Another issue is how resource constraints for SCSI commands
* might be handled by the FCP channel (just guessing for now).
* If the FCP channel would always map resource constraints,
* e.g. no free FC exchange ID due to I/O stress caused by
* other sharing Linux instances, to faked queue-full
* conditions then this would be a misinterpretation and
* violation of SCSI standards.
* If there are SCSI stack races as indicated below
* then they need to be fixed just there.
* Providing all issue above are not applicable or will
* be fixed appropriately, removing the following hack
* is the right thing to do.
*/
/*
* Note: This is a rather nasty chop at the problem. We cannot
* risk adding to the mlqueue however as this will block the
* device. If it is the last outstanding command for this host
* it will remain blocked indefinitely. This would be quite possible
* on the zSeries FCP adapter.
* Also, there exists a race with scsi_insert_special relying on
* scsi_request_fn to recalculate some command data which may not
* happen when q->plugged is true in scsi_request_fn
*/
if (status_byte(scpnt->result) == QUEUE_FULL) {
ZFCP_LOG_DEBUG("Changing QUEUE_FULL to BUSY....\n");
scpnt->result &= ~(QUEUE_FULL << 1);
scpnt->result |= (BUSY << 1);
}
#endif
ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
zfcp_cmd_dbf_event_scsi("response", scpnt);
......@@ -4682,7 +4602,7 @@ zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req,
}
static inline int
zfcp_fsf_req_create_sbal_check(unsigned long *flags,
zfcp_fsf_req_sbal_check(unsigned long *flags,
struct zfcp_qdio_queue *queue, int needed)
{
write_lock_irqsave(&queue->queue_lock, *flags);
......@@ -4713,29 +4633,24 @@ zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd)
* @adapter: adapter for which request queue is examined
* @req_flags: flags indicating whether to wait for needed SBAL or not
* @lock_flags: lock_flags is queue_lock is taken
*
* locking: on success the queue_lock for the request queue of the adapter
* is held
* Return: 0 on success, otherwise -EIO, or -ERESTARTSYS
* Locks: lock adapter->request_queue->queue_lock on success
*/
static int
zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags,
unsigned long *lock_flags)
{
int condition;
long ret;
struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) {
wait_event_interruptible_timeout(adapter->request_wq,
(condition =
zfcp_fsf_req_create_sbal_check
(lock_flags, req_queue, 1)),
ret = wait_event_interruptible_timeout(adapter->request_wq,
zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1),
ZFCP_SBAL_TIMEOUT);
if (!condition) {
return -EIO;
}
} else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) {
if (ret < 0)
return ret;
} else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1))
return -EIO;
}
return 0;
}
......
......@@ -227,6 +227,10 @@
#define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006
#define FSF_HBA_PORTSTATE_ERROR 0x00000007
/* IO states of adapter */
#define FSF_IOSTAT_NPORT_RJT 0x00000004
#define FSF_IOSTAT_FABRIC_RJT 0x00000005
#define FSF_IOSTAT_LS_RJT 0x00000009
struct fsf_queue_designator;
struct fsf_status_read_buffer;
......
......@@ -31,7 +31,7 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
/* this drivers version (do not edit !!! generated and updated by cvs) */
#define ZFCP_SCSI_REVISION "$Revision: 1.65 $"
#define ZFCP_SCSI_REVISION "$Revision: 1.66 $"
#include "zfcp_ext.h"
......@@ -430,7 +430,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
u64 dbf_fsf_req = 0;
u64 dbf_fsf_status = 0;
u64 dbf_fsf_qual[2] = { 0, 0 };
char dbf_result[ZFCP_ABORT_DBF_LENGTH] = { "##undef" };
char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef";
memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH);
memcpy(dbf_opcode,
......
......@@ -26,18 +26,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.33 $"
#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.36 $"
#include "zfcp_ext.h"
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
static const char fc_topologies[5][25] = {
{"<error>"},
{"point-to-point"},
{"fabric"},
{"arbitrated loop"},
{"fabric (virt. adapter)"}
"<error>",
"point-to-point",
"fabric",
"arbitrated loop",
"fabric (virt. adapter)"
};
/**
......@@ -74,29 +74,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
adapter->hardware_version);
ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
/**
* zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter
* @dev: pointer to belonging device
* @buf: pointer to input buffer
*
* Show function of "in_recovery" attribute of adapter. Will be
* "0" if no error recovery is pending for adapter, otherwise "1".
*/
static ssize_t
zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf)
{
struct zfcp_adapter *adapter;
adapter = dev_get_drvdata(dev);
if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
}
static DEVICE_ATTR(in_recovery, S_IRUGO,
zfcp_sysfs_adapter_in_recovery_show, NULL);
ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
/**
* zfcp_sysfs_port_add_store - add a port to sysfs tree
......@@ -138,7 +117,7 @@ zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count)
zfcp_port_put(port);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store);
......@@ -197,7 +176,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count)
zfcp_port_dequeue(port);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
static DEVICE_ATTR(port_remove, S_IWUSR, NULL, zfcp_sysfs_port_remove_store);
......@@ -241,7 +220,7 @@ zfcp_sysfs_adapter_failed_store(struct device *dev,
zfcp_erp_wait(adapter);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
/**
......
......@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.14 $"
#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.15 $"
#include "zfcp_ext.h"
......@@ -65,7 +65,7 @@ static ssize_t zfcp_sysfs_loglevel_##_name##_store(struct device_driver *drv, \
static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev, \
char *buf) \
{ \
return sprintf(buf,"%d\n", \
return sprintf(buf,"%d\n", (unsigned int) \
ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define)); \
} \
\
......
......@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.41 $"
#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.43 $"
#include "zfcp_ext.h"
......@@ -66,6 +66,8 @@ ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
/**
* zfcp_sysfs_unit_add_store - add a unit to sysfs tree
......@@ -107,7 +109,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count)
zfcp_unit_put(unit);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
......@@ -164,7 +166,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count)
zfcp_unit_dequeue(unit);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
......@@ -206,7 +208,7 @@ zfcp_sysfs_port_failed_store(struct device *dev, const char *buf, size_t count)
zfcp_erp_wait(port->adapter);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
/**
......@@ -232,29 +234,6 @@ zfcp_sysfs_port_failed_show(struct device *dev, char *buf)
static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_port_failed_show,
zfcp_sysfs_port_failed_store);
/**
* zfcp_sysfs_port_in_recovery_show - recovery state of port
* @dev: pointer to belonging device
* @buf: pointer to input buffer
*
* Show function of "in_recovery" attribute of port. Will be
* "0" if no error recovery is pending for port, otherwise "1".
*/
static ssize_t
zfcp_sysfs_port_in_recovery_show(struct device *dev, char *buf)
{
struct zfcp_port *port;
port = dev_get_drvdata(dev);
if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
}
static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show,
NULL);
/**
* zfcp_port_common_attrs
* sysfs attributes that are common for all kind of fc ports.
......
......@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.25 $"
#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.27 $"
#include "zfcp_ext.h"
......@@ -64,6 +64,8 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
/**
* zfcp_sysfs_unit_failed_store - failed state of unit
......@@ -101,7 +103,7 @@ zfcp_sysfs_unit_failed_store(struct device *dev, const char *buf, size_t count)
zfcp_erp_wait(unit->port->adapter);
out:
up(&zfcp_data.config_sema);
return retval ? retval : count;
return retval ? retval : (ssize_t) count;
}
/**
......@@ -127,29 +129,6 @@ zfcp_sysfs_unit_failed_show(struct device *dev, char *buf)
static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
zfcp_sysfs_unit_failed_store);
/**
* zfcp_sysfs_unit_in_recovery_show - recovery state of unit
* @dev: pointer to belonging device
* @buf: pointer to input buffer
*
* Show function of "in_recovery" attribute of unit. Will be
* "0" if no error recovery is pending for unit, otherwise "1".
*/
static ssize_t
zfcp_sysfs_unit_in_recovery_show(struct device *dev, char *buf)
{
struct zfcp_unit *unit;
unit = dev_get_drvdata(dev);
if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
}
static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_unit_in_recovery_show,
NULL);
static struct attribute *zfcp_unit_attrs[] = {
&dev_attr_scsi_lun.attr,
&dev_attr_failed.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