linux/drivers/s390/scsi/zfcp_reqlist.h
<<
>>
Prefs
   1/*
   2 * zfcp device driver
   3 *
   4 * Data structure and helper functions for tracking pending FSF
   5 * requests.
   6 *
   7 * Copyright IBM Corp. 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