cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zfcp_reqlist.h (5552B)


      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 */