183827f40a2d97261528087331b0bee6ce2cf27c5root/**************************************************************************
283827f40a2d97261528087331b0bee6ce2cf27c5root *
383827f40a2d97261528087331b0bee6ce2cf27c5root * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
483827f40a2d97261528087331b0bee6ce2cf27c5root * All Rights Reserved.
583827f40a2d97261528087331b0bee6ce2cf27c5root * Copyright 2009 VMware, Inc., Palo Alto, CA., USA
683827f40a2d97261528087331b0bee6ce2cf27c5root * All Rights Reserved.
783827f40a2d97261528087331b0bee6ce2cf27c5root *
883827f40a2d97261528087331b0bee6ce2cf27c5root * Permission is hereby granted, free of charge, to any person obtaining a
983827f40a2d97261528087331b0bee6ce2cf27c5root * copy of this software and associated documentation files (the
1083827f40a2d97261528087331b0bee6ce2cf27c5root * "Software"), to deal in the Software without restriction, including
1183827f40a2d97261528087331b0bee6ce2cf27c5root * without limitation the rights to use, copy, modify, merge, publish,
1283827f40a2d97261528087331b0bee6ce2cf27c5root * distribute, sub license, and/or sell copies of the Software, and to
1383827f40a2d97261528087331b0bee6ce2cf27c5root * permit persons to whom the Software is furnished to do so, subject to
1483827f40a2d97261528087331b0bee6ce2cf27c5root * the following conditions:
1583827f40a2d97261528087331b0bee6ce2cf27c5root *
1683827f40a2d97261528087331b0bee6ce2cf27c5root * The above copyright notice and this permission notice (including the
1783827f40a2d97261528087331b0bee6ce2cf27c5root * next paragraph) shall be included in all copies or substantial portions
1883827f40a2d97261528087331b0bee6ce2cf27c5root * of the Software.
1983827f40a2d97261528087331b0bee6ce2cf27c5root *
2083827f40a2d97261528087331b0bee6ce2cf27c5root * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2183827f40a2d97261528087331b0bee6ce2cf27c5root * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2283827f40a2d97261528087331b0bee6ce2cf27c5root * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
2383827f40a2d97261528087331b0bee6ce2cf27c5root * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
2483827f40a2d97261528087331b0bee6ce2cf27c5root * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2583827f40a2d97261528087331b0bee6ce2cf27c5root * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2683827f40a2d97261528087331b0bee6ce2cf27c5root * USE OR OTHER DEALINGS IN THE SOFTWARE.
2783827f40a2d97261528087331b0bee6ce2cf27c5root *
2883827f40a2d97261528087331b0bee6ce2cf27c5root **************************************************************************/
2983827f40a2d97261528087331b0bee6ce2cf27c5root/*
3083827f40a2d97261528087331b0bee6ce2cf27c5root * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
3183827f40a2d97261528087331b0bee6ce2cf27c5root */
3283827f40a2d97261528087331b0bee6ce2cf27c5root
3383827f40a2d97261528087331b0bee6ce2cf27c5root#ifdef HAVE_CONFIG_H
3483827f40a2d97261528087331b0bee6ce2cf27c5root#include "config.h"
3583827f40a2d97261528087331b0bee6ce2cf27c5root#endif
3683827f40a2d97261528087331b0bee6ce2cf27c5root
3777bfea2e6a3dc1e30a17780b48b7b231eef77255Thierry Strudel#include <drm/psb_ttm_placement_user.h>
3883827f40a2d97261528087331b0bee6ce2cf27c5root#include <stdint.h>
3983827f40a2d97261528087331b0bee6ce2cf27c5root#include <sys/time.h>
4083827f40a2d97261528087331b0bee6ce2cf27c5root#include <errno.h>
4183827f40a2d97261528087331b0bee6ce2cf27c5root#include <unistd.h>
4283827f40a2d97261528087331b0bee6ce2cf27c5root#include <assert.h>
4383827f40a2d97261528087331b0bee6ce2cf27c5root#include <string.h>
4483827f40a2d97261528087331b0bee6ce2cf27c5root#include <sys/mman.h>
4583827f40a2d97261528087331b0bee6ce2cf27c5root#include <xf86drm.h>
4683827f40a2d97261528087331b0bee6ce2cf27c5root#include "wsbm_pool.h"
4783827f40a2d97261528087331b0bee6ce2cf27c5root#include "wsbm_fencemgr.h"
4883827f40a2d97261528087331b0bee6ce2cf27c5root#include "wsbm_priv.h"
4983827f40a2d97261528087331b0bee6ce2cf27c5root#include "wsbm_manager.h"
5083827f40a2d97261528087331b0bee6ce2cf27c5root
5183827f40a2d97261528087331b0bee6ce2cf27c5root#define WSBM_SLABPOOL_ALLOC_RETRIES 100
5283827f40a2d97261528087331b0bee6ce2cf27c5root#define DRMRESTARTCOMMANDWRITE(_fd, _val, _arg, _ret)			\
5383827f40a2d97261528087331b0bee6ce2cf27c5root	do {								\
5483827f40a2d97261528087331b0bee6ce2cf27c5root		(_ret) = drmCommandWrite(_fd, _val, &(_arg), sizeof(_arg)); \
5583827f40a2d97261528087331b0bee6ce2cf27c5root	} while ((_ret) == -EAGAIN || (_ret) == -ERESTART);		\
5683827f40a2d97261528087331b0bee6ce2cf27c5root
5783827f40a2d97261528087331b0bee6ce2cf27c5root#define DRMRESTARTCOMMANDWRITEREAD(_fd, _val, _arg, _ret)		\
5883827f40a2d97261528087331b0bee6ce2cf27c5root	do {								\
5983827f40a2d97261528087331b0bee6ce2cf27c5root		(_ret) = drmCommandWriteRead(_fd, _val, &(_arg), sizeof(_arg)); \
6083827f40a2d97261528087331b0bee6ce2cf27c5root	} while ((_ret) == -EAGAIN || (_ret) == -ERESTART);		\
6183827f40a2d97261528087331b0bee6ce2cf27c5root
6283827f40a2d97261528087331b0bee6ce2cf27c5root
6383827f40a2d97261528087331b0bee6ce2cf27c5root#ifdef DEBUG_FENCESIGNALED
6483827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int createbuffer = 0;
6583827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int fencesignaled = 0;
6683827f40a2d97261528087331b0bee6ce2cf27c5root#endif
6783827f40a2d97261528087331b0bee6ce2cf27c5root
6883827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlab;
6983827f40a2d97261528087331b0bee6ce2cf27c5root
7083827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabBuffer
7183827f40a2d97261528087331b0bee6ce2cf27c5root{
7283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmKernelBuf kBuf;
7383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufStorage storage;
7483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmCond event;
7583827f40a2d97261528087331b0bee6ce2cf27c5root
7683827f40a2d97261528087331b0bee6ce2cf27c5root    /*
7783827f40a2d97261528087331b0bee6ce2cf27c5root     * Remains constant after creation.
7883827f40a2d97261528087331b0bee6ce2cf27c5root     */
7983827f40a2d97261528087331b0bee6ce2cf27c5root
8083827f40a2d97261528087331b0bee6ce2cf27c5root    int isSlabBuffer;
8183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *parent;
8283827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t start;
8383827f40a2d97261528087331b0bee6ce2cf27c5root    void *virtual;
8483827f40a2d97261528087331b0bee6ce2cf27c5root    unsigned long requestedSize;
8583827f40a2d97261528087331b0bee6ce2cf27c5root    uint64_t mapHandle;
8683827f40a2d97261528087331b0bee6ce2cf27c5root
8783827f40a2d97261528087331b0bee6ce2cf27c5root    /*
8883827f40a2d97261528087331b0bee6ce2cf27c5root     * Protected by struct _WsbmSlabSizeHeader::mutex
8983827f40a2d97261528087331b0bee6ce2cf27c5root     */
9083827f40a2d97261528087331b0bee6ce2cf27c5root
9183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead head;
9283827f40a2d97261528087331b0bee6ce2cf27c5root
9383827f40a2d97261528087331b0bee6ce2cf27c5root    /*
9483827f40a2d97261528087331b0bee6ce2cf27c5root     * Protected by this::mutex
9583827f40a2d97261528087331b0bee6ce2cf27c5root     */
9683827f40a2d97261528087331b0bee6ce2cf27c5root
9783827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmFenceObject *fence;
9883827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t fenceType;
9983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmAtomic writers;	       /* (Only upping) */
10083827f40a2d97261528087331b0bee6ce2cf27c5root    int unFenced;
10183827f40a2d97261528087331b0bee6ce2cf27c5root};
10283827f40a2d97261528087331b0bee6ce2cf27c5root
10383827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabPool;
10483827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabKernelBO
10583827f40a2d97261528087331b0bee6ce2cf27c5root{
10683827f40a2d97261528087331b0bee6ce2cf27c5root
10783827f40a2d97261528087331b0bee6ce2cf27c5root    /*
10883827f40a2d97261528087331b0bee6ce2cf27c5root     * Constant at creation
10983827f40a2d97261528087331b0bee6ce2cf27c5root     */
11083827f40a2d97261528087331b0bee6ce2cf27c5root
11183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmKernelBuf kBuf;
11283827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t pageAlignment;
11383827f40a2d97261528087331b0bee6ce2cf27c5root    void *virtual;
11483827f40a2d97261528087331b0bee6ce2cf27c5root    unsigned long actualSize;
11583827f40a2d97261528087331b0bee6ce2cf27c5root    uint64_t mapHandle;
11683827f40a2d97261528087331b0bee6ce2cf27c5root
11783827f40a2d97261528087331b0bee6ce2cf27c5root    /*
11883827f40a2d97261528087331b0bee6ce2cf27c5root     * Protected by struct _WsbmSlabCache::mutex
11983827f40a2d97261528087331b0bee6ce2cf27c5root     */
12083827f40a2d97261528087331b0bee6ce2cf27c5root
12183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool;
12283827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t proposedPlacement;
12383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead timeoutHead;
12483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead head;
12583827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval timeFreed;
12683827f40a2d97261528087331b0bee6ce2cf27c5root};
12783827f40a2d97261528087331b0bee6ce2cf27c5root
12883827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlab
12983827f40a2d97261528087331b0bee6ce2cf27c5root{
13083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead head;
13183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead freeBuffers;
13283827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t numBuffers;
13383827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t numFree;
13483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *buffers;
13583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header;
13683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabKernelBO *kbo;
13783827f40a2d97261528087331b0bee6ce2cf27c5root};
13883827f40a2d97261528087331b0bee6ce2cf27c5root
13983827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabSizeHeader
14083827f40a2d97261528087331b0bee6ce2cf27c5root{
14183827f40a2d97261528087331b0bee6ce2cf27c5root    /*
14283827f40a2d97261528087331b0bee6ce2cf27c5root     * Constant at creation.
14383827f40a2d97261528087331b0bee6ce2cf27c5root     */
14483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool;
14583827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t bufSize;
14683827f40a2d97261528087331b0bee6ce2cf27c5root
14783827f40a2d97261528087331b0bee6ce2cf27c5root    /*
14883827f40a2d97261528087331b0bee6ce2cf27c5root     * Protected by this::mutex
14983827f40a2d97261528087331b0bee6ce2cf27c5root     */
15083827f40a2d97261528087331b0bee6ce2cf27c5root
15183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead slabs;
15283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead freeSlabs;
15383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead delayedBuffers;
15483827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t numDelayed;
15583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmMutex mutex;
15683827f40a2d97261528087331b0bee6ce2cf27c5root};
15783827f40a2d97261528087331b0bee6ce2cf27c5root
15883827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabCache
15983827f40a2d97261528087331b0bee6ce2cf27c5root{
16083827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval slabTimeout;
16183827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval checkInterval;
16283827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval nextCheck;
16383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead timeoutList;
16483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead unCached;
16583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead cached;
16683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmMutex mutex;
16783827f40a2d97261528087331b0bee6ce2cf27c5root};
16883827f40a2d97261528087331b0bee6ce2cf27c5root
16983827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabPool
17083827f40a2d97261528087331b0bee6ce2cf27c5root{
17183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufferPool pool;
17283827f40a2d97261528087331b0bee6ce2cf27c5root
17383827f40a2d97261528087331b0bee6ce2cf27c5root    /*
17483827f40a2d97261528087331b0bee6ce2cf27c5root     * The data of this structure remains constant after
17583827f40a2d97261528087331b0bee6ce2cf27c5root     * initialization and thus needs no mutex protection.
17683827f40a2d97261528087331b0bee6ce2cf27c5root     */
17783827f40a2d97261528087331b0bee6ce2cf27c5root
17883827f40a2d97261528087331b0bee6ce2cf27c5root    unsigned int devOffset;
17983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabCache *cache;
18083827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t proposedPlacement;
18183827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t validMask;
18283827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t *bucketSizes;
18383827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t numBuckets;
18483827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t pageSize;
18583827f40a2d97261528087331b0bee6ce2cf27c5root    int pageAlignment;
18683827f40a2d97261528087331b0bee6ce2cf27c5root    int maxSlabSize;
18783827f40a2d97261528087331b0bee6ce2cf27c5root    int desiredNumBuffers;
18883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *headers;
18983827f40a2d97261528087331b0bee6ce2cf27c5root};
19083827f40a2d97261528087331b0bee6ce2cf27c5root
19183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic inline struct _WsbmSlabPool *
19283827f40a2d97261528087331b0bee6ce2cf27c5rootslabPoolFromPool(struct _WsbmBufferPool *pool)
19383827f40a2d97261528087331b0bee6ce2cf27c5root{
19483827f40a2d97261528087331b0bee6ce2cf27c5root    return containerOf(pool, struct _WsbmSlabPool, pool);
19583827f40a2d97261528087331b0bee6ce2cf27c5root}
19683827f40a2d97261528087331b0bee6ce2cf27c5root
19783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic inline struct _WsbmSlabPool *
19883827f40a2d97261528087331b0bee6ce2cf27c5rootslabPoolFromBuf(struct _WsbmSlabBuffer *sBuf)
19983827f40a2d97261528087331b0bee6ce2cf27c5root{
20083827f40a2d97261528087331b0bee6ce2cf27c5root    return slabPoolFromPool(sBuf->storage.pool);
20183827f40a2d97261528087331b0bee6ce2cf27c5root}
20283827f40a2d97261528087331b0bee6ce2cf27c5root
20383827f40a2d97261528087331b0bee6ce2cf27c5rootstatic inline struct _WsbmSlabBuffer *
20483827f40a2d97261528087331b0bee6ce2cf27c5rootslabBuffer(struct _WsbmBufStorage *buf)
20583827f40a2d97261528087331b0bee6ce2cf27c5root{
20683827f40a2d97261528087331b0bee6ce2cf27c5root    return containerOf(buf, struct _WsbmSlabBuffer, storage);
20783827f40a2d97261528087331b0bee6ce2cf27c5root}
20883827f40a2d97261528087331b0bee6ce2cf27c5root
20983827f40a2d97261528087331b0bee6ce2cf27c5root/*
21083827f40a2d97261528087331b0bee6ce2cf27c5root * FIXME: Perhaps arrange timeout slabs in size buckets for fast
21183827f40a2d97261528087331b0bee6ce2cf27c5root * retreival??
21283827f40a2d97261528087331b0bee6ce2cf27c5root */
21383827f40a2d97261528087331b0bee6ce2cf27c5root
21483827f40a2d97261528087331b0bee6ce2cf27c5rootstatic inline int
21583827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmTimeAfterEq(struct timeval *arg1, struct timeval *arg2)
21683827f40a2d97261528087331b0bee6ce2cf27c5root{
21783827f40a2d97261528087331b0bee6ce2cf27c5root    return ((arg1->tv_sec > arg2->tv_sec) ||
21883827f40a2d97261528087331b0bee6ce2cf27c5root	    ((arg1->tv_sec == arg2->tv_sec) &&
21983827f40a2d97261528087331b0bee6ce2cf27c5root	     (arg1->tv_usec > arg2->tv_usec)));
22083827f40a2d97261528087331b0bee6ce2cf27c5root}
22183827f40a2d97261528087331b0bee6ce2cf27c5root
22283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic inline void
22383827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmTimeAdd(struct timeval *arg, struct timeval *add)
22483827f40a2d97261528087331b0bee6ce2cf27c5root{
22583827f40a2d97261528087331b0bee6ce2cf27c5root    unsigned int sec;
22683827f40a2d97261528087331b0bee6ce2cf27c5root
22783827f40a2d97261528087331b0bee6ce2cf27c5root    arg->tv_sec += add->tv_sec;
22883827f40a2d97261528087331b0bee6ce2cf27c5root    arg->tv_usec += add->tv_usec;
22983827f40a2d97261528087331b0bee6ce2cf27c5root    sec = arg->tv_usec / 1000000;
23083827f40a2d97261528087331b0bee6ce2cf27c5root    arg->tv_sec += sec;
23183827f40a2d97261528087331b0bee6ce2cf27c5root    arg->tv_usec -= sec * 1000000;
23283827f40a2d97261528087331b0bee6ce2cf27c5root}
23383827f40a2d97261528087331b0bee6ce2cf27c5root
23483827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
23583827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmFreeKernelBO(struct _WsbmSlabKernelBO *kbo)
23683827f40a2d97261528087331b0bee6ce2cf27c5root{
23783827f40a2d97261528087331b0bee6ce2cf27c5root    struct ttm_pl_reference_req arg;
23883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool;
23983827f40a2d97261528087331b0bee6ce2cf27c5root
24083827f40a2d97261528087331b0bee6ce2cf27c5root    if (!kbo)
24183827f40a2d97261528087331b0bee6ce2cf27c5root	return;
24283827f40a2d97261528087331b0bee6ce2cf27c5root
24383827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool = kbo->slabPool;
24483827f40a2d97261528087331b0bee6ce2cf27c5root    arg.handle = kbo->kBuf.handle;
24583827f40a2d97261528087331b0bee6ce2cf27c5root    (void)munmap(kbo->virtual, kbo->actualSize);
24683827f40a2d97261528087331b0bee6ce2cf27c5root    (void)drmCommandWrite(slabPool->pool.fd,
24783827f40a2d97261528087331b0bee6ce2cf27c5root			  slabPool->devOffset + TTM_PL_UNREF, &arg,
24883827f40a2d97261528087331b0bee6ce2cf27c5root			  sizeof(arg));
24983827f40a2d97261528087331b0bee6ce2cf27c5root    free(kbo);
25083827f40a2d97261528087331b0bee6ce2cf27c5root}
25183827f40a2d97261528087331b0bee6ce2cf27c5root
25283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
25383827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmFreeTimeoutKBOsLocked(struct _WsbmSlabCache *cache, struct timeval *time)
25483827f40a2d97261528087331b0bee6ce2cf27c5root{
25583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list, *next;
25683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabKernelBO *kbo;
25783827f40a2d97261528087331b0bee6ce2cf27c5root
25883827f40a2d97261528087331b0bee6ce2cf27c5root    if (!wsbmTimeAfterEq(time, &cache->nextCheck))
25983827f40a2d97261528087331b0bee6ce2cf27c5root	return;
26083827f40a2d97261528087331b0bee6ce2cf27c5root
26183827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTFOREACHSAFE(list, next, &cache->timeoutList) {
26283827f40a2d97261528087331b0bee6ce2cf27c5root	kbo = WSBMLISTENTRY(list, struct _WsbmSlabKernelBO, timeoutHead);
26383827f40a2d97261528087331b0bee6ce2cf27c5root
26483827f40a2d97261528087331b0bee6ce2cf27c5root	if (!wsbmTimeAfterEq(time, &kbo->timeFreed))
26583827f40a2d97261528087331b0bee6ce2cf27c5root	    break;
26683827f40a2d97261528087331b0bee6ce2cf27c5root
26783827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDELINIT(&kbo->timeoutHead);
26883827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDELINIT(&kbo->head);
26983827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmFreeKernelBO(kbo);
27083827f40a2d97261528087331b0bee6ce2cf27c5root    }
27183827f40a2d97261528087331b0bee6ce2cf27c5root
27283827f40a2d97261528087331b0bee6ce2cf27c5root    cache->nextCheck = *time;
27383827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmTimeAdd(&cache->nextCheck, &cache->checkInterval);
27483827f40a2d97261528087331b0bee6ce2cf27c5root}
27583827f40a2d97261528087331b0bee6ce2cf27c5root
27683827f40a2d97261528087331b0bee6ce2cf27c5root/*
27783827f40a2d97261528087331b0bee6ce2cf27c5root * Add a _SlabKernelBO to the free slab manager.
27883827f40a2d97261528087331b0bee6ce2cf27c5root * This means that it is available for reuse, but if it's not
27983827f40a2d97261528087331b0bee6ce2cf27c5root * reused in a while, it will be freed.
28083827f40a2d97261528087331b0bee6ce2cf27c5root */
28183827f40a2d97261528087331b0bee6ce2cf27c5root
28283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
28383827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSetKernelBOFree(struct _WsbmSlabCache *cache,
28483827f40a2d97261528087331b0bee6ce2cf27c5root		    struct _WsbmSlabKernelBO *kbo)
28583827f40a2d97261528087331b0bee6ce2cf27c5root{
28683827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval time;
28783827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval timeFreed;
28883827f40a2d97261528087331b0bee6ce2cf27c5root
28983827f40a2d97261528087331b0bee6ce2cf27c5root    gettimeofday(&time, NULL);
29083827f40a2d97261528087331b0bee6ce2cf27c5root    timeFreed = time;
29183827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&cache->mutex);
29283827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmTimeAdd(&timeFreed, &cache->slabTimeout);
29383827f40a2d97261528087331b0bee6ce2cf27c5root    kbo->timeFreed = timeFreed;
29483827f40a2d97261528087331b0bee6ce2cf27c5root
29583827f40a2d97261528087331b0bee6ce2cf27c5root    if (kbo->kBuf.placement & TTM_PL_FLAG_CACHED)
29683827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADD(&kbo->head, &cache->cached);
29783827f40a2d97261528087331b0bee6ce2cf27c5root    else
29883827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADD(&kbo->head, &cache->unCached);
29983827f40a2d97261528087331b0bee6ce2cf27c5root
30083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTADDTAIL(&kbo->timeoutHead, &cache->timeoutList);
30183827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmFreeTimeoutKBOsLocked(cache, &time);
30283827f40a2d97261528087331b0bee6ce2cf27c5root
30383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&cache->mutex);
30483827f40a2d97261528087331b0bee6ce2cf27c5root}
30583827f40a2d97261528087331b0bee6ce2cf27c5root
30683827f40a2d97261528087331b0bee6ce2cf27c5root/*
30783827f40a2d97261528087331b0bee6ce2cf27c5root * Get a _SlabKernelBO for us to use as storage for a slab.
30883827f40a2d97261528087331b0bee6ce2cf27c5root */
30983827f40a2d97261528087331b0bee6ce2cf27c5root
31083827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmSlabKernelBO *
31183827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmAllocKernelBO(struct _WsbmSlabSizeHeader *header)
31283827f40a2d97261528087331b0bee6ce2cf27c5root{
31383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool = header->slabPool;
31483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabCache *cache = slabPool->cache;
31583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list, *head;
31683827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t size = header->bufSize * slabPool->desiredNumBuffers;
31783827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabKernelBO *kbo;
31883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabKernelBO *kboTmp;
31983827f40a2d97261528087331b0bee6ce2cf27c5root    int ret;
32083827f40a2d97261528087331b0bee6ce2cf27c5root
32183827f40a2d97261528087331b0bee6ce2cf27c5root    /*
32283827f40a2d97261528087331b0bee6ce2cf27c5root     * FIXME: We should perhaps allow some variation in slabsize in order
32383827f40a2d97261528087331b0bee6ce2cf27c5root     * to efficiently reuse slabs.
32483827f40a2d97261528087331b0bee6ce2cf27c5root     */
32583827f40a2d97261528087331b0bee6ce2cf27c5root
3263795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    size = (size <= (uint32_t) slabPool->maxSlabSize) ? size : (uint32_t) slabPool->maxSlabSize;
32783827f40a2d97261528087331b0bee6ce2cf27c5root    if (size < header->bufSize)
32883827f40a2d97261528087331b0bee6ce2cf27c5root	size = header->bufSize;
32983827f40a2d97261528087331b0bee6ce2cf27c5root    size = (size + slabPool->pageSize - 1) & ~(slabPool->pageSize - 1);
33083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&cache->mutex);
33183827f40a2d97261528087331b0bee6ce2cf27c5root
33283827f40a2d97261528087331b0bee6ce2cf27c5root    kbo = NULL;
33383827f40a2d97261528087331b0bee6ce2cf27c5root
33483827f40a2d97261528087331b0bee6ce2cf27c5root  retry:
33583827f40a2d97261528087331b0bee6ce2cf27c5root    head = (slabPool->proposedPlacement & TTM_PL_FLAG_CACHED) ?
33683827f40a2d97261528087331b0bee6ce2cf27c5root	&cache->cached : &cache->unCached;
33783827f40a2d97261528087331b0bee6ce2cf27c5root
33883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTFOREACH(list, head) {
33983827f40a2d97261528087331b0bee6ce2cf27c5root	kboTmp = WSBMLISTENTRY(list, struct _WsbmSlabKernelBO, head);
34083827f40a2d97261528087331b0bee6ce2cf27c5root
34183827f40a2d97261528087331b0bee6ce2cf27c5root	if ((kboTmp->actualSize == size) &&
34283827f40a2d97261528087331b0bee6ce2cf27c5root	    (slabPool->pageAlignment == 0 ||
34383827f40a2d97261528087331b0bee6ce2cf27c5root	     (kboTmp->pageAlignment % slabPool->pageAlignment) == 0)) {
34483827f40a2d97261528087331b0bee6ce2cf27c5root
34583827f40a2d97261528087331b0bee6ce2cf27c5root	    if (!kbo)
34683827f40a2d97261528087331b0bee6ce2cf27c5root		kbo = kboTmp;
34783827f40a2d97261528087331b0bee6ce2cf27c5root
34883827f40a2d97261528087331b0bee6ce2cf27c5root	    if ((kbo->proposedPlacement ^ slabPool->proposedPlacement) == 0)
34983827f40a2d97261528087331b0bee6ce2cf27c5root		break;
35083827f40a2d97261528087331b0bee6ce2cf27c5root
35183827f40a2d97261528087331b0bee6ce2cf27c5root	}
35283827f40a2d97261528087331b0bee6ce2cf27c5root    }
35383827f40a2d97261528087331b0bee6ce2cf27c5root
35483827f40a2d97261528087331b0bee6ce2cf27c5root    if (kbo) {
35583827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDELINIT(&kbo->head);
35683827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDELINIT(&kbo->timeoutHead);
35783827f40a2d97261528087331b0bee6ce2cf27c5root    }
35883827f40a2d97261528087331b0bee6ce2cf27c5root
35983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&cache->mutex);
36083827f40a2d97261528087331b0bee6ce2cf27c5root
36183827f40a2d97261528087331b0bee6ce2cf27c5root    if (kbo) {
36283827f40a2d97261528087331b0bee6ce2cf27c5root	uint32_t new_mask =
36383827f40a2d97261528087331b0bee6ce2cf27c5root	    kbo->proposedPlacement ^ slabPool->proposedPlacement;
36483827f40a2d97261528087331b0bee6ce2cf27c5root
36583827f40a2d97261528087331b0bee6ce2cf27c5root	ret = 0;
36683827f40a2d97261528087331b0bee6ce2cf27c5root	if (new_mask) {
36783827f40a2d97261528087331b0bee6ce2cf27c5root	    union ttm_pl_setstatus_arg arg;
36883827f40a2d97261528087331b0bee6ce2cf27c5root	    struct ttm_pl_setstatus_req *req = &arg.req;
36983827f40a2d97261528087331b0bee6ce2cf27c5root	    struct ttm_pl_rep *rep = &arg.rep;
37083827f40a2d97261528087331b0bee6ce2cf27c5root
37183827f40a2d97261528087331b0bee6ce2cf27c5root	    req->handle = kbo->kBuf.handle;
37283827f40a2d97261528087331b0bee6ce2cf27c5root	    req->set_placement = slabPool->proposedPlacement & new_mask;
37383827f40a2d97261528087331b0bee6ce2cf27c5root	    req->clr_placement = ~slabPool->proposedPlacement & new_mask;
37483827f40a2d97261528087331b0bee6ce2cf27c5root	    DRMRESTARTCOMMANDWRITEREAD(slabPool->pool.fd,
37583827f40a2d97261528087331b0bee6ce2cf27c5root				       slabPool->devOffset + TTM_PL_SETSTATUS,
37683827f40a2d97261528087331b0bee6ce2cf27c5root				       arg, ret);
37783827f40a2d97261528087331b0bee6ce2cf27c5root	    if (ret == 0) {
37883827f40a2d97261528087331b0bee6ce2cf27c5root		kbo->kBuf.gpuOffset = rep->gpu_offset;
37983827f40a2d97261528087331b0bee6ce2cf27c5root		kbo->kBuf.placement = rep->placement;
38083827f40a2d97261528087331b0bee6ce2cf27c5root	    }
38183827f40a2d97261528087331b0bee6ce2cf27c5root	    kbo->proposedPlacement = slabPool->proposedPlacement;
38283827f40a2d97261528087331b0bee6ce2cf27c5root	}
38383827f40a2d97261528087331b0bee6ce2cf27c5root
38483827f40a2d97261528087331b0bee6ce2cf27c5root	if (ret == 0)
38583827f40a2d97261528087331b0bee6ce2cf27c5root	    return kbo;
38683827f40a2d97261528087331b0bee6ce2cf27c5root
38783827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmFreeKernelBO(kbo);
38883827f40a2d97261528087331b0bee6ce2cf27c5root	kbo = NULL;
38983827f40a2d97261528087331b0bee6ce2cf27c5root	goto retry;
39083827f40a2d97261528087331b0bee6ce2cf27c5root    }
39183827f40a2d97261528087331b0bee6ce2cf27c5root
39283827f40a2d97261528087331b0bee6ce2cf27c5root    kbo = calloc(1, sizeof(*kbo));
39383827f40a2d97261528087331b0bee6ce2cf27c5root    if (!kbo)
39483827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
39583827f40a2d97261528087331b0bee6ce2cf27c5root
39683827f40a2d97261528087331b0bee6ce2cf27c5root    {
39783827f40a2d97261528087331b0bee6ce2cf27c5root	union ttm_pl_create_arg arg;
39883827f40a2d97261528087331b0bee6ce2cf27c5root
39983827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->slabPool = slabPool;
40083827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMINITLISTHEAD(&kbo->head);
40183827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMINITLISTHEAD(&kbo->timeoutHead);
40283827f40a2d97261528087331b0bee6ce2cf27c5root
40383827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.size = size;
40483827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.placement = slabPool->proposedPlacement;
40583827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.page_alignment = slabPool->pageAlignment;
40683827f40a2d97261528087331b0bee6ce2cf27c5root
40783827f40a2d97261528087331b0bee6ce2cf27c5root	DRMRESTARTCOMMANDWRITEREAD(slabPool->pool.fd,
40883827f40a2d97261528087331b0bee6ce2cf27c5root				   slabPool->devOffset + TTM_PL_CREATE,
40983827f40a2d97261528087331b0bee6ce2cf27c5root				   arg, ret);
41083827f40a2d97261528087331b0bee6ce2cf27c5root	if (ret)
41183827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err0;
41283827f40a2d97261528087331b0bee6ce2cf27c5root
41383827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->kBuf.gpuOffset = arg.rep.gpu_offset;
41483827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->kBuf.placement = arg.rep.placement;
41583827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->kBuf.handle = arg.rep.handle;
41683827f40a2d97261528087331b0bee6ce2cf27c5root
41783827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->actualSize = arg.rep.bo_size;
41883827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->mapHandle = arg.rep.map_handle;
41983827f40a2d97261528087331b0bee6ce2cf27c5root	kbo->proposedPlacement = slabPool->proposedPlacement;
42083827f40a2d97261528087331b0bee6ce2cf27c5root    }
42183827f40a2d97261528087331b0bee6ce2cf27c5root
42283827f40a2d97261528087331b0bee6ce2cf27c5root    kbo->virtual = mmap(0, kbo->actualSize,
42383827f40a2d97261528087331b0bee6ce2cf27c5root			PROT_READ | PROT_WRITE, MAP_SHARED,
42483827f40a2d97261528087331b0bee6ce2cf27c5root			slabPool->pool.fd, kbo->mapHandle);
42583827f40a2d97261528087331b0bee6ce2cf27c5root
42683827f40a2d97261528087331b0bee6ce2cf27c5root    if (kbo->virtual == MAP_FAILED) {
42783827f40a2d97261528087331b0bee6ce2cf27c5root	ret = -errno;
42883827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
42983827f40a2d97261528087331b0bee6ce2cf27c5root    }
43083827f40a2d97261528087331b0bee6ce2cf27c5root
43183827f40a2d97261528087331b0bee6ce2cf27c5root    return kbo;
43283827f40a2d97261528087331b0bee6ce2cf27c5root
43383827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
43483827f40a2d97261528087331b0bee6ce2cf27c5root    {
43583827f40a2d97261528087331b0bee6ce2cf27c5root	struct ttm_pl_reference_req arg = {.handle = kbo->kBuf.handle };
43683827f40a2d97261528087331b0bee6ce2cf27c5root
43783827f40a2d97261528087331b0bee6ce2cf27c5root	(void)drmCommandWrite(slabPool->pool.fd,
43883827f40a2d97261528087331b0bee6ce2cf27c5root			      slabPool->devOffset + TTM_PL_UNREF,
43983827f40a2d97261528087331b0bee6ce2cf27c5root			      &arg, sizeof(arg));
44083827f40a2d97261528087331b0bee6ce2cf27c5root    }
44183827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
44283827f40a2d97261528087331b0bee6ce2cf27c5root    free(kbo);
44383827f40a2d97261528087331b0bee6ce2cf27c5root    return NULL;
44483827f40a2d97261528087331b0bee6ce2cf27c5root}
44583827f40a2d97261528087331b0bee6ce2cf27c5root
44683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
44783827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmAllocSlab(struct _WsbmSlabSizeHeader *header)
44883827f40a2d97261528087331b0bee6ce2cf27c5root{
44983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
45083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
45183827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t numBuffers;
4523795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    uint32_t ret;
4533795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    uint32_t i;
45483827f40a2d97261528087331b0bee6ce2cf27c5root
45583827f40a2d97261528087331b0bee6ce2cf27c5root    slab = calloc(1, sizeof(*slab));
45683827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slab)
45783827f40a2d97261528087331b0bee6ce2cf27c5root	return -ENOMEM;
45883827f40a2d97261528087331b0bee6ce2cf27c5root
45983827f40a2d97261528087331b0bee6ce2cf27c5root    slab->kbo = wsbmAllocKernelBO(header);
46083827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slab->kbo) {
46183827f40a2d97261528087331b0bee6ce2cf27c5root	ret = -ENOMEM;
46283827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err0;
46383827f40a2d97261528087331b0bee6ce2cf27c5root    }
46483827f40a2d97261528087331b0bee6ce2cf27c5root
46583827f40a2d97261528087331b0bee6ce2cf27c5root    numBuffers = slab->kbo->actualSize / header->bufSize;
46683827f40a2d97261528087331b0bee6ce2cf27c5root
46783827f40a2d97261528087331b0bee6ce2cf27c5root    slab->buffers = calloc(numBuffers, sizeof(*slab->buffers));
46883827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slab->buffers) {
46983827f40a2d97261528087331b0bee6ce2cf27c5root	ret = -ENOMEM;
47083827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
47183827f40a2d97261528087331b0bee6ce2cf27c5root    }
47283827f40a2d97261528087331b0bee6ce2cf27c5root
47383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&slab->head);
47483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&slab->freeBuffers);
47583827f40a2d97261528087331b0bee6ce2cf27c5root    slab->numBuffers = numBuffers;
47683827f40a2d97261528087331b0bee6ce2cf27c5root    slab->numFree = 0;
47783827f40a2d97261528087331b0bee6ce2cf27c5root    slab->header = header;
47883827f40a2d97261528087331b0bee6ce2cf27c5root
47983827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf = slab->buffers;
48083827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < numBuffers; ++i) {
48183827f40a2d97261528087331b0bee6ce2cf27c5root	ret = wsbmBufStorageInit(&sBuf->storage, &header->slabPool->pool);
48283827f40a2d97261528087331b0bee6ce2cf27c5root	if (ret)
48383827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err2;
48483827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->parent = slab;
48583827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->start = i * header->bufSize;
48683827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->virtual = (void *)((uint8_t *) slab->kbo->virtual +
48783827f40a2d97261528087331b0bee6ce2cf27c5root				 sBuf->start);
48883827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmAtomicSet(&sBuf->writers, 0);
48983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->isSlabBuffer = 1;
49083827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_INIT(&sBuf->event);
49183827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(&sBuf->head, &slab->freeBuffers);
49283827f40a2d97261528087331b0bee6ce2cf27c5root	slab->numFree++;
49383827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf++;
49483827f40a2d97261528087331b0bee6ce2cf27c5root    }
49583827f40a2d97261528087331b0bee6ce2cf27c5root
49683827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTADDTAIL(&slab->head, &header->slabs);
49783827f40a2d97261528087331b0bee6ce2cf27c5root
49883827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
49983827f40a2d97261528087331b0bee6ce2cf27c5root
50083827f40a2d97261528087331b0bee6ce2cf27c5root  out_err2:
50183827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf = slab->buffers;
50283827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < numBuffers; ++i) {
50383827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->parent == slab) {
50483827f40a2d97261528087331b0bee6ce2cf27c5root	    WSBM_COND_FREE(&sBuf->event);
50583827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmBufStorageTakedown(&sBuf->storage);
50683827f40a2d97261528087331b0bee6ce2cf27c5root	}
50783827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf++;
50883827f40a2d97261528087331b0bee6ce2cf27c5root    }
50983827f40a2d97261528087331b0bee6ce2cf27c5root    free(slab->buffers);
51083827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
51183827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmSetKernelBOFree(header->slabPool->cache, slab->kbo);
51283827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
51383827f40a2d97261528087331b0bee6ce2cf27c5root    free(slab);
51483827f40a2d97261528087331b0bee6ce2cf27c5root    return ret;
51583827f40a2d97261528087331b0bee6ce2cf27c5root}
51683827f40a2d97261528087331b0bee6ce2cf27c5root
51783827f40a2d97261528087331b0bee6ce2cf27c5root/*
51883827f40a2d97261528087331b0bee6ce2cf27c5root * Delete a buffer from the slab header delayed list and put
51983827f40a2d97261528087331b0bee6ce2cf27c5root * it on the slab free list.
52083827f40a2d97261528087331b0bee6ce2cf27c5root */
52183827f40a2d97261528087331b0bee6ce2cf27c5root
52283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
52383827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabFreeBufferLocked(struct _WsbmSlabBuffer *buf)
52483827f40a2d97261528087331b0bee6ce2cf27c5root{
52583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab = buf->parent;
52683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header = slab->header;
52783827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list = &buf->head;
52883827f40a2d97261528087331b0bee6ce2cf27c5root
52983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTDEL(list);
53083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTADDTAIL(list, &slab->freeBuffers);
53183827f40a2d97261528087331b0bee6ce2cf27c5root    slab->numFree++;
53283827f40a2d97261528087331b0bee6ce2cf27c5root
53383827f40a2d97261528087331b0bee6ce2cf27c5root    if (slab->head.next == &slab->head)
53483827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(&slab->head, &header->slabs);
53583827f40a2d97261528087331b0bee6ce2cf27c5root
53683827f40a2d97261528087331b0bee6ce2cf27c5root    if (slab->numFree == slab->numBuffers) {
53783827f40a2d97261528087331b0bee6ce2cf27c5root	list = &slab->head;
53883827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDEL(list);
53983827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(list, &header->freeSlabs);
54083827f40a2d97261528087331b0bee6ce2cf27c5root    }
54183827f40a2d97261528087331b0bee6ce2cf27c5root
54283827f40a2d97261528087331b0bee6ce2cf27c5root    if (header->slabs.next == &header->slabs ||
54383827f40a2d97261528087331b0bee6ce2cf27c5root	slab->numFree != slab->numBuffers) {
54483827f40a2d97261528087331b0bee6ce2cf27c5root
54583827f40a2d97261528087331b0bee6ce2cf27c5root	struct _WsbmListHead *next;
54683827f40a2d97261528087331b0bee6ce2cf27c5root	struct _WsbmSlabCache *cache = header->slabPool->cache;
54783827f40a2d97261528087331b0bee6ce2cf27c5root
54883827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTFOREACHSAFE(list, next, &header->freeSlabs) {
5493795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel	    uint32_t i;
55083827f40a2d97261528087331b0bee6ce2cf27c5root	    struct _WsbmSlabBuffer *sBuf;
55183827f40a2d97261528087331b0bee6ce2cf27c5root
55283827f40a2d97261528087331b0bee6ce2cf27c5root	    slab = WSBMLISTENTRY(list, struct _WsbmSlab, head);
55383827f40a2d97261528087331b0bee6ce2cf27c5root
55483827f40a2d97261528087331b0bee6ce2cf27c5root	    WSBMLISTDELINIT(list);
55583827f40a2d97261528087331b0bee6ce2cf27c5root
55683827f40a2d97261528087331b0bee6ce2cf27c5root	    sBuf = slab->buffers;
55783827f40a2d97261528087331b0bee6ce2cf27c5root	    for (i = 0; i < slab->numBuffers; ++i) {
55883827f40a2d97261528087331b0bee6ce2cf27c5root		if (sBuf->parent == slab) {
55983827f40a2d97261528087331b0bee6ce2cf27c5root		    WSBM_COND_FREE(&sBuf->event);
56083827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmBufStorageTakedown(&sBuf->storage);
56183827f40a2d97261528087331b0bee6ce2cf27c5root		}
56283827f40a2d97261528087331b0bee6ce2cf27c5root		sBuf++;
56383827f40a2d97261528087331b0bee6ce2cf27c5root	    }
56483827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmSetKernelBOFree(cache, slab->kbo);
56583827f40a2d97261528087331b0bee6ce2cf27c5root	    free(slab->buffers);
56683827f40a2d97261528087331b0bee6ce2cf27c5root	    free(slab);
56783827f40a2d97261528087331b0bee6ce2cf27c5root	}
56883827f40a2d97261528087331b0bee6ce2cf27c5root    }
56983827f40a2d97261528087331b0bee6ce2cf27c5root}
57083827f40a2d97261528087331b0bee6ce2cf27c5root
57183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
57283827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabCheckFreeLocked(struct _WsbmSlabSizeHeader *header, int wait)
57383827f40a2d97261528087331b0bee6ce2cf27c5root{
57483827f40a2d97261528087331b0bee6ce2cf27c5root  struct _WsbmListHead *list, *prev, *first, *head;
57583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
57683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
57783827f40a2d97261528087331b0bee6ce2cf27c5root    int firstWasSignaled = 1;
57883827f40a2d97261528087331b0bee6ce2cf27c5root    int signaled;
5793795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    uint32_t i;
58083827f40a2d97261528087331b0bee6ce2cf27c5root    int ret;
58183827f40a2d97261528087331b0bee6ce2cf27c5root
58283827f40a2d97261528087331b0bee6ce2cf27c5root    /*
58383827f40a2d97261528087331b0bee6ce2cf27c5root     * Rerun the freeing test if the youngest tested buffer
58483827f40a2d97261528087331b0bee6ce2cf27c5root     * was signaled, since there might be more idle buffers
58583827f40a2d97261528087331b0bee6ce2cf27c5root     * in the delay list.
58683827f40a2d97261528087331b0bee6ce2cf27c5root     */
58783827f40a2d97261528087331b0bee6ce2cf27c5root
58883827f40a2d97261528087331b0bee6ce2cf27c5root    while (firstWasSignaled) {
58983827f40a2d97261528087331b0bee6ce2cf27c5root	firstWasSignaled = 0;
59083827f40a2d97261528087331b0bee6ce2cf27c5root	signaled = 0;
59183827f40a2d97261528087331b0bee6ce2cf27c5root	first = header->delayedBuffers.next;
59283827f40a2d97261528087331b0bee6ce2cf27c5root
59383827f40a2d97261528087331b0bee6ce2cf27c5root	/* Only examine the oldest 1/3 of delayed buffers:
59483827f40a2d97261528087331b0bee6ce2cf27c5root	 */
59583827f40a2d97261528087331b0bee6ce2cf27c5root	if (header->numDelayed > 3) {
59683827f40a2d97261528087331b0bee6ce2cf27c5root	    for (i = 0; i < header->numDelayed; i += 3) {
59783827f40a2d97261528087331b0bee6ce2cf27c5root		first = first->next;
59883827f40a2d97261528087331b0bee6ce2cf27c5root	    }
59983827f40a2d97261528087331b0bee6ce2cf27c5root	}
60083827f40a2d97261528087331b0bee6ce2cf27c5root
60183827f40a2d97261528087331b0bee6ce2cf27c5root	/*
60283827f40a2d97261528087331b0bee6ce2cf27c5root	 * No need to take the buffer mutex for each buffer we loop
60383827f40a2d97261528087331b0bee6ce2cf27c5root	 * through since we're currently the only user.
60483827f40a2d97261528087331b0bee6ce2cf27c5root	 */
60583827f40a2d97261528087331b0bee6ce2cf27c5root
60683827f40a2d97261528087331b0bee6ce2cf27c5root	head = first->next;
60783827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTFOREACHPREVSAFE(list, prev, head) {
60883827f40a2d97261528087331b0bee6ce2cf27c5root
60983827f40a2d97261528087331b0bee6ce2cf27c5root	    if (list == &header->delayedBuffers)
61083827f40a2d97261528087331b0bee6ce2cf27c5root		break;
61183827f40a2d97261528087331b0bee6ce2cf27c5root
61283827f40a2d97261528087331b0bee6ce2cf27c5root	    sBuf = WSBMLISTENTRY(list, struct _WsbmSlabBuffer, head);
61383827f40a2d97261528087331b0bee6ce2cf27c5root
61483827f40a2d97261528087331b0bee6ce2cf27c5root	    slab = sBuf->parent;
61583827f40a2d97261528087331b0bee6ce2cf27c5root
61683827f40a2d97261528087331b0bee6ce2cf27c5root	    if (!signaled) {
61783827f40a2d97261528087331b0bee6ce2cf27c5root		if (wait) {
61883827f40a2d97261528087331b0bee6ce2cf27c5root		    ret = wsbmFenceFinish(sBuf->fence, sBuf->fenceType, 0);
61983827f40a2d97261528087331b0bee6ce2cf27c5root		    if (ret)
62083827f40a2d97261528087331b0bee6ce2cf27c5root			break;
62183827f40a2d97261528087331b0bee6ce2cf27c5root		    signaled = 1;
62283827f40a2d97261528087331b0bee6ce2cf27c5root		    wait = 0;
62383827f40a2d97261528087331b0bee6ce2cf27c5root		} else {
62483827f40a2d97261528087331b0bee6ce2cf27c5root		    signaled =
62583827f40a2d97261528087331b0bee6ce2cf27c5root			wsbmFenceSignaled(sBuf->fence, sBuf->fenceType);
62683827f40a2d97261528087331b0bee6ce2cf27c5root#ifdef DEBUG_FENCESIGNALED
62783827f40a2d97261528087331b0bee6ce2cf27c5root		    fencesignaled++;
62883827f40a2d97261528087331b0bee6ce2cf27c5root#endif
62983827f40a2d97261528087331b0bee6ce2cf27c5root		}
63083827f40a2d97261528087331b0bee6ce2cf27c5root		if (signaled) {
63183827f40a2d97261528087331b0bee6ce2cf27c5root		    if (list == first)
63283827f40a2d97261528087331b0bee6ce2cf27c5root			firstWasSignaled = 1;
63383827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmFenceUnreference(&sBuf->fence);
63483827f40a2d97261528087331b0bee6ce2cf27c5root		    header->numDelayed--;
63583827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmSlabFreeBufferLocked(sBuf);
63683827f40a2d97261528087331b0bee6ce2cf27c5root		} else
63783827f40a2d97261528087331b0bee6ce2cf27c5root		    break;
63883827f40a2d97261528087331b0bee6ce2cf27c5root	    } else if (wsbmFenceSignaledCached(sBuf->fence, sBuf->fenceType)) {
63983827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceUnreference(&sBuf->fence);
64083827f40a2d97261528087331b0bee6ce2cf27c5root		header->numDelayed--;
64183827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmSlabFreeBufferLocked(sBuf);
64283827f40a2d97261528087331b0bee6ce2cf27c5root	    }
64383827f40a2d97261528087331b0bee6ce2cf27c5root	}
64483827f40a2d97261528087331b0bee6ce2cf27c5root    }
64583827f40a2d97261528087331b0bee6ce2cf27c5root}
64683827f40a2d97261528087331b0bee6ce2cf27c5root
64783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmSlabBuffer *
64883827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabAllocBuffer(struct _WsbmSlabSizeHeader *header)
64983827f40a2d97261528087331b0bee6ce2cf27c5root{
65083827f40a2d97261528087331b0bee6ce2cf27c5root    static struct _WsbmSlabBuffer *buf;
65183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
65283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list;
65383827f40a2d97261528087331b0bee6ce2cf27c5root    int count = WSBM_SLABPOOL_ALLOC_RETRIES;
65483827f40a2d97261528087331b0bee6ce2cf27c5root
65583827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
65683827f40a2d97261528087331b0bee6ce2cf27c5root    while (header->slabs.next == &header->slabs && count > 0) {
65783827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmSlabCheckFreeLocked(header, 0);
65883827f40a2d97261528087331b0bee6ce2cf27c5root	if (header->slabs.next != &header->slabs)
65983827f40a2d97261528087331b0bee6ce2cf27c5root	    break;
66083827f40a2d97261528087331b0bee6ce2cf27c5root
66183827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_MUTEX_UNLOCK(&header->mutex);
66283827f40a2d97261528087331b0bee6ce2cf27c5root	if (count != WSBM_SLABPOOL_ALLOC_RETRIES)
66383827f40a2d97261528087331b0bee6ce2cf27c5root	    usleep(1000);
66483827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_MUTEX_LOCK(&header->mutex);
66583827f40a2d97261528087331b0bee6ce2cf27c5root	(void)wsbmAllocSlab(header);
66683827f40a2d97261528087331b0bee6ce2cf27c5root	count--;
66783827f40a2d97261528087331b0bee6ce2cf27c5root    }
66883827f40a2d97261528087331b0bee6ce2cf27c5root
66983827f40a2d97261528087331b0bee6ce2cf27c5root    list = header->slabs.next;
67083827f40a2d97261528087331b0bee6ce2cf27c5root    if (list == &header->slabs) {
67183827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_MUTEX_UNLOCK(&header->mutex);
67283827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
67383827f40a2d97261528087331b0bee6ce2cf27c5root    }
67483827f40a2d97261528087331b0bee6ce2cf27c5root    slab = WSBMLISTENTRY(list, struct _WsbmSlab, head);
67583827f40a2d97261528087331b0bee6ce2cf27c5root    if (--slab->numFree == 0)
67683827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDELINIT(list);
67783827f40a2d97261528087331b0bee6ce2cf27c5root
67883827f40a2d97261528087331b0bee6ce2cf27c5root    list = slab->freeBuffers.next;
67983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTDELINIT(list);
68083827f40a2d97261528087331b0bee6ce2cf27c5root
68183827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
68283827f40a2d97261528087331b0bee6ce2cf27c5root    buf = WSBMLISTENTRY(list, struct _WsbmSlabBuffer, head);
68383827f40a2d97261528087331b0bee6ce2cf27c5root
68483827f40a2d97261528087331b0bee6ce2cf27c5root    buf->storage.destroyContainer = NULL;
68583827f40a2d97261528087331b0bee6ce2cf27c5root
68683827f40a2d97261528087331b0bee6ce2cf27c5root#ifdef DEBUG_FENCESIGNALED
68783827f40a2d97261528087331b0bee6ce2cf27c5root    createbuffer++;
68883827f40a2d97261528087331b0bee6ce2cf27c5root#endif
68983827f40a2d97261528087331b0bee6ce2cf27c5root    return buf;
69083827f40a2d97261528087331b0bee6ce2cf27c5root}
69183827f40a2d97261528087331b0bee6ce2cf27c5root
69283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmBufStorage *
69383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_create(struct _WsbmBufferPool *pool, unsigned long size,
69483827f40a2d97261528087331b0bee6ce2cf27c5root	    uint32_t placement, unsigned alignment)
69583827f40a2d97261528087331b0bee6ce2cf27c5root{
69683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool = slabPoolFromPool(pool);
69783827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header;
69883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
6993795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    uint32_t i;
70083827f40a2d97261528087331b0bee6ce2cf27c5root    int ret;
70183827f40a2d97261528087331b0bee6ce2cf27c5root
70283827f40a2d97261528087331b0bee6ce2cf27c5root    /*
70383827f40a2d97261528087331b0bee6ce2cf27c5root     * FIXME: Check for compatibility.
70483827f40a2d97261528087331b0bee6ce2cf27c5root     */
70583827f40a2d97261528087331b0bee6ce2cf27c5root
70683827f40a2d97261528087331b0bee6ce2cf27c5root    header = slabPool->headers;
70783827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < slabPool->numBuckets; ++i) {
70883827f40a2d97261528087331b0bee6ce2cf27c5root	if (header->bufSize >= size)
70983827f40a2d97261528087331b0bee6ce2cf27c5root	    break;
71083827f40a2d97261528087331b0bee6ce2cf27c5root	header++;
71183827f40a2d97261528087331b0bee6ce2cf27c5root    }
71283827f40a2d97261528087331b0bee6ce2cf27c5root
71383827f40a2d97261528087331b0bee6ce2cf27c5root    if (i < slabPool->numBuckets) {
71483827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf = wsbmSlabAllocBuffer(header);
71583827f40a2d97261528087331b0bee6ce2cf27c5root	return ((sBuf) ? &sBuf->storage : NULL);
71683827f40a2d97261528087331b0bee6ce2cf27c5root    }
71783827f40a2d97261528087331b0bee6ce2cf27c5root
71883827f40a2d97261528087331b0bee6ce2cf27c5root    /*
71983827f40a2d97261528087331b0bee6ce2cf27c5root     * Fall back to allocate a buffer object directly from DRM.
72083827f40a2d97261528087331b0bee6ce2cf27c5root     * and wrap it in a wsbmBO structure.
72183827f40a2d97261528087331b0bee6ce2cf27c5root     */
72283827f40a2d97261528087331b0bee6ce2cf27c5root
72383827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf = calloc(1, sizeof(*sBuf));
72483827f40a2d97261528087331b0bee6ce2cf27c5root
72583827f40a2d97261528087331b0bee6ce2cf27c5root    if (!sBuf)
72683827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
72783827f40a2d97261528087331b0bee6ce2cf27c5root
72883827f40a2d97261528087331b0bee6ce2cf27c5root    if (alignment) {
72983827f40a2d97261528087331b0bee6ce2cf27c5root	if ((alignment < slabPool->pageSize)
73083827f40a2d97261528087331b0bee6ce2cf27c5root	    && (slabPool->pageSize % alignment))
73183827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err0;
73283827f40a2d97261528087331b0bee6ce2cf27c5root	if ((alignment > slabPool->pageSize)
73383827f40a2d97261528087331b0bee6ce2cf27c5root	    && (alignment % slabPool->pageSize))
73483827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err0;
73583827f40a2d97261528087331b0bee6ce2cf27c5root    }
73683827f40a2d97261528087331b0bee6ce2cf27c5root
73783827f40a2d97261528087331b0bee6ce2cf27c5root    ret = wsbmBufStorageInit(&sBuf->storage, pool);
73883827f40a2d97261528087331b0bee6ce2cf27c5root    if (ret)
73983827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err0;
74083827f40a2d97261528087331b0bee6ce2cf27c5root
74183827f40a2d97261528087331b0bee6ce2cf27c5root    ret = WSBM_COND_INIT(&sBuf->event);
74283827f40a2d97261528087331b0bee6ce2cf27c5root    if (ret)
74383827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
74483827f40a2d97261528087331b0bee6ce2cf27c5root
74583827f40a2d97261528087331b0bee6ce2cf27c5root    {
74683827f40a2d97261528087331b0bee6ce2cf27c5root	union ttm_pl_create_arg arg;
74783827f40a2d97261528087331b0bee6ce2cf27c5root
74883827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.size = size;
74983827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.placement = placement;
75083827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.page_alignment = alignment / slabPool->pageSize;
75183827f40a2d97261528087331b0bee6ce2cf27c5root
75283827f40a2d97261528087331b0bee6ce2cf27c5root	DRMRESTARTCOMMANDWRITEREAD(pool->fd,
75383827f40a2d97261528087331b0bee6ce2cf27c5root				   slabPool->devOffset + TTM_PL_CREATE,
75483827f40a2d97261528087331b0bee6ce2cf27c5root				   arg, ret);
75583827f40a2d97261528087331b0bee6ce2cf27c5root
75683827f40a2d97261528087331b0bee6ce2cf27c5root	if (ret)
75783827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err2;
75883827f40a2d97261528087331b0bee6ce2cf27c5root
75983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->kBuf.gpuOffset = arg.rep.gpu_offset;
76083827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->kBuf.placement = arg.rep.placement;
76183827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->kBuf.handle = arg.rep.handle;
76283827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->mapHandle = arg.rep.map_handle;
76383827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->requestedSize = size;
76483827f40a2d97261528087331b0bee6ce2cf27c5root
76583827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->virtual = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED,
76683827f40a2d97261528087331b0bee6ce2cf27c5root			     pool->fd, sBuf->mapHandle);
76783827f40a2d97261528087331b0bee6ce2cf27c5root
76883827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->virtual == MAP_FAILED)
76983827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err3;
77083827f40a2d97261528087331b0bee6ce2cf27c5root    }
77183827f40a2d97261528087331b0bee6ce2cf27c5root
77283827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicSet(&sBuf->writers, 0);
77383827f40a2d97261528087331b0bee6ce2cf27c5root    return &sBuf->storage;
77483827f40a2d97261528087331b0bee6ce2cf27c5root  out_err3:
77583827f40a2d97261528087331b0bee6ce2cf27c5root    {
77683827f40a2d97261528087331b0bee6ce2cf27c5root	struct ttm_pl_reference_req arg;
77783827f40a2d97261528087331b0bee6ce2cf27c5root
77883827f40a2d97261528087331b0bee6ce2cf27c5root	arg.handle = sBuf->kBuf.handle;
77983827f40a2d97261528087331b0bee6ce2cf27c5root	(void)drmCommandWriteRead(pool->fd,
78083827f40a2d97261528087331b0bee6ce2cf27c5root				  slabPool->devOffset + TTM_PL_UNREF,
78183827f40a2d97261528087331b0bee6ce2cf27c5root				  &arg, sizeof(arg));
78283827f40a2d97261528087331b0bee6ce2cf27c5root    }
78383827f40a2d97261528087331b0bee6ce2cf27c5root  out_err2:
78483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_COND_FREE(&sBuf->event);
78583827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
78683827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmBufStorageTakedown(&sBuf->storage);
78783827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
78883827f40a2d97261528087331b0bee6ce2cf27c5root    free(sBuf);
78983827f40a2d97261528087331b0bee6ce2cf27c5root    return NULL;
79083827f40a2d97261528087331b0bee6ce2cf27c5root}
79183827f40a2d97261528087331b0bee6ce2cf27c5root
79283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
79383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_destroy(struct _WsbmBufStorage **p_buf)
79483827f40a2d97261528087331b0bee6ce2cf27c5root{
79583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufStorage *buf = *p_buf;
79683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
79783827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
79883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header;
79983827f40a2d97261528087331b0bee6ce2cf27c5root
80083827f40a2d97261528087331b0bee6ce2cf27c5root    *p_buf = NULL;
80183827f40a2d97261528087331b0bee6ce2cf27c5root
80283827f40a2d97261528087331b0bee6ce2cf27c5root    if (!sBuf->isSlabBuffer) {
80383827f40a2d97261528087331b0bee6ce2cf27c5root	struct _WsbmSlabPool *slabPool = slabPoolFromBuf(sBuf);
80483827f40a2d97261528087331b0bee6ce2cf27c5root	struct ttm_pl_reference_req arg;
80583827f40a2d97261528087331b0bee6ce2cf27c5root
80683827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->virtual != NULL) {
80783827f40a2d97261528087331b0bee6ce2cf27c5root	    (void)munmap(sBuf->virtual, sBuf->requestedSize);
80883827f40a2d97261528087331b0bee6ce2cf27c5root	    sBuf->virtual = NULL;
80983827f40a2d97261528087331b0bee6ce2cf27c5root	}
81083827f40a2d97261528087331b0bee6ce2cf27c5root
81183827f40a2d97261528087331b0bee6ce2cf27c5root	arg.handle = sBuf->kBuf.handle;
81283827f40a2d97261528087331b0bee6ce2cf27c5root	(void)drmCommandWrite(slabPool->pool.fd,
81383827f40a2d97261528087331b0bee6ce2cf27c5root			      slabPool->devOffset + TTM_PL_UNREF,
81483827f40a2d97261528087331b0bee6ce2cf27c5root			      &arg, sizeof(arg));
81583827f40a2d97261528087331b0bee6ce2cf27c5root
81683827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_FREE(&sBuf->event);
81783827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmBufStorageTakedown(&sBuf->storage);
81883827f40a2d97261528087331b0bee6ce2cf27c5root	free(sBuf);
81983827f40a2d97261528087331b0bee6ce2cf27c5root	return;
82083827f40a2d97261528087331b0bee6ce2cf27c5root    }
82183827f40a2d97261528087331b0bee6ce2cf27c5root
82283827f40a2d97261528087331b0bee6ce2cf27c5root    slab = sBuf->parent;
82383827f40a2d97261528087331b0bee6ce2cf27c5root    header = slab->header;
82483827f40a2d97261528087331b0bee6ce2cf27c5root
82583827f40a2d97261528087331b0bee6ce2cf27c5root    /*
82683827f40a2d97261528087331b0bee6ce2cf27c5root     * No need to take the buffer mutex below since we're the only user.
82783827f40a2d97261528087331b0bee6ce2cf27c5root     */
82883827f40a2d97261528087331b0bee6ce2cf27c5root
82983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
83083827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->unFenced = 0;
83183827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicSet(&sBuf->writers, 0);
83283827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicSet(&sBuf->storage.refCount, 1);
83383827f40a2d97261528087331b0bee6ce2cf27c5root
83483827f40a2d97261528087331b0bee6ce2cf27c5root    if (sBuf->fence && !wsbmFenceSignaledCached(sBuf->fence, sBuf->fenceType)) {
83583827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(&sBuf->head, &header->delayedBuffers);
83683827f40a2d97261528087331b0bee6ce2cf27c5root	header->numDelayed++;
83783827f40a2d97261528087331b0bee6ce2cf27c5root    } else {
83883827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->fence)
83983827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmFenceUnreference(&sBuf->fence);
84083827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmSlabFreeBufferLocked(sBuf);
84183827f40a2d97261528087331b0bee6ce2cf27c5root    }
84283827f40a2d97261528087331b0bee6ce2cf27c5root
84383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
84483827f40a2d97261528087331b0bee6ce2cf27c5root}
84583827f40a2d97261528087331b0bee6ce2cf27c5root
84683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
84783827f40a2d97261528087331b0bee6ce2cf27c5rootwaitIdleLocked(struct _WsbmSlabBuffer *sBuf, int lazy)
84883827f40a2d97261528087331b0bee6ce2cf27c5root{
84983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufStorage *storage = &sBuf->storage;
85083827f40a2d97261528087331b0bee6ce2cf27c5root
85183827f40a2d97261528087331b0bee6ce2cf27c5root    while (sBuf->unFenced || sBuf->fence != NULL) {
85283827f40a2d97261528087331b0bee6ce2cf27c5root
85383827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->unFenced)
85483827f40a2d97261528087331b0bee6ce2cf27c5root	    WSBM_COND_WAIT(&sBuf->event, &storage->mutex);
85583827f40a2d97261528087331b0bee6ce2cf27c5root
85683827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->fence != NULL) {
85783827f40a2d97261528087331b0bee6ce2cf27c5root	    if (!wsbmFenceSignaled(sBuf->fence, sBuf->fenceType)) {
85883827f40a2d97261528087331b0bee6ce2cf27c5root		struct _WsbmFenceObject *fence =
85983827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmFenceReference(sBuf->fence);
86083827f40a2d97261528087331b0bee6ce2cf27c5root
86183827f40a2d97261528087331b0bee6ce2cf27c5root		WSBM_MUTEX_UNLOCK(&storage->mutex);
86283827f40a2d97261528087331b0bee6ce2cf27c5root		(void)wsbmFenceFinish(fence, sBuf->fenceType, lazy);
86383827f40a2d97261528087331b0bee6ce2cf27c5root		WSBM_MUTEX_LOCK(&storage->mutex);
86483827f40a2d97261528087331b0bee6ce2cf27c5root		if (sBuf->fence == fence)
86583827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmFenceUnreference(&sBuf->fence);
86683827f40a2d97261528087331b0bee6ce2cf27c5root
86783827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceUnreference(&fence);
86883827f40a2d97261528087331b0bee6ce2cf27c5root	    } else {
86983827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceUnreference(&sBuf->fence);
87083827f40a2d97261528087331b0bee6ce2cf27c5root	    }
87183827f40a2d97261528087331b0bee6ce2cf27c5root	}
87283827f40a2d97261528087331b0bee6ce2cf27c5root    }
87383827f40a2d97261528087331b0bee6ce2cf27c5root}
87483827f40a2d97261528087331b0bee6ce2cf27c5root
87583827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
87683827f40a2d97261528087331b0bee6ce2cf27c5rootpool_waitIdle(struct _WsbmBufStorage *buf, int lazy)
87783827f40a2d97261528087331b0bee6ce2cf27c5root{
87883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
87983827f40a2d97261528087331b0bee6ce2cf27c5root
88083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
88183827f40a2d97261528087331b0bee6ce2cf27c5root    waitIdleLocked(sBuf, lazy);
88283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
88383827f40a2d97261528087331b0bee6ce2cf27c5root
88483827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
88583827f40a2d97261528087331b0bee6ce2cf27c5root}
88683827f40a2d97261528087331b0bee6ce2cf27c5root
88783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
8883795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudelpool_map(struct _WsbmBufStorage *buf, unsigned mode __attribute__ ((unused)), void **virtual)
88983827f40a2d97261528087331b0bee6ce2cf27c5root{
89083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
89183827f40a2d97261528087331b0bee6ce2cf27c5root
89283827f40a2d97261528087331b0bee6ce2cf27c5root    *virtual = sBuf->virtual;
89383827f40a2d97261528087331b0bee6ce2cf27c5root
89483827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
89583827f40a2d97261528087331b0bee6ce2cf27c5root}
89683827f40a2d97261528087331b0bee6ce2cf27c5root
89783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
8983795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudelpool_releaseFromCpu(struct _WsbmBufStorage *buf, unsigned mode __attribute__ ((unused)))
89983827f40a2d97261528087331b0bee6ce2cf27c5root{
90083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
90183827f40a2d97261528087331b0bee6ce2cf27c5root
90283827f40a2d97261528087331b0bee6ce2cf27c5root    if (wsbmAtomicDecZero(&sBuf->writers))
90383827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_BROADCAST(&sBuf->event);
90483827f40a2d97261528087331b0bee6ce2cf27c5root}
90583827f40a2d97261528087331b0bee6ce2cf27c5root
90683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
90783827f40a2d97261528087331b0bee6ce2cf27c5rootpool_syncForCpu(struct _WsbmBufStorage *buf, unsigned mode)
90883827f40a2d97261528087331b0bee6ce2cf27c5root{
90983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
91083827f40a2d97261528087331b0bee6ce2cf27c5root    int ret = 0;
91183827f40a2d97261528087331b0bee6ce2cf27c5root
91283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
91383827f40a2d97261528087331b0bee6ce2cf27c5root    if ((mode & WSBM_SYNCCPU_DONT_BLOCK)) {
91483827f40a2d97261528087331b0bee6ce2cf27c5root	int signaled;
91583827f40a2d97261528087331b0bee6ce2cf27c5root
91683827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->unFenced) {
91783827f40a2d97261528087331b0bee6ce2cf27c5root	    ret = -EBUSY;
91883827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_unlock;
91983827f40a2d97261528087331b0bee6ce2cf27c5root	}
92083827f40a2d97261528087331b0bee6ce2cf27c5root
92183827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->isSlabBuffer)
92283827f40a2d97261528087331b0bee6ce2cf27c5root	    signaled = (sBuf->fence == NULL) ||
92383827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceSignaledCached(sBuf->fence, sBuf->fenceType);
92483827f40a2d97261528087331b0bee6ce2cf27c5root	else
92583827f40a2d97261528087331b0bee6ce2cf27c5root	    signaled = (sBuf->fence == NULL) ||
92683827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceSignaled(sBuf->fence, sBuf->fenceType);
92783827f40a2d97261528087331b0bee6ce2cf27c5root
92883827f40a2d97261528087331b0bee6ce2cf27c5root	ret = 0;
92983827f40a2d97261528087331b0bee6ce2cf27c5root	if (signaled) {
93083827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmFenceUnreference(&sBuf->fence);
93183827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmAtomicInc(&sBuf->writers);
93283827f40a2d97261528087331b0bee6ce2cf27c5root	} else
93383827f40a2d97261528087331b0bee6ce2cf27c5root	    ret = -EBUSY;
93483827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_unlock;
93583827f40a2d97261528087331b0bee6ce2cf27c5root    }
93683827f40a2d97261528087331b0bee6ce2cf27c5root    waitIdleLocked(sBuf, 0);
93783827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicInc(&sBuf->writers);
93883827f40a2d97261528087331b0bee6ce2cf27c5root  out_unlock:
93983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
94083827f40a2d97261528087331b0bee6ce2cf27c5root    return ret;
94183827f40a2d97261528087331b0bee6ce2cf27c5root}
94283827f40a2d97261528087331b0bee6ce2cf27c5root
94383827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
9443795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudelpool_unmap(struct _WsbmBufStorage *buf __attribute__ ((unused)))
94583827f40a2d97261528087331b0bee6ce2cf27c5root{
94683827f40a2d97261528087331b0bee6ce2cf27c5root    ;
94783827f40a2d97261528087331b0bee6ce2cf27c5root}
94883827f40a2d97261528087331b0bee6ce2cf27c5root
94983827f40a2d97261528087331b0bee6ce2cf27c5rootstatic unsigned long
95083827f40a2d97261528087331b0bee6ce2cf27c5rootpool_poolOffset(struct _WsbmBufStorage *buf)
95183827f40a2d97261528087331b0bee6ce2cf27c5root{
95283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
95383827f40a2d97261528087331b0bee6ce2cf27c5root
95483827f40a2d97261528087331b0bee6ce2cf27c5root    return sBuf->start;
95583827f40a2d97261528087331b0bee6ce2cf27c5root}
95683827f40a2d97261528087331b0bee6ce2cf27c5root
95783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic unsigned long
95883827f40a2d97261528087331b0bee6ce2cf27c5rootpool_size(struct _WsbmBufStorage *buf)
95983827f40a2d97261528087331b0bee6ce2cf27c5root{
96083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
96183827f40a2d97261528087331b0bee6ce2cf27c5root
96283827f40a2d97261528087331b0bee6ce2cf27c5root    if (!sBuf->isSlabBuffer)
96383827f40a2d97261528087331b0bee6ce2cf27c5root	return sBuf->requestedSize;
96483827f40a2d97261528087331b0bee6ce2cf27c5root
96583827f40a2d97261528087331b0bee6ce2cf27c5root    return sBuf->parent->header->bufSize;
96683827f40a2d97261528087331b0bee6ce2cf27c5root}
96783827f40a2d97261528087331b0bee6ce2cf27c5root
96883827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmKernelBuf *
96983827f40a2d97261528087331b0bee6ce2cf27c5rootpool_kernel(struct _WsbmBufStorage *buf)
97083827f40a2d97261528087331b0bee6ce2cf27c5root{
97183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
97283827f40a2d97261528087331b0bee6ce2cf27c5root
97383827f40a2d97261528087331b0bee6ce2cf27c5root    return (sBuf->isSlabBuffer) ? &sBuf->parent->kbo->kBuf : &sBuf->kBuf;
97483827f40a2d97261528087331b0bee6ce2cf27c5root}
97583827f40a2d97261528087331b0bee6ce2cf27c5root
97683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic unsigned long
97783827f40a2d97261528087331b0bee6ce2cf27c5rootpool_offset(struct _WsbmBufStorage *buf)
97883827f40a2d97261528087331b0bee6ce2cf27c5root{
97983827f40a2d97261528087331b0bee6ce2cf27c5root    return pool_kernel(buf)->gpuOffset + pool_poolOffset(buf);
98083827f40a2d97261528087331b0bee6ce2cf27c5root}
98183827f40a2d97261528087331b0bee6ce2cf27c5root
98283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
98383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_fence(struct _WsbmBufStorage *buf, struct _WsbmFenceObject *fence)
98483827f40a2d97261528087331b0bee6ce2cf27c5root{
98583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
98683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmKernelBuf *kBuf;
98783827f40a2d97261528087331b0bee6ce2cf27c5root
98883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
98983827f40a2d97261528087331b0bee6ce2cf27c5root    if (sBuf->fence)
99083827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmFenceUnreference(&sBuf->fence);
99183827f40a2d97261528087331b0bee6ce2cf27c5root
99283827f40a2d97261528087331b0bee6ce2cf27c5root    kBuf = pool_kernel(buf);
99383827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->fenceType = kBuf->fence_type_mask;
99483827f40a2d97261528087331b0bee6ce2cf27c5root    if (!wsbmFenceSignaledCached(fence, sBuf->fenceType))
99583827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->fence = wsbmFenceReference(fence);
99683827f40a2d97261528087331b0bee6ce2cf27c5root
99783827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->unFenced = 0;
99883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_COND_BROADCAST(&sBuf->event);
99983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
100083827f40a2d97261528087331b0bee6ce2cf27c5root}
100183827f40a2d97261528087331b0bee6ce2cf27c5root
100283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
100383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_validate(struct _WsbmBufStorage *buf,
10043795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel        uint64_t set_flags __attribute__ ((unused)), uint64_t clr_flags __attribute__ ((unused)))
100583827f40a2d97261528087331b0bee6ce2cf27c5root{
100683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
100783827f40a2d97261528087331b0bee6ce2cf27c5root
100883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
100983827f40a2d97261528087331b0bee6ce2cf27c5root    while (wsbmAtomicRead(&sBuf->writers) != 0) {
101083827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_WAIT(&sBuf->event, &buf->mutex);
101183827f40a2d97261528087331b0bee6ce2cf27c5root    }
101283827f40a2d97261528087331b0bee6ce2cf27c5root
101383827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->unFenced = 1;
101483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
101583827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
101683827f40a2d97261528087331b0bee6ce2cf27c5root}
101783827f40a2d97261528087331b0bee6ce2cf27c5root
101883827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
101983827f40a2d97261528087331b0bee6ce2cf27c5rootpool_unvalidate(struct _WsbmBufStorage *buf)
102083827f40a2d97261528087331b0bee6ce2cf27c5root{
102183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
102283827f40a2d97261528087331b0bee6ce2cf27c5root
102383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
102483827f40a2d97261528087331b0bee6ce2cf27c5root    if (sBuf->unFenced) {
102583827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->unFenced = 0;
102683827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_BROADCAST(&sBuf->event);
102783827f40a2d97261528087331b0bee6ce2cf27c5root    }
102883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
102983827f40a2d97261528087331b0bee6ce2cf27c5root}
103083827f40a2d97261528087331b0bee6ce2cf27c5root
103183827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabCache *
103283827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabCacheInit(uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec)
103383827f40a2d97261528087331b0bee6ce2cf27c5root{
103483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabCache *tmp;
103583827f40a2d97261528087331b0bee6ce2cf27c5root
103683827f40a2d97261528087331b0bee6ce2cf27c5root    tmp = calloc(1, sizeof(*tmp));
103783827f40a2d97261528087331b0bee6ce2cf27c5root    if (!tmp)
103883827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
103983827f40a2d97261528087331b0bee6ce2cf27c5root
104083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_INIT(&tmp->mutex);
104183827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&tmp->mutex);
104283827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->slabTimeout.tv_usec = slabTimeoutMsec * 1000;
104383827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->slabTimeout.tv_sec = tmp->slabTimeout.tv_usec / 1000000;
104483827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->slabTimeout.tv_usec -= tmp->slabTimeout.tv_sec * 1000000;
104583827f40a2d97261528087331b0bee6ce2cf27c5root
104683827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->checkInterval.tv_usec = checkIntervalMsec * 1000;
104783827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->checkInterval.tv_sec = tmp->checkInterval.tv_usec / 1000000;
104883827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->checkInterval.tv_usec -= tmp->checkInterval.tv_sec * 1000000;
104983827f40a2d97261528087331b0bee6ce2cf27c5root
105083827f40a2d97261528087331b0bee6ce2cf27c5root    gettimeofday(&tmp->nextCheck, NULL);
105183827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmTimeAdd(&tmp->nextCheck, &tmp->checkInterval);
105283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&tmp->timeoutList);
105383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&tmp->unCached);
105483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&tmp->cached);
105583827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&tmp->mutex);
105683827f40a2d97261528087331b0bee6ce2cf27c5root
105783827f40a2d97261528087331b0bee6ce2cf27c5root    return tmp;
105883827f40a2d97261528087331b0bee6ce2cf27c5root}
105983827f40a2d97261528087331b0bee6ce2cf27c5root
106083827f40a2d97261528087331b0bee6ce2cf27c5rootvoid
106183827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabCacheFinish(struct _WsbmSlabCache *cache)
106283827f40a2d97261528087331b0bee6ce2cf27c5root{
106383827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval time;
106483827f40a2d97261528087331b0bee6ce2cf27c5root
106583827f40a2d97261528087331b0bee6ce2cf27c5root    time = cache->nextCheck;
106683827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&cache->mutex);
106783827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmTimeAdd(&time, &cache->checkInterval);
106883827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmFreeTimeoutKBOsLocked(cache, &time);
106983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&cache->mutex);
107083827f40a2d97261528087331b0bee6ce2cf27c5root
107183827f40a2d97261528087331b0bee6ce2cf27c5root    assert(cache->timeoutList.next == &cache->timeoutList);
107283827f40a2d97261528087331b0bee6ce2cf27c5root    assert(cache->unCached.next == &cache->unCached);
107383827f40a2d97261528087331b0bee6ce2cf27c5root    assert(cache->cached.next == &cache->cached);
107483827f40a2d97261528087331b0bee6ce2cf27c5root
107583827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_FREE(&cache->mutex);
107683827f40a2d97261528087331b0bee6ce2cf27c5root    free(cache);
107783827f40a2d97261528087331b0bee6ce2cf27c5root}
107883827f40a2d97261528087331b0bee6ce2cf27c5root
107983827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
108083827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmInitSizeHeader(struct _WsbmSlabPool *slabPool, uint32_t size,
108183827f40a2d97261528087331b0bee6ce2cf27c5root		   struct _WsbmSlabSizeHeader *header)
108283827f40a2d97261528087331b0bee6ce2cf27c5root{
108383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_INIT(&header->mutex);
108483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
108583827f40a2d97261528087331b0bee6ce2cf27c5root
108683827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&header->slabs);
108783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&header->freeSlabs);
108883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&header->delayedBuffers);
108983827f40a2d97261528087331b0bee6ce2cf27c5root
109083827f40a2d97261528087331b0bee6ce2cf27c5root    header->numDelayed = 0;
109183827f40a2d97261528087331b0bee6ce2cf27c5root    header->slabPool = slabPool;
109283827f40a2d97261528087331b0bee6ce2cf27c5root    header->bufSize = size;
109383827f40a2d97261528087331b0bee6ce2cf27c5root
109483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
109583827f40a2d97261528087331b0bee6ce2cf27c5root}
109683827f40a2d97261528087331b0bee6ce2cf27c5root
109783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
109883827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmFinishSizeHeader(struct _WsbmSlabSizeHeader *header)
109983827f40a2d97261528087331b0bee6ce2cf27c5root{
110083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list, *next;
110183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
110283827f40a2d97261528087331b0bee6ce2cf27c5root
110383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
110483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTFOREACHSAFE(list, next, &header->delayedBuffers) {
110583827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf = WSBMLISTENTRY(list, struct _WsbmSlabBuffer, head);
110683827f40a2d97261528087331b0bee6ce2cf27c5root
110783827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->fence) {
110883827f40a2d97261528087331b0bee6ce2cf27c5root	    (void)wsbmFenceFinish(sBuf->fence, sBuf->fenceType, 0);
110983827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmFenceUnreference(&sBuf->fence);
111083827f40a2d97261528087331b0bee6ce2cf27c5root	}
111183827f40a2d97261528087331b0bee6ce2cf27c5root	header->numDelayed--;
111283827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmSlabFreeBufferLocked(sBuf);
111383827f40a2d97261528087331b0bee6ce2cf27c5root    }
111483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
111583827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_FREE(&header->mutex);
111683827f40a2d97261528087331b0bee6ce2cf27c5root}
111783827f40a2d97261528087331b0bee6ce2cf27c5root
111883827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
111983827f40a2d97261528087331b0bee6ce2cf27c5rootpool_takedown(struct _WsbmBufferPool *pool)
112083827f40a2d97261528087331b0bee6ce2cf27c5root{
112183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool = slabPoolFromPool(pool);
11223795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    unsigned int i;
112383827f40a2d97261528087331b0bee6ce2cf27c5root
112483827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < slabPool->numBuckets; ++i) {
112583827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmFinishSizeHeader(&slabPool->headers[i]);
112683827f40a2d97261528087331b0bee6ce2cf27c5root    }
112783827f40a2d97261528087331b0bee6ce2cf27c5root
112883827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool->headers);
112983827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool->bucketSizes);
113083827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool);
113183827f40a2d97261528087331b0bee6ce2cf27c5root}
113283827f40a2d97261528087331b0bee6ce2cf27c5root
113383827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmBufferPool *
113483827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabPoolInit(int fd,
113583827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t devOffset,
113683827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t placement,
113783827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t validMask,
113883827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t smallestSize,
113983827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t numSizes,
114083827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t desiredNumBuffers,
114183827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t maxSlabSize,
114283827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t pageAlignment, struct _WsbmSlabCache *cache)
114383827f40a2d97261528087331b0bee6ce2cf27c5root{
114483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufferPool *pool;
114583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool;
114683827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t i;
114783827f40a2d97261528087331b0bee6ce2cf27c5root
114883827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool = calloc(1, sizeof(*slabPool));
114983827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slabPool)
115083827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
115183827f40a2d97261528087331b0bee6ce2cf27c5root
115283827f40a2d97261528087331b0bee6ce2cf27c5root    pool = &slabPool->pool;
115383827f40a2d97261528087331b0bee6ce2cf27c5root
115483827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->bucketSizes = calloc(numSizes, sizeof(*slabPool->bucketSizes));
115583827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slabPool->bucketSizes)
115683827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err0;
115783827f40a2d97261528087331b0bee6ce2cf27c5root
115883827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->headers = calloc(numSizes, sizeof(*slabPool->headers));
115983827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slabPool->headers)
116083827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
116183827f40a2d97261528087331b0bee6ce2cf27c5root
116283827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->devOffset = devOffset;
116383827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->cache = cache;
116483827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->proposedPlacement = placement;
116583827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->validMask = validMask;
116683827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->numBuckets = numSizes;
116783827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->pageSize = getpagesize();
116883827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->pageAlignment = pageAlignment;
116983827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->maxSlabSize = maxSlabSize;
117083827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->desiredNumBuffers = desiredNumBuffers;
117183827f40a2d97261528087331b0bee6ce2cf27c5root
117283827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < slabPool->numBuckets; ++i) {
117383827f40a2d97261528087331b0bee6ce2cf27c5root	slabPool->bucketSizes[i] = (smallestSize << i);
117483827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmInitSizeHeader(slabPool, slabPool->bucketSizes[i],
117583827f40a2d97261528087331b0bee6ce2cf27c5root			   &slabPool->headers[i]);
117683827f40a2d97261528087331b0bee6ce2cf27c5root    }
117783827f40a2d97261528087331b0bee6ce2cf27c5root
117883827f40a2d97261528087331b0bee6ce2cf27c5root    pool->fd = fd;
117983827f40a2d97261528087331b0bee6ce2cf27c5root    pool->map = &pool_map;
118083827f40a2d97261528087331b0bee6ce2cf27c5root    pool->unmap = &pool_unmap;
118183827f40a2d97261528087331b0bee6ce2cf27c5root    pool->destroy = &pool_destroy;
118283827f40a2d97261528087331b0bee6ce2cf27c5root    pool->offset = &pool_offset;
118383827f40a2d97261528087331b0bee6ce2cf27c5root    pool->poolOffset = &pool_poolOffset;
118483827f40a2d97261528087331b0bee6ce2cf27c5root    pool->size = &pool_size;
118583827f40a2d97261528087331b0bee6ce2cf27c5root    pool->create = &pool_create;
118683827f40a2d97261528087331b0bee6ce2cf27c5root    pool->fence = &pool_fence;
118783827f40a2d97261528087331b0bee6ce2cf27c5root    pool->kernel = &pool_kernel;
118883827f40a2d97261528087331b0bee6ce2cf27c5root    pool->validate = &pool_validate;
118983827f40a2d97261528087331b0bee6ce2cf27c5root    pool->unvalidate = &pool_unvalidate;
119083827f40a2d97261528087331b0bee6ce2cf27c5root    pool->waitIdle = &pool_waitIdle;
119183827f40a2d97261528087331b0bee6ce2cf27c5root    pool->takeDown = &pool_takedown;
119283827f40a2d97261528087331b0bee6ce2cf27c5root    pool->releasefromcpu = &pool_releaseFromCpu;
119383827f40a2d97261528087331b0bee6ce2cf27c5root    pool->syncforcpu = &pool_syncForCpu;
119483827f40a2d97261528087331b0bee6ce2cf27c5root
119583827f40a2d97261528087331b0bee6ce2cf27c5root    return pool;
119683827f40a2d97261528087331b0bee6ce2cf27c5root
119783827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
119883827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool->bucketSizes);
119983827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
120083827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool);
120183827f40a2d97261528087331b0bee6ce2cf27c5root
120283827f40a2d97261528087331b0bee6ce2cf27c5root    return NULL;
120383827f40a2d97261528087331b0bee6ce2cf27c5root}
1204