diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 36 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 34 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 7 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 1 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 32 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_reqlist.h | 183 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 5 |
8 files changed, 203 insertions, 98 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 9d0c941b7d33..f42da9d57093 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include "zfcp_ext.h" | 33 | #include "zfcp_ext.h" |
34 | #include "zfcp_fc.h" | 34 | #include "zfcp_fc.h" |
35 | #include "zfcp_reqlist.h" | ||
35 | 36 | ||
36 | #define ZFCP_BUS_ID_SIZE 20 | 37 | #define ZFCP_BUS_ID_SIZE 20 |
37 | 38 | ||
@@ -49,36 +50,6 @@ static struct kmem_cache *zfcp_cache_hw_align(const char *name, | |||
49 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); | 50 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); |
50 | } | 51 | } |
51 | 52 | ||
52 | static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter) | ||
53 | { | ||
54 | int idx; | ||
55 | |||
56 | adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), | ||
57 | GFP_KERNEL); | ||
58 | if (!adapter->req_list) | ||
59 | return -ENOMEM; | ||
60 | |||
61 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) | ||
62 | INIT_LIST_HEAD(&adapter->req_list[idx]); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * zfcp_reqlist_isempty - is the request list empty | ||
68 | * @adapter: pointer to struct zfcp_adapter | ||
69 | * | ||
70 | * Returns: true if list is empty, false otherwise | ||
71 | */ | ||
72 | int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) | ||
73 | { | ||
74 | unsigned int idx; | ||
75 | |||
76 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) | ||
77 | if (!list_empty(&adapter->req_list[idx])) | ||
78 | return 0; | ||
79 | return 1; | ||
80 | } | ||
81 | |||
82 | static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | 53 | static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) |
83 | { | 54 | { |
84 | struct ccw_device *cdev; | 55 | struct ccw_device *cdev; |
@@ -539,7 +510,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
539 | if (zfcp_allocate_low_mem_buffers(adapter)) | 510 | if (zfcp_allocate_low_mem_buffers(adapter)) |
540 | goto failed; | 511 | goto failed; |
541 | 512 | ||
542 | if (zfcp_reqlist_alloc(adapter)) | 513 | adapter->req_list = zfcp_reqlist_alloc(); |
514 | if (!adapter->req_list) | ||
543 | goto failed; | 515 | goto failed; |
544 | 516 | ||
545 | if (zfcp_dbf_adapter_register(adapter)) | 517 | if (zfcp_dbf_adapter_register(adapter)) |
@@ -560,8 +532,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
560 | INIT_LIST_HEAD(&adapter->erp_ready_head); | 532 | INIT_LIST_HEAD(&adapter->erp_ready_head); |
561 | INIT_LIST_HEAD(&adapter->erp_running_head); | 533 | INIT_LIST_HEAD(&adapter->erp_running_head); |
562 | 534 | ||
563 | spin_lock_init(&adapter->req_list_lock); | ||
564 | |||
565 | rwlock_init(&adapter->erp_lock); | 535 | rwlock_init(&adapter->erp_lock); |
566 | rwlock_init(&adapter->abort_lock); | 536 | rwlock_init(&adapter->abort_lock); |
567 | 537 | ||
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index c22cb72a5ae8..6f65a2179537 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include "zfcp_ext.h" | 12 | #include "zfcp_ext.h" |
13 | #include "zfcp_reqlist.h" | ||
13 | 14 | ||
14 | #define ZFCP_MODEL_PRIV 0x4 | 15 | #define ZFCP_MODEL_PRIV 0x4 |
15 | 16 | ||
@@ -162,7 +163,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) | |||
162 | } | 163 | } |
163 | 164 | ||
164 | /* initialize request counter */ | 165 | /* initialize request counter */ |
165 | BUG_ON(!zfcp_reqlist_isempty(adapter)); | 166 | BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); |
166 | adapter->req_no = 0; | 167 | adapter->req_no = 0; |
167 | 168 | ||
168 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, | 169 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 6ed48654c299..ff4e2ca19beb 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -39,9 +39,7 @@ | |||
39 | #include <asm/sysinfo.h> | 39 | #include <asm/sysinfo.h> |
40 | #include "zfcp_fsf.h" | 40 | #include "zfcp_fsf.h" |
41 | 41 | ||
42 | /********************* GENERAL DEFINES *********************************/ | 42 | struct zfcp_reqlist; |
43 | |||
44 | #define REQUEST_LIST_SIZE 128 | ||
45 | 43 | ||
46 | /********************* SCSI SPECIFIC DEFINES *********************************/ | 44 | /********************* SCSI SPECIFIC DEFINES *********************************/ |
47 | #define ZFCP_SCSI_ER_TIMEOUT (10*HZ) | 45 | #define ZFCP_SCSI_ER_TIMEOUT (10*HZ) |
@@ -206,8 +204,7 @@ struct zfcp_adapter { | |||
206 | struct list_head port_list; /* remote port list */ | 204 | struct list_head port_list; /* remote port list */ |
207 | rwlock_t port_list_lock; /* port list lock */ | 205 | rwlock_t port_list_lock; /* port list lock */ |
208 | unsigned long req_no; /* unique FSF req number */ | 206 | unsigned long req_no; /* unique FSF req number */ |
209 | struct list_head *req_list; /* list of pending reqs */ | 207 | struct zfcp_reqlist *req_list; |
210 | spinlock_t req_list_lock; /* request list lock */ | ||
211 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ | 208 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ |
212 | rwlock_t abort_lock; /* Protects against SCSI | 209 | rwlock_t abort_lock; /* Protects against SCSI |
213 | stack abort/command | 210 | stack abort/command |
@@ -351,31 +348,4 @@ struct zfcp_data { | |||
351 | #define ZFCP_SET 0x00000100 | 348 | #define ZFCP_SET 0x00000100 |
352 | #define ZFCP_CLEAR 0x00000200 | 349 | #define ZFCP_CLEAR 0x00000200 |
353 | 350 | ||
354 | /* | ||
355 | * Helper functions for request ID management. | ||
356 | */ | ||
357 | static inline int zfcp_reqlist_hash(unsigned long req_id) | ||
358 | { | ||
359 | return req_id % REQUEST_LIST_SIZE; | ||
360 | } | ||
361 | |||
362 | static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter, | ||
363 | struct zfcp_fsf_req *fsf_req) | ||
364 | { | ||
365 | list_del(&fsf_req->list); | ||
366 | } | ||
367 | |||
368 | static inline struct zfcp_fsf_req * | ||
369 | zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id) | ||
370 | { | ||
371 | struct zfcp_fsf_req *request; | ||
372 | unsigned int idx; | ||
373 | |||
374 | idx = zfcp_reqlist_hash(req_id); | ||
375 | list_for_each_entry(request, &adapter->req_list[idx], list) | ||
376 | if (request->req_id == req_id) | ||
377 | return request; | ||
378 | return NULL; | ||
379 | } | ||
380 | |||
381 | #endif /* ZFCP_DEF_H */ | 351 | #endif /* ZFCP_DEF_H */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index d40d5b0f263f..fe8e4c2b9563 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include "zfcp_ext.h" | 13 | #include "zfcp_ext.h" |
14 | #include "zfcp_reqlist.h" | ||
14 | 15 | ||
15 | #define ZFCP_MAX_ERPS 3 | 16 | #define ZFCP_MAX_ERPS 3 |
16 | 17 | ||
@@ -483,8 +484,8 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | |||
483 | if (!act->fsf_req_id) | 484 | if (!act->fsf_req_id) |
484 | return; | 485 | return; |
485 | 486 | ||
486 | spin_lock(&adapter->req_list_lock); | 487 | spin_lock(&adapter->req_list->lock); |
487 | req = zfcp_reqlist_find(adapter, act->fsf_req_id); | 488 | req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id); |
488 | if (req && req->erp_action == act) { | 489 | if (req && req->erp_action == act) { |
489 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | | 490 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | |
490 | ZFCP_STATUS_ERP_TIMEDOUT)) { | 491 | ZFCP_STATUS_ERP_TIMEDOUT)) { |
@@ -498,7 +499,7 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | |||
498 | act->fsf_req_id = 0; | 499 | act->fsf_req_id = 0; |
499 | } else | 500 | } else |
500 | act->fsf_req_id = 0; | 501 | act->fsf_req_id = 0; |
501 | spin_unlock(&adapter->req_list_lock); | 502 | spin_unlock(&adapter->req_list->lock); |
502 | } | 503 | } |
503 | 504 | ||
504 | /** | 505 | /** |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 66bdb34143cb..85cb135d5e7f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -21,7 +21,6 @@ extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); | |||
21 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, | 21 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, |
22 | u32); | 22 | u32); |
23 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); | 23 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); |
24 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); | ||
25 | extern void zfcp_sg_free_table(struct scatterlist *, int); | 24 | extern void zfcp_sg_free_table(struct scatterlist *, int); |
26 | extern int zfcp_sg_setup_table(struct scatterlist *, int); | 25 | extern int zfcp_sg_setup_table(struct scatterlist *, int); |
27 | extern void zfcp_device_unregister(struct device *, | 26 | extern void zfcp_device_unregister(struct device *, |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index fd2371b69489..36a6f4a7b8d7 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "zfcp_ext.h" | 14 | #include "zfcp_ext.h" |
15 | #include "zfcp_fc.h" | 15 | #include "zfcp_fc.h" |
16 | #include "zfcp_dbf.h" | 16 | #include "zfcp_dbf.h" |
17 | #include "zfcp_reqlist.h" | ||
17 | 18 | ||
18 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | 19 | static void zfcp_fsf_request_timeout_handler(unsigned long data) |
19 | { | 20 | { |
@@ -457,15 +458,10 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) | |||
457 | void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) | 458 | void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) |
458 | { | 459 | { |
459 | struct zfcp_fsf_req *req, *tmp; | 460 | struct zfcp_fsf_req *req, *tmp; |
460 | unsigned long flags; | ||
461 | LIST_HEAD(remove_queue); | 461 | LIST_HEAD(remove_queue); |
462 | unsigned int i; | ||
463 | 462 | ||
464 | BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); | 463 | BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); |
465 | spin_lock_irqsave(&adapter->req_list_lock, flags); | 464 | zfcp_reqlist_move(adapter->req_list, &remove_queue); |
466 | for (i = 0; i < REQUEST_LIST_SIZE; i++) | ||
467 | list_splice_init(&adapter->req_list[i], &remove_queue); | ||
468 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
469 | 465 | ||
470 | list_for_each_entry_safe(req, tmp, &remove_queue, list) { | 466 | list_for_each_entry_safe(req, tmp, &remove_queue, list) { |
471 | list_del(&req->list); | 467 | list_del(&req->list); |
@@ -770,27 +766,17 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | |||
770 | { | 766 | { |
771 | struct zfcp_adapter *adapter = req->adapter; | 767 | struct zfcp_adapter *adapter = req->adapter; |
772 | struct zfcp_qdio *qdio = adapter->qdio; | 768 | struct zfcp_qdio *qdio = adapter->qdio; |
773 | unsigned long flags; | 769 | int with_qtcb = (req->qtcb != NULL); |
774 | int idx; | ||
775 | int with_qtcb = (req->qtcb != NULL); | ||
776 | int req_id = req->req_id; | 770 | int req_id = req->req_id; |
777 | 771 | ||
778 | /* put allocated FSF request into hash table */ | 772 | zfcp_reqlist_add(adapter->req_list, req); |
779 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
780 | idx = zfcp_reqlist_hash(req_id); | ||
781 | list_add_tail(&req->list, &adapter->req_list[idx]); | ||
782 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
783 | 773 | ||
784 | req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count); | 774 | req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count); |
785 | req->issued = get_clock(); | 775 | req->issued = get_clock(); |
786 | if (zfcp_qdio_send(qdio, &req->queue_req)) { | 776 | if (zfcp_qdio_send(qdio, &req->queue_req)) { |
787 | del_timer(&req->timer); | 777 | del_timer(&req->timer); |
788 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
789 | /* lookup request again, list might have changed */ | 778 | /* lookup request again, list might have changed */ |
790 | req = zfcp_reqlist_find(adapter, req_id); | 779 | zfcp_reqlist_find_rm(adapter->req_list, req_id); |
791 | if (req) | ||
792 | zfcp_reqlist_remove(adapter, req); | ||
793 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
794 | zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); | 780 | zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); |
795 | return -EIO; | 781 | return -EIO; |
796 | } | 782 | } |
@@ -2518,15 +2504,14 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) | |||
2518 | struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx]; | 2504 | struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx]; |
2519 | struct qdio_buffer_element *sbale; | 2505 | struct qdio_buffer_element *sbale; |
2520 | struct zfcp_fsf_req *fsf_req; | 2506 | struct zfcp_fsf_req *fsf_req; |
2521 | unsigned long flags, req_id; | 2507 | unsigned long req_id; |
2522 | int idx; | 2508 | int idx; |
2523 | 2509 | ||
2524 | for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { | 2510 | for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { |
2525 | 2511 | ||
2526 | sbale = &sbal->element[idx]; | 2512 | sbale = &sbal->element[idx]; |
2527 | req_id = (unsigned long) sbale->addr; | 2513 | req_id = (unsigned long) sbale->addr; |
2528 | spin_lock_irqsave(&adapter->req_list_lock, flags); | 2514 | fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id); |
2529 | fsf_req = zfcp_reqlist_find(adapter, req_id); | ||
2530 | 2515 | ||
2531 | if (!fsf_req) | 2516 | if (!fsf_req) |
2532 | /* | 2517 | /* |
@@ -2536,9 +2521,6 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) | |||
2536 | panic("error: unknown req_id (%lx) on adapter %s.\n", | 2521 | panic("error: unknown req_id (%lx) on adapter %s.\n", |
2537 | req_id, dev_name(&adapter->ccw_device->dev)); | 2522 | req_id, dev_name(&adapter->ccw_device->dev)); |
2538 | 2523 | ||
2539 | list_del(&fsf_req->list); | ||
2540 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
2541 | |||
2542 | fsf_req->queue_req.sbal_response = sbal_idx; | 2524 | fsf_req->queue_req.sbal_response = sbal_idx; |
2543 | fsf_req->queue_req.qdio_inb_usage = | 2525 | fsf_req->queue_req.qdio_inb_usage = |
2544 | atomic_read(&qdio->resp_q.count); | 2526 | atomic_read(&qdio->resp_q.count); |
diff --git a/drivers/s390/scsi/zfcp_reqlist.h b/drivers/s390/scsi/zfcp_reqlist.h new file mode 100644 index 000000000000..a72d1b730aba --- /dev/null +++ b/drivers/s390/scsi/zfcp_reqlist.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * zfcp device driver | ||
3 | * | ||
4 | * Data structure and helper functions for tracking pending FSF | ||
5 | * requests. | ||
6 | * | ||
7 | * Copyright IBM Corporation 2009 | ||
8 | */ | ||
9 | |||
10 | #ifndef ZFCP_REQLIST_H | ||
11 | #define ZFCP_REQLIST_H | ||
12 | |||
13 | /* number of hash buckets */ | ||
14 | #define ZFCP_REQ_LIST_BUCKETS 128 | ||
15 | |||
16 | /** | ||
17 | * struct zfcp_reqlist - Container for request list (reqlist) | ||
18 | * @lock: Spinlock for protecting the hash list | ||
19 | * @list: Array of hashbuckets, each is a list of requests in this bucket | ||
20 | */ | ||
21 | struct zfcp_reqlist { | ||
22 | spinlock_t lock; | ||
23 | struct list_head buckets[ZFCP_REQ_LIST_BUCKETS]; | ||
24 | }; | ||
25 | |||
26 | static inline int zfcp_reqlist_hash(unsigned long req_id) | ||
27 | { | ||
28 | return req_id % ZFCP_REQ_LIST_BUCKETS; | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * zfcp_reqlist_alloc - Allocate and initialize reqlist | ||
33 | * | ||
34 | * Returns pointer to allocated reqlist on success, or NULL on | ||
35 | * allocation failure. | ||
36 | */ | ||
37 | static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void) | ||
38 | { | ||
39 | unsigned int i; | ||
40 | struct zfcp_reqlist *rl; | ||
41 | |||
42 | rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL); | ||
43 | if (!rl) | ||
44 | return NULL; | ||
45 | |||
46 | spin_lock_init(&rl->lock); | ||
47 | |||
48 | for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) | ||
49 | INIT_LIST_HEAD(&rl->buckets[i]); | ||
50 | |||
51 | return rl; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * zfcp_reqlist_isempty - Check whether the request list empty | ||
56 | * @rl: pointer to reqlist | ||
57 | * | ||
58 | * Returns: 1 if list is empty, 0 if not | ||
59 | */ | ||
60 | static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl) | ||
61 | { | ||
62 | unsigned int i; | ||
63 | |||
64 | for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) | ||
65 | if (!list_empty(&rl->buckets[i])) | ||
66 | return 0; | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * zfcp_reqlist_free - Free allocated memory for reqlist | ||
72 | * @rl: The reqlist where to free memory | ||
73 | */ | ||
74 | static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl) | ||
75 | { | ||
76 | /* sanity check */ | ||
77 | BUG_ON(!zfcp_reqlist_isempty(rl)); | ||
78 | |||
79 | kfree(rl); | ||
80 | } | ||
81 | |||
82 | static inline struct zfcp_fsf_req * | ||
83 | _zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) | ||
84 | { | ||
85 | struct zfcp_fsf_req *req; | ||
86 | unsigned int i; | ||
87 | |||
88 | i = zfcp_reqlist_hash(req_id); | ||
89 | list_for_each_entry(req, &rl->buckets[i], list) | ||
90 | if (req->req_id == req_id) | ||
91 | return req; | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * zfcp_reqlist_find - Lookup FSF request by its request id | ||
97 | * @rl: The reqlist where to lookup the FSF request | ||
98 | * @req_id: The request id to look for | ||
99 | * | ||
100 | * Returns a pointer to the FSF request with the specified request id | ||
101 | * or NULL if there is no known FSF request with this id. | ||
102 | */ | ||
103 | static inline struct zfcp_fsf_req * | ||
104 | zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) | ||
105 | { | ||
106 | unsigned long flags; | ||
107 | struct zfcp_fsf_req *req; | ||
108 | |||
109 | spin_lock_irqsave(&rl->lock, flags); | ||
110 | req = _zfcp_reqlist_find(rl, req_id); | ||
111 | spin_unlock_irqrestore(&rl->lock, flags); | ||
112 | |||
113 | return req; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist | ||
118 | * @rl: reqlist where to search and remove entry | ||
119 | * @req_id: The request id of the request to look for | ||
120 | * | ||
121 | * This functions tries to find the FSF request with the specified | ||
122 | * id and then removes it from the reqlist. The reqlist lock is held | ||
123 | * during both steps of the operation. | ||
124 | * | ||
125 | * Returns: Pointer to the FSF request if the request has been found, | ||
126 | * NULL if it has not been found. | ||
127 | */ | ||
128 | static inline struct zfcp_fsf_req * | ||
129 | zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id) | ||
130 | { | ||
131 | unsigned long flags; | ||
132 | struct zfcp_fsf_req *req; | ||
133 | |||
134 | spin_lock_irqsave(&rl->lock, flags); | ||
135 | req = _zfcp_reqlist_find(rl, req_id); | ||
136 | if (req) | ||
137 | list_del(&req->list); | ||
138 | spin_unlock_irqrestore(&rl->lock, flags); | ||
139 | |||
140 | return req; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * zfcp_reqlist_add - Add entry to reqlist | ||
145 | * @rl: reqlist where to add the entry | ||
146 | * @req: The entry to add | ||
147 | * | ||
148 | * The request id always increases. As an optimization new requests | ||
149 | * are added here with list_add_tail at the end of the bucket lists | ||
150 | * while old requests are looked up starting at the beginning of the | ||
151 | * lists. | ||
152 | */ | ||
153 | static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl, | ||
154 | struct zfcp_fsf_req *req) | ||
155 | { | ||
156 | unsigned int i; | ||
157 | unsigned long flags; | ||
158 | |||
159 | i = zfcp_reqlist_hash(req->req_id); | ||
160 | |||
161 | spin_lock_irqsave(&rl->lock, flags); | ||
162 | list_add_tail(&req->list, &rl->buckets[i]); | ||
163 | spin_unlock_irqrestore(&rl->lock, flags); | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * zfcp_reqlist_move - Move all entries from reqlist to simple list | ||
168 | * @rl: The zfcp_reqlist where to remove all entries | ||
169 | * @list: The list where to move all entries | ||
170 | */ | ||
171 | static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl, | ||
172 | struct list_head *list) | ||
173 | { | ||
174 | unsigned int i; | ||
175 | unsigned long flags; | ||
176 | |||
177 | spin_lock_irqsave(&rl->lock, flags); | ||
178 | for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) | ||
179 | list_splice_init(&rl->buckets[i], list); | ||
180 | spin_unlock_irqrestore(&rl->lock, flags); | ||
181 | } | ||
182 | |||
183 | #endif /* ZFCP_REQLIST_H */ | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 8e6fc68d6bd4..e1e56f523116 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "zfcp_ext.h" | 15 | #include "zfcp_ext.h" |
16 | #include "zfcp_dbf.h" | 16 | #include "zfcp_dbf.h" |
17 | #include "zfcp_fc.h" | 17 | #include "zfcp_fc.h" |
18 | #include "zfcp_reqlist.h" | ||
18 | 19 | ||
19 | static unsigned int default_depth = 32; | 20 | static unsigned int default_depth = 32; |
20 | module_param_named(queue_depth, default_depth, uint, 0600); | 21 | module_param_named(queue_depth, default_depth, uint, 0600); |
@@ -189,9 +190,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
189 | /* avoid race condition between late normal completion and abort */ | 190 | /* avoid race condition between late normal completion and abort */ |
190 | write_lock_irqsave(&adapter->abort_lock, flags); | 191 | write_lock_irqsave(&adapter->abort_lock, flags); |
191 | 192 | ||
192 | spin_lock(&adapter->req_list_lock); | 193 | old_req = zfcp_reqlist_find(adapter->req_list, old_reqid); |
193 | old_req = zfcp_reqlist_find(adapter, old_reqid); | ||
194 | spin_unlock(&adapter->req_list_lock); | ||
195 | if (!old_req) { | 194 | if (!old_req) { |
196 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 195 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
197 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, | 196 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, |