root/drivers/s390/scsi/zfcp_reqlist.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. zfcp_reqlist_hash
  2. zfcp_reqlist_alloc
  3. zfcp_reqlist_isempty
  4. zfcp_reqlist_free
  5. _zfcp_reqlist_find
  6. zfcp_reqlist_find
  7. zfcp_reqlist_find_rm
  8. zfcp_reqlist_add
  9. zfcp_reqlist_move
  10. zfcp_reqlist_apply_for_all

   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  */
  22 struct zfcp_reqlist {
  23         spinlock_t lock;
  24         struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
  25 };
  26 
  27 static 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  */
  38 static 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  */
  61 static 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  */
  75 static 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 
  83 static 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  */
 104 static inline struct zfcp_fsf_req *
 105 zfcp_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  */
 129 static inline struct zfcp_fsf_req *
 130 zfcp_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  */
 154 static 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  */
 172 static 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  */
 197 static inline void
 198 zfcp_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 */

/* [<][>][^][v][top][bottom][index][help] */