• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/s390/scsi/
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 */
21struct zfcp_reqlist {
22	spinlock_t lock;
23	struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
24};
25
26static 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 */
37static 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 */
60static 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 */
74static 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
82static 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 */
103static inline struct zfcp_fsf_req *
104zfcp_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 */
128static inline struct zfcp_fsf_req *
129zfcp_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 */
153static 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 */
171static 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 */
184