diff options
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 84 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 13 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 13 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 32 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 231 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 18 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 299 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 112 |
8 files changed, 333 insertions, 469 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index adc9d8f2c28f..5d39b2df0cc4 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 fdabadeaa9ee..81680efa1721 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 c033145d0f19..0aa3b1ac76af 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 94d1b74db356..8f882690994d 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 7f60b6fdf724..862a411a4aa0 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 146d7a2b4c4a..b8794d77285d 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 ff2eacf5ec8c..277826cdd0c8 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 1bb55086db9f..7cafa34e4c7f 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 */ |