Linux Audio

Check our new training course

Loading...
v5.9
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 * zfcp device driver
  4 *
  5 * Data structure and helper functions for tracking pending FSF
  6 * requests.
  7 *
  8 * Copyright IBM Corp. 2009, 2016
  9 */
 10
 11#ifndef ZFCP_REQLIST_H
 12#define ZFCP_REQLIST_H
 13
 
 
 14/* number of hash buckets */
 15#define ZFCP_REQ_LIST_BUCKETS 128
 16
 17/**
 18 * struct zfcp_reqlist - Container for request list (reqlist)
 19 * @lock: Spinlock for protecting the hash list
 20 * @buckets: Array of hashbuckets, each is a list of requests in this bucket
 21 */
 22struct zfcp_reqlist {
 23	spinlock_t lock;
 24	struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
 25};
 26
 27static inline int zfcp_reqlist_hash(unsigned long req_id)
 28{
 29	return req_id % ZFCP_REQ_LIST_BUCKETS;
 30}
 31
 32/**
 33 * zfcp_reqlist_alloc - Allocate and initialize reqlist
 34 *
 35 * Returns pointer to allocated reqlist on success, or NULL on
 36 * allocation failure.
 37 */
 38static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void)
 39{
 40	unsigned int i;
 41	struct zfcp_reqlist *rl;
 42
 43	rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL);
 44	if (!rl)
 45		return NULL;
 46
 47	spin_lock_init(&rl->lock);
 48
 49	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
 50		INIT_LIST_HEAD(&rl->buckets[i]);
 51
 52	return rl;
 53}
 54
 55/**
 56 * zfcp_reqlist_isempty - Check whether the request list empty
 57 * @rl: pointer to reqlist
 58 *
 59 * Returns: 1 if list is empty, 0 if not
 60 */
 61static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl)
 62{
 63	unsigned int i;
 64
 65	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
 66		if (!list_empty(&rl->buckets[i]))
 67			return 0;
 68	return 1;
 69}
 70
 71/**
 72 * zfcp_reqlist_free - Free allocated memory for reqlist
 73 * @rl: The reqlist where to free memory
 74 */
 75static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl)
 76{
 77	/* sanity check */
 78	BUG_ON(!zfcp_reqlist_isempty(rl));
 79
 80	kfree(rl);
 81}
 82
 83static inline struct zfcp_fsf_req *
 84_zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
 85{
 86	struct zfcp_fsf_req *req;
 87	unsigned int i;
 88
 89	i = zfcp_reqlist_hash(req_id);
 90	list_for_each_entry(req, &rl->buckets[i], list)
 91		if (req->req_id == req_id)
 92			return req;
 93	return NULL;
 94}
 95
 96/**
 97 * zfcp_reqlist_find - Lookup FSF request by its request id
 98 * @rl: The reqlist where to lookup the FSF request
 99 * @req_id: The request id to look for
100 *
101 * Returns a pointer to the FSF request with the specified request id
102 * or NULL if there is no known FSF request with this id.
103 */
104static inline struct zfcp_fsf_req *
105zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
106{
107	unsigned long flags;
108	struct zfcp_fsf_req *req;
109
110	spin_lock_irqsave(&rl->lock, flags);
111	req = _zfcp_reqlist_find(rl, req_id);
112	spin_unlock_irqrestore(&rl->lock, flags);
113
114	return req;
115}
116
117/**
118 * zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist
119 * @rl: reqlist where to search and remove entry
120 * @req_id: The request id of the request to look for
121 *
122 * This functions tries to find the FSF request with the specified
123 * id and then removes it from the reqlist. The reqlist lock is held
124 * during both steps of the operation.
125 *
126 * Returns: Pointer to the FSF request if the request has been found,
127 * NULL if it has not been found.
128 */
129static inline struct zfcp_fsf_req *
130zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id)
131{
132	unsigned long flags;
133	struct zfcp_fsf_req *req;
134
135	spin_lock_irqsave(&rl->lock, flags);
136	req = _zfcp_reqlist_find(rl, req_id);
137	if (req)
138		list_del(&req->list);
139	spin_unlock_irqrestore(&rl->lock, flags);
140
141	return req;
142}
143
144/**
145 * zfcp_reqlist_add - Add entry to reqlist
146 * @rl: reqlist where to add the entry
147 * @req: The entry to add
148 *
149 * The request id always increases. As an optimization new requests
150 * are added here with list_add_tail at the end of the bucket lists
151 * while old requests are looked up starting at the beginning of the
152 * lists.
153 */
154static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl,
155				    struct zfcp_fsf_req *req)
156{
157	unsigned int i;
158	unsigned long flags;
159
160	i = zfcp_reqlist_hash(req->req_id);
161
162	spin_lock_irqsave(&rl->lock, flags);
163	list_add_tail(&req->list, &rl->buckets[i]);
164	spin_unlock_irqrestore(&rl->lock, flags);
165}
166
167/**
168 * zfcp_reqlist_move - Move all entries from reqlist to simple list
169 * @rl: The zfcp_reqlist where to remove all entries
170 * @list: The list where to move all entries
171 */
172static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
173				     struct list_head *list)
174{
175	unsigned int i;
176	unsigned long flags;
177
178	spin_lock_irqsave(&rl->lock, flags);
179	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
180		list_splice_init(&rl->buckets[i], list);
181	spin_unlock_irqrestore(&rl->lock, flags);
182}
183
184/**
185 * zfcp_reqlist_apply_for_all() - apply a function to every request.
186 * @rl: the requestlist that contains the target requests.
187 * @f: the function to apply to each request; the first parameter of the
188 *     function will be the target-request; the second parameter is the same
189 *     pointer as given with the argument @data.
190 * @data: freely chosen argument; passed through to @f as second parameter.
191 *
192 * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
193 * table (not a 'safe' variant, so don't modify the list).
194 *
195 * Holds @rl->lock over the entire request-iteration.
196 */
197static inline void
198zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
199			   void (*f)(struct zfcp_fsf_req *, void *), void *data)
200{
201	struct zfcp_fsf_req *req;
202	unsigned long flags;
203	unsigned int i;
204
205	spin_lock_irqsave(&rl->lock, flags);
206	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
207		list_for_each_entry(req, &rl->buckets[i], list)
208			f(req, data);
209	spin_unlock_irqrestore(&rl->lock, flags);
210}
211
212#endif /* ZFCP_REQLIST_H */
v6.8
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 * zfcp device driver
  4 *
  5 * Data structure and helper functions for tracking pending FSF
  6 * requests.
  7 *
  8 * Copyright IBM Corp. 2009, 2023
  9 */
 10
 11#ifndef ZFCP_REQLIST_H
 12#define ZFCP_REQLIST_H
 13
 14#include <linux/types.h>
 15
 16/* number of hash buckets */
 17#define ZFCP_REQ_LIST_BUCKETS 128u
 18
 19/**
 20 * struct zfcp_reqlist - Container for request list (reqlist)
 21 * @lock: Spinlock for protecting the hash list
 22 * @buckets: Array of hashbuckets, each is a list of requests in this bucket
 23 */
 24struct zfcp_reqlist {
 25	spinlock_t lock;
 26	struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
 27};
 28
 29static inline size_t zfcp_reqlist_hash(u64 req_id)
 30{
 31	return req_id % ZFCP_REQ_LIST_BUCKETS;
 32}
 33
 34/**
 35 * zfcp_reqlist_alloc - Allocate and initialize reqlist
 36 *
 37 * Returns pointer to allocated reqlist on success, or NULL on
 38 * allocation failure.
 39 */
 40static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void)
 41{
 42	size_t i;
 43	struct zfcp_reqlist *rl;
 44
 45	rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL);
 46	if (!rl)
 47		return NULL;
 48
 49	spin_lock_init(&rl->lock);
 50
 51	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
 52		INIT_LIST_HEAD(&rl->buckets[i]);
 53
 54	return rl;
 55}
 56
 57/**
 58 * zfcp_reqlist_isempty - Check whether the request list empty
 59 * @rl: pointer to reqlist
 60 *
 61 * Returns: 1 if list is empty, 0 if not
 62 */
 63static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl)
 64{
 65	size_t i;
 66
 67	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
 68		if (!list_empty(&rl->buckets[i]))
 69			return 0;
 70	return 1;
 71}
 72
 73/**
 74 * zfcp_reqlist_free - Free allocated memory for reqlist
 75 * @rl: The reqlist where to free memory
 76 */
 77static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl)
 78{
 79	/* sanity check */
 80	BUG_ON(!zfcp_reqlist_isempty(rl));
 81
 82	kfree(rl);
 83}
 84
 85static inline struct zfcp_fsf_req *
 86_zfcp_reqlist_find(struct zfcp_reqlist *rl, u64 req_id)
 87{
 88	struct zfcp_fsf_req *req;
 89	size_t i;
 90
 91	i = zfcp_reqlist_hash(req_id);
 92	list_for_each_entry(req, &rl->buckets[i], list)
 93		if (req->req_id == req_id)
 94			return req;
 95	return NULL;
 96}
 97
 98/**
 99 * zfcp_reqlist_find - Lookup FSF request by its request id
100 * @rl: The reqlist where to lookup the FSF request
101 * @req_id: The request id to look for
102 *
103 * Returns a pointer to the FSF request with the specified request id
104 * or NULL if there is no known FSF request with this id.
105 */
106static inline struct zfcp_fsf_req *
107zfcp_reqlist_find(struct zfcp_reqlist *rl, u64 req_id)
108{
109	unsigned long flags;
110	struct zfcp_fsf_req *req;
111
112	spin_lock_irqsave(&rl->lock, flags);
113	req = _zfcp_reqlist_find(rl, req_id);
114	spin_unlock_irqrestore(&rl->lock, flags);
115
116	return req;
117}
118
119/**
120 * zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist
121 * @rl: reqlist where to search and remove entry
122 * @req_id: The request id of the request to look for
123 *
124 * This functions tries to find the FSF request with the specified
125 * id and then removes it from the reqlist. The reqlist lock is held
126 * during both steps of the operation.
127 *
128 * Returns: Pointer to the FSF request if the request has been found,
129 * NULL if it has not been found.
130 */
131static inline struct zfcp_fsf_req *
132zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, u64 req_id)
133{
134	unsigned long flags;
135	struct zfcp_fsf_req *req;
136
137	spin_lock_irqsave(&rl->lock, flags);
138	req = _zfcp_reqlist_find(rl, req_id);
139	if (req)
140		list_del(&req->list);
141	spin_unlock_irqrestore(&rl->lock, flags);
142
143	return req;
144}
145
146/**
147 * zfcp_reqlist_add - Add entry to reqlist
148 * @rl: reqlist where to add the entry
149 * @req: The entry to add
150 *
151 * The request id always increases. As an optimization new requests
152 * are added here with list_add_tail at the end of the bucket lists
153 * while old requests are looked up starting at the beginning of the
154 * lists.
155 */
156static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl,
157				    struct zfcp_fsf_req *req)
158{
159	size_t i;
160	unsigned long flags;
161
162	i = zfcp_reqlist_hash(req->req_id);
163
164	spin_lock_irqsave(&rl->lock, flags);
165	list_add_tail(&req->list, &rl->buckets[i]);
166	spin_unlock_irqrestore(&rl->lock, flags);
167}
168
169/**
170 * zfcp_reqlist_move - Move all entries from reqlist to simple list
171 * @rl: The zfcp_reqlist where to remove all entries
172 * @list: The list where to move all entries
173 */
174static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
175				     struct list_head *list)
176{
177	size_t i;
178	unsigned long flags;
179
180	spin_lock_irqsave(&rl->lock, flags);
181	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
182		list_splice_init(&rl->buckets[i], list);
183	spin_unlock_irqrestore(&rl->lock, flags);
184}
185
186/**
187 * zfcp_reqlist_apply_for_all() - apply a function to every request.
188 * @rl: the requestlist that contains the target requests.
189 * @f: the function to apply to each request; the first parameter of the
190 *     function will be the target-request; the second parameter is the same
191 *     pointer as given with the argument @data.
192 * @data: freely chosen argument; passed through to @f as second parameter.
193 *
194 * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
195 * table (not a 'safe' variant, so don't modify the list).
196 *
197 * Holds @rl->lock over the entire request-iteration.
198 */
199static inline void
200zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
201			   void (*f)(struct zfcp_fsf_req *, void *), void *data)
202{
203	struct zfcp_fsf_req *req;
204	unsigned long flags;
205	size_t i;
206
207	spin_lock_irqsave(&rl->lock, flags);
208	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
209		list_for_each_entry(req, &rl->buckets[i], list)
210			f(req, data);
211	spin_unlock_irqrestore(&rl->lock, flags);
212}
213
214#endif /* ZFCP_REQLIST_H */