summaryrefslogtreecommitdiff
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c84
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c13
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c13
-rw-r--r--drivers/s390/scsi/zfcp_def.h32
-rw-r--r--drivers/s390/scsi/zfcp_erp.c231
-rw-r--r--drivers/s390/scsi/zfcp_ext.h18
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c299
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c112
8 files changed, 333 insertions, 469 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index adc9d8f2c28..5d39b2df0cc 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -189,6 +189,10 @@ struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *request, *tmp;
unsigned int i;
+ /* 0 is reserved as an invalid req_id */
+ if (req_id == 0)
+ return NULL;
+
i = req_id % REQUEST_LIST_SIZE;
list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
@@ -299,11 +303,45 @@ zfcp_init_device_configure(void)
return;
}
+static int calc_alignment(int size)
+{
+ int align = 1;
+
+ if (!size)
+ return 0;
+
+ while ((size - align) > 0)
+ align <<= 1;
+
+ return align;
+}
+
static int __init
zfcp_module_init(void)
{
+ int retval = -ENOMEM;
+ int size, align;
+
+ size = sizeof(struct zfcp_fsf_req_qtcb);
+ align = calc_alignment(size);
+ zfcp_data.fsf_req_qtcb_cache =
+ kmem_cache_create("zfcp_fsf", size, align, 0, NULL, NULL);
+ if (!zfcp_data.fsf_req_qtcb_cache)
+ goto out;
- int retval = 0;
+ size = sizeof(struct fsf_status_read_buffer);
+ align = calc_alignment(size);
+ zfcp_data.sr_buffer_cache =
+ kmem_cache_create("zfcp_sr", size, align, 0, NULL, NULL);
+ if (!zfcp_data.sr_buffer_cache)
+ goto out_sr_cache;
+
+ size = sizeof(struct zfcp_gid_pn_data);
+ align = calc_alignment(size);
+ zfcp_data.gid_pn_cache =
+ kmem_cache_create("zfcp_gid", size, align, 0, NULL, NULL);
+ if (!zfcp_data.gid_pn_cache)
+ goto out_gid_cache;
atomic_set(&zfcp_data.loglevel, loglevel);
@@ -313,15 +351,16 @@ zfcp_module_init(void)
/* initialize adapters to be removed list head */
INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh);
- zfcp_transport_template = fc_attach_transport(&zfcp_transport_functions);
- if (!zfcp_transport_template)
- return -ENODEV;
+ zfcp_data.scsi_transport_template =
+ fc_attach_transport(&zfcp_transport_functions);
+ if (!zfcp_data.scsi_transport_template)
+ goto out_transport;
retval = misc_register(&zfcp_cfdc_misc);
if (retval != 0) {
ZFCP_LOG_INFO("registration of misc device "
"zfcp_cfdc failed\n");
- goto out;
+ goto out_misc;
}
ZFCP_LOG_TRACE("major/minor for zfcp_cfdc: %d/%d\n",
@@ -333,9 +372,6 @@ zfcp_module_init(void)
/* initialise configuration rw lock */
rwlock_init(&zfcp_data.config_lock);
- /* save address of data structure managing the driver module */
- zfcp_data.scsi_host_template.module = THIS_MODULE;
-
/* setup dynamic I/O */
retval = zfcp_ccw_register();
if (retval) {
@@ -350,6 +386,14 @@ zfcp_module_init(void)
out_ccw_register:
misc_deregister(&zfcp_cfdc_misc);
+ out_misc:
+ fc_release_transport(zfcp_data.scsi_transport_template);
+ out_transport:
+ kmem_cache_destroy(zfcp_data.gid_pn_cache);
+ out_gid_cache:
+ kmem_cache_destroy(zfcp_data.sr_buffer_cache);
+ out_sr_cache:
+ kmem_cache_destroy(zfcp_data.fsf_req_qtcb_cache);
out:
return retval;
}
@@ -935,20 +979,20 @@ static int
zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
adapter->pool.fsf_req_erp =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_erp)
return -ENOMEM;
adapter->pool.fsf_req_scsi =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_scsi)
return -ENOMEM;
adapter->pool.fsf_req_abort =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_abort)
return -ENOMEM;
@@ -959,14 +1003,14 @@ zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
return -ENOMEM;
adapter->pool.data_status_read =
- mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR,
- sizeof(struct fsf_status_read_buffer));
+ mempool_create_slab_pool(ZFCP_POOL_STATUS_READ_NR,
+ zfcp_data.sr_buffer_cache);
if (!adapter->pool.data_status_read)
return -ENOMEM;
adapter->pool.data_gid_pn =
- mempool_create_kmalloc_pool(ZFCP_POOL_DATA_GID_PN_NR,
- sizeof(struct zfcp_gid_pn_data));
+ mempool_create_slab_pool(ZFCP_POOL_DATA_GID_PN_NR,
+ zfcp_data.gid_pn_cache);
if (!adapter->pool.data_gid_pn)
return -ENOMEM;
@@ -1091,9 +1135,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
/* initialize lock of associated request queue */
rwlock_init(&adapter->request_queue.queue_lock);
- /* intitialise SCSI ER timer */
- init_timer(&adapter->scsi_er_timer);
-
/* mark adapter unusable as long as sysfs registration is not complete */
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -1609,7 +1650,6 @@ zfcp_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
gid_pn->ct.handler = zfcp_ns_gid_pn_handler;
gid_pn->ct.handler_data = (unsigned long) gid_pn;
gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
- gid_pn->ct.timer = &erp_action->timer;
gid_pn->port = erp_action->port;
ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index fdabadeaa9e..81680efa172 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -275,19 +275,6 @@ zfcp_ccw_register(void)
}
/**
- * zfcp_ccw_unregister - ccw unregister function
- *
- * Unregisters the driver from common i/o layer. Function will be called at
- * module unload/system shutdown.
- */
-void __exit
-zfcp_ccw_unregister(void)
-{
- zfcp_sysfs_driver_remove_files(&zfcp_ccw_driver.driver);
- ccw_driver_unregister(&zfcp_ccw_driver);
-}
-
-/**
* zfcp_ccw_shutdown - gets called on reboot/shutdown
*
* Makes sure that QDIO queues are down when the system gets stopped.
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index c033145d0f1..0aa3b1ac76a 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -707,7 +707,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
struct zfcp_fsf_req *fsf_req,
- struct zfcp_fsf_req *old_fsf_req)
+ unsigned long old_req_id)
{
struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
@@ -768,8 +768,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
rec->fsf_seqno = fsf_req->seq_no;
rec->fsf_issued = fsf_req->issued;
}
- rec->type.old_fsf_reqid =
- (unsigned long) old_fsf_req;
+ rec->type.old_fsf_reqid = old_req_id;
} else {
strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
dump->total_size = buflen;
@@ -794,17 +793,17 @@ zfcp_scsi_dbf_event_result(const char *tag, int level,
struct zfcp_fsf_req *fsf_req)
{
_zfcp_scsi_dbf_event_common("rslt", tag, level,
- adapter, scsi_cmnd, fsf_req, NULL);
+ adapter, scsi_cmnd, fsf_req, 0);
}
inline void
zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
struct zfcp_fsf_req *new_fsf_req,
- struct zfcp_fsf_req *old_fsf_req)
+ unsigned long old_req_id)
{
_zfcp_scsi_dbf_event_common("abrt", tag, 1,
- adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
+ adapter, scsi_cmnd, new_fsf_req, old_req_id);
}
inline void
@@ -814,7 +813,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
struct zfcp_adapter *adapter = unit->port->adapter;
_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
- tag, 1, adapter, scsi_cmnd, NULL, NULL);
+ tag, 1, adapter, scsi_cmnd, NULL, 0);
}
static int
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 94d1b74db35..8f882690994 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -19,7 +19,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#ifndef ZFCP_DEF_H
#define ZFCP_DEF_H
@@ -32,6 +31,10 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mempool.h>
+#include <linux/syscalls.h>
+#include <linux/ioctl.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h>
@@ -39,14 +42,11 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
-#include "zfcp_fsf.h"
#include <asm/ccwdev.h>
#include <asm/qdio.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
-#include <linux/mempool.h>
-#include <linux/syscalls.h>
-#include <linux/ioctl.h>
+#include "zfcp_fsf.h"
/********************* GENERAL DEFINES *********************************/
@@ -137,7 +137,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list)
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
/* timeout value for "default timer" for fsf requests */
-#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
+#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ)
/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
@@ -543,7 +543,7 @@ do { \
} while (0)
#if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
-# define ZFCP_LOG_NORMAL(fmt, args...)
+# define ZFCP_LOG_NORMAL(fmt, args...) do { } while (0)
#else
# define ZFCP_LOG_NORMAL(fmt, args...) \
do { \
@@ -553,7 +553,7 @@ do { \
#endif
#if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO
-# define ZFCP_LOG_INFO(fmt, args...)
+# define ZFCP_LOG_INFO(fmt, args...) do { } while (0)
#else
# define ZFCP_LOG_INFO(fmt, args...) \
do { \
@@ -563,14 +563,14 @@ do { \
#endif
#if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG
-# define ZFCP_LOG_DEBUG(fmt, args...)
+# define ZFCP_LOG_DEBUG(fmt, args...) do { } while (0)
#else
# define ZFCP_LOG_DEBUG(fmt, args...) \
ZFCP_LOG(ZFCP_LOG_LEVEL_DEBUG, fmt , ##args)
#endif
#if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_TRACE
-# define ZFCP_LOG_TRACE(fmt, args...)
+# define ZFCP_LOG_TRACE(fmt, args...) do { } while (0)
#else
# define ZFCP_LOG_TRACE(fmt, args...) \
ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args)
@@ -779,7 +779,6 @@ typedef void (*zfcp_send_ct_handler_t)(unsigned long);
* @handler_data: data passed to handler function
* @pool: pointer to memory pool for ct request structure
* @timeout: FSF timeout for this request
- * @timer: timer (e.g. for request initiated by erp)
* @completion: completion for synchronization purposes
* @status: used to pass error status to calling function
*/
@@ -793,7 +792,6 @@ struct zfcp_send_ct {
unsigned long handler_data;
mempool_t *pool;
int timeout;
- struct timer_list *timer;
struct completion *completion;
int status;
};
@@ -821,7 +819,6 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
* @resp_count: number of elements in response scatter-gather list
* @handler: handler function (called for response to the request)
* @handler_data: data passed to handler function
- * @timer: timer (e.g. for request initiated by erp)
* @completion: completion for synchronization purposes
* @ls_code: hex code of ELS command
* @status: used to pass error status to calling function
@@ -836,7 +833,6 @@ struct zfcp_send_els {
unsigned int resp_count;
zfcp_send_els_handler_t handler;
unsigned long handler_data;
- struct timer_list *timer;
struct completion *completion;
int ls_code;
int status;
@@ -886,7 +882,6 @@ struct zfcp_adapter {
struct list_head port_remove_lh; /* head of ports to be
removed */
u32 ports; /* number of remote ports */
- struct timer_list scsi_er_timer; /* SCSI err recovery watch */
atomic_t reqs_active; /* # active FSF reqs */
unsigned long req_no; /* unique FSF req number */
struct list_head *req_list; /* list of pending reqs */
@@ -1003,6 +998,7 @@ struct zfcp_fsf_req {
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
unsigned long data; /* private data of request */
+ struct timer_list timer; /* used for erp or scsi er */
struct zfcp_erp_action *erp_action; /* used if this request is
issued on behalf of erp */
mempool_t *pool; /* used if request was alloacted
@@ -1016,6 +1012,7 @@ typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*);
/* driver data */
struct zfcp_data {
struct scsi_host_template scsi_host_template;
+ struct scsi_transport_template *scsi_transport_template;
atomic_t status; /* Module status flags */
struct list_head adapter_list_head; /* head of adapter list */
struct list_head adapter_remove_lh; /* head of adapters to be
@@ -1031,6 +1028,9 @@ struct zfcp_data {
wwn_t init_wwpn;
fcp_lun_t init_fcp_lun;
char *driver_version;
+ kmem_cache_t *fsf_req_qtcb_cache;
+ kmem_cache_t *sr_buffer_cache;
+ kmem_cache_t *gid_pn_cache;
};
/**
@@ -1051,7 +1051,7 @@ struct zfcp_sg_list {
#define ZFCP_POOL_DATA_GID_PN_NR 1
/* struct used by memory pools for fsf_requests */
-struct zfcp_fsf_req_pool_element {
+struct zfcp_fsf_req_qtcb {
struct zfcp_fsf_req fsf_req;
struct fsf_qtcb qtcb;
};
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 7f60b6fdf72..862a411a4aa 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -64,8 +64,6 @@ static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int);
static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int);
static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *);
-static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *);
-static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
@@ -93,6 +91,7 @@ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *);
static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *);
static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *);
+static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
static void zfcp_erp_action_dismiss_port(struct zfcp_port *);
static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
@@ -111,64 +110,86 @@ static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *);
static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *);
static void zfcp_erp_memwait_handler(unsigned long);
-static void zfcp_erp_timeout_handler(unsigned long);
-static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *);
/**
- * zfcp_fsf_request_timeout_handler - called if a request timed out
- * @data: pointer to adapter for handler function
- *
- * This function needs to be called if requests (ELS, Generic Service,
- * or SCSI commands) exceed a certain time limit. The assumption is
- * that after the time limit the adapter get stuck. So we trigger a reopen of
- * the adapter. This should not be used for error recovery, SCSI abort
- * commands and SCSI requests from SCSI mid-layer.
+ * zfcp_close_qdio - close qdio queues for an adapter
*/
-void
-zfcp_fsf_request_timeout_handler(unsigned long data)
+static void zfcp_close_qdio(struct zfcp_adapter *adapter)
{
- struct zfcp_adapter *adapter;
+ struct zfcp_qdio_queue *req_queue;
+ int first, count;
- adapter = (struct zfcp_adapter *) data;
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+ return;
- zfcp_erp_adapter_reopen(adapter, 0);
+ /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
+ req_queue = &adapter->request_queue;
+ write_lock_irq(&req_queue->queue_lock);
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
+ write_unlock_irq(&req_queue->queue_lock);
+
+ debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
+ while (qdio_shutdown(adapter->ccw_device,
+ QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+ msleep(1000);
+ debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
+
+ /* cleanup used outbound sbals */
+ count = atomic_read(&req_queue->free_count);
+ if (count < QDIO_MAX_BUFFERS_PER_Q) {
+ first = (req_queue->free_index+count) % QDIO_MAX_BUFFERS_PER_Q;
+ count = QDIO_MAX_BUFFERS_PER_Q - count;
+ zfcp_qdio_zero_sbals(req_queue->buffer, first, count);
+ }
+ req_queue->free_index = 0;
+ atomic_set(&req_queue->free_count, 0);
+ req_queue->distance_from_int = 0;
+ adapter->response_queue.free_index = 0;
+ atomic_set(&adapter->response_queue.free_count, 0);
}
/**
- * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks
+ * zfcp_close_fsf - stop FSF operations for an adapter
*
- * This function needs to be called whenever a SCSI error recovery
- * action (abort/reset) does not return. Re-opening the adapter means
- * that the abort/reset command can be returned by zfcp. It won't complete
- * via the adapter anymore (because qdio queues are closed). If ERP is
- * already running on this adapter it will be stopped.
+ * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of
+ * requests waiting for completion; especially this returns SCSI commands
+ * with error state).
*/
-void zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
+static void zfcp_close_fsf(struct zfcp_adapter *adapter)
{
- struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
- unsigned long flags;
-
- ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. "
- "Restarting all operations on the adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
- debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout");
+ /* close queues to ensure that buffers are not accessed by adapter */
+ zfcp_close_qdio(adapter);
+ zfcp_fsf_req_dismiss_all(adapter);
+ /* reset FSF request sequence number */
+ adapter->fsf_req_seq_no = 0;
+ /* all ports and units are closed */
+ zfcp_erp_modify_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+}
- write_lock_irqsave(&adapter->erp_lock, flags);
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
- &adapter->status)) {
- zfcp_erp_modify_adapter_status(adapter,
- ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
- ZFCP_CLEAR);
- zfcp_erp_action_dismiss_adapter(adapter);
- write_unlock_irqrestore(&adapter->erp_lock, flags);
- /* dismiss all pending requests including requests for ERP */
- zfcp_fsf_req_dismiss_all(adapter);
- adapter->fsf_req_seq_no = 0;
- } else
- write_unlock_irqrestore(&adapter->erp_lock, flags);
+/**
+ * zfcp_fsf_request_timeout_handler - called if a request timed out
+ * @data: pointer to adapter for handler function
+ *
+ * This function needs to be called if requests (ELS, Generic Service,
+ * or SCSI commands) exceed a certain time limit. The assumption is
+ * that after the time limit the adapter get stuck. So we trigger a reopen of
+ * the adapter.
+ */
+static void zfcp_fsf_request_timeout_handler(unsigned long data)
+{
+ struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
zfcp_erp_adapter_reopen(adapter, 0);
}
+void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+{
+ fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
+ fsf_req->timer.data = (unsigned long) fsf_req->adapter;
+ fsf_req->timer.expires = timeout;
+ add_timer(&fsf_req->timer);
+}
+
/*
* function:
*
@@ -282,7 +303,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
struct zfcp_ls_adisc *adisc;
void *address = NULL;
int retval = 0;
- struct timer_list *timer;
send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
if (send_els == NULL)
@@ -329,22 +349,11 @@ zfcp_erp_adisc(struct zfcp_port *port)
(wwn_t) adisc->wwnn, adisc->hard_nport_id,
adisc->nport_id);
- timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
- if (!timer)
- goto nomem;
-
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
- send_els->timer = timer;
-
retval = zfcp_fsf_send_els(send_els);
if (retval != 0) {
ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
"0x%08x on adapter %s\n", send_els->d_id,
zfcp_get_busid_by_adapter(adapter));
- del_timer(send_els->timer);
goto freemem;
}
@@ -356,7 +365,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
if (address != NULL)
__free_pages(send_els->req->page, 0);
if (send_els != NULL) {
- kfree(send_els->timer);
kfree(send_els->req);
kfree(send_els->resp);
kfree(send_els);
@@ -382,9 +390,6 @@ zfcp_erp_adisc_handler(unsigned long data)
struct zfcp_ls_adisc_acc *adisc;
send_els = (struct zfcp_send_els *) data;
-
- del_timer(send_els->timer);
-
adapter = send_els->adapter;
port = send_els->port;
d_id = send_els->d_id;
@@ -433,7 +438,6 @@ zfcp_erp_adisc_handler(unsigned long data)
out:
zfcp_port_put(port);
__free_pages(send_els->req->page, 0);
- kfree(send_els->timer);
kfree(send_els->req);
kfree(send_els->resp);
kfree(send_els);
@@ -909,8 +913,6 @@ static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");
debug_event(adapter->erp_dbf, 2, &erp_action->action,
sizeof (int));
- if (!(set_mask & ZFCP_STATUS_ERP_TIMEDOUT))
- del_timer(&erp_action->timer);
erp_action->status |= set_mask;
zfcp_erp_action_ready(erp_action);
} else {
@@ -957,8 +959,7 @@ zfcp_erp_memwait_handler(unsigned long data)
* action gets an appropriate flag and will be processed
* accordingly
*/
-static void
-zfcp_erp_timeout_handler(unsigned long data)
+void zfcp_erp_timeout_handler(unsigned long data)
{
struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
struct zfcp_adapter *adapter = erp_action->adapter;
@@ -1934,8 +1935,7 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
&erp_action->adapter->status);
failed_openfcp:
- zfcp_erp_adapter_strategy_close_qdio(erp_action);
- zfcp_erp_adapter_strategy_close_fsf(erp_action);
+ zfcp_close_fsf(erp_action->adapter);
failed_qdio:
out:
return retval;
@@ -2040,59 +2040,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
return retval;
}
-/**
- * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter
- */
-static void
-zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
-{
- int first_used;
- int used_count;
- struct zfcp_adapter *adapter = erp_action->adapter;
-
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) {
- ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO "
- "queues on adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
- return;
- }
-
- /*
- * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that
- * do_QDIO won't be called while qdio_shutdown is in progress.
- */
- write_lock_irq(&adapter->request_queue.queue_lock);
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
- write_unlock_irq(&adapter->request_queue.queue_lock);
-
- debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
- while (qdio_shutdown(adapter->ccw_device,
- QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
- msleep(1000);
- debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
-
- /*
- * First we had to stop QDIO operation.
- * Now it is safe to take the following actions.
- */
-
- /* Cleanup only necessary when there are unacknowledged buffers */
- if (atomic_read(&adapter->request_queue.free_count)
- < QDIO_MAX_BUFFERS_PER_Q) {
- first_used = (adapter->request_queue.free_index +
- atomic_read(&adapter->request_queue.free_count))
- % QDIO_MAX_BUFFERS_PER_Q;
- used_count = QDIO_MAX_BUFFERS_PER_Q -
- atomic_read(&adapter->request_queue.free_count);
- zfcp_qdio_zero_sbals(adapter->request_queue.buffer,
- first_used, used_count);
- }
- adapter->response_queue.free_index = 0;
- atomic_set(&adapter->response_queue.free_count, 0);
- adapter->request_queue.free_index = 0;
- atomic_set(&adapter->request_queue.free_count, 0);
- adapter->request_queue.distance_from_int = 0;
-}
static int
zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
@@ -2127,7 +2074,6 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
write_lock_irq(&adapter->erp_lock);
zfcp_erp_action_to_running(erp_action);
write_unlock_irq(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
if (zfcp_fsf_exchange_config_data(erp_action)) {
retval = ZFCP_ERP_FAILED;
debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
@@ -2196,7 +2142,6 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
zfcp_erp_action_to_running(erp_action);
write_unlock_irq(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
if (ret == -EOPNOTSUPP) {
debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
@@ -2248,27 +2193,6 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
return retval;
}
-/**
- * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter
- */
-static void
-zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action)
-{
- struct zfcp_adapter *adapter = erp_action->adapter;
-
- /*
- * wake waiting initiators of requests,
- * return SCSI commands (with error status),
- * clean up all requests (synchronously)
- */
- zfcp_fsf_req_dismiss_all(adapter);
- /* reset FSF request sequence number */
- adapter->fsf_req_seq_no = 0;
- /* all ports and units are closed */
- zfcp_erp_modify_adapter_status(adapter,
- ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
-}
-
/*
* function:
*
@@ -2605,7 +2529,6 @@ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_close_physical_port(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem");
@@ -2662,7 +2585,6 @@ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_close_port(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem");
@@ -2700,7 +2622,6 @@ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_open_port(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem");
@@ -2738,7 +2659,6 @@ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_ns_gid_pn_request(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
@@ -2864,7 +2784,6 @@ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_unit *unit = erp_action->unit;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_close_unit(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem");
@@ -2905,7 +2824,6 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_unit *unit = erp_action->unit;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_open_unit(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem");
@@ -2930,14 +2848,13 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
return retval;
}
-static inline void
-zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action)
+void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
{
- init_timer(&erp_action->timer);
- erp_action->timer.function = zfcp_erp_timeout_handler;
- erp_action->timer.data = (unsigned long) erp_action;
- /* jiffies will be added in zfcp_fsf_req_send */
- erp_action->timer.expires = ZFCP_ERP_FSFREQ_TIMEOUT;
+ BUG_ON(!fsf_req->erp_action);
+ fsf_req->timer.function = zfcp_erp_timeout_handler;
+ fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
+ fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT;
+ add_timer(&fsf_req->timer);
}
/*
@@ -3241,7 +3158,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
}
-void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
{
struct zfcp_port *port;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 146d7a2b4c4..b8794d77285 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -55,7 +55,6 @@ extern void zfcp_unit_dequeue(struct zfcp_unit *);
/******************************* S/390 IO ************************************/
extern int zfcp_ccw_register(void);
-extern void zfcp_ccw_unregister(void);
extern void zfcp_qdio_zero_sbals(struct qdio_buffer **, int, int);
extern int zfcp_qdio_allocate(struct zfcp_adapter *);
@@ -88,8 +87,8 @@ extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *,
struct fsf_qtcb_bottom_port *);
extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
u32, u32, struct zfcp_sg_list *);
-extern void zfcp_fsf_request_timeout_handler(unsigned long);
-extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long);
+extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
+extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
extern int zfcp_fsf_status_read(struct zfcp_adapter *, int);
extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
@@ -99,8 +98,7 @@ extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
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 *,
- struct timer_list*, int);
+ struct scsi_cmnd *, int, int);
extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *);
extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
@@ -124,14 +122,11 @@ extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *);
extern void set_host_byte(u32 *, char);
extern void set_driver_byte(u32 *, char);
extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
-extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *);
extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
- struct scsi_cmnd *, struct timer_list *);
-extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
- struct timer_list *);
-extern struct scsi_transport_template *zfcp_transport_template;
+ struct scsi_cmnd *, int);
+extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, int);
extern struct fc_function_template zfcp_transport_functions;
/******************************** ERP ****************************************/
@@ -139,7 +134,6 @@ extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int);
extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int);
extern void zfcp_erp_adapter_failed(struct zfcp_adapter *);
-extern void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int);
extern int zfcp_erp_port_reopen(struct zfcp_port *, int);
@@ -187,7 +181,7 @@ extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
struct scsi_cmnd *, struct zfcp_fsf_req *,
- struct zfcp_fsf_req *);
+ unsigned long);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
struct scsi_cmnd *);
extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ff2eacf5ec8..277826cdd0c 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -42,7 +42,7 @@ static inline int zfcp_fsf_req_sbal_check(
static inline int zfcp_use_one_sbal(
struct scatterlist *, int, struct scatterlist *, int);
static struct zfcp_fsf_req *zfcp_fsf_req_alloc(mempool_t *, int);
-static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *);
+static int zfcp_fsf_req_send(struct zfcp_fsf_req *);
static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
@@ -100,14 +100,19 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
if (req_flags & ZFCP_REQ_NO_QTCB)
size = sizeof(struct zfcp_fsf_req);
else
- size = sizeof(struct zfcp_fsf_req_pool_element);
+ size = sizeof(struct zfcp_fsf_req_qtcb);
- if (likely(pool != NULL))
+ if (likely(pool))
ptr = mempool_alloc(pool, GFP_ATOMIC);
- else
- ptr = kmalloc(size, GFP_ATOMIC);
+ else {
+ if (req_flags & ZFCP_REQ_NO_QTCB)
+ ptr = kmalloc(size, GFP_ATOMIC);
+ else
+ ptr = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
+ SLAB_ATOMIC);
+ }
- if (unlikely(NULL == ptr))
+ if (unlikely(!ptr))
goto out;
memset(ptr, 0, size);
@@ -115,9 +120,8 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
if (req_flags & ZFCP_REQ_NO_QTCB) {
fsf_req = (struct zfcp_fsf_req *) ptr;
} else {
- fsf_req = &((struct zfcp_fsf_req_pool_element *) ptr)->fsf_req;
- fsf_req->qtcb =
- &((struct zfcp_fsf_req_pool_element *) ptr)->qtcb;
+ fsf_req = &((struct zfcp_fsf_req_qtcb *) ptr)->fsf_req;
+ fsf_req->qtcb = &((struct zfcp_fsf_req_qtcb *) ptr)->qtcb;
}
fsf_req->pool = pool;
@@ -139,10 +143,17 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
void
zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
{
- if (likely(fsf_req->pool != NULL))
+ if (likely(fsf_req->pool)) {
mempool_free(fsf_req, fsf_req->pool);
- else
- kfree(fsf_req);
+ return;
+ }
+
+ if (fsf_req->qtcb) {
+ kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, fsf_req);
+ return;
+ }
+
+ kfree(fsf_req);
}
/**
@@ -214,8 +225,10 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
*/
zfcp_fsf_status_read_handler(fsf_req);
goto out;
- } else
+ } else {
+ del_timer(&fsf_req->timer);
zfcp_fsf_protstatus_eval(fsf_req);
+ }
/*
* fsf_req may be deleted due to waking up functions, so
@@ -774,8 +787,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
sbale->addr = (void *) status_buffer;
sbale->length = sizeof(struct fsf_status_read_buffer);
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_DEBUG("error: Could not set-up unsolicited status "
"environment.\n");
@@ -1101,8 +1113,8 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
struct zfcp_unit *unit, int req_flags)
{
volatile struct qdio_buffer_element *sbale;
- unsigned long lock_flags;
struct zfcp_fsf_req *fsf_req = NULL;
+ unsigned long lock_flags;
int retval = 0;
/* setup new FSF request */
@@ -1132,12 +1144,9 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
/* set handle of request which should be aborted */
fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id;
- /* start QDIO request for this FSF request */
-
- zfcp_fsf_start_scsi_er_timer(adapter);
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
- del_timer(&adapter->scsi_er_timer);
ZFCP_LOG_INFO("error: Failed to send abort command request "
"on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1173,8 +1182,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
unsigned char status_qual =
new_fsf_req->qtcb->header.fsf_status_qual.word[0];
- del_timer(&new_fsf_req->adapter->scsi_er_timer);
-
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */
goto skip_fsfstatus;
@@ -1380,11 +1387,6 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
goto failed_req;
}
- if (erp_action != NULL) {
- erp_action->fsf_req = fsf_req;
- fsf_req->erp_action = erp_action;
- }
-
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
if (zfcp_use_one_sbal(ct->req, ct->req_count,
ct->resp, ct->resp_count)){
@@ -1451,8 +1453,14 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
zfcp_san_dbf_event_ct_request(fsf_req);
- /* start QDIO request for this FSF request */
- ret = zfcp_fsf_req_send(fsf_req, ct->timer);
+ if (erp_action) {
+ erp_action->fsf_req = fsf_req;
+ fsf_req->erp_action = erp_action;
+ zfcp_erp_start_timer(fsf_req);
+ } else
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+
+ ret = zfcp_fsf_req_send(fsf_req);
if (ret) {
ZFCP_LOG_DEBUG("error: initiation of CT request failed "
"(adapter %s, port 0x%016Lx)\n",
@@ -1749,8 +1757,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
zfcp_san_dbf_event_els_request(fsf_req);
- /* start QDIO request for this FSF request */
- ret = zfcp_fsf_req_send(fsf_req, els->timer);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+ ret = zfcp_fsf_req_send(fsf_req);
if (ret) {
ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
"(adapter %s, port d_id: 0x%08x)\n",
@@ -1947,6 +1955,7 @@ int
zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -1955,7 +1964,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
FSF_QTCB_EXCHANGE_CONFIG_DATA,
ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create exchange configuration "
"data request for adapter %s.\n",
@@ -1963,26 +1972,26 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->erp_action = erp_action;
- erp_action->fsf_req->qtcb->bottom.config.feature_selection =
+ fsf_req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_CFDC |
FSF_FEATURE_LUN_SHARING |
FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO
("error: Could not send exchange configuration data "
"command on the adapter %s\n",
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2212,10 +2221,9 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
struct fsf_qtcb_bottom_port *data)
{
volatile struct qdio_buffer_element *sbale;
- int retval = 0;
- unsigned long lock_flags;
struct zfcp_fsf_req *fsf_req;
- struct timer_list *timer;
+ unsigned long lock_flags;
+ int retval = 0;
if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
ZFCP_LOG_INFO("error: exchange port data "
@@ -2248,22 +2256,11 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
if (erp_action) {
erp_action->fsf_req = fsf_req;
fsf_req->erp_action = erp_action;
- timer = &erp_action->timer;
- } else {
- timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
- if (!timer) {
- write_unlock_irqrestore(&adapter->request_queue.queue_lock,
- lock_flags);
- zfcp_fsf_req_free(fsf_req);
- return -ENOMEM;
- }
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
- }
+ zfcp_erp_start_timer(fsf_req);
+ } else
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
- retval = zfcp_fsf_req_send(fsf_req, timer);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send an exchange port data "
"command on the adapter %s\n",
@@ -2271,8 +2268,6 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
zfcp_fsf_req_free(fsf_req);
if (erp_action)
erp_action->fsf_req = NULL;
- else
- kfree(timer);
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
return retval;
@@ -2283,9 +2278,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
if (!erp_action) {
wait_event(fsf_req->completion_wq,
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- del_timer_sync(timer);
zfcp_fsf_req_free(fsf_req);
- kfree(timer);
}
return retval;
}
@@ -2367,6 +2360,7 @@ int
zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -2375,7 +2369,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
FSF_QTCB_OPEN_PORT_WITH_DID,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create open port request "
"for port 0x%016Lx on adapter %s.\n",
@@ -2384,24 +2378,24 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
+ fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->port;
- erp_action->fsf_req->erp_action = erp_action;
+ fsf_req->data = (unsigned long) erp_action->port;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send open port request for "
"port 0x%016Lx on adapter %s.\n",
erp_action->port->wwpn,
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2623,6 +2617,7 @@ int
zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -2631,7 +2626,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
FSF_QTCB_CLOSE_PORT,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create a close port request "
"for port 0x%016Lx on adapter %s.\n",
@@ -2640,25 +2635,25 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->port;
- erp_action->fsf_req->erp_action = erp_action;
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
-
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ fsf_req->data = (unsigned long) erp_action->port;
+ fsf_req->erp_action = erp_action;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
+
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send a close port request for "
"port 0x%016Lx on adapter %s.\n",
erp_action->port->wwpn,
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2755,16 +2750,17 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
int
zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
{
- int retval = 0;
- unsigned long lock_flags;
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
+ unsigned long lock_flags;
+ int retval = 0;
/* setup new FSF request */
retval = zfcp_fsf_req_create(erp_action->adapter,
FSF_QTCB_CLOSE_PHYSICAL_PORT,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &erp_action->fsf_req);
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create close physical port "
"request (adapter %s, port 0x%016Lx)\n",
@@ -2774,8 +2770,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -2783,20 +2778,19 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING,
&erp_action->port->status);
/* save a pointer to this port */
- erp_action->fsf_req->data = (unsigned long) erp_action->port;
- /* port to be closed */
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
- erp_action->fsf_req->erp_action = erp_action;
-
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ fsf_req->data = (unsigned long) erp_action->port;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
+
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send close physical port "
"request (adapter %s, port 0x%016Lx)\n",
zfcp_get_busid_by_adapter(erp_action->adapter),
erp_action->port->wwpn);
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2961,6 +2955,7 @@ int
zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -2969,7 +2964,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
FSF_QTCB_OPEN_LUN,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create open unit request for "
"unit 0x%016Lx on port 0x%016Lx on adapter %s.\n",
@@ -2979,24 +2974,22 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
- erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
- erp_action->unit->fcp_lun;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE))
- erp_action->fsf_req->qtcb->bottom.support.option =
+ fsf_req->qtcb->bottom.support.option =
FSF_OPEN_LUN_SUPPRESS_BOXING;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->unit;
- erp_action->fsf_req->erp_action = erp_action;
+ fsf_req->data = (unsigned long) erp_action->unit;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(erp_action->fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send an open unit request "
"on the adapter %s, port 0x%016Lx for "
@@ -3004,7 +2997,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(erp_action->adapter),
erp_action->port->wwpn,
erp_action->unit->fcp_lun);
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -3297,6 +3290,7 @@ int
zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -3305,7 +3299,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
FSF_QTCB_CLOSE_LUN,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create close unit request for "
"unit 0x%016Lx on port 0x%016Lx on adapter %s.\n",
@@ -3315,27 +3309,26 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
- erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->unit;
- erp_action->fsf_req->erp_action = erp_action;
+ fsf_req->data = (unsigned long) erp_action->unit;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(erp_action->fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send a close unit request for "
"unit 0x%016Lx on port 0x%016Lx onadapter %s.\n",
erp_action->unit->fcp_lun,
erp_action->port->wwpn,
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -3488,7 +3481,7 @@ int
zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
struct zfcp_unit *unit,
struct scsi_cmnd * scsi_cmnd,
- struct timer_list *timer, int req_flags)
+ int use_timer, int req_flags)
{
struct zfcp_fsf_req *fsf_req = NULL;
struct fcp_cmnd_iu *fcp_cmnd_iu;
@@ -3516,7 +3509,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
fsf_req->unit = unit;
/* associate FSF request with SCSI request (for look up on abort) */
- scsi_cmnd->host_scribble = (char *) fsf_req;
+ scsi_cmnd->host_scribble = (unsigned char *) fsf_req->req_id;
/* associate SCSI command with FSF request */
fsf_req->data = (unsigned long) scsi_cmnd;
@@ -3629,11 +3622,10 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
- /*
- * start QDIO request for this FSF request
- * covered by an SBALE)
- */
- retval = zfcp_fsf_req_send(fsf_req, timer);
+ if (use_timer)
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+
+ retval = zfcp_fsf_req_send(fsf_req);
if (unlikely(retval < 0)) {
ZFCP_LOG_INFO("error: Could not send FCP command request "
"on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
@@ -3718,11 +3710,9 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
fcp_cmnd_iu->task_management_flags = tm_flags;
- /* start QDIO request for this FSF request */
- zfcp_fsf_start_scsi_er_timer(adapter);
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
- del_timer(&adapter->scsi_er_timer);
ZFCP_LOG_INFO("error: Could not send an FCP-command (task "
"management) on adapter %s, port 0x%016Lx for "
"unit LUN 0x%016Lx\n",
@@ -4226,7 +4216,6 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu);
struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data;
- del_timer(&fsf_req->adapter->scsi_er_timer);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
goto skip_fsfstatus;
@@ -4295,7 +4284,6 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *fsf_req;
struct fsf_qtcb_bottom_support *bottom;
volatile struct qdio_buffer_element *sbale;
- struct timer_list *timer;
unsigned long lock_flags;
int req_flags = 0;
int direction;
@@ -4327,12 +4315,6 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
goto out;
}
- timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
- if (!timer) {
- retval = -ENOMEM;
- goto out;
- }
-
retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags,
NULL, &lock_flags, &fsf_req);
if (retval < 0) {
@@ -4367,12 +4349,8 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
} else
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
-
- retval = zfcp_fsf_req_send(fsf_req, timer);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("initiation of cfdc up/download failed"
"(adapter %s)\n",
@@ -4392,15 +4370,12 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
*fsf_req_ptr = fsf_req;
- del_timer_sync(timer);
- goto free_timer;
+ goto out;
free_fsf_req:
zfcp_fsf_req_free(fsf_req);
unlock_queue_lock:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
- free_timer:
- kfree(timer);
out:
return retval;
}
@@ -4656,7 +4631,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
{
volatile struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *fsf_req = NULL;
- unsigned long flags;
int ret = 0;
struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
@@ -4673,12 +4647,13 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
fsf_req->fsf_command = fsf_cmd;
INIT_LIST_HEAD(&fsf_req->list);
- /* unique request id */
- spin_lock_irqsave(&adapter->req_list_lock, flags);
+ /* this is serialized (we are holding req_queue-lock of adapter */
+ if (adapter->req_no == 0)
+ adapter->req_no++;
fsf_req->req_id = adapter->req_no++;
- spin_unlock_irqrestore(&adapter->req_list_lock, flags);
- zfcp_fsf_req_qtcb_init(fsf_req);
+ init_timer(&fsf_req->timer);
+ zfcp_fsf_req_qtcb_init(fsf_req);
/* initialize waitqueue which may be used to wait on
this request completion */
@@ -4748,8 +4723,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
* returns: 0 - request transfer succesfully started
* !0 - start of request transfer failed
*/
-static int
-zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
+static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_adapter *adapter;
struct zfcp_qdio_queue *req_queue;
@@ -4777,12 +4751,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
inc_seq_no = (fsf_req->qtcb != NULL);
- /* figure out expiration time of timeout and start timeout */
- if (unlikely(timer)) {
- timer->expires += jiffies;
- add_timer(timer);
- }
-
ZFCP_LOG_TRACE("request queue of adapter %s: "
"next free SBAL is %i, %i free SBALs\n",
zfcp_get_busid_by_adapter(adapter),
@@ -4819,12 +4787,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
if (unlikely(retval)) {
/* Queues are down..... */
retval = -EIO;
- /*
- * FIXME(potential race):
- * timer might be expired (absolutely unlikely)
- */
- if (timer)
- del_timer(timer);
+ del_timer(&fsf_req->timer);
spin_lock(&adapter->req_list_lock);
zfcp_reqlist_remove(adapter, fsf_req->req_id);
spin_unlock(&adapter->req_list_lock);
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 1bb55086db9..7cafa34e4c7 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -39,11 +39,10 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
-struct scsi_transport_template *zfcp_transport_template;
-
struct zfcp_data zfcp_data = {
.scsi_host_template = {
.name = ZFCP_NAME,
+ .module = THIS_MODULE,
.proc_name = "zfcp",
.slave_alloc = zfcp_scsi_slave_alloc,
.slave_configure = zfcp_scsi_slave_configure,
@@ -232,7 +231,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
*/
int
zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
- struct scsi_cmnd *scpnt, struct timer_list *timer)
+ struct scsi_cmnd *scpnt, int use_timer)
{
int tmp;
int retval;
@@ -268,7 +267,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
goto out;
}
- tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer,
+ tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer,
ZFCP_REQ_AUTO_CLEANUP);
if (unlikely(tmp < 0)) {
@@ -292,21 +291,22 @@ zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt)
* zfcp_scsi_command_sync - send a SCSI command and wait for completion
* @unit: unit where command is sent to
* @scpnt: scsi command to be sent
- * @timer: timer to be started if request is successfully initiated
+ * @use_timer: indicates whether timer should be setup or not
* Return: 0
*
* Errors are indicated in scpnt->result
*/
int
zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt,
- struct timer_list *timer)
+ int use_timer)
{
int ret;
DECLARE_COMPLETION(wait);
scpnt->SCp.ptr = (void *) &wait; /* silent re-use */
scpnt->scsi_done = zfcp_scsi_command_sync_handler;
- ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer);
+ ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt,
+ use_timer);
if (ret == 0)
wait_for_completion(&wait);
@@ -342,7 +342,7 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
unit = (struct zfcp_unit *) scpnt->device->hostdata;
- return zfcp_scsi_command_async(adapter, unit, scpnt, NULL);
+ return zfcp_scsi_command_async(adapter, unit, scpnt, 0);
}
static struct zfcp_unit *
@@ -379,16 +379,15 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
* will handle late commands. (Usually, the normal completion of late
* commands is ignored with respect to the running abort operation.)
*/
-int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
struct Scsi_Host *scsi_host;
struct zfcp_adapter *adapter;
struct zfcp_unit *unit;
- int retval = SUCCESS;
- struct zfcp_fsf_req *new_fsf_req = NULL;
- struct zfcp_fsf_req *old_fsf_req;
+ struct zfcp_fsf_req *fsf_req;
unsigned long flags;
+ unsigned long old_req_id;
+ int retval = SUCCESS;
scsi_host = scpnt->device->host;
adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
@@ -400,55 +399,47 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* avoid race condition between late normal completion and abort */
write_lock_irqsave(&adapter->abort_lock, flags);
- /*
- * Check whether command has just completed and can not be aborted.
- * Even if the command has just been completed late, we can access
- * scpnt since the SCSI stack does not release it at least until
- * this routine returns. (scpnt is parameter passed to this routine
- * and must not disappear during abort even on late completion.)
- */
- old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
- if (!old_fsf_req) {
+ /* Check whether corresponding fsf_req is still pending */
+ spin_lock(&adapter->req_list_lock);
+ fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long)
+ scpnt->host_scribble);
+ spin_unlock(&adapter->req_list_lock);
+ if (!fsf_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0);
retval = SUCCESS;
goto out;
}
- old_fsf_req->data = 0;
- old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
+ fsf_req->data = 0;
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
+ old_req_id = fsf_req->req_id;
- /* don't access old_fsf_req after releasing the abort_lock */
+ /* don't access old fsf_req after releasing the abort_lock */
write_unlock_irqrestore(&adapter->abort_lock, flags);
- /* call FSF routine which does the abort */
- new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req,
- adapter, unit, 0);
- if (!new_fsf_req) {
+
+ fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0);
+ if (!fsf_req) {
ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
- old_fsf_req);
+ old_req_id);
retval = FAILED;
goto out;
}
- /* wait for completion of abort */
- __wait_event(new_fsf_req->completion_wq,
- new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ __wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- /* status should be valid since signals were not permitted */
- if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
- zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
- NULL);
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0);
retval = SUCCESS;
- } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
- zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
- NULL);
+ } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0);
retval = SUCCESS;
} else {
- zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
- NULL);
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0);
retval = FAILED;
}
- zfcp_fsf_req_free(new_fsf_req);
+ zfcp_fsf_req_free(fsf_req);
out:
return retval;
}
@@ -548,14 +539,11 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,
/**
* zfcp_scsi_eh_host_reset_handler - handler for host and bus reset
- *
- * If ERP is already running it will be stopped.
*/
int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
struct zfcp_unit *unit;
struct zfcp_adapter *adapter;
- unsigned long flags;
unit = (struct zfcp_unit*) scpnt->device->hostdata;
adapter = unit->port->adapter;
@@ -563,22 +551,8 @@ int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
ZFCP_LOG_NORMAL("host/bus reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
- write_lock_irqsave(&adapter->erp_lock, flags);
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
- &adapter->status)) {
- zfcp_erp_modify_adapter_status(adapter,
- ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
- ZFCP_CLEAR);
- zfcp_erp_action_dismiss_adapter(adapter);
- write_unlock_irqrestore(&adapter->erp_lock, flags);
- zfcp_fsf_req_dismiss_all(adapter);
- adapter->fsf_req_seq_no = 0;
- zfcp_erp_adapter_reopen(adapter, 0);
- } else {
- write_unlock_irqrestore(&adapter->erp_lock, flags);
- zfcp_erp_adapter_reopen(adapter, 0);
- zfcp_erp_wait(adapter);
- }
+ zfcp_erp_adapter_reopen(adapter, 0);
+ zfcp_erp_wait(adapter);
return SUCCESS;
}
@@ -607,7 +581,7 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
adapter->scsi_host->max_channel = 0;
adapter->scsi_host->unique_id = unique_id++; /* FIXME */
adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;
- adapter->scsi_host->transportt = zfcp_transport_template;
+ adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;
/*
* save a pointer to our own adapter data structure within
@@ -648,16 +622,6 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
return;
}
-
-void
-zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
-{
- adapter->scsi_er_timer.function = zfcp_fsf_scsi_er_timeout_handler;
- adapter->scsi_er_timer.data = (unsigned long) adapter;
- adapter->scsi_er_timer.expires = jiffies + ZFCP_SCSI_ER_TIMEOUT;
- add_timer(&adapter->scsi_er_timer);
-}
-
/*
* Support functions for FC transport class
*/