diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 17:53:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 17:53:36 -0700 |
commit | 39695224bd84dc4be29abad93a0ec232a16fc519 (patch) | |
tree | 2bfa5cb50788a4c8be9f2e9f4412e47a565f4508 /drivers/s390/scsi/zfcp_fsf.c | |
parent | a9bbd210a44102cc50b30a5f3d111dbf5f2f9cd4 (diff) | |
parent | ea038f63ac52439e7816295fa6064fe95e6c1f51 (diff) | |
download | kernel_samsung_smdk4412-39695224bd84dc4be29abad93a0ec232a16fc519.zip kernel_samsung_smdk4412-39695224bd84dc4be29abad93a0ec232a16fc519.tar.gz kernel_samsung_smdk4412-39695224bd84dc4be29abad93a0ec232a16fc519.tar.bz2 |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (209 commits)
[SCSI] fix oops during scsi scanning
[SCSI] libsrp: fix memory leak in srp_ring_free()
[SCSI] libiscsi, bnx2i: make bound ep check common
[SCSI] libiscsi: add completion function for drivers that do not need pdu processing
[SCSI] scsi_dh_rdac: changes for rdac debug logging
[SCSI] scsi_dh_rdac: changes to collect the rdac debug information during the initialization
[SCSI] scsi_dh_rdac: move the init code from rdac_activate to rdac_bus_attach
[SCSI] sg: fix oops in the error path in sg_build_indirect()
[SCSI] mptsas : Bump version to 3.04.12
[SCSI] mptsas : FW event thread and scsi mid layer deadlock in SYNCHRONIZE CACHE command
[SCSI] mptsas : Send DID_NO_CONNECT for pending IOs of removed device
[SCSI] mptsas : PAE Kernel more than 4 GB kernel panic
[SCSI] mptsas : NULL pointer on big endian systems causing Expander not to tear off
[SCSI] mptsas : Sanity check for phyinfo is added
[SCSI] scsi_dh_rdac: Add support for Sun StorageTek ST2500, ST2510 and ST2530
[SCSI] pmcraid: PMC-Sierra MaxRAID driver to support 6Gb/s SAS RAID controller
[SCSI] qla2xxx: Update version number to 8.03.01-k6.
[SCSI] qla2xxx: Properly delete rports attached to a vport.
[SCSI] qla2xxx: Correct various NPIV issues.
[SCSI] qla2xxx: Correct qla2x00_eh_wait_on_command() to wait correctly.
...
Diffstat (limited to 'drivers/s390/scsi/zfcp_fsf.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 635 |
1 files changed, 339 insertions, 296 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 47795fb..f09c863 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -11,9 +11,7 @@ #include <linux/blktrace_api.h> #include "zfcp_ext.h" - -#define ZFCP_REQ_AUTO_CLEANUP 0x00000002 -#define ZFCP_REQ_NO_QTCB 0x00000008 +#include "zfcp_dbf.h" static void zfcp_fsf_request_timeout_handler(unsigned long data) { @@ -111,43 +109,15 @@ static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) void zfcp_fsf_req_free(struct zfcp_fsf_req *req) { if (likely(req->pool)) { + if (likely(req->qtcb)) + mempool_free(req->qtcb, req->adapter->pool.qtcb_pool); mempool_free(req, req->pool); return; } - if (req->qtcb) { - kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, req); - return; - } -} - -/** - * zfcp_fsf_req_dismiss_all - dismiss all fsf requests - * @adapter: pointer to struct zfcp_adapter - * - * Never ever call this without shutting down the adapter first. - * Otherwise the adapter would continue using and corrupting s390 storage. - * Included BUG_ON() call to ensure this is done. - * ERP is supposed to be the only user of this function. - */ -void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) -{ - struct zfcp_fsf_req *req, *tmp; - unsigned long flags; - LIST_HEAD(remove_queue); - unsigned int i; - - BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); - spin_lock_irqsave(&adapter->req_list_lock, flags); - for (i = 0; i < REQUEST_LIST_SIZE; i++) - list_splice_init(&adapter->req_list[i], &remove_queue); - spin_unlock_irqrestore(&adapter->req_list_lock, flags); - - list_for_each_entry_safe(req, tmp, &remove_queue, list) { - list_del(&req->list); - req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; - zfcp_fsf_req_complete(req); - } + if (likely(req->qtcb)) + kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb); + kfree(req); } static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) @@ -278,13 +248,13 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) struct fsf_status_read_buffer *sr_buf = req->data; if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { - zfcp_hba_dbf_event_fsf_unsol("dism", adapter, sr_buf); - mempool_free(sr_buf, adapter->pool.data_status_read); + zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf); + mempool_free(sr_buf, adapter->pool.status_read_data); zfcp_fsf_req_free(req); return; } - zfcp_hba_dbf_event_fsf_unsol("read", adapter, sr_buf); + zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf); switch (sr_buf->status_type) { case FSF_STATUS_READ_PORT_CLOSED: @@ -299,7 +269,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) dev_warn(&adapter->ccw_device->dev, "The error threshold for checksum statistics " "has been exceeded\n"); - zfcp_hba_dbf_event_berr(adapter, req); + zfcp_dbf_hba_berr(adapter->dbf, req); break; case FSF_STATUS_READ_LINK_DOWN: zfcp_fsf_status_read_link_down(req); @@ -331,11 +301,11 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) break; } - mempool_free(sr_buf, adapter->pool.data_status_read); + mempool_free(sr_buf, adapter->pool.status_read_data); zfcp_fsf_req_free(req); atomic_inc(&adapter->stat_miss); - queue_work(zfcp_data.work_queue, &adapter->stat_work); + queue_work(adapter->work_queue, &adapter->stat_work); } static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) @@ -385,7 +355,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) struct fsf_qtcb *qtcb = req->qtcb; union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual; - zfcp_hba_dbf_event_fsf_response(req); + zfcp_dbf_hba_fsf_response(req); if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { req->status |= ZFCP_STATUS_FSFREQ_ERROR | @@ -458,7 +428,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) * is called to process the completion status and trigger further * events related to the FSF request. */ -void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) +static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) { if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { zfcp_fsf_status_read_handler(req); @@ -472,23 +442,40 @@ void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) if (req->erp_action) zfcp_erp_notify(req->erp_action, 0); - req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) zfcp_fsf_req_free(req); else - /* notify initiator waiting for the requests completion */ - /* - * FIXME: Race! We must not access fsf_req here as it might have been - * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED - * flag. It's an improbable case. But, we have the same paranoia for - * the cleanup flag already. - * Might better be handled using complete()? - * (setting the flag and doing wakeup ought to be atomic - * with regard to checking the flag as long as waitqueue is - * part of the to be released structure) - */ - wake_up(&req->completion_wq); + complete(&req->completion); +} + +/** + * zfcp_fsf_req_dismiss_all - dismiss all fsf requests + * @adapter: pointer to struct zfcp_adapter + * + * Never ever call this without shutting down the adapter first. + * Otherwise the adapter would continue using and corrupting s390 storage. + * Included BUG_ON() call to ensure this is done. + * ERP is supposed to be the only user of this function. + */ +void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) +{ + struct zfcp_fsf_req *req, *tmp; + unsigned long flags; + LIST_HEAD(remove_queue); + unsigned int i; + + BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); + spin_lock_irqsave(&adapter->req_list_lock, flags); + for (i = 0; i < REQUEST_LIST_SIZE; i++) + list_splice_init(&adapter->req_list[i], &remove_queue); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); + + list_for_each_entry_safe(req, tmp, &remove_queue, list) { + list_del(&req->list); + req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; + zfcp_fsf_req_complete(req); + } } static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) @@ -650,79 +637,77 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) } } -static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter) +static int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio) { - struct zfcp_qdio_queue *req_q = &adapter->req_q; + struct zfcp_qdio_queue *req_q = &qdio->req_q; - spin_lock_bh(&adapter->req_q_lock); + spin_lock_bh(&qdio->req_q_lock); if (atomic_read(&req_q->count)) return 1; - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return 0; } -static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) +static int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio) { + struct zfcp_adapter *adapter = qdio->adapter; long ret; - spin_unlock_bh(&adapter->req_q_lock); - ret = wait_event_interruptible_timeout(adapter->request_wq, - zfcp_fsf_sbal_check(adapter), 5 * HZ); + spin_unlock_bh(&qdio->req_q_lock); + ret = wait_event_interruptible_timeout(qdio->req_q_wq, + zfcp_fsf_sbal_check(qdio), 5 * HZ); if (ret > 0) return 0; if (!ret) { - atomic_inc(&adapter->qdio_outb_full); + atomic_inc(&qdio->req_q_full); /* assume hanging outbound queue, try queue recovery */ zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL); } - spin_lock_bh(&adapter->req_q_lock); + spin_lock_bh(&qdio->req_q_lock); return -EIO; } -static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool) +static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool) { struct zfcp_fsf_req *req; - req = mempool_alloc(pool, GFP_ATOMIC); - if (!req) + + if (likely(pool)) + req = mempool_alloc(pool, GFP_ATOMIC); + else + req = kmalloc(sizeof(*req), GFP_ATOMIC); + + if (unlikely(!req)) return NULL; + memset(req, 0, sizeof(*req)); req->pool = pool; return req; } -static struct zfcp_fsf_req *zfcp_fsf_alloc_qtcb(mempool_t *pool) +static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool) { - struct zfcp_fsf_req_qtcb *qtcb; + struct fsf_qtcb *qtcb; if (likely(pool)) qtcb = mempool_alloc(pool, GFP_ATOMIC); else - qtcb = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache, - GFP_ATOMIC); + qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC); + if (unlikely(!qtcb)) return NULL; memset(qtcb, 0, sizeof(*qtcb)); - qtcb->fsf_req.qtcb = &qtcb->qtcb; - qtcb->fsf_req.pool = pool; - - return &qtcb->fsf_req; + return qtcb; } -static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, - u32 fsf_cmd, int req_flags, - mempool_t *pool) +static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, + u32 fsf_cmd, mempool_t *pool) { struct qdio_buffer_element *sbale; - - struct zfcp_fsf_req *req; - struct zfcp_qdio_queue *req_q = &adapter->req_q; - - if (req_flags & ZFCP_REQ_NO_QTCB) - req = zfcp_fsf_alloc_noqtcb(pool); - else - req = zfcp_fsf_alloc_qtcb(pool); + struct zfcp_qdio_queue *req_q = &qdio->req_q; + struct zfcp_adapter *adapter = qdio->adapter; + struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool); if (unlikely(!req)) return ERR_PTR(-ENOMEM); @@ -732,22 +717,32 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, INIT_LIST_HEAD(&req->list); init_timer(&req->timer); - init_waitqueue_head(&req->completion_wq); + init_completion(&req->completion); req->adapter = adapter; req->fsf_command = fsf_cmd; req->req_id = adapter->req_no; - req->sbal_number = 1; - req->sbal_first = req_q->first; - req->sbal_last = req_q->first; - req->sbale_curr = 1; + req->queue_req.sbal_number = 1; + req->queue_req.sbal_first = req_q->first; + req->queue_req.sbal_last = req_q->first; + req->queue_req.sbale_curr = 1; - sbale = zfcp_qdio_sbale_req(req); + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].addr = (void *) req->req_id; sbale[0].flags |= SBAL_FLAGS0_COMMAND; - if (likely(req->qtcb)) { - req->qtcb->prefix.req_seq_no = req->adapter->fsf_req_seq_no; + if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { + if (likely(pool)) + req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool); + else + req->qtcb = zfcp_qtcb_alloc(NULL); + + if (unlikely(!req->qtcb)) { + zfcp_fsf_req_free(req); + return ERR_PTR(-ENOMEM); + } + + req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; req->qtcb->prefix.req_id = req->req_id; req->qtcb->prefix.ulp_info = 26; req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command]; @@ -765,15 +760,13 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, return ERR_PTR(-EIO); } - if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) - req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; - return req; } static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; + struct zfcp_qdio *qdio = adapter->qdio; unsigned long flags; int idx; int with_qtcb = (req->qtcb != NULL); @@ -784,9 +777,9 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) list_add_tail(&req->list, &adapter->req_list[idx]); spin_unlock_irqrestore(&adapter->req_list_lock, flags); - req->qdio_outb_usage = atomic_read(&adapter->req_q.count); + req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count); req->issued = get_clock(); - if (zfcp_qdio_send(req)) { + if (zfcp_qdio_send(qdio, &req->queue_req)) { del_timer(&req->timer); spin_lock_irqsave(&adapter->req_list_lock, flags); /* lookup request again, list might have changed */ @@ -811,38 +804,37 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) * @req_flags: request flags * Returns: 0 on success, ERROR otherwise */ -int zfcp_fsf_status_read(struct zfcp_adapter *adapter) +int zfcp_fsf_status_read(struct zfcp_qdio *qdio) { + struct zfcp_adapter *adapter = qdio->adapter; struct zfcp_fsf_req *req; struct fsf_status_read_buffer *sr_buf; struct qdio_buffer_element *sbale; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS, - ZFCP_REQ_NO_QTCB, - adapter->pool.fsf_req_status_read); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, + adapter->pool.status_read_req); if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); - sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY; - req->sbale_curr = 2; + req->queue_req.sbale_curr = 2; - sr_buf = mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC); + sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC); if (!sr_buf) { retval = -ENOMEM; goto failed_buf; } memset(sr_buf, 0, sizeof(*sr_buf)); req->data = sr_buf; - sbale = zfcp_qdio_sbale_curr(req); + sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req); sbale->addr = (void *) sr_buf; sbale->length = sizeof(*sr_buf); @@ -853,12 +845,12 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter) goto out; failed_req_send: - mempool_free(sr_buf, adapter->pool.data_status_read); + mempool_free(sr_buf, adapter->pool.status_read_data); failed_buf: zfcp_fsf_req_free(req); - zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); + zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL); out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -900,7 +892,7 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) case FSF_ADAPTER_STATUS_AVAILABLE: switch (fsq->word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: - zfcp_test_link(unit->port); + zfcp_fc_test_link(unit->port); /* fall through */ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -925,13 +917,13 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, { struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; - struct zfcp_adapter *adapter = unit->port->adapter; + struct zfcp_qdio *qdio = unit->port->adapter->qdio; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, - 0, adapter->pool.fsf_req_abort); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND, + qdio->adapter->pool.scsi_abort); if (IS_ERR(req)) { req = NULL; goto out; @@ -941,7 +933,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, ZFCP_STATUS_COMMON_UNBLOCKED))) goto out_error_free; - sbale = zfcp_qdio_sbale_req(req); + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -959,7 +951,7 @@ out_error_free: zfcp_fsf_req_free(req); req = NULL; out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return req; } @@ -976,7 +968,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_san_dbf_event_ct_response(req); + zfcp_dbf_san_ct_response(req); send_ct->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -1035,8 +1027,10 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, struct scatterlist *sg_resp, int max_sbals) { - struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req); - u32 feat = req->adapter->adapter_features; + struct zfcp_adapter *adapter = req->adapter; + struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio, + &req->queue_req); + u32 feat = adapter->adapter_features; int bytes; if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { @@ -1053,18 +1047,25 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, return 0; } - bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, + bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req, + SBAL_FLAGS0_TYPE_WRITE_READ, sg_req, max_sbals); if (bytes <= 0) return -EIO; req->qtcb->bottom.support.req_buf_length = bytes; - req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; + req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; - bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, + bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req, + SBAL_FLAGS0_TYPE_WRITE_READ, sg_resp, max_sbals); if (bytes <= 0) return -EIO; + + /* common settings for ct/gs and els requests */ req->qtcb->bottom.support.resp_buf_length = bytes; + req->qtcb->bottom.support.service_class = FSF_CLASS_3; + req->qtcb->bottom.support.timeout = 2 * R_A_TOV; + zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10); return 0; } @@ -1073,27 +1074,26 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) * @ct: pointer to struct zfcp_send_ct with data for request * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req - * @erp_action: if non-null the Generic Service request sent within ERP */ -int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, - struct zfcp_erp_action *erp_action) +int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool) { struct zfcp_wka_port *wka_port = ct->wka_port; - struct zfcp_adapter *adapter = wka_port->adapter; + struct zfcp_qdio *qdio = wka_port->adapter->qdio; struct zfcp_fsf_req *req; int ret = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC, - ZFCP_REQ_AUTO_CLEANUP, pool); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool); + if (IS_ERR(req)) { ret = PTR_ERR(req); goto out; } + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp, FSF_MAX_SBALS_PER_REQ); if (ret) @@ -1101,18 +1101,9 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, req->handler = zfcp_fsf_send_ct_handler; req->qtcb->header.port_handle = wka_port->handle; - req->qtcb->bottom.support.service_class = FSF_CLASS_3; - req->qtcb->bottom.support.timeout = ct->timeout; req->data = ct; - zfcp_san_dbf_event_ct_request(req); - - if (erp_action) { - erp_action->fsf_req = req; - req->erp_action = erp_action; - zfcp_fsf_start_erp_timer(req); - } else - zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); + zfcp_dbf_san_ct_request(req); ret = zfcp_fsf_req_send(req); if (ret) @@ -1122,10 +1113,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, failed_send: zfcp_fsf_req_free(req); - if (erp_action) - erp_action->fsf_req = NULL; out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return ret; } @@ -1142,7 +1131,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_san_dbf_event_els_response(req); + zfcp_dbf_san_els_response(req); send_els->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -1152,7 +1141,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) switch (header->fsf_status_qual.word[0]){ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: if (port && (send_els->ls_code != ZFCP_LS_ADISC)) - zfcp_test_link(port); + zfcp_fc_test_link(port); /*fall through */ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: case FSF_SQ_RETRY_IF_POSSIBLE: @@ -1188,35 +1177,32 @@ skip_fsfstatus: int zfcp_fsf_send_els(struct zfcp_send_els *els) { struct zfcp_fsf_req *req; - struct zfcp_adapter *adapter = els->adapter; - struct fsf_qtcb_bottom_support *bottom; + struct zfcp_qdio *qdio = els->adapter->qdio; int ret = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, - ZFCP_REQ_AUTO_CLEANUP, NULL); + + req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL); + if (IS_ERR(req)) { ret = PTR_ERR(req); goto out; } + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2); if (ret) goto failed_send; - bottom = &req->qtcb->bottom.support; + req->qtcb->bottom.support.d_id = els->d_id; req->handler = zfcp_fsf_send_els_handler; - bottom->d_id = els->d_id; - bottom->service_class = FSF_CLASS_3; - bottom->timeout = 2 * R_A_TOV; req->data = els; - zfcp_san_dbf_event_els_request(req); + zfcp_dbf_san_els_request(req); - zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); ret = zfcp_fsf_req_send(req); if (ret) goto failed_send; @@ -1226,7 +1212,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) failed_send: zfcp_fsf_req_free(req); out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return ret; } @@ -1234,22 +1220,23 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) { struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_qdio *qdio = erp_action->adapter->qdio; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, - FSF_QTCB_EXCHANGE_CONFIG_DATA, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + + req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, + qdio->adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1269,29 +1256,29 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } -int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, +int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, struct fsf_qtcb_bottom_config *data) { struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out_unlock; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, - 0, NULL); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out_unlock; } - sbale = zfcp_qdio_sbale_req(req); + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; req->handler = zfcp_fsf_exchange_config_data_handler; @@ -1307,16 +1294,15 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); if (!retval) - wait_event(req->completion_wq, - req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + wait_for_completion(&req->completion); zfcp_fsf_req_free(req); return retval; out_unlock: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1327,26 +1313,28 @@ out_unlock: */ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) { + struct zfcp_qdio *qdio = erp_action->adapter->qdio; struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req; - struct zfcp_adapter *adapter = erp_action->adapter; int retval = -EIO; - if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) + if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) return -EOPNOTSUPP; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + + req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, + qdio->adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1361,32 +1349,32 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } /** * zfcp_fsf_exchange_port_data_sync - request information about local port - * @adapter: pointer to struct zfcp_adapter + * @qdio: pointer to struct zfcp_qdio * @data: pointer to struct fsf_qtcb_bottom_port * Returns: 0 on success, error otherwise */ -int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, +int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, struct fsf_qtcb_bottom_port *data) { struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; int retval = -EIO; - if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) + if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) return -EOPNOTSUPP; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out_unlock; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, - NULL); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out_unlock; @@ -1395,24 +1383,24 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, if (data) req->data = data; - sbale = zfcp_qdio_sbale_req(req); + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; req->handler = zfcp_fsf_exchange_port_data_handler; zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); if (!retval) - wait_event(req->completion_wq, - req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + wait_for_completion(&req->completion); + zfcp_fsf_req_free(req); return retval; out_unlock: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1498,25 +1486,25 @@ out: int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) { struct qdio_buffer_element *sbale; - struct zfcp_adapter *adapter = erp_action->adapter; - struct zfcp_fsf_req *req; + struct zfcp_qdio *qdio = erp_action->adapter->qdio; struct zfcp_port *port = erp_action->port; + struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, - FSF_QTCB_OPEN_PORT_WITH_DID, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, + qdio->adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1535,7 +1523,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) zfcp_port_put(port); } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1569,23 +1557,24 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) { struct qdio_buffer_element *sbale; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_qdio *qdio = erp_action->adapter->qdio; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, + qdio->adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1602,7 +1591,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1645,24 +1634,24 @@ out: int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port) { struct qdio_buffer_element *sbale; - struct zfcp_adapter *adapter = wka_port->adapter; + struct zfcp_qdio *qdio = wka_port->adapter->qdio; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, - FSF_QTCB_OPEN_PORT_WITH_DID, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, + qdio->adapter->pool.erp_req); + if (unlikely(IS_ERR(req))) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1675,7 +1664,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port) if (retval) zfcp_fsf_req_free(req); out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1700,23 +1689,24 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port) { struct qdio_buffer_element *sbale; - struct zfcp_adapter *adapter = wka_port->adapter; + struct zfcp_qdio *qdio = wka_port->adapter->qdio; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, + qdio->adapter->pool.erp_req); + if (unlikely(IS_ERR(req))) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1729,7 +1719,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port) if (retval) zfcp_fsf_req_free(req); out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1791,23 +1781,24 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) { struct qdio_buffer_element *sbale; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_qdio *qdio = erp_action->adapter->qdio; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT, + qdio->adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -1824,7 +1815,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -1895,7 +1886,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) case FSF_ADAPTER_STATUS_AVAILABLE: switch (header->fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: - zfcp_test_link(unit->port); + zfcp_fc_test_link(unit->port); /* fall through */ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -1964,22 +1955,24 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) { struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_qdio *qdio = adapter->qdio; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN, + adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -2000,7 +1993,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -2028,7 +2021,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) case FSF_ADAPTER_STATUS_AVAILABLE: switch (req->qtcb->header.fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: - zfcp_test_link(unit->port); + zfcp_fc_test_link(unit->port); /* fall through */ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -2049,22 +2042,24 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) { struct qdio_buffer_element *sbale; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_qdio *qdio = erp_action->adapter->qdio; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp); + + req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN, + qdio->adapter->pool.erp_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } - sbale = zfcp_qdio_sbale_req(req); + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -2082,7 +2077,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return retval; } @@ -2141,8 +2136,8 @@ static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req) } if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) trace.flags |= ZFCP_BLK_REQ_ERROR; - trace.inb_usage = fsf_req->qdio_inb_usage; - trace.outb_usage = fsf_req->qdio_outb_usage; + trace.inb_usage = fsf_req->queue_req.qdio_inb_usage; + trace.outb_usage = fsf_req->queue_req.qdio_outb_usage; blk_add_driver_data(req->q, req, &trace, sizeof(trace)); } @@ -2215,11 +2210,11 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) } skip_fsfstatus: if (scpnt->result != 0) - zfcp_scsi_dbf_event_result("erro", 3, req->adapter, scpnt, req); + zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req); else if (scpnt->retries > 0) - zfcp_scsi_dbf_event_result("retr", 4, req->adapter, scpnt, req); + zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req); else - zfcp_scsi_dbf_event_result("norm", 6, req->adapter, scpnt, req); + zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req); scpnt->host_scribble = NULL; (scpnt->scsi_done) (scpnt); @@ -2309,7 +2304,7 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) case FSF_ADAPTER_STATUS_AVAILABLE: if (header->fsf_status_qual.word[0] == FSF_SQ_INVOKE_LINK_TEST_PROCEDURE) - zfcp_test_link(unit->port); + zfcp_fc_test_link(unit->port); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; } @@ -2350,24 +2345,27 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, unsigned int sbtype = SBAL_FLAGS0_TYPE_READ; int real_bytes, retval = -EIO; struct zfcp_adapter *adapter = unit->port->adapter; + struct zfcp_qdio *qdio = adapter->qdio; if (unlikely(!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_UNBLOCKED))) return -EBUSY; - spin_lock(&adapter->req_q_lock); - if (atomic_read(&adapter->req_q.count) <= 0) { - atomic_inc(&adapter->qdio_outb_full); + spin_lock(&qdio->req_q_lock); + if (atomic_read(&qdio->req_q.count) <= 0) { + atomic_inc(&qdio->req_q_full); goto out; } - req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_scsi); + + req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, + adapter->pool.scsi_req); + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } + req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; zfcp_unit_get(unit); req->unit = unit; req->data = scsi_cmnd; @@ -2419,11 +2417,11 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32); - real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype, + real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype, scsi_sglist(scsi_cmnd), FSF_MAX_SBALS_PER_REQ); if (unlikely(real_bytes < 0)) { - if (req->sbal_number >= FSF_MAX_SBALS_PER_REQ) { + if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) { dev_err(&adapter->ccw_device->dev, "Oversize data package, unit 0x%016Lx " "on port 0x%016Lx closed\n", @@ -2448,7 +2446,7 @@ failed_scsi_cmnd: zfcp_fsf_req_free(req); scsi_cmnd->host_scribble = NULL; out: - spin_unlock(&adapter->req_q_lock); + spin_unlock(&qdio->req_q_lock); return retval; } @@ -2463,17 +2461,19 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; struct fcp_cmnd_iu *fcp_cmnd_iu; - struct zfcp_adapter *adapter = unit->port->adapter; + struct zfcp_qdio *qdio = unit->port->adapter->qdio; if (unlikely(!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_UNBLOCKED))) return NULL; - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0, - adapter->pool.fsf_req_scsi); + + req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, + qdio->adapter->pool.scsi_req); + if (IS_ERR(req)) { req = NULL; goto out; @@ -2489,7 +2489,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + sizeof(u32); - sbale = zfcp_qdio_sbale_req(req); + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; @@ -2504,7 +2504,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) zfcp_fsf_req_free(req); req = NULL; out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); return req; } @@ -2522,6 +2522,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, struct zfcp_fsf_cfdc *fsf_cfdc) { struct qdio_buffer_element *sbale; + struct zfcp_qdio *qdio = adapter->qdio; struct zfcp_fsf_req *req = NULL; struct fsf_qtcb_bottom_support *bottom; int direction, retval = -EIO, bytes; @@ -2540,11 +2541,11 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, return ERR_PTR(-EINVAL); } - spin_lock_bh(&adapter->req_q_lock); - if (zfcp_fsf_req_sbal_get(adapter)) + spin_lock_bh(&qdio->req_q_lock); + if (zfcp_fsf_req_sbal_get(qdio)) goto out; - req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL); + req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL); if (IS_ERR(req)) { retval = -EPERM; goto out; @@ -2552,14 +2553,15 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, req->handler = zfcp_fsf_control_file_handler; - sbale = zfcp_qdio_sbale_req(req); + sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); sbale[0].flags |= direction; bottom = &req->qtcb->bottom.support; bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; bottom->option = fsf_cfdc->option; - bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg, + bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, + direction, fsf_cfdc->sg, FSF_MAX_SBALS_PER_REQ); if (bytes != ZFCP_CFDC_MAX_SIZE) { zfcp_fsf_req_free(req); @@ -2569,12 +2571,53 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock_bh(&adapter->req_q_lock); + spin_unlock_bh(&qdio->req_q_lock); if (!retval) { - wait_event(req->completion_wq, - req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + wait_for_completion(&req->completion); return req; } return ERR_PTR(retval); } + +/** + * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO + * @adapter: pointer to struct zfcp_adapter + * @sbal_idx: response queue index of SBAL to be processed + */ +void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) +{ + struct zfcp_adapter *adapter = qdio->adapter; + struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx]; + struct qdio_buffer_element *sbale; + struct zfcp_fsf_req *fsf_req; + unsigned long flags, req_id; + int idx; + + for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { + + sbale = &sbal->element[idx]; + req_id = (unsigned long) sbale->addr; + spin_lock_irqsave(&adapter->req_list_lock, flags); + fsf_req = zfcp_reqlist_find(adapter, req_id); + + if (!fsf_req) + /* + * Unknown request means that we have potentially memory + * corruption and must stop the machine immediately. + */ + panic("error: unknown req_id (%lx) on adapter %s.\n", + req_id, dev_name(&adapter->ccw_device->dev)); + + list_del(&fsf_req->list); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); + + fsf_req->queue_req.sbal_response = sbal_idx; + fsf_req->queue_req.qdio_inb_usage = + atomic_read(&qdio->resp_q.count); + zfcp_fsf_req_complete(fsf_req); + + if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY)) + break; + } +} |