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