From: Martin Schwidefsky From: Heiko Carstens From: Andreas Herrmann From: Maxim Shchetynin 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: Martin Schwidefsky Signed-off-by: Andrew Morton --- 25-akpm/drivers/s390/scsi/zfcp_aux.c | 205 ++++++++++++++++++++++-- 25-akpm/drivers/s390/scsi/zfcp_def.h | 23 +- 25-akpm/drivers/s390/scsi/zfcp_erp.c | 209 +++++++------------------ 25-akpm/drivers/s390/scsi/zfcp_ext.h | 6 25-akpm/drivers/s390/scsi/zfcp_fsf.c | 121 ++------------ 25-akpm/drivers/s390/scsi/zfcp_fsf.h | 4 25-akpm/drivers/s390/scsi/zfcp_scsi.c | 4 25-akpm/drivers/s390/scsi/zfcp_sysfs_adapter.c | 43 +---- 25-akpm/drivers/s390/scsi/zfcp_sysfs_driver.c | 4 25-akpm/drivers/s390/scsi/zfcp_sysfs_port.c | 33 --- 25-akpm/drivers/s390/scsi/zfcp_sysfs_unit.c | 29 --- 11 files changed, 311 insertions(+), 370 deletions(-) diff -puN drivers/s390/scsi/zfcp_aux.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_aux.c --- 25/drivers/s390/scsi/zfcp_aux.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_aux.c Tue Aug 17 15:45:35 2004 @@ -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(unsig 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 initia 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, 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, 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 *s * -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_ * -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(unsig 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(unsig 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 @@ failed: 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 diff -puN drivers/s390/scsi/zfcp_def.h~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_def.h --- 25/drivers/s390/scsi/zfcp_def.h~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_def.h Tue Aug 17 15:45:35 2004 @@ -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,13 +296,11 @@ 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; - u8 reason_code; - u8 reason_expl; - u8 vendor_unique; +struct zfcp_ls_rjt_par { + u8 action; + u8 reason_code; + u8 reason_expl; + u8 vendor_unique; } __attribute__ ((packed)); struct zfcp_ls_rtv { @@ -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 */ diff -puN drivers/s390/scsi/zfcp_erp.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_erp.c --- 25/drivers/s390/scsi/zfcp_erp.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_erp.c Tue Aug 17 15:45:35 2004 @@ -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_c 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,185 +413,99 @@ out: } -/* - * 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) { + switch (req_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; + case ZFCP_LS_RTV: + rtv = (struct zfcp_ls_rtv_acc*)resp; + ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id " + "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n", + port->d_id, port->adapter->s_id, + rtv->r_a_tov, rtv->e_d_tov, + rtv->qualifier & + ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm'); break; - case ZFCP_LS_ACC: - switch (req_code) { + case ZFCP_LS_RLS: + rls = (struct zfcp_ls_rls_acc*)resp; + ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id " + "0x%08x (link_failure_count=%u, " + "loss_of_sync_count=%u, " + "loss_of_signal_count=%u, " + "primitive_sequence_protocol_error=%u, " + "invalid_transmition_word=%u, " + "invalid_crc_count=%u)\n", + port->d_id, port->adapter->s_id, + rls->link_failure_count, + rls->loss_of_sync_count, + rls->loss_of_signal_count, + rls->prim_seq_prot_error, + rls->invalid_transmition_word, + rls->invalid_crc_count); + break; - case ZFCP_LS_RTV: - rtv = (struct zfcp_ls_rtv_acc*)resp; - ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id " - "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n", - port->d_id, port->adapter->s_id, - rtv->r_a_tov, rtv->e_d_tov, - rtv->qualifier & - ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm'); - break; - - case ZFCP_LS_RLS: - rls = (struct zfcp_ls_rls_acc*)resp; - ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id " - "0x%08x (link_failure_count=%u, " - "loss_of_sync_count=%u, " - "loss_of_signal_count=%u, " - "primitive_sequence_protocol_error=%u, " - "invalid_transmition_word=%u, " - "invalid_crc_count=%u)\n", - port->d_id, port->adapter->s_id, - rls->link_failure_count, - rls->loss_of_sync_count, - rls->loss_of_signal_count, - rls->prim_seq_prot_error, - rls->invalid_transmition_word, - rls->invalid_crc_count); - break; - - case ZFCP_LS_PDISC: - pdisc = (struct zfcp_ls_pdisc_acc*)resp; - ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id " - "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "vendor='%-16s')\n", port->d_id, - port->adapter->s_id, pdisc->wwpn, - pdisc->wwnn, pdisc->vendor_version); - break; - - case ZFCP_LS_ADISC: - adisc = (struct zfcp_ls_adisc_acc*)resp; - ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " - "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "hard_nport_id=0x%08x, " - "nport_id=0x%08x)\n", port->d_id, - port->adapter->s_id, adisc->wwpn, - adisc->wwnn, adisc->hard_nport_id, - adisc->nport_id); - /* FIXME: set wwnn in during open port */ - if (port->wwnn == 0) - port->wwnn = adisc->wwnn; - break; - } + case ZFCP_LS_PDISC: + pdisc = (struct zfcp_ls_pdisc_acc*)resp; + ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id " + "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " + "vendor='%-16s')\n", port->d_id, + port->adapter->s_id, pdisc->wwpn, + pdisc->wwnn, pdisc->vendor_version); 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; - } + case ZFCP_LS_ADISC: + adisc = (struct zfcp_ls_adisc_acc*)resp; + ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " + "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " + "hard_nport_id=0x%08x, " + "nport_id=0x%08x)\n", port->d_id, + port->adapter->s_id, adisc->wwpn, + adisc->wwnn, adisc->hard_nport_id, + adisc->nport_id); + /* FIXME: set wwnn in during open port */ + if (port->wwnn == 0) + port->wwnn = adisc->wwnn; + break; } -skip_fsfstatus: + out: __free_pages(send_els->req->page, 0); kfree(send_els->req); kfree(send_els->resp); - - return retval; + kfree(send_els); } diff -puN drivers/s390/scsi/zfcp_ext.h~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_ext.h --- 25/drivers/s390/scsi/zfcp_ext.h~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_ext.h Tue Aug 17 15:45:35 2004 @@ -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_sen 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 *); diff -puN drivers/s390/scsi/zfcp_fsf.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_fsf.c --- 25/drivers/s390/scsi/zfcp_fsf.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_fsf.c Tue Aug 17 15:45:35 2004 @@ -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( 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(str /* 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 @@ skip_fsfstatus: 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(s } 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,8 +4602,8 @@ zfcp_fsf_req_wait_and_cleanup(struct zfc } static inline int -zfcp_fsf_req_create_sbal_check(unsigned long *flags, - struct zfcp_qdio_queue *queue, int needed) +zfcp_fsf_req_sbal_check(unsigned long *flags, + struct zfcp_qdio_queue *queue, int needed) { write_lock_irqsave(&queue->queue_lock, *flags); if (likely(atomic_read(&queue->free_count) >= needed)) @@ -4713,29 +4633,24 @@ zfcp_fsf_req_qtcb_init(struct zfcp_fsf_r * @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)), - ZFCP_SBAL_TIMEOUT); - if (!condition) { - return -EIO; - } - } else if (!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 (ret < 0) + return ret; + } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1)) return -EIO; - } return 0; } diff -puN drivers/s390/scsi/zfcp_fsf.h~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_fsf.h --- 25/drivers/s390/scsi/zfcp_fsf.h~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_fsf.h Tue Aug 17 15:45:35 2004 @@ -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; diff -puN drivers/s390/scsi/zfcp_scsi.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_scsi.c --- 25/drivers/s390/scsi/zfcp_scsi.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_scsi.c Tue Aug 17 15:45:35 2004 @@ -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_c 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, diff -puN drivers/s390/scsi/zfcp_sysfs_adapter.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_sysfs_adapter.c --- 25/drivers/s390/scsi/zfcp_sysfs_adapter.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_sysfs_adapter.c Tue Aug 17 15:45:35 2004 @@ -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] = { - {""}, - {"point-to-point"}, - {"fabric"}, - {"arbitrated loop"}, - {"fabric (virt. adapter)"} + "", + "point-to-point", + "fabric", + "arbitrated loop", + "fabric (virt. adapter)" }; /** @@ -74,29 +74,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(hardware_versio 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 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 devi 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 d zfcp_erp_wait(adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** diff -puN drivers/s390/scsi/zfcp_sysfs_driver.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_sysfs_driver.c --- 25/drivers/s390/scsi/zfcp_sysfs_driver.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_sysfs_driver.c Tue Aug 17 15:45:35 2004 @@ -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_##_na 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)); \ } \ \ diff -puN drivers/s390/scsi/zfcp_sysfs_port.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_sysfs_port.c --- 25/drivers/s390/scsi/zfcp_sysfs_port.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_sysfs_port.c Tue Aug 17 15:45:35 2004 @@ -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" 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 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 devi 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 devi zfcp_erp_wait(port->adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** @@ -233,29 +235,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_I 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. */ diff -puN drivers/s390/scsi/zfcp_sysfs_unit.c~s390-zfcp-host-adapter drivers/s390/scsi/zfcp_sysfs_unit.c --- 25/drivers/s390/scsi/zfcp_sysfs_unit.c~s390-zfcp-host-adapter Tue Aug 17 15:45:35 2004 +++ 25-akpm/drivers/s390/scsi/zfcp_sysfs_unit.c Tue Aug 17 15:45:35 2004 @@ -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_ 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 devi 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 devic 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, _