zfcp updates for 2.6.31
Subsystems (3)
cover zfcp updates for 2.6.31
James,
this is the series of zfcp patches for the 2.6.31 merge window. My plan was to resubmit the zfcp FC pass-through patch to fix the small issues found during review on linux-scsi. Now that the patch has already been included in scsi-misc, i put the changes in a new patch. I assume this is the simpler approach.
The patches apply on the current scsi-misc tree.
--
Christof Schmitt
PATCH 1/9 zfcp: Use correct req_id for traces
From: Christof Schmitt <[email protected]>
The zfcp traces used the fsf_req address in place of the req_id. Change this to save the correct req_id.
---
drivers/s390/scsi/zfcp_dbf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/s390/scsi/zfcp_dbf.c +5 -5
@@ -163,7 +163,7 @@ void zfcp_hba_dbf_event_fsf_response(str } response->fsf_command = fsf_req->fsf_command; - response->fsf_reqid = (unsigned long )fsf_req; + response->fsf_reqid = fsf_req->req_id; response->fsf_seqno = fsf_req->seq_no; response->fsf_issued = fsf_req->issued; response->fsf_prot_status = qtcb->prefix.prot_status;
@@ -737,7 +737,7 @@ void zfcp_san_dbf_event_ct_request(strucspin_lock_irqsave (&adapter->san_dbf_lock, flags);memset (r,0 ,sizeof (*r));strncpy (r->tag,"octc" ,ZFCP_DBF_TAG_SIZE ); - r->fsf_reqid = (unsigned long )fsf_req; + r->fsf_reqid = fsf_req->req_id; r->fsf_seqno = fsf_req->seq_no; r->s_id =fc_host_port_id (adapter->scsi_host); r->d_id = wka_port->d_id;
@@ -773,7 +773,7 @@ void zfcp_san_dbf_event_ct_response(struspin_lock_irqsave (&adapter->san_dbf_lock, flags);memset (r,0 ,sizeof (*r));strncpy (r->tag,"rctc" ,ZFCP_DBF_TAG_SIZE ); - r->fsf_reqid = (unsigned long )fsf_req; + r->fsf_reqid = fsf_req->req_id; r->fsf_seqno = fsf_req->seq_no; r->s_id = wka_port->d_id; r->d_id =fc_host_port_id (adapter->scsi_host);
@@ -803,7 +803,7 @@ static void zfcp_san_dbf_event_els(constspin_lock_irqsave (&adapter->san_dbf_lock, flags);memset (rec,0 ,sizeof (*rec));strncpy (rec->tag, tag,ZFCP_DBF_TAG_SIZE ); - rec->fsf_reqid = (unsigned long )fsf_req; + rec->fsf_reqid = fsf_req->req_id; rec->fsf_seqno = fsf_req->seq_no; rec->s_id = s_id; rec->d_id = d_id;
@@ -965,7 +965,7 @@ static void zfcp_scsi_dbf_event(const ch ZFCP_DBF_SCSI_FCP_SNS_INFO); } - rec->fsf_reqid = (unsigned long )fsf_req; + rec->fsf_reqid = fsf_req->req_id; rec->fsf_seqno = fsf_req->seq_no; rec->fsf_issued = fsf_req->issued; }
PATCH 2/9 zfcp: Update message and add description
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Update the newly introduced message for the boxed status to conform to match the style of s390 and zfcp messages.
---
drivers/s390/scsi/zfcp_ccw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_ccw.c +2 -2
@@ -176,8 +176,8 @@ static int zfcp_ccw_notify(struct ccw_de "ccnoti4", NULL);break ;case CIO_BOXED : -dev_warn (&adapter->ccw_device->dev, -"The ccw device did not respond in time.\n" ); +dev_warn (&adapter->ccw_device->dev,"The FCP device " +"did not respond within the specified time\n" );zfcp_erp_adapter_shutdown (adapter,0 ,"ccnoti5" ,NULL );break ; }
PATCH 3/9 zfcp: Make queue_depth adjustable
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
zfcp did always set the queue_depth for SCSI devices to 32, not allowing to change this. Introduce a kernel parameter zfcp.queue_depth and the change_queue_depth callback to allow changing the queue_depth when it is required.
---
drivers/s390/scsi/zfcp_scsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_scsi.c +12 -1
@@ -12,6 +12,10 @@#include "zfcp_ext.h" #include <asm/atomic.h> +static unsigned int default_depth =32 ; +module_param_named (queue_depth, default_depth, uint,0600 ); +MODULE_PARM_DESC (queue_depth,"Default queue depth for new SCSI devices" ); +/* Find start of Sense Information in FCP response unit*/ char *zfcp_get_fcp_sns_info_ptr (struct fcp_rsp_iu *fcp_rsp_iu) {
@@ -24,6 +28,12 @@ char *zfcp_get_fcp_sns_info_ptr(struct freturn fcp_sns_info_ptr; } +static int zfcp_scsi_change_queue_depth (struct scsi_device *sdev,int depth) +{ +scsi_adjust_queue_depth (sdev,scsi_get_tag_type (sdev), depth); +return sdev->queue_depth; +} +static void zfcp_scsi_slave_destroy (struct scsi_device *sdpnt) {struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
@@ -34,7 +44,7 @@ static void zfcp_scsi_slave_destroy(strustatic int zfcp_scsi_slave_configure (struct scsi_device *sdp) {if (sdp->tagged_supported) -scsi_adjust_queue_depth (sdp,MSG_SIMPLE_TAG ,32 ); +scsi_adjust_queue_depth (sdp,MSG_SIMPLE_TAG , default_depth);else scsi_adjust_queue_depth (sdp,0 ,1 );return 0 ;
@@ -662,6 +672,7 @@ struct zfcp_data zfcp_data = { .name = "zfcp", .module = THIS_MODULE, .proc_name = "zfcp", + .change_queue_depth = zfcp_scsi_change_queue_depth, .slave_alloc = zfcp_scsi_slave_alloc, .slave_configure = zfcp_scsi_slave_configure, .slave_destroy = zfcp_scsi_slave_destroy,
PATCH 4/9 zfcp: Remove unnecessary default case and assignments
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
enum dma_data_direction only has the 4 values DMA_BIDIRECTIONAL, DMA_TO_DEVICE, DMA_FROM_DEVICE and DMA_NONE. No need to have the default case. While changing this, setup sbtype in one place to make sparse happy.
The default value of retval is already -EIO, so remove the additional assignment for these two cases.
---
drivers/s390/scsi/zfcp_fsf.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +2 -8
@@ -2314,7 +2314,7 @@ int zfcp_fsf_send_fcp_command_task(struc {struct zfcp_fsf_req *req;struct fcp_cmnd_iu *fcp_cmnd_iu; -unsigned int sbtype; +unsigned int sbtype =SBAL_FLAGS0_TYPE_READ ;int real_bytes, retval = -EIO ;struct zfcp_adapter *adapter = unit->port->adapter;
@@ -2356,11 +2356,9 @@ int zfcp_fsf_send_fcp_command_task(strucswitch (scsi_cmnd->sc_data_direction) {case DMA_NONE : req->qtcb->bottom.io.data_direction =FSF_DATADIR_CMND ; - sbtype =SBAL_FLAGS0_TYPE_READ ;break ;case DMA_FROM_DEVICE : req->qtcb->bottom.io.data_direction =FSF_DATADIR_READ ; - sbtype =SBAL_FLAGS0_TYPE_READ ; fcp_cmnd_iu->rddata =1 ;break ;case DMA_TO_DEVICE :
@@ -2369,8 +2367,6 @@ int zfcp_fsf_send_fcp_command_task(struc fcp_cmnd_iu->wddata =1 ;break ;case DMA_BIDIRECTIONAL : -default : - retval = -EIO ; goto failed_scsi_cmnd; }
@@ -2394,9 +2390,7 @@ int zfcp_fsf_send_fcp_command_task(strucscsi_sglist (scsi_cmnd), FSF_MAX_SBALS_PER_REQ);if (unlikely (real_bytes <0 )) { -if (req->sbal_number <FSF_MAX_SBALS_PER_REQ ) - retval = -EIO ; -else { +if (req->sbal_number >=FSF_MAX_SBALS_PER_REQ ) { dev_err(&adapter->ccw_device->dev, "Oversize data package, unit 0x%016Lx " "on port 0x%016Lx closed\n",
PATCH 5/9 zfcp: Add comments to switch/case fallthroughs
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Add comments where there is a deliberate fall through in switch/case statements. This makes some code checkers happy and makes it clear that there is no missing break statement.
---
drivers/s390/scsi/zfcp_erp.c | 1 + drivers/s390/scsi/zfcp_fsf.c | 5 +++++ 2 files changed, 6 insertions(+)
drivers/s390/scsi/zfcp_erp.c +1 -0
@@ -880,6 +880,7 @@ static int zfcp_erp_port_strategy_open_czfcp_port_put (port);return ZFCP_ERP_CONTINUES ; } +/* fall through */ case ZFCP_ERP_STEP_NAMESERVER_LOOKUP :if (!port->d_id)return ZFCP_ERP_FAILED ;
drivers/s390/scsi/zfcp_fsf.c +5 -0
@@ -526,6 +526,7 @@ static int zfcp_fsf_exchange_config_evalbreak ;case FSF_TOPO_AL :fc_host_port_type (shost) =FC_PORTTYPE_NLPORT ; +/* fall through */ default :dev_err (&adapter->ccw_device->dev, "Unknown or unsupported arbitrated loop "
@@ -897,6 +898,7 @@ static void zfcp_fsf_abort_fcp_command_hswitch (fsq->word[0 ]) {case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE :zfcp_test_link (unit->port); +/* fall through */ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED : req->status |=ZFCP_STATUS_FSFREQ_ERROR ;break ;
@@ -993,6 +995,7 @@ static void zfcp_fsf_send_ct_handler(strbreak ;case FSF_PORT_HANDLE_NOT_VALID :zfcp_erp_adapter_reopen (adapter,0 ,"fsscth1" , req); +/* fall through */ case FSF_GENERIC_COMMAND_REJECTED :case FSF_PAYLOAD_SIZE_MISMATCH :case FSF_REQUEST_SIZE_TOO_LARGE :
@@ -1590,8 +1593,10 @@ static void zfcp_fsf_open_wka_port_handlcase FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED :dev_warn (&req->adapter->ccw_device->dev,"Opening WKA port 0x%x failed\n" , wka_port->d_id); +/* fall through */ case FSF_ADAPTER_STATUS_AVAILABLE : req->status |=ZFCP_STATUS_FSFREQ_ERROR ; +/* fall through */ case FSF_ACCESS_DENIED : wka_port->status =ZFCP_WKA_PORT_OFFLINE ;break ;
PATCH 6/9 zfcp: Increase ref counter for port open requests
In reply to Christof SchmittFrom: Martin Petermann <[email protected]>
In rare cases, open port request might timeout, erp calls zfcp_port_put, port gets dequeued. Now, the late returning (or dismissed) fsf-port-open calls the fsf_port_open_handler that tries to reference the port data structure leading to a kernel oops.
---
drivers/s390/scsi/zfcp_fsf.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +9 -3
@@ -1402,7 +1402,7 @@ static void zfcp_fsf_open_port_handler(sstruct fsf_plogi *plogi;if (req->status &ZFCP_STATUS_FSFREQ_ERROR ) -return ; + goto out;switch (header->fsf_status) {case FSF_PORT_ALREADY_OPEN :
@@ -1464,6 +1464,9 @@ static void zfcp_fsf_open_port_handler(s req->status |=ZFCP_STATUS_FSFREQ_ERROR ;break ; } + +out: +zfcp_port_put (port); }/**
@@ -1476,6 +1479,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_astruct qdio_buffer_element *sbale;struct zfcp_adapter *adapter = erp_action->adapter;struct zfcp_fsf_req *req; +struct zfcp_port *port = erp_action->port;int retval = -EIO ;spin_lock_bh (&adapter->req_q_lock);
@@ -1496,16 +1500,18 @@ int zfcp_fsf_open_port(struct zfcp_erp_a sbale[1 ].flags |=SBAL_FLAGS_LAST_ENTRY ; req->handler = zfcp_fsf_open_port_handler; - req->qtcb->bottom.support.d_id = erp_action->port->d_id; - req->data = erp_action->port; + req->qtcb->bottom.support.d_id = port->d_id; + req->data = port; req->erp_action = erp_action; erp_action->fsf_req = req; +zfcp_port_get (port);zfcp_fsf_start_erp_timer (req); retval =zfcp_fsf_req_send (req);if (retval) {zfcp_fsf_req_free (req); erp_action->fsf_req =NULL ; +zfcp_port_put (port); } out:spin_unlock_bh (&adapter->req_q_lock);
PATCH 7/9 zfcp: Changed D_ID left port disabled
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
If the destination ID (D_ID) of a remote storage port changed, e.g. re-plugged cable on the switch in a different switch port, the port was never (re-)attached within Linux. This patch fixes the broken mapping between the WWPN and the D_ID.
---
drivers/s390/scsi/zfcp_erp.c | 7 ++++++- drivers/s390/scsi/zfcp_fc.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_erp.c +6 -1
@@ -895,8 +895,13 @@ static int zfcp_erp_port_strategy_open_c act->step =ZFCP_ERP_STEP_PORT_CLOSING ;return ZFCP_ERP_CONTINUES ; } -/* fall through otherwise */ } +if (port->d_id && !(p_status &ZFCP_STATUS_COMMON_NOESC )) { + port->d_id =0 ; +_zfcp_erp_port_reopen (port,0 ,"erpsoc1" ,NULL ); +return ZFCP_ERP_EXIT ; + } +/* fall through otherwise */ }return ZFCP_ERP_FAILED ; }
drivers/s390/scsi/zfcp_fc.c +6 -1
@@ -160,9 +160,14 @@ static void _zfcp_fc_incoming_rscn(strucstruct zfcp_port *port;read_lock_irqsave (&zfcp_data.config_lock, flags); -list_for_each_entry (port, &fsf_req->adapter->port_list_head, list) +list_for_each_entry (port, &fsf_req->adapter->port_list_head, list) {if ((port->d_id & range) == (elem->nport_did & range))zfcp_test_link (port); +if (!port->d_id) +zfcp_erp_port_reopen (port, +ZFCP_STATUS_COMMON_ERP_FAILED , +"fcrscn1" ,NULL ); + }read_unlock_irqrestore (&zfcp_data.config_lock, flags); }
PATCH 8/9 zfcp: Keep ccw device and model id in zfcp_ccw.c
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Keep the information about the device and model id in zfcp_ccw. This requires an additional helper function to check for the privileged cfdc subchannel, but it allows the removal of the redundant defines from the zfcp_def header file.
---
drivers/s390/scsi/zfcp_ccw.c | 26 ++++++++++++++++++-------- drivers/s390/scsi/zfcp_def.h | 7 ------- drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fsf.c | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-)
drivers/s390/scsi/zfcp_ccw.c +18 -8
@@ -11,6 +11,24 @@#include "zfcp_ext.h" +#define ZFCP_MODEL_PRIV 0x4 + +static struct ccw_device_id zfcp_ccw_device_id[] = { + {CCW_DEVICE_DEVTYPE (0x1731 ,0x3 ,0x1732 ,0x3 ) }, + {CCW_DEVICE_DEVTYPE (0x1731 ,0x3 ,0x1732 ,ZFCP_MODEL_PRIV ) }, + {}, +}; +MODULE_DEVICE_TABLE (ccw, zfcp_ccw_device_id); + +/** +* zfcp_ccw_priv_sch - check if subchannel is privileged +* @adapter: Adapter/Subchannel to check +*/ +int zfcp_ccw_priv_sch (struct zfcp_adapter *adapter) +{ +return adapter->ccw_device->id.dev_model ==ZFCP_MODEL_PRIV ; +} +/** * zfcp_ccw_probe - probe function of zfcp driver * @ccw_device: pointer to belonging ccw device
@@ -199,14 +217,6 @@ static void zfcp_ccw_shutdown(struct ccwup (&zfcp_data.config_sema); } -static struct ccw_device_id zfcp_ccw_device_id[] = { - {CCW_DEVICE_DEVTYPE (0x1731 ,0x3 ,0x1732 ,0x3 ) }, - {CCW_DEVICE_DEVTYPE (0x1731 ,0x3 ,0x1732 ,0x4 ) },/* priv. */ - {}, -}; - -MODULE_DEVICE_TABLE (ccw, zfcp_ccw_device_id); -static struct ccw_driver zfcp_ccw_driver = { .owner =THIS_MODULE , .name ="zfcp" ,
drivers/s390/scsi/zfcp_def.h +0 -7
@@ -50,13 +50,6 @@/********************* CIO/QDIO SPECIFIC DEFINES *****************************/ -/* Adapter Identification Parameters */ -#define ZFCP_CONTROL_UNIT_TYPE 0x1731 -#define ZFCP_CONTROL_UNIT_MODEL 0x03 -#define ZFCP_DEVICE_TYPE 0x1732 -#define ZFCP_DEVICE_MODEL 0x03 -#define ZFCP_DEVICE_MODEL_PRIV 0x04 -/* DMQ bug workaround: don't use last SBALE */ #define ZFCP_MAX_SBALES_PER_SBAL (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
drivers/s390/scsi/zfcp_ext.h +1 -0
@@ -27,6 +27,7 @@ extern int zfcp_sg_setup_table(struct sc/* zfcp_ccw.c */ extern int zfcp_ccw_register (void ); +extern int zfcp_ccw_priv_sch (struct zfcp_adapter *);extern struct zfcp_adapter *zfcp_get_adapter_by_busid (char *);/* zfcp_cfdc.c */
drivers/s390/scsi/zfcp_fsf.c +1 -1
@@ -1887,7 +1887,7 @@ static void zfcp_fsf_open_unit_handler(sif (!(adapter->connection_features &FSF_FEATURE_NPIV_MODE ) && (adapter->adapter_features &FSF_FEATURE_LUN_SHARING ) && - (adapter->ccw_device->id.dev_model !=ZFCP_DEVICE_MODEL_PRIV )) { + !zfcp_ccw_priv_sch (adapter)) { exclusive = (bottom->lun_access_info &FSF_UNIT_ACCESS_EXCLUSIVE ); readwrite = (bottom->lun_access_info &
PATCH 9/9 zfcp: Update FC pass-through support
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Don't access the block layer request, get the payload length instead from the FC job. Simplify access to the zfcp_port, only the d_id is required, if the port is no longer accessed later. This is possible when the els_handler does not access the port pointer from the ELS request.
--- drivers/s390/scsi/zfcp_fc.c | 9 +++------ drivers/s390/scsi/zfcp_fsf.c | 3 ++- 2 files changed, 5 insertions(+), 7 deletions(-)
drivers/s390/scsi/zfcp_fc.c +3 -6
@@ -704,7 +704,7 @@ static void zfcp_fc_generic_els_handler( } reply->reply_data.ctels_reply.status =FC_CTELS_STATUS_OK ; - reply->reply_payload_rcv_len =blk_rq_bytes (job->req->next_rq); + reply->reply_payload_rcv_len = job->reply_payload.payload_len; out: job->state_flags =FC_RQST_STATE_DONE ;
@@ -736,15 +736,12 @@ int zfcp_fc_execute_els_fc_job(struct fcread_lock_irq (&zfcp_data.config_lock); port = rport->dd_data;if (port) -zfcp_port_get (port); + els_fc_job->els.d_id = port->d_id;read_unlock_irq (&zfcp_data.config_lock);if (!port) {kfree (els_fc_job);return -EINVAL ; } - els_fc_job->els.port = port; - els_fc_job->els.d_id = port->d_id; -zfcp_port_put (port); }else { port_did = job->request->rqst_data.h_els.port_id; els_fc_job->els.d_id = (port_did[0] << 16) +
@@ -772,8 +769,8 @@ static void zfcp_fc_generic_ct_handler(u job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ?FC_CTELS_STATUS_REJECT :FC_CTELS_STATUS_OK ; + job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; job->state_flags =FC_RQST_STATE_DONE ; - job->reply->reply_payload_rcv_len =blk_rq_bytes (job->req->next_rq); job->job_done (job);zfcp_wka_port_put (ct_fc_job->ct.wka_port);
drivers/s390/scsi/zfcp_fsf.c +2 -1
@@ -1146,7 +1146,8 @@ static void zfcp_fsf_send_els_handler(stcase FSF_RESPONSE_SIZE_TOO_LARGE :break ;case FSF_ACCESS_DENIED : -zfcp_fsf_access_denied_port (req, port); +if (port) +zfcp_fsf_access_denied_port (req, port);break ;case FSF_SBAL_MISMATCH :/* should never occure, avoided in zfcp_fsf_send_els */