zfcp updates for 2.6.30
Subsystems (3)
cover zfcp updates for 2.6.30
James,
here is the series of zfcp updates for the 2.6.30 merge window. The patches are based on the current linux-2.6 tree.
--
Christof Schmitt
PATCH 1/18 zfcp: Remove some port flags
From: Christof Schmitt <[email protected]>
PORT_PHYS_CLOSING is only set and cleared, but not actually used for status checking.
PORT_INVALID_WWPN is set when the GID_PN request does not return a d_id for a remote port, e.g. when a remote port has been unplugged. For this case, the d_id is zero. In the erp we can check the d_id and use the normal escalation procedure that gives up after three retries and remove the special case.
PORT_NO_WWPN is unused: Each port in the remote port list has a valid wwpn. The WKA ports are now tracked outside the port list. Remove the PORT_NO_WWPN flag, since this is no longer set for any port.
---
drivers/s390/scsi/zfcp_aux.c | 13 ++++++------- drivers/s390/scsi/zfcp_def.h | 3 --- drivers/s390/scsi/zfcp_erp.c | 16 ++-------------- drivers/s390/scsi/zfcp_fc.c | 5 ++--- drivers/s390/scsi/zfcp_fsf.c | 6 +----- 5 files changed, 11 insertions(+), 32 deletions(-)
drivers/s390/scsi/zfcp_aux.c +6 -7
@@ -249,8 +249,8 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_port *port;list_for_each_entry (port, &adapter->port_list_head, list) -if ((port->wwpn == wwpn) && !(atomic_read (&port->status) & - (ZFCP_STATUS_PORT_NO_WWPN |ZFCP_STATUS_COMMON_REMOVE ))) +if ((port->wwpn == wwpn) && + !(atomic_read (&port->status) &ZFCP_STATUS_COMMON_REMOVE ))return port;return NULL ; }
@@ -620,11 +620,10 @@ struct zfcp_port *zfcp_port_enqueue(strudev_set_drvdata (&port->sysfs_device, port);read_lock_irq (&zfcp_data.config_lock); -if (!(status &ZFCP_STATUS_PORT_NO_WWPN )) -if (zfcp_get_port_by_wwpn (adapter, wwpn)) { -read_unlock_irq (&zfcp_data.config_lock); - goto err_out_free; - } +if (zfcp_get_port_by_wwpn (adapter, wwpn)) { +read_unlock_irq (&zfcp_data.config_lock); + goto err_out_free; + }read_unlock_irq (&zfcp_data.config_lock);if (device_register (&port->sysfs_device))
drivers/s390/scsi/zfcp_def.h +0 -3
@@ -243,9 +243,6 @@ struct zfcp_ls_adisc {/* remote port status */ #define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001 -#define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004 -#define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 -#define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020/* well known address (WKA) port status*/ enum zfcp_wka_status {
drivers/s390/scsi/zfcp_erp.c +2 -14
@@ -777,10 +777,7 @@ static int zfcp_erp_port_forced_strategystatic void zfcp_erp_port_strategy_clearstati (struct zfcp_port *port) { -atomic_clear_mask (ZFCP_STATUS_COMMON_ACCESS_DENIED | -ZFCP_STATUS_PORT_PHYS_CLOSING | -ZFCP_STATUS_PORT_INVALID_WWPN , - &port->status); +atomic_clear_mask (ZFCP_STATUS_COMMON_ACCESS_DENIED , &port->status); }static int zfcp_erp_port_forced_strategy (struct zfcp_erp_action *erp_action)
@@ -875,13 +872,8 @@ static int zfcp_erp_port_strategy_open_creturn ZFCP_ERP_CONTINUES ; }case ZFCP_ERP_STEP_NAMESERVER_LOOKUP : -if (!port->d_id) { -if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN )) { -zfcp_erp_port_failed (port,26 ,NULL ); -return ZFCP_ERP_EXIT ; - } +if (!port->d_id)return ZFCP_ERP_FAILED ; - }return zfcp_erp_port_strategy_open_port (act);case ZFCP_ERP_STEP_PORT_OPENING :
@@ -1269,10 +1261,6 @@ static void zfcp_erp_action_cleanup(strucase ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :case ZFCP_ERP_ACTION_REOPEN_PORT : -if (atomic_read (&port->status) &ZFCP_STATUS_PORT_NO_WWPN ) { -zfcp_port_put (port); -return ; - }if ((result ==ZFCP_ERP_SUCCEEDED ) && !port->rport)zfcp_erp_rport_register (port);if ((result !=ZFCP_ERP_SUCCEEDED ) && port->rport) {
drivers/s390/scsi/zfcp_fc.c +2 -3
@@ -259,10 +259,9 @@ static void zfcp_fc_ns_gid_pn_eval(unsigif (ct->status)return ; -if (ct_iu_resp->header.cmd_rsp_code !=ZFCP_CT_ACCEPT ) { -atomic_set_mask (ZFCP_STATUS_PORT_INVALID_WWPN , &port->status); +if (ct_iu_resp->header.cmd_rsp_code !=ZFCP_CT_ACCEPT )return ; - } +/* paranoia */ if (ct_iu_req->wwpn != port->wwpn)return ;
drivers/s390/scsi/zfcp_fsf.c +1 -5
@@ -1712,7 +1712,7 @@ static void zfcp_fsf_close_physical_portstruct zfcp_unit *unit;if (req->status &ZFCP_STATUS_FSFREQ_ERROR ) - goto skip_fsfstatus; +return ;switch (header->fsf_status) {case FSF_PORT_HANDLE_NOT_VALID :
@@ -1752,8 +1752,6 @@ static void zfcp_fsf_close_physical_port &unit->status);break ; } -skip_fsfstatus: -atomic_clear_mask (ZFCP_STATUS_PORT_PHYS_CLOSING , &port->status); }/**
@@ -1789,8 +1787,6 @@ int zfcp_fsf_close_physical_port(struct req->erp_action = erp_action; req->handler = zfcp_fsf_close_physical_port_handler; erp_action->fsf_req = req; -atomic_set_mask (ZFCP_STATUS_PORT_PHYS_CLOSING , - &erp_action->port->status);zfcp_fsf_start_erp_timer (req); retval =zfcp_fsf_req_send (req);
PATCH 2/18 zfcp: Remove UNIT_REGISTERED status flag
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Use the device pointer in zfcp_unit for tracking if we have a registered SCSI device. With this approach, the flag ZFCP_STATUS_UNIT_REGISTERED is only redundant and can be removed.
---
drivers/s390/scsi/zfcp_ccw.c | 3 +-- drivers/s390/scsi/zfcp_def.h | 1 - drivers/s390/scsi/zfcp_erp.c | 2 -- drivers/s390/scsi/zfcp_scsi.c | 4 +--- 4 files changed, 2 insertions(+), 8 deletions(-)
drivers/s390/scsi/zfcp_ccw.c +1 -2
@@ -72,8 +72,7 @@ static void zfcp_ccw_remove(struct ccw_dlist_for_each_entry_safe (port, p, &port_remove_lh, list) {list_for_each_entry_safe (unit, u, &unit_remove_lh, list) { -if (atomic_read (&unit->status) & -ZFCP_STATUS_UNIT_REGISTERED ) +if (unit->device)scsi_remove_device (unit->device);zfcp_unit_dequeue (unit); }
drivers/s390/scsi/zfcp_def.h +0 -1
@@ -255,7 +255,6 @@ enum zfcp_wka_status {/* logical unit status */ #define ZFCP_STATUS_UNIT_SHARED 0x00000004#define ZFCP_STATUS_UNIT_READONLY 0x00000008 -#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020/* FSF request status (this does not have a common part) */
drivers/s390/scsi/zfcp_erp.c +0 -2
@@ -1250,8 +1250,6 @@ static void zfcp_erp_action_cleanup(strucase ZFCP_ERP_ACTION_REOPEN_UNIT :if ((result ==ZFCP_ERP_SUCCEEDED ) && !unit->device && port->rport) { -atomic_set_mask (ZFCP_STATUS_UNIT_REGISTERED , - &unit->status);if (!(atomic_read (&unit->status) &ZFCP_STATUS_UNIT_SCSI_WORK_PENDING ))zfcp_erp_schedule_work (unit);
drivers/s390/scsi/zfcp_scsi.c +1 -3
@@ -27,7 +27,6 @@ char *zfcp_get_fcp_sns_info_ptr(struct fstatic void zfcp_scsi_slave_destroy (struct scsi_device *sdpnt) {struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; -atomic_clear_mask (ZFCP_STATUS_UNIT_REGISTERED , &unit->status); unit->device =NULL ;zfcp_erp_unit_failed (unit,12 ,NULL );zfcp_unit_put (unit);
@@ -133,8 +132,7 @@ static int zfcp_scsi_slave_alloc(structread_lock_irqsave (&zfcp_data.config_lock, flags); unit =zfcp_unit_lookup (adapter, sdp->channel, sdp->id, sdp->lun); -if (unit && - (atomic_read (&unit->status) &ZFCP_STATUS_UNIT_REGISTERED )) { +if (unit) { sdp->hostdata = unit; unit->device = sdp;zfcp_unit_get (unit);
PATCH 3/18 zfcp: add measurement data for average qdio queue utilisation
In reply to Christof SchmittFrom: Martin Peschke <[email protected]>
Provide measurement data for the utilisation of the QDIO outbound queue. The additional value allows to calculate an average queue utilisation by looking at the deltas per time unit. Needed for capacity planning. It is up to user space to handle wrap-arounds of the 64 bit value.
The new counter neatly complements the existing counter for queue full conditions. That is why, both statistics counter have been integrated.
---
drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_def.h | 3 +++ drivers/s390/scsi/zfcp_qdio.c | 20 ++++++++++++++++++++ drivers/s390/scsi/zfcp_sysfs.c | 3 ++- 4 files changed, 26 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_aux.c +1 -0
@@ -501,6 +501,7 @@ int zfcp_adapter_enqueue(struct ccw_devispin_lock_init (&adapter->scsi_dbf_lock);spin_lock_init (&adapter->rec_dbf_lock);spin_lock_init (&adapter->req_q_lock); +spin_lock_init (&adapter->qdio_stat_lock);rwlock_init (&adapter->erp_lock);rwlock_init (&adapter->abort_lock);
drivers/s390/scsi/zfcp_def.h +3 -0
@@ -445,6 +445,9 @@ struct zfcp_adapter {spinlock_t req_q_lock;/* for operations on queue */ int req_q_pci_batch;/* SBALs since PCI indication was last set */ +ktime_t req_q_time;/* time of last fill level change */ +u64 req_q_util;/* for accounting */ +spinlock_t qdio_stat_lock;u32 fsf_req_seq_no;/* FSF cmnd seq number */ wait_queue_head_t request_wq;/* can be used to wait for more avaliable SBALs */
drivers/s390/scsi/zfcp_qdio.c +20 -0
@@ -77,6 +77,23 @@ static void zfcp_qdio_zero_sbals(struct } } +/* this needs to be called prior to updating the queue fill level */ +static void zfcp_qdio_account (struct zfcp_adapter *adapter) +{ +ktime_t now; +s64 span; +int free, used; + +spin_lock (&adapter->qdio_stat_lock); + now =ktime_get (); + span =ktime_us_delta (now, adapter->req_q_time); + free =max (0 ,atomic_read (&adapter->req_q.count)); + used =QDIO_MAX_BUFFERS_PER_Q - free; + adapter->req_q_util += used * span; + adapter->req_q_time = now; +spin_unlock (&adapter->qdio_stat_lock); +} +static void zfcp_qdio_int_req (struct ccw_device *cdev,unsigned int qdio_err,int queue_no,int first,int count,unsigned long parm)
@@ -93,6 +110,7 @@ static void zfcp_qdio_int_req(struct ccw/* cleanup all SBALs being program-owned now */ zfcp_qdio_zero_sbals (queue->sbal, first, count); +zfcp_qdio_account (adapter);atomic_add (count, &queue->count);wake_up (&adapter->request_wq); }
@@ -359,6 +377,8 @@ int zfcp_qdio_send(struct zfcp_fsf_req * sbale->flags |=SBAL_FLAGS0_PCI ; } +zfcp_qdio_account (adapter); + retval =do_QDIO (adapter->ccw_device,QDIO_FLAG_SYNC_OUTPUT ,0 , first, count);if (unlikely (retval)) {
drivers/s390/scsi/zfcp_sysfs.c +2 -1
@@ -487,7 +487,8 @@ static ssize_t zfcp_sysfs_adapter_q_fullstruct zfcp_adapter *adapter = (struct zfcp_adapter *) scsi_host->hostdata[0 ]; -return sprintf (buf,"%d\n" ,atomic_read (&adapter->qdio_outb_full)); +return sprintf (buf,"%d %llu\n" ,atomic_read (&adapter->qdio_outb_full), + (unsigned long long )adapter->req_q_util); } static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
PATCH 4/18 zfcp: Simplify latency lock handling
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
The lock only needs to protect the softirq context called from qdio against the userspace context called from sysfs. spin_lock and spin_lock_bh is enough.
---
drivers/s390/scsi/zfcp_fsf.c | 5 ++--- drivers/s390/scsi/zfcp_sysfs.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +2 -3
@@ -2069,7 +2069,6 @@ static void zfcp_fsf_req_latency(structstruct fsf_qual_latency_info *lat_inf;struct latency_cont *lat;struct zfcp_unit *unit = req->unit; -unsigned long flags; lat_inf = &req->qtcb->prefix.prot_status_qual.latency_info;
@@ -2087,11 +2086,11 @@ static void zfcp_fsf_req_latency(structreturn ; } -spin_lock_irqsave (&unit->latencies.lock, flags); +spin_lock (&unit->latencies.lock);zfcp_fsf_update_lat (&lat->channel, lat_inf->channel_lat);zfcp_fsf_update_lat (&lat->fabric, lat_inf->fabric_lat); lat->counter++; -spin_unlock_irqrestore (&unit->latencies.lock, flags); +spin_unlock (&unit->latencies.lock); }#ifdef CONFIG_BLK_DEV_IO_TRACE
drivers/s390/scsi/zfcp_sysfs.c +2 -3
@@ -318,10 +318,9 @@ zfcp_sysfs_unit_##_name##_latency_show(sstruct zfcp_unit *unit = sdev->hostdata; \struct zfcp_latencies *lat = &unit->latencies; \struct zfcp_adapter *adapter = unit->port->adapter; \ -unsigned long flags; \unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \ \ -spin_lock_irqsave (&lat->lock, flags); \ +spin_lock_bh (&lat->lock); \ fsum = lat->_name.fabric.sum * adapter->timer_ticks; \ fmin = lat->_name.fabric.min * adapter->timer_ticks; \ fmax = lat->_name.fabric.max * adapter->timer_ticks; \
@@ -329,7 +328,7 @@ zfcp_sysfs_unit_##_name##_latency_show(s cmin = lat->_name.channel.min * adapter->timer_ticks; \ cmax = lat->_name.channel.max * adapter->timer_ticks; \ cc = lat->_name.counter; \ -spin_unlock_irqrestore (&lat->lock, flags); \ +spin_unlock_bh (&lat->lock); \ \do_div (fsum,1000 ); \do_div (fmin,1000 ); \
PATCH 5/18 zfcp: Only increment req_id for successfully issued requests
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Only increment the req_id for successfully issued requests. This avoids some confusion when debugging issued fsf requests.
---
drivers/s390/scsi/zfcp_fsf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_fsf.c +2 -1
@@ -735,7 +735,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req req->adapter = adapter; req->fsf_command = fsf_cmd; - req->req_id = adapter->req_no++; + req->req_id = adapter->req_no; req->sbal_number =1 ; req->sbal_first = req_q->first; req->sbal_last = req_q->first;
@@ -798,6 +798,7 @@ static int zfcp_fsf_req_send(struct zfcp/* Don't increase for unsolicited status */ if (req->qtcb) adapter->fsf_req_seq_no++; + adapter->req_no++;return 0 ; }
PATCH 6/18 zfcp: Wait for free SBALs when possible
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
For calls from zfcp erp, scsi_eh and sysfs switch the calls issuing FSF requests to zfcp_fsf_req_sbal_get to wait for free SBALs.
---
drivers/s390/scsi/zfcp_fsf.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +9 -9
@@ -929,8 +929,8 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_struct qdio_buffer_element *sbale;struct zfcp_fsf_req *req =NULL ; -spin_lock (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +spin_lock_bh (&adapter->req_q_lock); +if (zfcp_fsf_req_sbal_get (adapter)) goto out; req =zfcp_fsf_req_create (adapter,FSF_QTCB_ABORT_FCP_CMND , req_flags, adapter->pool.fsf_req_abort);
@@ -961,7 +961,7 @@ out_error_free:zfcp_fsf_req_free (req); req =NULL ; out: -spin_unlock (&adapter->req_q_lock); +spin_unlock_bh (&adapter->req_q_lock);return req; }
@@ -1225,7 +1225,7 @@ int zfcp_fsf_exchange_config_data(structint retval = -EIO ;spin_lock_bh (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +if (zfcp_fsf_req_sbal_get (adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
@@ -1321,7 +1321,7 @@ int zfcp_fsf_exchange_port_data(struct zreturn -EOPNOTSUPP ;spin_lock_bh (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +if (zfcp_fsf_req_sbal_get (adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, ZFCP_REQ_AUTO_CLEANUP,
@@ -1367,7 +1367,7 @@ int zfcp_fsf_exchange_port_data_sync(strreturn -EOPNOTSUPP ;spin_lock_bh (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +if (zfcp_fsf_req_sbal_get (adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
@@ -2453,8 +2453,8 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_c ZFCP_STATUS_COMMON_UNBLOCKED)))return NULL ; -spin_lock (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +spin_lock_bh (&adapter->req_q_lock); +if (zfcp_fsf_req_sbal_get (adapter)) goto out; req =zfcp_fsf_req_create (adapter,FSF_QTCB_FCP_CMND , req_flags, adapter->pool.fsf_req_scsi);
@@ -2488,7 +2488,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_czfcp_fsf_req_free (req); req =NULL ; out: -spin_unlock (&adapter->req_q_lock); +spin_unlock_bh (&adapter->req_q_lock);return req; }
PATCH 7/18 zfcp: Improve reliability of SCSI eh handlers in zfcp
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
When the SCSI midlayer is running error recovery, the low-level error recovery in zfcp could be running and preventing the SCSI midlayer to issue error recovery requests. To avoid unnecessary error recovery escalation, wait for the zfcp erp to finish and retry if necessary.
While reworking the SCSI eh handlers, alsa cleanup the code and simplify the interface from zfcp_scsi to the fsf layer.
---
drivers/s390/scsi/zfcp_def.h | 3 - drivers/s390/scsi/zfcp_ext.h | 11 +-- drivers/s390/scsi/zfcp_fsf.c | 39 ++++--------- drivers/s390/scsi/zfcp_scsi.c | 122 ++++++++++++++++++++---------------------- 4 files changed, 77 insertions(+), 98 deletions(-)
drivers/s390/scsi/zfcp_def.h +0 -3
@@ -586,9 +586,6 @@ struct zfcp_fsf_req_qtcb {/********************** ZFCP SPECIFIC DEFINES ********************************/ -#define ZFCP_REQ_AUTO_CLEANUP 0x00000002 -#define ZFCP_REQ_NO_QTCB 0x00000008 -#define ZFCP_SET 0x00000100#define ZFCP_CLEAR 0x00000200
drivers/s390/scsi/zfcp_ext.h +4 -7
@@ -125,16 +125,13 @@ extern int zfcp_status_read_refill(strucextern int zfcp_fsf_send_ct (struct zfcp_send_ct *,mempool_t *,struct zfcp_erp_action *);extern int zfcp_fsf_send_els (struct zfcp_send_els *); -extern int zfcp_fsf_send_fcp_command_task (struct zfcp_adapter *, -struct zfcp_unit *, -struct scsi_cmnd *,int ,int ); +extern int zfcp_fsf_send_fcp_command_task (struct zfcp_unit *, +struct scsi_cmnd *);extern void zfcp_fsf_req_complete (struct zfcp_fsf_req *);extern void zfcp_fsf_req_free (struct zfcp_fsf_req *); -extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm (struct zfcp_adapter *, -struct zfcp_unit *,u8 ,int ); +extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm (struct zfcp_unit *,u8 );extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command (unsigned long , -struct zfcp_adapter *, -struct zfcp_unit *,int ); +struct zfcp_unit *);/* zfcp_qdio.c */ extern int zfcp_qdio_allocate (struct zfcp_adapter *);
drivers/s390/scsi/zfcp_fsf.c +14 -25
@@ -12,6 +12,9 @@#include <linux/blktrace_api.h> #include "zfcp_ext.h" +#define ZFCP_REQ_AUTO_CLEANUP 0x00000002 +#define ZFCP_REQ_NO_QTCB 0x00000008 +static void zfcp_fsf_request_timeout_handler (unsigned long data) {struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
@@ -913,27 +916,22 @@ static void zfcp_fsf_abort_fcp_command_h/** * zfcp_fsf_abort_fcp_command - abort running SCSI command * @old_req_id: unsigned long -* @adapter: pointer to struct zfcp_adapter * @unit: pointer to struct zfcp_unit -* @req_flags: integer specifying the request flags * Returns: pointer to struct zfcp_fsf_req -* -* FIXME(design): should be watched by a timeout !!! */ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command (unsigned long old_req_id, -struct zfcp_adapter *adapter, -struct zfcp_unit *unit, -int req_flags) +struct zfcp_unit *unit) {struct qdio_buffer_element *sbale;struct zfcp_fsf_req *req =NULL ; +struct zfcp_adapter *adapter = unit->port->adapter;spin_lock_bh (&adapter->req_q_lock);if (zfcp_fsf_req_sbal_get (adapter)) goto out; req =zfcp_fsf_req_create (adapter,FSF_QTCB_ABORT_FCP_CMND , - req_flags, adapter->pool.fsf_req_abort); +0 , adapter->pool.fsf_req_abort);if (IS_ERR (req)) { req =NULL ; goto out;
@@ -2310,21 +2308,17 @@ static void zfcp_set_fcp_dl(struct fcp_c/** * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) -* @adapter: adapter where scsi command is issued * @unit: unit where command is sent to * @scsi_cmnd: scsi command to be sent -* @timer: timer to be started when request is initiated -* @req_flags: flags for fsf_request */ -int zfcp_fsf_send_fcp_command_task (struct zfcp_adapter *adapter, -struct zfcp_unit *unit, -struct scsi_cmnd *scsi_cmnd, -int use_timer,int req_flags) +int zfcp_fsf_send_fcp_command_task (struct zfcp_unit *unit, +struct scsi_cmnd *scsi_cmnd) {struct zfcp_fsf_req *req;struct fcp_cmnd_iu *fcp_cmnd_iu;unsigned int sbtype;int real_bytes, retval = -EIO ; +struct zfcp_adapter *adapter = unit->port->adapter;if (unlikely (!(atomic_read (&unit->status) &ZFCP_STATUS_COMMON_UNBLOCKED )))
@@ -2333,7 +2327,8 @@ int zfcp_fsf_send_fcp_command_task(strucspin_lock (&adapter->req_q_lock);if (!zfcp_fsf_sbal_available (adapter)) goto out; - req =zfcp_fsf_req_create (adapter,FSF_QTCB_FCP_CMND , req_flags, + req =zfcp_fsf_req_create (adapter,FSF_QTCB_FCP_CMND , +ZFCP_REQ_AUTO_CLEANUP , adapter->pool.fsf_req_scsi);if (IS_ERR (req)) { retval =PTR_ERR (req);
@@ -2415,9 +2410,6 @@ int zfcp_fsf_send_fcp_command_task(struczfcp_set_fcp_dl (fcp_cmnd_iu, real_bytes); -if (use_timer) -zfcp_fsf_start_timer (req,ZFCP_FSF_REQUEST_TIMEOUT ); - retval =zfcp_fsf_req_send (req);if (unlikely (retval)) goto failed_scsi_cmnd;
@@ -2435,19 +2427,16 @@ out:/** * zfcp_fsf_send_fcp_ctm - send SCSI task management command -* @adapter: pointer to struct zfcp-adapter * @unit: pointer to struct zfcp_unit * @tm_flags: unsigned byte for task management flags -* @req_flags: int request flags * Returns: on success pointer to struct fsf_req, NULL otherwise */ -struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm (struct zfcp_adapter *adapter, -struct zfcp_unit *unit, -u8 tm_flags,int req_flags) +struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm (struct zfcp_unit *unit,u8 tm_flags) {struct qdio_buffer_element *sbale;struct zfcp_fsf_req *req =NULL ;struct fcp_cmnd_iu *fcp_cmnd_iu; +struct zfcp_adapter *adapter = unit->port->adapter;if (unlikely (!(atomic_read (&unit->status) &ZFCP_STATUS_COMMON_UNBLOCKED )))
@@ -2456,7 +2445,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_cspin_lock_bh (&adapter->req_q_lock);if (zfcp_fsf_req_sbal_get (adapter)) goto out; - req =zfcp_fsf_req_create (adapter,FSF_QTCB_FCP_CMND , req_flags, + req =zfcp_fsf_req_create (adapter,FSF_QTCB_FCP_CMND ,0 , adapter->pool.fsf_req_scsi);if (IS_ERR (req)) { req =NULL ;
drivers/s390/scsi/zfcp_scsi.c +59 -63
185 lines not on this page · raw message
PATCH 8/18 zfcp: Send ELS ADISC from workqueue
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Issue ELS ADISC requests from workqueue. This allows the link test request to be sent when the request queue is full due to I/O load for other remote ports. It also simplifies request queue locking, zfcp_fsf_send_fcp_command_task is now the only function that has interrupts disabled from the caller. This is also a prereq for the FC passthrough support that issues ELS requests from userspace.
---
drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fc.c | 28 ++++++++++++++++++---------- drivers/s390/scsi/zfcp_fsf.c | 18 ++++++------------ 5 files changed, 27 insertions(+), 22 deletions(-)
drivers/s390/scsi/zfcp_aux.c +1 -0
@@ -604,6 +604,7 @@ struct zfcp_port *zfcp_port_enqueue(struinit_waitqueue_head (&port->remove_wq);INIT_LIST_HEAD (&port->unit_list_head);INIT_WORK (&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup); +INIT_WORK (&port->test_link_work, zfcp_fc_link_test_work); port->adapter = adapter; port->d_id = d_id;
drivers/s390/scsi/zfcp_def.h +1 -0
@@ -513,6 +513,7 @@ struct zfcp_port {u32 maxframe_size;u32 supported_classes;struct work_struct gid_pn_work; +struct work_struct test_link_work; };struct zfcp_unit {
drivers/s390/scsi/zfcp_ext.h +1 -0
@@ -101,6 +101,7 @@ extern void zfcp_fc_incoming_els(structextern int zfcp_fc_ns_gid_pn (struct zfcp_erp_action *);extern void zfcp_fc_plogi_evaluate (struct zfcp_port *,struct fsf_plogi *);extern void zfcp_test_link (struct zfcp_port *); +extern void zfcp_fc_link_test_work (struct work_struct *);extern void zfcp_fc_nameserver_init (struct zfcp_adapter *);/* zfcp_fsf.c */
drivers/s390/scsi/zfcp_fc.c +18 -10
@@ -421,19 +421,12 @@ static int zfcp_fc_adisc(struct zfcp_porreturn zfcp_fsf_send_els (&adisc->els); } -/** -* zfcp_test_link - lightweight link test procedure -* @port: port to be tested -* -* Test status of a link to a remote port using the ELS command ADISC. -* If there is a problem with the remote port, error recovery steps -* will be triggered. -*/ -void zfcp_test_link (struct zfcp_port *port) +void zfcp_fc_link_test_work (struct work_struct *work) { +struct zfcp_port *port = + container_of(work, struct zfcp_port, test_link_work);int retval; -zfcp_port_get (port); retval =zfcp_fc_adisc (port);if (retval ==0 )return ;
@@ -444,6 +437,21 @@ void zfcp_test_link(struct zfcp_port *pozfcp_erp_port_forced_reopen (port,0 ,65 ,NULL ); } +/** +* zfcp_test_link - lightweight link test procedure +* @port: port to be tested +* +* Test status of a link to a remote port using the ELS command ADISC. +* If there is a problem with the remote port, error recovery steps +* will be triggered. +*/ +void zfcp_test_link (struct zfcp_port *port) +{ +zfcp_port_get (port); +if (!queue_work (zfcp_data.work_queue, &port->test_link_work)) +zfcp_port_put (port); +} +static void zfcp_free_sg_env (struct zfcp_gpn_ft *gpn_ft,int buf_num) {struct scatterlist *sg = &gpn_ft->sg_req;
drivers/s390/scsi/zfcp_fsf.c +6 -12
@@ -647,14 +647,6 @@ static void zfcp_fsf_exchange_port_data_ } } -static int zfcp_fsf_sbal_available (struct zfcp_adapter *adapter) -{ -if (atomic_read (&adapter->req_q.count) >0 ) -return 1 ; -atomic_inc (&adapter->qdio_outb_full); -return 0 ; -} - static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) __releases(&adapter->req_q_lock) __acquires(&adapter->req_q_lock)
@@ -1177,8 +1169,8 @@ int zfcp_fsf_send_els(struct zfcp_send_e ZFCP_STATUS_COMMON_UNBLOCKED)))return -EBUSY ; -spin_lock (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +spin_lock_bh (&adapter->req_q_lock); +if (zfcp_fsf_req_sbal_get (adapter)) goto out; req =zfcp_fsf_req_create (adapter,FSF_QTCB_SEND_ELS ,ZFCP_REQ_AUTO_CLEANUP ,NULL );
@@ -1211,7 +1203,7 @@ int zfcp_fsf_send_els(struct zfcp_send_e failed_send:zfcp_fsf_req_free (req); out: -spin_unlock (&adapter->req_q_lock); +spin_unlock_bh (&adapter->req_q_lock);return ret; }
@@ -2325,8 +2317,10 @@ int zfcp_fsf_send_fcp_command_task(strucreturn -EBUSY ;spin_lock (&adapter->req_q_lock); -if (!zfcp_fsf_sbal_available (adapter)) +if (atomic_read (&adapter->req_q.count) <=0 ) { +atomic_inc (&adapter->qdio_outb_full); goto out; + } req =zfcp_fsf_req_create (adapter,FSF_QTCB_FCP_CMND ,ZFCP_REQ_AUTO_CLEANUP , adapter->pool.fsf_req_scsi);
PATCH 9/18 zfcp: remove undefined subtype for status read response
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
The status read response FSF_STATUS_READ_SUB_ERROR_PORT is not defined in the specs and therefore not valid.
All occurrences are removed from the code.
---
drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 9 +-------- drivers/s390/scsi/zfcp_fsf.h | 4 ---- 3 files changed, 2 insertions(+), 13 deletions(-)
drivers/s390/scsi/zfcp_dbf.c +1 -1
@@ -615,7 +615,7 @@ static const char *zfcp_rec_dbf_ids[] = [119] = "unknown protocol status", [120] = "unknown fsf command", [121] = "no recommendation for status qualifier", - [122] = "status read physical port closed in error", + [122] = "", [123] = "fc service class not supported", [124] = "", [125] = "need newer zfcp",
drivers/s390/scsi/zfcp_fsf.c +1 -8
@@ -162,14 +162,7 @@ static void zfcp_fsf_status_read_port_cllist_for_each_entry (port, &adapter->port_list_head, list)if (port->d_id == d_id) {read_unlock_irqrestore (&zfcp_data.config_lock, flags); -switch (sr_buf->status_subtype) { -case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT : -zfcp_erp_port_reopen (port,0 ,101 , req); -break ; -case FSF_STATUS_READ_SUB_ERROR_PORT : -zfcp_erp_port_shutdown (port,0 ,122 , req); -break ; - } +zfcp_erp_port_reopen (port,0 ,101 , req);return ; }read_unlock_irqrestore (&zfcp_data.config_lock, flags);
drivers/s390/scsi/zfcp_fsf.h +0 -4
@@ -127,10 +127,6 @@#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C -/* status subtypes in status read buffer */ -#define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 -#define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 -/* status subtypes for link down */ #define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001
PATCH 10/18 zfcp: prevent adapter close on initial adapter open
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
An adapter close was always performed whether it was required, (e.g. in an error scenario) or not (e.g. initial open). This patch is changing the process in only doing an adapter close when it is required.
---
drivers/s390/scsi/zfcp_erp.c | 69 +++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 35 deletions(-)
drivers/s390/scsi/zfcp_erp.c +34 -35
@@ -705,32 +705,10 @@ static int zfcp_erp_adapter_strategy_opereturn ZFCP_ERP_SUCCEEDED ; } -static int zfcp_erp_adapter_strategy_generic (struct zfcp_erp_action *act, -int close) +static void zfcp_erp_adapter_strategy_close (struct zfcp_erp_action *act) { -int retval =ZFCP_ERP_SUCCEEDED ;struct zfcp_adapter *adapter = act->adapter; -if (close) - goto close_only; - - retval =zfcp_erp_adapter_strategy_open_qdio (act); -if (retval !=ZFCP_ERP_SUCCEEDED ) - goto failed_qdio; - - retval =zfcp_erp_adapter_strategy_open_fsf (act); -if (retval !=ZFCP_ERP_SUCCEEDED ) - goto failed_openfcp; - -atomic_set_mask (ZFCP_STATUS_COMMON_OPEN , &act->adapter->status); - -return ZFCP_ERP_SUCCEEDED ; - - close_only: -atomic_clear_mask (ZFCP_STATUS_COMMON_OPEN , - &act->adapter->status); - - failed_openfcp:/* close queues to ensure that buffers are not accessed by adapter */ zfcp_qdio_close (adapter);zfcp_fsf_req_dismiss_all (adapter);
@@ -738,27 +716,48 @@ static int zfcp_erp_adapter_strategy_gen/* all ports and units are closed */ zfcp_erp_modify_adapter_status (adapter,24 ,NULL ,ZFCP_STATUS_COMMON_OPEN ,ZFCP_CLEAR ); - failed_qdio: +atomic_clear_mask (ZFCP_STATUS_ADAPTER_XCONFIG_OK | -ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED , - &act->adapter->status); -return retval; +ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED , &adapter->status); } -static int zfcp_erp_adapter_strategy (struct zfcp_erp_action *act) +static int zfcp_erp_adapter_strategy_open (struct zfcp_erp_action *act) { -int retval; +struct zfcp_adapter *adapter = act->adapter; -zfcp_erp_adapter_strategy_generic (act,1 );/* close */ -if (act->status &ZFCP_STATUS_ERP_CLOSE_ONLY ) -return ZFCP_ERP_EXIT ; +if (zfcp_erp_adapter_strategy_open_qdio (act)) { +atomic_clear_mask (ZFCP_STATUS_ADAPTER_XCONFIG_OK | +ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED , + &adapter->status); +return ZFCP_ERP_FAILED ; + } - retval =zfcp_erp_adapter_strategy_generic (act,0 );/* open */ +if (zfcp_erp_adapter_strategy_open_fsf (act)) { +zfcp_erp_adapter_strategy_close (act); +return ZFCP_ERP_FAILED ; + } -if (retval ==ZFCP_ERP_FAILED ) +atomic_set_mask (ZFCP_STATUS_COMMON_OPEN , &adapter->status); + +return ZFCP_ERP_SUCCEEDED ; +} + +static int zfcp_erp_adapter_strategy (struct zfcp_erp_action *act) +{ +struct zfcp_adapter *adapter = act->adapter; + +if (atomic_read (&adapter->status) &ZFCP_STATUS_COMMON_OPEN ) { +zfcp_erp_adapter_strategy_close (act); +if (act->status &ZFCP_STATUS_ERP_CLOSE_ONLY ) +return ZFCP_ERP_EXIT ; + } + +if (zfcp_erp_adapter_strategy_open (act)) {ssleep (8 ); +return ZFCP_ERP_FAILED ; + } -return retval; +return ZFCP_ERP_SUCCEEDED ; }static int zfcp_erp_port_forced_strategy_close (struct zfcp_erp_action *act)
PATCH 11/18 zfcp: replace current ERP logging with a more convenient version
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
The current number based id ERP logging is replaced by a string based tag version. The benefit is an easier location of the code in question and the removal of the lengthy array referencing the individual messages.
The string (7 bytes) based version does not use more space since those bytes were "used" anyway due to the alignment of the structure. The encoding of the 7 byte string is as follows
[0-1] = filename
[2-5] = task/function
[6] = sectionDue to the character of this string (fixed length) a string termination is not required here.
---
drivers/s390/scsi/zfcp_aux.c | 3 drivers/s390/scsi/zfcp_ccw.c | 18 +-- drivers/s390/scsi/zfcp_dbf.c | 188 +++-------------------------------------- drivers/s390/scsi/zfcp_dbf.h | 3 drivers/s390/scsi/zfcp_erp.c | 137 +++++++++++++++-------------- drivers/s390/scsi/zfcp_ext.h | 55 ++++++----- drivers/s390/scsi/zfcp_fc.c | 14 +-- drivers/s390/scsi/zfcp_fsf.c | 131 ++++++++++++++-------------- drivers/s390/scsi/zfcp_qdio.c | 6 - drivers/s390/scsi/zfcp_scsi.c | 4 drivers/s390/scsi/zfcp_sysfs.c | 12 +- 11 files changed, 215 insertions(+), 356 deletions(-)
drivers/s390/scsi/zfcp_aux.c +2 -1
@@ -421,7 +421,8 @@ int zfcp_status_read_refill(struct zfcp_while (atomic_read (&adapter->stat_miss) >0 )if (zfcp_fsf_status_read (adapter)) {if (atomic_read (&adapter->stat_miss) >=16 ) { -zfcp_erp_adapter_reopen (adapter,0 ,103 ,NULL ); +zfcp_erp_adapter_reopen (adapter,0 ,"axsref1" , +NULL );return 1 ; }break ;
drivers/s390/scsi/zfcp_ccw.c +9 -9
@@ -109,10 +109,10 @@ static int zfcp_ccw_set_online(struct ccBUG_ON (!zfcp_reqlist_isempty (adapter)); adapter->req_no =0 ; -zfcp_erp_modify_adapter_status (adapter,10 ,NULL , +zfcp_erp_modify_adapter_status (adapter,"ccsonl1" ,NULL ,ZFCP_STATUS_COMMON_RUNNING ,ZFCP_SET ); -zfcp_erp_adapter_reopen (adapter,ZFCP_STATUS_COMMON_ERP_FAILED ,85 , -NULL ); +zfcp_erp_adapter_reopen (adapter,ZFCP_STATUS_COMMON_ERP_FAILED , +"ccsonl2" ,NULL );zfcp_erp_wait (adapter);up (&zfcp_data.config_sema);flush_work (&adapter->scan_work);
@@ -136,7 +136,7 @@ static int zfcp_ccw_set_offline(struct cdown (&zfcp_data.config_sema); adapter =dev_get_drvdata (&ccw_device->dev); -zfcp_erp_adapter_shutdown (adapter,0 ,86 ,NULL ); +zfcp_erp_adapter_shutdown (adapter,0 ,"ccsoff1" ,NULL );zfcp_erp_wait (adapter);zfcp_erp_thread_kill (adapter);up (&zfcp_data.config_sema);
@@ -159,21 +159,21 @@ static int zfcp_ccw_notify(struct ccw_decase CIO_GONE :dev_warn (&adapter->ccw_device->dev,"The FCP device has been detached\n" ); -zfcp_erp_adapter_shutdown (adapter,0 ,87 ,NULL ); +zfcp_erp_adapter_shutdown (adapter,0 ,"ccnoti1" ,NULL );break ;case CIO_NO_PATH :dev_warn (&adapter->ccw_device->dev,"The CHPID for the FCP device is offline\n" ); -zfcp_erp_adapter_shutdown (adapter,0 ,88 ,NULL ); +zfcp_erp_adapter_shutdown (adapter,0 ,"ccnoti2" ,NULL );break ;case CIO_OPER :dev_info (&adapter->ccw_device->dev,"The FCP device is operational again\n" ); -zfcp_erp_modify_adapter_status (adapter,11 ,NULL , +zfcp_erp_modify_adapter_status (adapter,"ccnoti3" ,NULL ,ZFCP_STATUS_COMMON_RUNNING ,ZFCP_SET );zfcp_erp_adapter_reopen (adapter,ZFCP_STATUS_COMMON_ERP_FAILED , -89 ,NULL ); +"ccnoti4" ,NULL );break ; }return 1 ;
@@ -189,7 +189,7 @@ static void zfcp_ccw_shutdown(struct ccwdown (&zfcp_data.config_sema); adapter =dev_get_drvdata (&cdev->dev); -zfcp_erp_adapter_shutdown (adapter,0 ,90 ,NULL ); +zfcp_erp_adapter_shutdown (adapter,0 ,"ccshut1" ,NULL );zfcp_erp_wait (adapter);up (&zfcp_data.config_sema); }
drivers/s390/scsi/zfcp_dbf.c +17 -171
273 lines not on this page · raw message
drivers/s390/scsi/zfcp_dbf.h +2 -1
@@ -25,6 +25,7 @@#include "zfcp_fsf.h" #define ZFCP_DBF_TAG_SIZE 4 +#define ZFCP_DBF_ID_SIZE 7struct zfcp_dbf_dump {u8 tag[ZFCP_DBF_TAG_SIZE ];
@@ -70,7 +71,7 @@ struct zfcp_rec_dbf_record_action {struct zfcp_rec_dbf_record {u8 id; -u8 id2; +char id2[7 ];union {struct zfcp_rec_dbf_record_action action;struct zfcp_rec_dbf_record_thread thread;
drivers/s390/scsi/zfcp_erp.c +70 -67
485 lines not on this page · raw message
drivers/s390/scsi/zfcp_ext.h +29 -26
75 lines not on this page · raw message
drivers/s390/scsi/zfcp_fc.c +7 -7
@@ -150,7 +150,7 @@ static void _zfcp_fc_incoming_rscn(struc/* Try to connect to unused ports anyway. */ zfcp_erp_port_reopen (port,ZFCP_STATUS_COMMON_ERP_FAILED , -82 , fsf_req); +"fcirsc1" , fsf_req); else if ((port->d_id & range) == (elem->nport_did & range)) /* Check connection status for connected ports */ zfcp_test_link(port);
@@ -196,7 +196,7 @@ static void zfcp_fc_incoming_wwpn(structread_unlock_irqrestore (&zfcp_data.config_lock, flags);if (port && (port->wwpn == wwpn)) -zfcp_erp_port_forced_reopen (port,0 ,83 , req); +zfcp_erp_port_forced_reopen (port,0 ,"fciwwp1" , req); }static void zfcp_fc_incoming_plogi (struct zfcp_fsf_req *req)
@@ -374,7 +374,7 @@ static void zfcp_fc_adisc_handler(unsignif (adisc->els.status) {/* request rejected or timed out */ -zfcp_erp_port_forced_reopen (port,0 ,63 ,NULL ); +zfcp_erp_port_forced_reopen (port,0 ,"fcadh_1" ,NULL ); goto out; }
@@ -382,7 +382,7 @@ static void zfcp_fc_adisc_handler(unsign port->wwnn = ls_adisc->wwnn;if (port->wwpn != ls_adisc->wwpn) -zfcp_erp_port_reopen (port,0 ,64 ,NULL ); +zfcp_erp_port_reopen (port,0 ,"fcadh_2" ,NULL ); out:zfcp_port_put (port);
@@ -434,7 +434,7 @@ void zfcp_fc_link_test_work(struct work_/* send of ADISC was not possible */ zfcp_port_put (port);if (retval != -EBUSY ) -zfcp_erp_port_forced_reopen (port,0 ,65 ,NULL ); +zfcp_erp_port_forced_reopen (port,0 ,"fcltwk1" ,NULL ); }/**
@@ -536,7 +536,7 @@ static void zfcp_validate_port(struct zfzfcp_port_put (port);return ; } -zfcp_erp_port_shutdown (port,0 ,151 ,NULL ); +zfcp_erp_port_shutdown (port,0 ,"fcpval1" ,NULL );zfcp_erp_wait (adapter);zfcp_port_put (port);zfcp_port_dequeue (port);
@@ -599,7 +599,7 @@ static int zfcp_scan_eval_gpn_ft(structif (IS_ERR (port)) ret =PTR_ERR (port);else -zfcp_erp_port_reopen (port,0 ,149 ,NULL ); +zfcp_erp_port_reopen (port,0 ,"fcegpf1" ,NULL ); }zfcp_erp_wait (adapter);
drivers/s390/scsi/zfcp_fsf.c +68 -63
433 lines not on this page · raw message
drivers/s390/scsi/zfcp_qdio.c +3 -3
@@ -58,7 +58,7 @@ void zfcp_qdio_free(struct zfcp_adapter } } -static void zfcp_qdio_handler_error (struct zfcp_adapter *adapter,u8 id) +static void zfcp_qdio_handler_error (struct zfcp_adapter *adapter,char *id) {dev_warn (&adapter->ccw_device->dev,"A QDIO problem occurred\n" );
@@ -103,7 +103,7 @@ static void zfcp_qdio_int_req(struct ccwif (unlikely (qdio_err)) {zfcp_hba_dbf_event_qdio (adapter, qdio_err, first, count); -zfcp_qdio_handler_error (adapter,140 ); +zfcp_qdio_handler_error (adapter,"qdireq1" );return ; }
@@ -172,7 +172,7 @@ static void zfcp_qdio_int_resp(struct ccif (unlikely (qdio_err)) {zfcp_hba_dbf_event_qdio (adapter, qdio_err, first, count); -zfcp_qdio_handler_error (adapter,147 ); +zfcp_qdio_handler_error (adapter,"qdires1" );return ; }
drivers/s390/scsi/zfcp_scsi.c +2 -2
@@ -28,7 +28,7 @@ static void zfcp_scsi_slave_destroy(stru {struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; unit->device =NULL ; -zfcp_erp_unit_failed (unit,12 ,NULL ); +zfcp_erp_unit_failed (unit,"scslvd1" ,NULL );zfcp_unit_put (unit); }
@@ -257,7 +257,7 @@ static int zfcp_scsi_eh_host_reset_handlstruct zfcp_unit *unit = scpnt->device->hostdata;struct zfcp_adapter *adapter = unit->port->adapter; -zfcp_erp_adapter_reopen (adapter,0 ,141 , scpnt); +zfcp_erp_adapter_reopen (adapter,0 ,"schrh_1" , scpnt);zfcp_erp_wait (adapter);return SUCCESS ;
drivers/s390/scsi/zfcp_sysfs.c +6 -6
@@ -112,9 +112,9 @@ static ZFCP_DEV_ATTR(_feat, failed, S_IW zfcp_sysfs_##_feat##_failed_show, \ zfcp_sysfs_##_feat##_failed_store); -ZFCP_SYSFS_FAILED (zfcp_adapter, adapter, adapter,44 ,93 ); -ZFCP_SYSFS_FAILED (zfcp_port, port, port->adapter,45 ,96 ); -ZFCP_SYSFS_FAILED (zfcp_unit, unit, unit->port->adapter,46 ,97 ); +ZFCP_SYSFS_FAILED (zfcp_adapter, adapter, adapter,"syafai1" ,"syafai2" ); +ZFCP_SYSFS_FAILED (zfcp_port, port, port->adapter,"sypfai1" ,"sypfai2" ); +ZFCP_SYSFS_FAILED (zfcp_unit, unit, unit->port->adapter,"syufai1" ,"syufai2" ); static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, struct device_attribute *attr,
@@ -168,7 +168,7 @@ static ssize_t zfcp_sysfs_port_remove_st goto out; } -zfcp_erp_port_shutdown (port,0 ,92 ,NULL ); +zfcp_erp_port_shutdown (port,0 ,"syprs_1" ,NULL );zfcp_erp_wait (adapter);zfcp_port_put (port);zfcp_port_dequeue (port);
@@ -222,7 +222,7 @@ static ssize_t zfcp_sysfs_unit_add_store retval =0 ; -zfcp_erp_unit_reopen (unit,0 ,94 ,NULL ); +zfcp_erp_unit_reopen (unit,0 ,"syuas_1" ,NULL );zfcp_erp_wait (unit->port->adapter);zfcp_unit_put (unit); out:
@@ -268,7 +268,7 @@ static ssize_t zfcp_sysfs_unit_remove_st goto out; } -zfcp_erp_unit_shutdown (unit,0 ,95 ,NULL ); +zfcp_erp_unit_shutdown (unit,0 ,"syurs_1" ,NULL );zfcp_erp_wait (unit->port->adapter);zfcp_unit_put (unit);zfcp_unit_dequeue (unit);
PATCH 12/18 zfcp: Remove PCI flag
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
The usage of the PCI flag to trigger interrupts is optional. Even without setting the flag, qdio still receives interrupts to continue working on the queue. Remove the PCI flag from zfcp, it is not necessary.
drivers/s390/scsi/zfcp_qdio.c +3 -20
@@ -11,9 +11,6 @@#include "zfcp_ext.h" -/* FIXME(tune): free space should be one max. SBAL chain plus what? */ -#define ZFCP_QDIO_PCI_INTERVAL (QDIO_MAX_BUFFERS_PER_Q \ - - (FSF_MAX_SBALS_PER_REQ + 4))#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))static int zfcp_qdio_buffers_enqueue (struct qdio_buffer **sbal)
@@ -364,23 +361,12 @@ int zfcp_qdio_send(struct zfcp_fsf_req *struct zfcp_qdio_queue *req_q = &adapter->req_q;int first = fsf_req->sbal_first;int count = fsf_req->sbal_number; -int retval, pci, pci_batch; -struct qdio_buffer_element *sbale; - -/* acknowledgements for transferred buffers */ - pci_batch = adapter->req_q_pci_batch + count; -if (unlikely (pci_batch >=ZFCP_QDIO_PCI_INTERVAL )) { - pci_batch %=ZFCP_QDIO_PCI_INTERVAL ; - pci = first + count - (pci_batch +1 ); - pci %=QDIO_MAX_BUFFERS_PER_Q ; - sbale =zfcp_qdio_sbale (req_q, pci,0 ); - sbale->flags |=SBAL_FLAGS0_PCI ; - } +int retval; +unsigned int qdio_flags =QDIO_FLAG_SYNC_OUTPUT ;zfcp_qdio_account (adapter); - retval =do_QDIO (adapter->ccw_device,QDIO_FLAG_SYNC_OUTPUT ,0 , first, - count); + retval =do_QDIO (adapter->ccw_device, qdio_flags,0 , first, count);if (unlikely (retval)) {zfcp_qdio_zero_sbals (req_q->sbal, first, count);return retval;
@@ -390,7 +376,6 @@ int zfcp_qdio_send(struct zfcp_fsf_req *atomic_sub (count, &req_q->count); req_q->first += count; req_q->first %=QDIO_MAX_BUFFERS_PER_Q ; - adapter->req_q_pci_batch = pci_batch;return 0 ; }
@@ -461,7 +446,6 @@ void zfcp_qdio_close(struct zfcp_adapter } req_q->first =0 ;atomic_set (&req_q->count,0 ); - adapter->req_q_pci_batch =0 ; adapter->resp_q.first =0 ;atomic_set (&adapter->resp_q.count,0 ); }
@@ -499,7 +483,6 @@ int zfcp_qdio_open(struct zfcp_adapter */* set index of first avalable SBALS / number of available SBALS */ adapter->req_q.first =0 ;atomic_set (&adapter->req_q.count,QDIO_MAX_BUFFERS_PER_Q ); - adapter->req_q_pci_batch =0 ;return 0 ;
drivers/s390/scsi/zfcp_def.h +0 -2
@@ -443,8 +443,6 @@ struct zfcp_adapter {spinlock_t req_list_lock;/* request list lock */ struct zfcp_qdio_queue req_q;/* request queue */ spinlock_t req_q_lock;/* for operations on queue */ -int req_q_pci_batch;/* SBALs since PCI indication -was last set */ ktime_t req_q_time;/* time of last fill level change */ u64 req_q_util;/* for accounting */ spinlock_t qdio_stat_lock;
PATCH 13/18 zfcp: Report fc_host_port_type as NPIV
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Report the fc_host_port_type as FC_PORTTYPE_NPIV when the subchannel is running in NPIV mode. This allows to see the correct type with lsscsi -H -t --list
---
drivers/s390/scsi/zfcp_fsf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +3 -2
@@ -616,9 +616,10 @@ static void zfcp_fsf_exchange_port_evaluif (req->data)memcpy (req->data, bottom,sizeof (*bottom)); -if (adapter->connection_features &FSF_FEATURE_NPIV_MODE ) +if (adapter->connection_features &FSF_FEATURE_NPIV_MODE ) {fc_host_permanent_port_name (shost) = bottom->wwpn; -else +fc_host_port_type (shost) =FC_PORTTYPE_NPIV ; + }else fc_host_permanent_port_name (shost) =fc_host_port_name (shost);fc_host_maxframe_size (shost) = bottom->maximum_frame_size;fc_host_supported_speeds (shost) = bottom->supported_speed;
PATCH 14/18 zfcp: incorrect reaction on incoming RSCN
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
After an error condition resolved a remote storage port was never re-opened. The incoming RSCN was not processed accordingly due to a misinterpreted status flag / return value combination.
---
drivers/s390/scsi/zfcp_fc.c | 18 +++++++----------- drivers/s390/scsi/zfcp_fsf.c | 4 ---- 2 files changed, 7 insertions(+), 15 deletions(-)
drivers/s390/scsi/zfcp_fc.c +7 -11
@@ -145,16 +145,10 @@ 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) { -if (!(atomic_read (&port->status) &ZFCP_STATUS_PORT_PHYS_OPEN )) -/* Try to connect to unused ports anyway. */ -zfcp_erp_port_reopen (port, -ZFCP_STATUS_COMMON_ERP_FAILED , -"fcirsc1" , fsf_req); -else if ((port->d_id & range) == (elem->nport_did & range)) -/* Check connection status for connected ports */ +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); - } +read_unlock_irqrestore (&zfcp_data.config_lock, flags); }
@@ -381,8 +375,10 @@ static void zfcp_fc_adisc_handler(unsignif (!port->wwnn) port->wwnn = ls_adisc->wwnn; -if (port->wwpn != ls_adisc->wwpn) -zfcp_erp_port_reopen (port,0 ,"fcadh_2" ,NULL ); +if ((port->wwpn != ls_adisc->wwpn) || + !(atomic_read (&port->status) &ZFCP_STATUS_COMMON_OPEN )) +zfcp_erp_port_reopen (port,ZFCP_STATUS_COMMON_ERP_FAILED , +"fcadh_2" ,NULL ); out:zfcp_port_put (port);
drivers/s390/scsi/zfcp_fsf.c +0 -4
@@ -1162,10 +1162,6 @@ int zfcp_fsf_send_els(struct zfcp_send_estruct fsf_qtcb_bottom_support *bottom;int ret = -EIO ; -if (unlikely (!(atomic_read (&els->port->status) & -ZFCP_STATUS_COMMON_UNBLOCKED ))) -return -EBUSY ; -spin_lock_bh (&adapter->req_q_lock);if (zfcp_fsf_req_sbal_get (adapter)) goto out;
PATCH 15/18 zfcp: Block FC transport rports early on errors
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Use the I/O blocking mechanism in the FC transport class to allow faster failovers for multipathing:
- Call fc_remote_port_delete early to set the rport to BLOCKED.
- Check the rport status in queuecommand with fc_remote_portchkready to no longer accept new I/O for this port and fail the I/O with the appropriate scsi_cmnd result.
- Implement the terminate_rport_io handler to abort all pending I/O requests
- Return SCSI commands with DID_TRANSPORT_DISRUPTED while erp is running.
- When updating the remote port status, check for late changes and update the remote ports status accordingly.
drivers/s390/scsi/zfcp_erp.c +11 -45
@@ -3,7 +3,7 @@* * Error Recovery Procedures (ERP). * -* Copyright IBM Corporation 2002, 2008 +* Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp"
@@ -240,6 +240,7 @@ static int _zfcp_erp_adapter_reopen(stru int clear_mask, char *id, void *ref) {zfcp_erp_adapter_block (adapter ,clear_mask ); +zfcp_scsi_schedule_rports_block (adapter);/* ensure propagation of failed status to new devices */ if (atomic_read (&adapter->status) &ZFCP_STATUS_COMMON_ERP_FAILED ) {
@@ -322,6 +323,7 @@ static void _zfcp_erp_port_forced_reopen int clear, char *id, void *ref) {zfcp_erp_port_block (port ,clear ); +zfcp_scsi_schedule_rport_block (port);if (atomic_read (&port->status) &ZFCP_STATUS_COMMON_ERP_FAILED )return ;
@@ -353,6 +355,7 @@ static int _zfcp_erp_port_reopen(struct void *ref) {zfcp_erp_port_block (port, clear); +zfcp_scsi_schedule_rport_block (port);if (atomic_read (&port->status) &ZFCP_STATUS_COMMON_ERP_FAILED ) {/* ensure propagation of failed status to new devices */
@@ -1211,37 +1214,6 @@ static void zfcp_erp_schedule_work(strucqueue_work (zfcp_data.work_queue, &p->work); } -static void zfcp_erp_rport_register (struct zfcp_port *port) -{ -struct fc_rport_identifiers ids; - ids.node_name = port->wwnn; - ids.port_name = port->wwpn; - ids.port_id = port->d_id; - ids.roles =FC_RPORT_ROLE_FCP_TARGET ; - port->rport =fc_remote_port_add (port->adapter->scsi_host,0 , &ids); -if (!port->rport) { -dev_err (&port->adapter->ccw_device->dev, -"Registering port 0x%016Lx failed\n" , - (unsigned long long )port->wwpn); -return ; - } - -scsi_target_unblock (&port->rport->dev); - port->rport->maxframe_size = port->maxframe_size; - port->rport->supported_classes = port->supported_classes; -} - -static void zfcp_erp_rports_del (struct zfcp_adapter *adapter) -{ -struct zfcp_port *port; -list_for_each_entry (port, &adapter->port_list_head, list) { -if (!port->rport) -continue ; -fc_remote_port_delete (port->rport); - port->rport =NULL ; - } -} -static void zfcp_erp_action_cleanup (struct zfcp_erp_action *act,int result) {struct zfcp_adapter *adapter = act->adapter;
@@ -1250,8 +1222,8 @@ static void zfcp_erp_action_cleanup(struswitch (act->action) {case ZFCP_ERP_ACTION_REOPEN_UNIT : -if ((result ==ZFCP_ERP_SUCCEEDED ) && - !unit->device && port->rport) { +flush_work (&port->rport_work); +if ((result ==ZFCP_ERP_SUCCEEDED ) && !unit->device) {if (!(atomic_read (&unit->status) &ZFCP_STATUS_UNIT_SCSI_WORK_PENDING ))zfcp_erp_schedule_work (unit);
@@ -1261,23 +1233,17 @@ static void zfcp_erp_action_cleanup(strucase ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :case ZFCP_ERP_ACTION_REOPEN_PORT : -if ((result ==ZFCP_ERP_SUCCEEDED ) && !port->rport) -zfcp_erp_rport_register (port); -if ((result !=ZFCP_ERP_SUCCEEDED ) && port->rport) { -fc_remote_port_delete (port->rport); - port->rport =NULL ; - } +if (result ==ZFCP_ERP_SUCCEEDED ) +zfcp_scsi_schedule_rport_register (port);zfcp_port_put (port);break ;case ZFCP_ERP_ACTION_REOPEN_ADAPTER : -if (result !=ZFCP_ERP_SUCCEEDED ) { -unregister_service_level (&adapter->service_level); -zfcp_erp_rports_del (adapter); - }else { +if (result ==ZFCP_ERP_SUCCEEDED ) {register_service_level (&adapter->service_level);schedule_work (&adapter->scan_work); - } + }else +unregister_service_level (&adapter->service_level);zfcp_adapter_put (adapter);break ; }
drivers/s390/scsi/zfcp_aux.c +3 -1
@@ -3,7 +3,7 @@* * Module interface and handling of zfcp data structures. * -* Copyright IBM Corporation 2002, 2008 +* Copyright IBM Corporation 2002, 2009 */ /*
@@ -606,10 +606,12 @@ struct zfcp_port *zfcp_port_enqueue(struINIT_LIST_HEAD (&port->unit_list_head);INIT_WORK (&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);INIT_WORK (&port->test_link_work, zfcp_fc_link_test_work); +INIT_WORK (&port->rport_work, zfcp_scsi_rport_work); port->adapter = adapter; port->d_id = d_id; port->wwpn = wwpn; + port->rport_task =RPORT_NONE ;/* mark port unusable as long as sysfs registration is not complete */ atomic_set_mask (status |ZFCP_STATUS_COMMON_REMOVE , &port->status);
drivers/s390/scsi/zfcp_def.h +3 -1
@@ -3,7 +3,7 @@* * Global definitions for the zfcp device driver. * -* Copyright IBM Corporation 2002, 2008 +* Copyright IBM Corporation 2002, 2009 */ #ifndef ZFCP_DEF_H
@@ -512,6 +512,8 @@ struct zfcp_port {u32 supported_classes;struct work_struct gid_pn_work;struct work_struct test_link_work; +struct work_struct rport_work; +enum {RPORT_NONE ,RPORT_ADD ,RPORT_DEL } rport_task; };struct zfcp_unit {
drivers/s390/scsi/zfcp_ext.h +5 -1
@@ -3,7 +3,7 @@* * External function declarations. * -* Copyright IBM Corporation 2002, 2008 +* Copyright IBM Corporation 2002, 2009 */ #ifndef ZFCP_EXT_H
@@ -154,6 +154,10 @@ extern int zfcp_adapter_scsi_register(stextern void zfcp_adapter_scsi_unregister (struct zfcp_adapter *);extern char *zfcp_get_fcp_sns_info_ptr (struct fcp_rsp_iu *);extern struct fc_function_template zfcp_transport_functions; +extern void zfcp_scsi_rport_work (struct work_struct *); +extern void zfcp_scsi_schedule_rport_register (struct zfcp_port *); +extern void zfcp_scsi_schedule_rport_block (struct zfcp_port *); +extern void zfcp_scsi_schedule_rports_block (struct zfcp_adapter *);/* zfcp_sysfs.c */ extern struct attribute_group zfcp_sysfs_unit_attrs;
drivers/s390/scsi/zfcp_fc.c +17 -4
@@ -3,7 +3,7 @@* * Fibre Channel related functions for the zfcp device driver. * -* Copyright IBM Corporation 2008 +* Copyright IBM Corporation 2008, 2009 */ #define KMSG_COMPONENT "zfcp"
@@ -376,10 +376,14 @@ static void zfcp_fc_adisc_handler(unsign port->wwnn = ls_adisc->wwnn;if ((port->wwpn != ls_adisc->wwpn) || - !(atomic_read (&port->status) &ZFCP_STATUS_COMMON_OPEN )) + !(atomic_read (&port->status) &ZFCP_STATUS_COMMON_OPEN )) {zfcp_erp_port_reopen (port,ZFCP_STATUS_COMMON_ERP_FAILED ,"fcadh_2" ,NULL ); + goto out; + } +/* port is good, unblock rport without going through erp */ +zfcp_scsi_schedule_rport_register (port); out:zfcp_port_put (port);kfree (adisc);
@@ -423,14 +427,23 @@ void zfcp_fc_link_test_work(struct work_ container_of(work, struct zfcp_port, test_link_work);int retval; +if (!(atomic_read (&port->status) &ZFCP_STATUS_COMMON_UNBLOCKED )) { +zfcp_port_put (port); +return ;/* port erp is running and will update rport status */ + } + +zfcp_port_get (port); + port->rport_task =RPORT_DEL ; +zfcp_scsi_rport_work (&port->rport_work); + retval =zfcp_fc_adisc (port);if (retval ==0 )return ;/* send of ADISC was not possible */ +zfcp_erp_port_forced_reopen (port,0 ,"fcltwk1" ,NULL ); +zfcp_port_put (port); -if (retval != -EBUSY ) -zfcp_erp_port_forced_reopen (port,0 ,"fcltwk1" ,NULL ); }/**
drivers/s390/scsi/zfcp_fsf.c +2 -1
@@ -3,7 +3,7 @@* * Implementation of FSF commands. * -* Copyright IBM Corporation 2002, 2008 +* Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp"
@@ -177,6 +177,7 @@ static void zfcp_fsf_link_down_info_evalreturn ;atomic_set_mask (ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED , &adapter->status); +zfcp_scsi_schedule_rports_block (adapter);if (!link_down) goto out;
drivers/s390/scsi/zfcp_scsi.c +116 -3
149 lines not on this page · raw message
PATCH 16/18 zfcp: erp failed status bit will not be set
In reply to Christof SchmittFrom: Martin Petermann <[email protected]>
It will not be necessary to set the erp failed status bit in case a SCSI device is removed by the SCSI mid layer. In the case a SCSI device is unavailable for a short time (15 to 20 seconds) a FCP unit will not get on-line again.
---
drivers/s390/scsi/zfcp_scsi.c | 1 - 1 file changed, 1 deletion(-)
drivers/s390/scsi/zfcp_scsi.c +0 -1
@@ -28,7 +28,6 @@ static void zfcp_scsi_slave_destroy(stru {struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; unit->device =NULL ; -zfcp_erp_unit_failed (unit,"scslvd1" ,NULL );zfcp_unit_put (unit); }
PATCH 17/18 zfcp: fix queue, scheduled work processing.
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
Ensure the refcounting is correct even if we were not able to schedule a work. In addition we have to make sure no scheduled work is pending while we're dequeing the adapter from the systems environment.
---
drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_erp.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/s390/scsi/zfcp_aux.c +1 -0
@@ -554,6 +554,7 @@ void zfcp_adapter_dequeue(struct zfcp_adcancel_work_sync (&adapter->scan_work);cancel_work_sync (&adapter->stat_work); +cancel_delayed_work_sync (&adapter->nsp.work);zfcp_adapter_scsi_unregister (adapter);sysfs_remove_group (&adapter->ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs);
drivers/s390/scsi/zfcp_erp.c +7 -3
@@ -857,7 +857,7 @@ void zfcp_erp_port_strategy_open_lookup( port->erp_action.step =ZFCP_ERP_STEP_NAMESERVER_LOOKUP ;if (retval)zfcp_erp_notify (&port->erp_action,ZFCP_ERP_FAILED ); - +zfcp_port_put (port); }static int zfcp_erp_port_strategy_open_common (struct zfcp_erp_action *act)
@@ -873,7 +873,10 @@ static int zfcp_erp_port_strategy_open_cif (fc_host_port_type (adapter->scsi_host) ==FC_PORTTYPE_PTP )return zfcp_erp_open_ptp_port (act);if (!port->d_id) { -queue_work (zfcp_data.work_queue, &port->gid_pn_work); +zfcp_port_get (port); +if (!queue_work (zfcp_data.work_queue, + &port->gid_pn_work)) +zfcp_port_put (port);return ZFCP_ERP_CONTINUES ; }case ZFCP_ERP_STEP_NAMESERVER_LOOKUP :
@@ -1211,7 +1214,8 @@ static void zfcp_erp_schedule_work(strucatomic_set_mask (ZFCP_STATUS_UNIT_SCSI_WORK_PENDING , &unit->status);INIT_WORK (&p->work, zfcp_erp_scsi_scan); p->unit = unit; -queue_work (zfcp_data.work_queue, &p->work); +if (!queue_work (zfcp_data.work_queue, &p->work)) +zfcp_unit_put (unit); }static void zfcp_erp_action_cleanup (struct zfcp_erp_action *act,int result)
PATCH 18/18 zfcp: Ensure all work is cancelled on adapter dequeue
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
A scheduled work might still be pending, running while the adapter is in progress to get dequeued from the system. This can lead to an invalid pointer dereference (Oops). Once the adpater is set online again, ensure the nameserver environment is initialized to the appropriate values again.
---
drivers/s390/scsi/zfcp_aux.c | 1 - drivers/s390/scsi/zfcp_ccw.c | 3 ++- drivers/s390/scsi/zfcp_fc.c | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-)
drivers/s390/scsi/zfcp_aux.c +0 -1
@@ -524,7 +524,6 @@ int zfcp_adapter_enqueue(struct ccw_devi goto sysfs_failed;atomic_clear_mask (ZFCP_STATUS_COMMON_REMOVE , &adapter->status); -zfcp_fc_nameserver_init (adapter);if (!zfcp_adapter_scsi_register (adapter))return 0 ;
drivers/s390/scsi/zfcp_ccw.c +2 -1
@@ -3,7 +3,7 @@* * Registration and callback for the s390 common I/O layer. * -* Copyright IBM Corporation 2002, 2008 +* Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp"
@@ -108,6 +108,7 @@ static int zfcp_ccw_set_online(struct cc/* initialize request counter */ BUG_ON (!zfcp_reqlist_isempty (adapter)); adapter->req_no =0 ; +zfcp_fc_nameserver_init (adapter);zfcp_erp_modify_adapter_status (adapter,"ccsonl1" ,NULL ,ZFCP_STATUS_COMMON_RUNNING ,ZFCP_SET );
drivers/s390/scsi/zfcp_fc.c +6 -2
@@ -98,8 +98,12 @@ static void zfcp_wka_port_offline(structstruct zfcp_wka_port *wka_port = container_of(dw, struct zfcp_wka_port, work); -wait_event (wka_port->completion_wq, -atomic_read (&wka_port->refcount) ==0 ); +/* Don't wait forvever. If the wka_port is too busy take it offline +through a new call later */ +if (!wait_event_timeout (wka_port->completion_wq, +atomic_read (&wka_port->refcount) ==0 , +HZ >>1 )) +return ;mutex_lock (&wka_port->mutex); if ((atomic_read(&wka_port->refcount) != 0) ||