Linux 4.1.16
[linux/fpc-iii.git] / drivers / s390 / scsi / zfcp_reqlist.h
blob7c2c6194dfca58e1eb2fe6466abf64fd928deb96
1 /*
2 * zfcp device driver
4 * Data structure and helper functions for tracking pending FSF
5 * requests.
7 * Copyright IBM Corp. 2009
8 */
10 #ifndef ZFCP_REQLIST_H
11 #define ZFCP_REQLIST_H
13 /* number of hash buckets */
14 #define ZFCP_REQ_LIST_BUCKETS 128
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
21 struct zfcp_reqlist {
22 spinlock_t lock;
23 struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
26 static inline int zfcp_reqlist_hash(unsigned long req_id)
28 return req_id % ZFCP_REQ_LIST_BUCKETS;
31 /**
32 * zfcp_reqlist_alloc - Allocate and initialize reqlist
34 * Returns pointer to allocated reqlist on success, or NULL on
35 * allocation failure.
37 static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void)
39 unsigned int i;
40 struct zfcp_reqlist *rl;
42 rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL);
43 if (!rl)
44 return NULL;
46 spin_lock_init(&rl->lock);
48 for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
49 INIT_LIST_HEAD(&rl->buckets[i]);
51 return rl;
54 /**
55 * zfcp_reqlist_isempty - Check whether the request list empty
56 * @rl: pointer to reqlist
58 * Returns: 1 if list is empty, 0 if not
60 static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl)
62 unsigned int i;
64 for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
65 if (!list_empty(&rl->buckets[i]))
66 return 0;
67 return 1;
70 /**
71 * zfcp_reqlist_free - Free allocated memory for reqlist
72 * @rl: The reqlist where to free memory
74 static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl)
76 /* sanity check */
77 BUG_ON(!zfcp_reqlist_isempty(rl));
79 kfree(rl);
82 static inline struct zfcp_fsf_req *
83 _zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
85 struct zfcp_fsf_req *req;
86 unsigned int i;
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;
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
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.
103 static inline struct zfcp_fsf_req *
104 zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
106 unsigned long flags;
107 struct zfcp_fsf_req *req;
109 spin_lock_irqsave(&rl->lock, flags);
110 req = _zfcp_reqlist_find(rl, req_id);
111 spin_unlock_irqrestore(&rl->lock, flags);
113 return req;
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
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.
125 * Returns: Pointer to the FSF request if the request has been found,
126 * NULL if it has not been found.
128 static inline struct zfcp_fsf_req *
129 zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id)
131 unsigned long flags;
132 struct zfcp_fsf_req *req;
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);
140 return req;
144 * zfcp_reqlist_add - Add entry to reqlist
145 * @rl: reqlist where to add the entry
146 * @req: The entry to add
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.
153 static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl,
154 struct zfcp_fsf_req *req)
156 unsigned int i;
157 unsigned long flags;
159 i = zfcp_reqlist_hash(req->req_id);
161 spin_lock_irqsave(&rl->lock, flags);
162 list_add_tail(&req->list, &rl->buckets[i]);
163 spin_unlock_irqrestore(&rl->lock, flags);
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
171 static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
172 struct list_head *list)
174 unsigned int i;
175 unsigned long flags;
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);
183 #endif /* ZFCP_REQLIST_H */