diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2008-11-04 10:35:08 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-11-05 12:46:39 -0500 |
commit | 3765138ae946e6e29b22bf15a9647c600c232639 (patch) | |
tree | 5704fb770db648506bba7ca8e7fa2c887b4998d0 | |
parent | 88f2a977870af655296a682fe2a58c822cd25bb2 (diff) |
[SCSI] zfcp: Fix request list handling in error path
Fix the handling of the request list in the error path:
- Use irqsave for the lock as in the good path.
- Before removing the request, check if it is still in the list, a
call to dismiss_all might have changed the list in between.
- zfcp_qdio_send does not change the queue counters on failure,
trying revert something is wrong, so remove this.
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 17 |
1 files changed, 6 insertions, 11 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5e8517fc8b62..d024442ee128 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -770,7 +770,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, | |||
770 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | 770 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) |
771 | { | 771 | { |
772 | struct zfcp_adapter *adapter = req->adapter; | 772 | struct zfcp_adapter *adapter = req->adapter; |
773 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | ||
774 | unsigned long flags; | 773 | unsigned long flags; |
775 | int idx; | 774 | int idx; |
776 | 775 | ||
@@ -780,19 +779,15 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | |||
780 | list_add_tail(&req->list, &adapter->req_list[idx]); | 779 | list_add_tail(&req->list, &adapter->req_list[idx]); |
781 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | 780 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); |
782 | 781 | ||
783 | req->qdio_outb_usage = atomic_read(&req_q->count); | 782 | req->qdio_outb_usage = atomic_read(&adapter->req_q.count); |
784 | req->issued = get_clock(); | 783 | req->issued = get_clock(); |
785 | if (zfcp_qdio_send(req)) { | 784 | if (zfcp_qdio_send(req)) { |
786 | /* Queues are down..... */ | ||
787 | del_timer(&req->timer); | 785 | del_timer(&req->timer); |
788 | spin_lock(&adapter->req_list_lock); | 786 | spin_lock_irqsave(&adapter->req_list_lock, flags); |
789 | zfcp_reqlist_remove(adapter, req); | 787 | /* lookup request again, list might have changed */ |
790 | spin_unlock(&adapter->req_list_lock); | 788 | if (zfcp_reqlist_find_safe(adapter, req)) |
791 | /* undo changes in request queue made for this request */ | 789 | zfcp_reqlist_remove(adapter, req); |
792 | atomic_add(req->sbal_number, &req_q->count); | 790 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); |
793 | req_q->first -= req->sbal_number; | ||
794 | req_q->first += QDIO_MAX_BUFFERS_PER_Q; | ||
795 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ | ||
796 | zfcp_erp_adapter_reopen(adapter, 0, 116, req); | 791 | zfcp_erp_adapter_reopen(adapter, 0, 116, req); |
797 | return -EIO; | 792 | return -EIO; |
798 | } | 793 | } |