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;
466ba6cd22cc9dbadb14dad331ef6ddc8b1e403a654Austin Hu    if (!numBuffers) {
467ba6cd22cc9dbadb14dad331ef6ddc8b1e403a654Austin Hu        ret = -ENOMEM;
468ba6cd22cc9dbadb14dad331ef6ddc8b1e403a654Austin Hu        goto out_err1;
469ba6cd22cc9dbadb14dad331ef6ddc8b1e403a654Austin Hu    }
47083827f40a2d97261528087331b0bee6ce2cf27c5root
47183827f40a2d97261528087331b0bee6ce2cf27c5root    slab->buffers = calloc(numBuffers, sizeof(*slab->buffers));
47283827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slab->buffers) {
47383827f40a2d97261528087331b0bee6ce2cf27c5root	ret = -ENOMEM;
47483827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
47583827f40a2d97261528087331b0bee6ce2cf27c5root    }
47683827f40a2d97261528087331b0bee6ce2cf27c5root
47783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&slab->head);
47883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&slab->freeBuffers);
47983827f40a2d97261528087331b0bee6ce2cf27c5root    slab->numBuffers = numBuffers;
48083827f40a2d97261528087331b0bee6ce2cf27c5root    slab->numFree = 0;
48183827f40a2d97261528087331b0bee6ce2cf27c5root    slab->header = header;
48283827f40a2d97261528087331b0bee6ce2cf27c5root
48383827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf = slab->buffers;
48483827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < numBuffers; ++i) {
48583827f40a2d97261528087331b0bee6ce2cf27c5root	ret = wsbmBufStorageInit(&sBuf->storage, &header->slabPool->pool);
48683827f40a2d97261528087331b0bee6ce2cf27c5root	if (ret)
48783827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err2;
48883827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->parent = slab;
48983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->start = i * header->bufSize;
49083827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->virtual = (void *)((uint8_t *) slab->kbo->virtual +
49183827f40a2d97261528087331b0bee6ce2cf27c5root				 sBuf->start);
49283827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmAtomicSet(&sBuf->writers, 0);
49383827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->isSlabBuffer = 1;
49483827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_INIT(&sBuf->event);
49583827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(&sBuf->head, &slab->freeBuffers);
49683827f40a2d97261528087331b0bee6ce2cf27c5root	slab->numFree++;
49783827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf++;
49883827f40a2d97261528087331b0bee6ce2cf27c5root    }
49983827f40a2d97261528087331b0bee6ce2cf27c5root
50083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTADDTAIL(&slab->head, &header->slabs);
50183827f40a2d97261528087331b0bee6ce2cf27c5root
50283827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
50383827f40a2d97261528087331b0bee6ce2cf27c5root
50483827f40a2d97261528087331b0bee6ce2cf27c5root  out_err2:
50583827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf = slab->buffers;
50683827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < numBuffers; ++i) {
50783827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->parent == slab) {
50883827f40a2d97261528087331b0bee6ce2cf27c5root	    WSBM_COND_FREE(&sBuf->event);
50983827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmBufStorageTakedown(&sBuf->storage);
51083827f40a2d97261528087331b0bee6ce2cf27c5root	}
51183827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf++;
51283827f40a2d97261528087331b0bee6ce2cf27c5root    }
51383827f40a2d97261528087331b0bee6ce2cf27c5root    free(slab->buffers);
51483827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
51583827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmSetKernelBOFree(header->slabPool->cache, slab->kbo);
51683827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
51783827f40a2d97261528087331b0bee6ce2cf27c5root    free(slab);
51883827f40a2d97261528087331b0bee6ce2cf27c5root    return ret;
51983827f40a2d97261528087331b0bee6ce2cf27c5root}
52083827f40a2d97261528087331b0bee6ce2cf27c5root
52183827f40a2d97261528087331b0bee6ce2cf27c5root/*
52283827f40a2d97261528087331b0bee6ce2cf27c5root * Delete a buffer from the slab header delayed list and put
52383827f40a2d97261528087331b0bee6ce2cf27c5root * it on the slab free list.
52483827f40a2d97261528087331b0bee6ce2cf27c5root */
52583827f40a2d97261528087331b0bee6ce2cf27c5root
52683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
52783827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabFreeBufferLocked(struct _WsbmSlabBuffer *buf)
52883827f40a2d97261528087331b0bee6ce2cf27c5root{
52983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab = buf->parent;
53083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header = slab->header;
53183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list = &buf->head;
53283827f40a2d97261528087331b0bee6ce2cf27c5root
53383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTDEL(list);
53483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTADDTAIL(list, &slab->freeBuffers);
53583827f40a2d97261528087331b0bee6ce2cf27c5root    slab->numFree++;
53683827f40a2d97261528087331b0bee6ce2cf27c5root
53783827f40a2d97261528087331b0bee6ce2cf27c5root    if (slab->head.next == &slab->head)
53883827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(&slab->head, &header->slabs);
53983827f40a2d97261528087331b0bee6ce2cf27c5root
54083827f40a2d97261528087331b0bee6ce2cf27c5root    if (slab->numFree == slab->numBuffers) {
54183827f40a2d97261528087331b0bee6ce2cf27c5root	list = &slab->head;
54283827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDEL(list);
54383827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(list, &header->freeSlabs);
54483827f40a2d97261528087331b0bee6ce2cf27c5root    }
54583827f40a2d97261528087331b0bee6ce2cf27c5root
54683827f40a2d97261528087331b0bee6ce2cf27c5root    if (header->slabs.next == &header->slabs ||
54783827f40a2d97261528087331b0bee6ce2cf27c5root	slab->numFree != slab->numBuffers) {
54883827f40a2d97261528087331b0bee6ce2cf27c5root
54983827f40a2d97261528087331b0bee6ce2cf27c5root	struct _WsbmListHead *next;
55083827f40a2d97261528087331b0bee6ce2cf27c5root	struct _WsbmSlabCache *cache = header->slabPool->cache;
55183827f40a2d97261528087331b0bee6ce2cf27c5root
55283827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTFOREACHSAFE(list, next, &header->freeSlabs) {
5533795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel	    uint32_t i;
55483827f40a2d97261528087331b0bee6ce2cf27c5root	    struct _WsbmSlabBuffer *sBuf;
55583827f40a2d97261528087331b0bee6ce2cf27c5root
55683827f40a2d97261528087331b0bee6ce2cf27c5root	    slab = WSBMLISTENTRY(list, struct _WsbmSlab, head);
55783827f40a2d97261528087331b0bee6ce2cf27c5root
55883827f40a2d97261528087331b0bee6ce2cf27c5root	    WSBMLISTDELINIT(list);
55983827f40a2d97261528087331b0bee6ce2cf27c5root
56083827f40a2d97261528087331b0bee6ce2cf27c5root	    sBuf = slab->buffers;
56183827f40a2d97261528087331b0bee6ce2cf27c5root	    for (i = 0; i < slab->numBuffers; ++i) {
56283827f40a2d97261528087331b0bee6ce2cf27c5root		if (sBuf->parent == slab) {
56383827f40a2d97261528087331b0bee6ce2cf27c5root		    WSBM_COND_FREE(&sBuf->event);
56483827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmBufStorageTakedown(&sBuf->storage);
56583827f40a2d97261528087331b0bee6ce2cf27c5root		}
56683827f40a2d97261528087331b0bee6ce2cf27c5root		sBuf++;
56783827f40a2d97261528087331b0bee6ce2cf27c5root	    }
56883827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmSetKernelBOFree(cache, slab->kbo);
56983827f40a2d97261528087331b0bee6ce2cf27c5root	    free(slab->buffers);
57083827f40a2d97261528087331b0bee6ce2cf27c5root	    free(slab);
57183827f40a2d97261528087331b0bee6ce2cf27c5root	}
57283827f40a2d97261528087331b0bee6ce2cf27c5root    }
57383827f40a2d97261528087331b0bee6ce2cf27c5root}
57483827f40a2d97261528087331b0bee6ce2cf27c5root
57583827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
57683827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabCheckFreeLocked(struct _WsbmSlabSizeHeader *header, int wait)
57783827f40a2d97261528087331b0bee6ce2cf27c5root{
57883827f40a2d97261528087331b0bee6ce2cf27c5root  struct _WsbmListHead *list, *prev, *first, *head;
57983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
58083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
58183827f40a2d97261528087331b0bee6ce2cf27c5root    int firstWasSignaled = 1;
58283827f40a2d97261528087331b0bee6ce2cf27c5root    int signaled;
5833795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    uint32_t i;
58483827f40a2d97261528087331b0bee6ce2cf27c5root    int ret;
58583827f40a2d97261528087331b0bee6ce2cf27c5root
58683827f40a2d97261528087331b0bee6ce2cf27c5root    /*
58783827f40a2d97261528087331b0bee6ce2cf27c5root     * Rerun the freeing test if the youngest tested buffer
58883827f40a2d97261528087331b0bee6ce2cf27c5root     * was signaled, since there might be more idle buffers
58983827f40a2d97261528087331b0bee6ce2cf27c5root     * in the delay list.
59083827f40a2d97261528087331b0bee6ce2cf27c5root     */
59183827f40a2d97261528087331b0bee6ce2cf27c5root
59283827f40a2d97261528087331b0bee6ce2cf27c5root    while (firstWasSignaled) {
59383827f40a2d97261528087331b0bee6ce2cf27c5root	firstWasSignaled = 0;
59483827f40a2d97261528087331b0bee6ce2cf27c5root	signaled = 0;
59583827f40a2d97261528087331b0bee6ce2cf27c5root	first = header->delayedBuffers.next;
59683827f40a2d97261528087331b0bee6ce2cf27c5root
59783827f40a2d97261528087331b0bee6ce2cf27c5root	/* Only examine the oldest 1/3 of delayed buffers:
59883827f40a2d97261528087331b0bee6ce2cf27c5root	 */
59983827f40a2d97261528087331b0bee6ce2cf27c5root	if (header->numDelayed > 3) {
60083827f40a2d97261528087331b0bee6ce2cf27c5root	    for (i = 0; i < header->numDelayed; i += 3) {
60183827f40a2d97261528087331b0bee6ce2cf27c5root		first = first->next;
60283827f40a2d97261528087331b0bee6ce2cf27c5root	    }
60383827f40a2d97261528087331b0bee6ce2cf27c5root	}
60483827f40a2d97261528087331b0bee6ce2cf27c5root
60583827f40a2d97261528087331b0bee6ce2cf27c5root	/*
60683827f40a2d97261528087331b0bee6ce2cf27c5root	 * No need to take the buffer mutex for each buffer we loop
60783827f40a2d97261528087331b0bee6ce2cf27c5root	 * through since we're currently the only user.
60883827f40a2d97261528087331b0bee6ce2cf27c5root	 */
60983827f40a2d97261528087331b0bee6ce2cf27c5root
61083827f40a2d97261528087331b0bee6ce2cf27c5root	head = first->next;
61183827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTFOREACHPREVSAFE(list, prev, head) {
61283827f40a2d97261528087331b0bee6ce2cf27c5root
61383827f40a2d97261528087331b0bee6ce2cf27c5root	    if (list == &header->delayedBuffers)
61483827f40a2d97261528087331b0bee6ce2cf27c5root		break;
61583827f40a2d97261528087331b0bee6ce2cf27c5root
61683827f40a2d97261528087331b0bee6ce2cf27c5root	    sBuf = WSBMLISTENTRY(list, struct _WsbmSlabBuffer, head);
61783827f40a2d97261528087331b0bee6ce2cf27c5root
61883827f40a2d97261528087331b0bee6ce2cf27c5root	    slab = sBuf->parent;
61983827f40a2d97261528087331b0bee6ce2cf27c5root
62083827f40a2d97261528087331b0bee6ce2cf27c5root	    if (!signaled) {
62183827f40a2d97261528087331b0bee6ce2cf27c5root		if (wait) {
62283827f40a2d97261528087331b0bee6ce2cf27c5root		    ret = wsbmFenceFinish(sBuf->fence, sBuf->fenceType, 0);
62383827f40a2d97261528087331b0bee6ce2cf27c5root		    if (ret)
62483827f40a2d97261528087331b0bee6ce2cf27c5root			break;
62583827f40a2d97261528087331b0bee6ce2cf27c5root		    signaled = 1;
62683827f40a2d97261528087331b0bee6ce2cf27c5root		    wait = 0;
62783827f40a2d97261528087331b0bee6ce2cf27c5root		} else {
62883827f40a2d97261528087331b0bee6ce2cf27c5root		    signaled =
62983827f40a2d97261528087331b0bee6ce2cf27c5root			wsbmFenceSignaled(sBuf->fence, sBuf->fenceType);
63083827f40a2d97261528087331b0bee6ce2cf27c5root#ifdef DEBUG_FENCESIGNALED
63183827f40a2d97261528087331b0bee6ce2cf27c5root		    fencesignaled++;
63283827f40a2d97261528087331b0bee6ce2cf27c5root#endif
63383827f40a2d97261528087331b0bee6ce2cf27c5root		}
63483827f40a2d97261528087331b0bee6ce2cf27c5root		if (signaled) {
63583827f40a2d97261528087331b0bee6ce2cf27c5root		    if (list == first)
63683827f40a2d97261528087331b0bee6ce2cf27c5root			firstWasSignaled = 1;
63783827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmFenceUnreference(&sBuf->fence);
63883827f40a2d97261528087331b0bee6ce2cf27c5root		    header->numDelayed--;
63983827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmSlabFreeBufferLocked(sBuf);
64083827f40a2d97261528087331b0bee6ce2cf27c5root		} else
64183827f40a2d97261528087331b0bee6ce2cf27c5root		    break;
64283827f40a2d97261528087331b0bee6ce2cf27c5root	    } else if (wsbmFenceSignaledCached(sBuf->fence, sBuf->fenceType)) {
64383827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceUnreference(&sBuf->fence);
64483827f40a2d97261528087331b0bee6ce2cf27c5root		header->numDelayed--;
64583827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmSlabFreeBufferLocked(sBuf);
64683827f40a2d97261528087331b0bee6ce2cf27c5root	    }
64783827f40a2d97261528087331b0bee6ce2cf27c5root	}
64883827f40a2d97261528087331b0bee6ce2cf27c5root    }
64983827f40a2d97261528087331b0bee6ce2cf27c5root}
65083827f40a2d97261528087331b0bee6ce2cf27c5root
65183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmSlabBuffer *
65283827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabAllocBuffer(struct _WsbmSlabSizeHeader *header)
65383827f40a2d97261528087331b0bee6ce2cf27c5root{
65483827f40a2d97261528087331b0bee6ce2cf27c5root    static struct _WsbmSlabBuffer *buf;
65583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
65683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list;
65783827f40a2d97261528087331b0bee6ce2cf27c5root    int count = WSBM_SLABPOOL_ALLOC_RETRIES;
65883827f40a2d97261528087331b0bee6ce2cf27c5root
65983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
66083827f40a2d97261528087331b0bee6ce2cf27c5root    while (header->slabs.next == &header->slabs && count > 0) {
66183827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmSlabCheckFreeLocked(header, 0);
66283827f40a2d97261528087331b0bee6ce2cf27c5root	if (header->slabs.next != &header->slabs)
66383827f40a2d97261528087331b0bee6ce2cf27c5root	    break;
66483827f40a2d97261528087331b0bee6ce2cf27c5root
66583827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_MUTEX_UNLOCK(&header->mutex);
66683827f40a2d97261528087331b0bee6ce2cf27c5root	if (count != WSBM_SLABPOOL_ALLOC_RETRIES)
66783827f40a2d97261528087331b0bee6ce2cf27c5root	    usleep(1000);
66883827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_MUTEX_LOCK(&header->mutex);
66983827f40a2d97261528087331b0bee6ce2cf27c5root	(void)wsbmAllocSlab(header);
67083827f40a2d97261528087331b0bee6ce2cf27c5root	count--;
67183827f40a2d97261528087331b0bee6ce2cf27c5root    }
67283827f40a2d97261528087331b0bee6ce2cf27c5root
67383827f40a2d97261528087331b0bee6ce2cf27c5root    list = header->slabs.next;
67483827f40a2d97261528087331b0bee6ce2cf27c5root    if (list == &header->slabs) {
67583827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_MUTEX_UNLOCK(&header->mutex);
67683827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
67783827f40a2d97261528087331b0bee6ce2cf27c5root    }
67883827f40a2d97261528087331b0bee6ce2cf27c5root    slab = WSBMLISTENTRY(list, struct _WsbmSlab, head);
67983827f40a2d97261528087331b0bee6ce2cf27c5root    if (--slab->numFree == 0)
68083827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTDELINIT(list);
68183827f40a2d97261528087331b0bee6ce2cf27c5root
68283827f40a2d97261528087331b0bee6ce2cf27c5root    list = slab->freeBuffers.next;
68383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTDELINIT(list);
68483827f40a2d97261528087331b0bee6ce2cf27c5root
68583827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
68683827f40a2d97261528087331b0bee6ce2cf27c5root    buf = WSBMLISTENTRY(list, struct _WsbmSlabBuffer, head);
68783827f40a2d97261528087331b0bee6ce2cf27c5root
68883827f40a2d97261528087331b0bee6ce2cf27c5root    buf->storage.destroyContainer = NULL;
68983827f40a2d97261528087331b0bee6ce2cf27c5root
69083827f40a2d97261528087331b0bee6ce2cf27c5root#ifdef DEBUG_FENCESIGNALED
69183827f40a2d97261528087331b0bee6ce2cf27c5root    createbuffer++;
69283827f40a2d97261528087331b0bee6ce2cf27c5root#endif
69383827f40a2d97261528087331b0bee6ce2cf27c5root    return buf;
69483827f40a2d97261528087331b0bee6ce2cf27c5root}
69583827f40a2d97261528087331b0bee6ce2cf27c5root
69683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmBufStorage *
69783827f40a2d97261528087331b0bee6ce2cf27c5rootpool_create(struct _WsbmBufferPool *pool, unsigned long size,
69883827f40a2d97261528087331b0bee6ce2cf27c5root	    uint32_t placement, unsigned alignment)
69983827f40a2d97261528087331b0bee6ce2cf27c5root{
70083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool = slabPoolFromPool(pool);
70183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header;
70283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
7033795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    uint32_t i;
70483827f40a2d97261528087331b0bee6ce2cf27c5root    int ret;
70583827f40a2d97261528087331b0bee6ce2cf27c5root
70683827f40a2d97261528087331b0bee6ce2cf27c5root    /*
70783827f40a2d97261528087331b0bee6ce2cf27c5root     * FIXME: Check for compatibility.
70883827f40a2d97261528087331b0bee6ce2cf27c5root     */
70983827f40a2d97261528087331b0bee6ce2cf27c5root
71083827f40a2d97261528087331b0bee6ce2cf27c5root    header = slabPool->headers;
71183827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < slabPool->numBuckets; ++i) {
71283827f40a2d97261528087331b0bee6ce2cf27c5root	if (header->bufSize >= size)
71383827f40a2d97261528087331b0bee6ce2cf27c5root	    break;
71483827f40a2d97261528087331b0bee6ce2cf27c5root	header++;
71583827f40a2d97261528087331b0bee6ce2cf27c5root    }
71683827f40a2d97261528087331b0bee6ce2cf27c5root
71783827f40a2d97261528087331b0bee6ce2cf27c5root    if (i < slabPool->numBuckets) {
71883827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf = wsbmSlabAllocBuffer(header);
71983827f40a2d97261528087331b0bee6ce2cf27c5root	return ((sBuf) ? &sBuf->storage : NULL);
72083827f40a2d97261528087331b0bee6ce2cf27c5root    }
72183827f40a2d97261528087331b0bee6ce2cf27c5root
72283827f40a2d97261528087331b0bee6ce2cf27c5root    /*
72383827f40a2d97261528087331b0bee6ce2cf27c5root     * Fall back to allocate a buffer object directly from DRM.
72483827f40a2d97261528087331b0bee6ce2cf27c5root     * and wrap it in a wsbmBO structure.
72583827f40a2d97261528087331b0bee6ce2cf27c5root     */
72683827f40a2d97261528087331b0bee6ce2cf27c5root
72783827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf = calloc(1, sizeof(*sBuf));
72883827f40a2d97261528087331b0bee6ce2cf27c5root
72983827f40a2d97261528087331b0bee6ce2cf27c5root    if (!sBuf)
73083827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
73183827f40a2d97261528087331b0bee6ce2cf27c5root
73283827f40a2d97261528087331b0bee6ce2cf27c5root    if (alignment) {
73383827f40a2d97261528087331b0bee6ce2cf27c5root	if ((alignment < slabPool->pageSize)
73483827f40a2d97261528087331b0bee6ce2cf27c5root	    && (slabPool->pageSize % alignment))
73583827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err0;
73683827f40a2d97261528087331b0bee6ce2cf27c5root	if ((alignment > slabPool->pageSize)
73783827f40a2d97261528087331b0bee6ce2cf27c5root	    && (alignment % slabPool->pageSize))
73883827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err0;
73983827f40a2d97261528087331b0bee6ce2cf27c5root    }
74083827f40a2d97261528087331b0bee6ce2cf27c5root
74183827f40a2d97261528087331b0bee6ce2cf27c5root    ret = wsbmBufStorageInit(&sBuf->storage, pool);
74283827f40a2d97261528087331b0bee6ce2cf27c5root    if (ret)
74383827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err0;
74483827f40a2d97261528087331b0bee6ce2cf27c5root
74583827f40a2d97261528087331b0bee6ce2cf27c5root    ret = WSBM_COND_INIT(&sBuf->event);
74683827f40a2d97261528087331b0bee6ce2cf27c5root    if (ret)
74783827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
74883827f40a2d97261528087331b0bee6ce2cf27c5root
74983827f40a2d97261528087331b0bee6ce2cf27c5root    {
75083827f40a2d97261528087331b0bee6ce2cf27c5root	union ttm_pl_create_arg arg;
75183827f40a2d97261528087331b0bee6ce2cf27c5root
75283827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.size = size;
75383827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.placement = placement;
75483827f40a2d97261528087331b0bee6ce2cf27c5root	arg.req.page_alignment = alignment / slabPool->pageSize;
75583827f40a2d97261528087331b0bee6ce2cf27c5root
75683827f40a2d97261528087331b0bee6ce2cf27c5root	DRMRESTARTCOMMANDWRITEREAD(pool->fd,
75783827f40a2d97261528087331b0bee6ce2cf27c5root				   slabPool->devOffset + TTM_PL_CREATE,
75883827f40a2d97261528087331b0bee6ce2cf27c5root				   arg, ret);
75983827f40a2d97261528087331b0bee6ce2cf27c5root
76083827f40a2d97261528087331b0bee6ce2cf27c5root	if (ret)
76183827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err2;
76283827f40a2d97261528087331b0bee6ce2cf27c5root
76383827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->kBuf.gpuOffset = arg.rep.gpu_offset;
76483827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->kBuf.placement = arg.rep.placement;
76583827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->kBuf.handle = arg.rep.handle;
76683827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->mapHandle = arg.rep.map_handle;
76783827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->requestedSize = size;
76883827f40a2d97261528087331b0bee6ce2cf27c5root
76983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->virtual = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED,
77083827f40a2d97261528087331b0bee6ce2cf27c5root			     pool->fd, sBuf->mapHandle);
77183827f40a2d97261528087331b0bee6ce2cf27c5root
77283827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->virtual == MAP_FAILED)
77383827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_err3;
77483827f40a2d97261528087331b0bee6ce2cf27c5root    }
77583827f40a2d97261528087331b0bee6ce2cf27c5root
77683827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicSet(&sBuf->writers, 0);
77783827f40a2d97261528087331b0bee6ce2cf27c5root    return &sBuf->storage;
77883827f40a2d97261528087331b0bee6ce2cf27c5root  out_err3:
77983827f40a2d97261528087331b0bee6ce2cf27c5root    {
78083827f40a2d97261528087331b0bee6ce2cf27c5root	struct ttm_pl_reference_req arg;
78183827f40a2d97261528087331b0bee6ce2cf27c5root
78283827f40a2d97261528087331b0bee6ce2cf27c5root	arg.handle = sBuf->kBuf.handle;
78383827f40a2d97261528087331b0bee6ce2cf27c5root	(void)drmCommandWriteRead(pool->fd,
78483827f40a2d97261528087331b0bee6ce2cf27c5root				  slabPool->devOffset + TTM_PL_UNREF,
78583827f40a2d97261528087331b0bee6ce2cf27c5root				  &arg, sizeof(arg));
78683827f40a2d97261528087331b0bee6ce2cf27c5root    }
78783827f40a2d97261528087331b0bee6ce2cf27c5root  out_err2:
78883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_COND_FREE(&sBuf->event);
78983827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
79083827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmBufStorageTakedown(&sBuf->storage);
79183827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
79283827f40a2d97261528087331b0bee6ce2cf27c5root    free(sBuf);
79383827f40a2d97261528087331b0bee6ce2cf27c5root    return NULL;
79483827f40a2d97261528087331b0bee6ce2cf27c5root}
79583827f40a2d97261528087331b0bee6ce2cf27c5root
79683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
79783827f40a2d97261528087331b0bee6ce2cf27c5rootpool_destroy(struct _WsbmBufStorage **p_buf)
79883827f40a2d97261528087331b0bee6ce2cf27c5root{
79983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufStorage *buf = *p_buf;
80083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
80183827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlab *slab;
80283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabSizeHeader *header;
80383827f40a2d97261528087331b0bee6ce2cf27c5root
80483827f40a2d97261528087331b0bee6ce2cf27c5root    *p_buf = NULL;
80583827f40a2d97261528087331b0bee6ce2cf27c5root
80683827f40a2d97261528087331b0bee6ce2cf27c5root    if (!sBuf->isSlabBuffer) {
80783827f40a2d97261528087331b0bee6ce2cf27c5root	struct _WsbmSlabPool *slabPool = slabPoolFromBuf(sBuf);
80883827f40a2d97261528087331b0bee6ce2cf27c5root	struct ttm_pl_reference_req arg;
80983827f40a2d97261528087331b0bee6ce2cf27c5root
81083827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->virtual != NULL) {
81183827f40a2d97261528087331b0bee6ce2cf27c5root	    (void)munmap(sBuf->virtual, sBuf->requestedSize);
81283827f40a2d97261528087331b0bee6ce2cf27c5root	    sBuf->virtual = NULL;
81383827f40a2d97261528087331b0bee6ce2cf27c5root	}
81483827f40a2d97261528087331b0bee6ce2cf27c5root
81583827f40a2d97261528087331b0bee6ce2cf27c5root	arg.handle = sBuf->kBuf.handle;
81683827f40a2d97261528087331b0bee6ce2cf27c5root	(void)drmCommandWrite(slabPool->pool.fd,
81783827f40a2d97261528087331b0bee6ce2cf27c5root			      slabPool->devOffset + TTM_PL_UNREF,
81883827f40a2d97261528087331b0bee6ce2cf27c5root			      &arg, sizeof(arg));
81983827f40a2d97261528087331b0bee6ce2cf27c5root
82083827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_FREE(&sBuf->event);
82183827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmBufStorageTakedown(&sBuf->storage);
82283827f40a2d97261528087331b0bee6ce2cf27c5root	free(sBuf);
82383827f40a2d97261528087331b0bee6ce2cf27c5root	return;
82483827f40a2d97261528087331b0bee6ce2cf27c5root    }
82583827f40a2d97261528087331b0bee6ce2cf27c5root
82683827f40a2d97261528087331b0bee6ce2cf27c5root    slab = sBuf->parent;
82783827f40a2d97261528087331b0bee6ce2cf27c5root    header = slab->header;
82883827f40a2d97261528087331b0bee6ce2cf27c5root
82983827f40a2d97261528087331b0bee6ce2cf27c5root    /*
83083827f40a2d97261528087331b0bee6ce2cf27c5root     * No need to take the buffer mutex below since we're the only user.
83183827f40a2d97261528087331b0bee6ce2cf27c5root     */
83283827f40a2d97261528087331b0bee6ce2cf27c5root
83383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
83483827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->unFenced = 0;
83583827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicSet(&sBuf->writers, 0);
83683827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicSet(&sBuf->storage.refCount, 1);
83783827f40a2d97261528087331b0bee6ce2cf27c5root
83883827f40a2d97261528087331b0bee6ce2cf27c5root    if (sBuf->fence && !wsbmFenceSignaledCached(sBuf->fence, sBuf->fenceType)) {
83983827f40a2d97261528087331b0bee6ce2cf27c5root	WSBMLISTADDTAIL(&sBuf->head, &header->delayedBuffers);
84083827f40a2d97261528087331b0bee6ce2cf27c5root	header->numDelayed++;
84183827f40a2d97261528087331b0bee6ce2cf27c5root    } else {
84283827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->fence)
84383827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmFenceUnreference(&sBuf->fence);
84483827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmSlabFreeBufferLocked(sBuf);
84583827f40a2d97261528087331b0bee6ce2cf27c5root    }
84683827f40a2d97261528087331b0bee6ce2cf27c5root
84783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
84883827f40a2d97261528087331b0bee6ce2cf27c5root}
84983827f40a2d97261528087331b0bee6ce2cf27c5root
85083827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
85183827f40a2d97261528087331b0bee6ce2cf27c5rootwaitIdleLocked(struct _WsbmSlabBuffer *sBuf, int lazy)
85283827f40a2d97261528087331b0bee6ce2cf27c5root{
85383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufStorage *storage = &sBuf->storage;
85483827f40a2d97261528087331b0bee6ce2cf27c5root
85583827f40a2d97261528087331b0bee6ce2cf27c5root    while (sBuf->unFenced || sBuf->fence != NULL) {
85683827f40a2d97261528087331b0bee6ce2cf27c5root
85783827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->unFenced)
85883827f40a2d97261528087331b0bee6ce2cf27c5root	    WSBM_COND_WAIT(&sBuf->event, &storage->mutex);
85983827f40a2d97261528087331b0bee6ce2cf27c5root
86083827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->fence != NULL) {
86183827f40a2d97261528087331b0bee6ce2cf27c5root	    if (!wsbmFenceSignaled(sBuf->fence, sBuf->fenceType)) {
86283827f40a2d97261528087331b0bee6ce2cf27c5root		struct _WsbmFenceObject *fence =
86383827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmFenceReference(sBuf->fence);
86483827f40a2d97261528087331b0bee6ce2cf27c5root
86583827f40a2d97261528087331b0bee6ce2cf27c5root		WSBM_MUTEX_UNLOCK(&storage->mutex);
86683827f40a2d97261528087331b0bee6ce2cf27c5root		(void)wsbmFenceFinish(fence, sBuf->fenceType, lazy);
86783827f40a2d97261528087331b0bee6ce2cf27c5root		WSBM_MUTEX_LOCK(&storage->mutex);
86883827f40a2d97261528087331b0bee6ce2cf27c5root		if (sBuf->fence == fence)
86983827f40a2d97261528087331b0bee6ce2cf27c5root		    wsbmFenceUnreference(&sBuf->fence);
87083827f40a2d97261528087331b0bee6ce2cf27c5root
87183827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceUnreference(&fence);
87283827f40a2d97261528087331b0bee6ce2cf27c5root	    } else {
87383827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceUnreference(&sBuf->fence);
87483827f40a2d97261528087331b0bee6ce2cf27c5root	    }
87583827f40a2d97261528087331b0bee6ce2cf27c5root	}
87683827f40a2d97261528087331b0bee6ce2cf27c5root    }
87783827f40a2d97261528087331b0bee6ce2cf27c5root}
87883827f40a2d97261528087331b0bee6ce2cf27c5root
87983827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
88083827f40a2d97261528087331b0bee6ce2cf27c5rootpool_waitIdle(struct _WsbmBufStorage *buf, int lazy)
88183827f40a2d97261528087331b0bee6ce2cf27c5root{
88283827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
88383827f40a2d97261528087331b0bee6ce2cf27c5root
88483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
88583827f40a2d97261528087331b0bee6ce2cf27c5root    waitIdleLocked(sBuf, lazy);
88683827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
88783827f40a2d97261528087331b0bee6ce2cf27c5root
88883827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
88983827f40a2d97261528087331b0bee6ce2cf27c5root}
89083827f40a2d97261528087331b0bee6ce2cf27c5root
89183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
8923795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudelpool_map(struct _WsbmBufStorage *buf, unsigned mode __attribute__ ((unused)), void **virtual)
89383827f40a2d97261528087331b0bee6ce2cf27c5root{
89483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
89583827f40a2d97261528087331b0bee6ce2cf27c5root
89683827f40a2d97261528087331b0bee6ce2cf27c5root    *virtual = sBuf->virtual;
89783827f40a2d97261528087331b0bee6ce2cf27c5root
89883827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
89983827f40a2d97261528087331b0bee6ce2cf27c5root}
90083827f40a2d97261528087331b0bee6ce2cf27c5root
90183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
9023795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudelpool_releaseFromCpu(struct _WsbmBufStorage *buf, unsigned mode __attribute__ ((unused)))
90383827f40a2d97261528087331b0bee6ce2cf27c5root{
90483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
90583827f40a2d97261528087331b0bee6ce2cf27c5root
90683827f40a2d97261528087331b0bee6ce2cf27c5root    if (wsbmAtomicDecZero(&sBuf->writers))
90783827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_BROADCAST(&sBuf->event);
90883827f40a2d97261528087331b0bee6ce2cf27c5root}
90983827f40a2d97261528087331b0bee6ce2cf27c5root
91083827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
91183827f40a2d97261528087331b0bee6ce2cf27c5rootpool_syncForCpu(struct _WsbmBufStorage *buf, unsigned mode)
91283827f40a2d97261528087331b0bee6ce2cf27c5root{
91383827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
91483827f40a2d97261528087331b0bee6ce2cf27c5root    int ret = 0;
91583827f40a2d97261528087331b0bee6ce2cf27c5root
91683827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
91783827f40a2d97261528087331b0bee6ce2cf27c5root    if ((mode & WSBM_SYNCCPU_DONT_BLOCK)) {
91883827f40a2d97261528087331b0bee6ce2cf27c5root	int signaled;
91983827f40a2d97261528087331b0bee6ce2cf27c5root
92083827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->unFenced) {
92183827f40a2d97261528087331b0bee6ce2cf27c5root	    ret = -EBUSY;
92283827f40a2d97261528087331b0bee6ce2cf27c5root	    goto out_unlock;
92383827f40a2d97261528087331b0bee6ce2cf27c5root	}
92483827f40a2d97261528087331b0bee6ce2cf27c5root
92583827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->isSlabBuffer)
92683827f40a2d97261528087331b0bee6ce2cf27c5root	    signaled = (sBuf->fence == NULL) ||
92783827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceSignaledCached(sBuf->fence, sBuf->fenceType);
92883827f40a2d97261528087331b0bee6ce2cf27c5root	else
92983827f40a2d97261528087331b0bee6ce2cf27c5root	    signaled = (sBuf->fence == NULL) ||
93083827f40a2d97261528087331b0bee6ce2cf27c5root		wsbmFenceSignaled(sBuf->fence, sBuf->fenceType);
93183827f40a2d97261528087331b0bee6ce2cf27c5root
93283827f40a2d97261528087331b0bee6ce2cf27c5root	ret = 0;
93383827f40a2d97261528087331b0bee6ce2cf27c5root	if (signaled) {
93483827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmFenceUnreference(&sBuf->fence);
93583827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmAtomicInc(&sBuf->writers);
93683827f40a2d97261528087331b0bee6ce2cf27c5root	} else
93783827f40a2d97261528087331b0bee6ce2cf27c5root	    ret = -EBUSY;
93883827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_unlock;
93983827f40a2d97261528087331b0bee6ce2cf27c5root    }
94083827f40a2d97261528087331b0bee6ce2cf27c5root    waitIdleLocked(sBuf, 0);
94183827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmAtomicInc(&sBuf->writers);
94283827f40a2d97261528087331b0bee6ce2cf27c5root  out_unlock:
94383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
94483827f40a2d97261528087331b0bee6ce2cf27c5root    return ret;
94583827f40a2d97261528087331b0bee6ce2cf27c5root}
94683827f40a2d97261528087331b0bee6ce2cf27c5root
94783827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
9483795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudelpool_unmap(struct _WsbmBufStorage *buf __attribute__ ((unused)))
94983827f40a2d97261528087331b0bee6ce2cf27c5root{
95083827f40a2d97261528087331b0bee6ce2cf27c5root    ;
95183827f40a2d97261528087331b0bee6ce2cf27c5root}
95283827f40a2d97261528087331b0bee6ce2cf27c5root
95383827f40a2d97261528087331b0bee6ce2cf27c5rootstatic unsigned long
95483827f40a2d97261528087331b0bee6ce2cf27c5rootpool_poolOffset(struct _WsbmBufStorage *buf)
95583827f40a2d97261528087331b0bee6ce2cf27c5root{
95683827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
95783827f40a2d97261528087331b0bee6ce2cf27c5root
95883827f40a2d97261528087331b0bee6ce2cf27c5root    return sBuf->start;
95983827f40a2d97261528087331b0bee6ce2cf27c5root}
96083827f40a2d97261528087331b0bee6ce2cf27c5root
96183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic unsigned long
96283827f40a2d97261528087331b0bee6ce2cf27c5rootpool_size(struct _WsbmBufStorage *buf)
96383827f40a2d97261528087331b0bee6ce2cf27c5root{
96483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
96583827f40a2d97261528087331b0bee6ce2cf27c5root
96683827f40a2d97261528087331b0bee6ce2cf27c5root    if (!sBuf->isSlabBuffer)
96783827f40a2d97261528087331b0bee6ce2cf27c5root	return sBuf->requestedSize;
96883827f40a2d97261528087331b0bee6ce2cf27c5root
96983827f40a2d97261528087331b0bee6ce2cf27c5root    return sBuf->parent->header->bufSize;
97083827f40a2d97261528087331b0bee6ce2cf27c5root}
97183827f40a2d97261528087331b0bee6ce2cf27c5root
97283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic struct _WsbmKernelBuf *
97383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_kernel(struct _WsbmBufStorage *buf)
97483827f40a2d97261528087331b0bee6ce2cf27c5root{
97583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
97683827f40a2d97261528087331b0bee6ce2cf27c5root
97783827f40a2d97261528087331b0bee6ce2cf27c5root    return (sBuf->isSlabBuffer) ? &sBuf->parent->kbo->kBuf : &sBuf->kBuf;
97883827f40a2d97261528087331b0bee6ce2cf27c5root}
97983827f40a2d97261528087331b0bee6ce2cf27c5root
98083827f40a2d97261528087331b0bee6ce2cf27c5rootstatic unsigned long
98183827f40a2d97261528087331b0bee6ce2cf27c5rootpool_offset(struct _WsbmBufStorage *buf)
98283827f40a2d97261528087331b0bee6ce2cf27c5root{
98383827f40a2d97261528087331b0bee6ce2cf27c5root    return pool_kernel(buf)->gpuOffset + pool_poolOffset(buf);
98483827f40a2d97261528087331b0bee6ce2cf27c5root}
98583827f40a2d97261528087331b0bee6ce2cf27c5root
98683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
98783827f40a2d97261528087331b0bee6ce2cf27c5rootpool_fence(struct _WsbmBufStorage *buf, struct _WsbmFenceObject *fence)
98883827f40a2d97261528087331b0bee6ce2cf27c5root{
98983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
99083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmKernelBuf *kBuf;
99183827f40a2d97261528087331b0bee6ce2cf27c5root
99283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
99383827f40a2d97261528087331b0bee6ce2cf27c5root    if (sBuf->fence)
99483827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmFenceUnreference(&sBuf->fence);
99583827f40a2d97261528087331b0bee6ce2cf27c5root
99683827f40a2d97261528087331b0bee6ce2cf27c5root    kBuf = pool_kernel(buf);
99783827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->fenceType = kBuf->fence_type_mask;
99883827f40a2d97261528087331b0bee6ce2cf27c5root    if (!wsbmFenceSignaledCached(fence, sBuf->fenceType))
99983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->fence = wsbmFenceReference(fence);
100083827f40a2d97261528087331b0bee6ce2cf27c5root
100183827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->unFenced = 0;
100283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_COND_BROADCAST(&sBuf->event);
100383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
100483827f40a2d97261528087331b0bee6ce2cf27c5root}
100583827f40a2d97261528087331b0bee6ce2cf27c5root
100683827f40a2d97261528087331b0bee6ce2cf27c5rootstatic int
100783827f40a2d97261528087331b0bee6ce2cf27c5rootpool_validate(struct _WsbmBufStorage *buf,
10083795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel        uint64_t set_flags __attribute__ ((unused)), uint64_t clr_flags __attribute__ ((unused)))
100983827f40a2d97261528087331b0bee6ce2cf27c5root{
101083827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
101183827f40a2d97261528087331b0bee6ce2cf27c5root
101283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
101383827f40a2d97261528087331b0bee6ce2cf27c5root    while (wsbmAtomicRead(&sBuf->writers) != 0) {
101483827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_WAIT(&sBuf->event, &buf->mutex);
101583827f40a2d97261528087331b0bee6ce2cf27c5root    }
101683827f40a2d97261528087331b0bee6ce2cf27c5root
101783827f40a2d97261528087331b0bee6ce2cf27c5root    sBuf->unFenced = 1;
101883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
101983827f40a2d97261528087331b0bee6ce2cf27c5root    return 0;
102083827f40a2d97261528087331b0bee6ce2cf27c5root}
102183827f40a2d97261528087331b0bee6ce2cf27c5root
102283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
102383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_unvalidate(struct _WsbmBufStorage *buf)
102483827f40a2d97261528087331b0bee6ce2cf27c5root{
102583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf = slabBuffer(buf);
102683827f40a2d97261528087331b0bee6ce2cf27c5root
102783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&buf->mutex);
102883827f40a2d97261528087331b0bee6ce2cf27c5root    if (sBuf->unFenced) {
102983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf->unFenced = 0;
103083827f40a2d97261528087331b0bee6ce2cf27c5root	WSBM_COND_BROADCAST(&sBuf->event);
103183827f40a2d97261528087331b0bee6ce2cf27c5root    }
103283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&buf->mutex);
103383827f40a2d97261528087331b0bee6ce2cf27c5root}
103483827f40a2d97261528087331b0bee6ce2cf27c5root
103583827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmSlabCache *
103683827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabCacheInit(uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec)
103783827f40a2d97261528087331b0bee6ce2cf27c5root{
103883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabCache *tmp;
103983827f40a2d97261528087331b0bee6ce2cf27c5root
104083827f40a2d97261528087331b0bee6ce2cf27c5root    tmp = calloc(1, sizeof(*tmp));
104183827f40a2d97261528087331b0bee6ce2cf27c5root    if (!tmp)
104283827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
104383827f40a2d97261528087331b0bee6ce2cf27c5root
104483827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_INIT(&tmp->mutex);
104583827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&tmp->mutex);
104683827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->slabTimeout.tv_usec = slabTimeoutMsec * 1000;
104783827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->slabTimeout.tv_sec = tmp->slabTimeout.tv_usec / 1000000;
104883827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->slabTimeout.tv_usec -= tmp->slabTimeout.tv_sec * 1000000;
104983827f40a2d97261528087331b0bee6ce2cf27c5root
105083827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->checkInterval.tv_usec = checkIntervalMsec * 1000;
105183827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->checkInterval.tv_sec = tmp->checkInterval.tv_usec / 1000000;
105283827f40a2d97261528087331b0bee6ce2cf27c5root    tmp->checkInterval.tv_usec -= tmp->checkInterval.tv_sec * 1000000;
105383827f40a2d97261528087331b0bee6ce2cf27c5root
105483827f40a2d97261528087331b0bee6ce2cf27c5root    gettimeofday(&tmp->nextCheck, NULL);
105583827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmTimeAdd(&tmp->nextCheck, &tmp->checkInterval);
105683827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&tmp->timeoutList);
105783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&tmp->unCached);
105883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&tmp->cached);
105983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&tmp->mutex);
106083827f40a2d97261528087331b0bee6ce2cf27c5root
106183827f40a2d97261528087331b0bee6ce2cf27c5root    return tmp;
106283827f40a2d97261528087331b0bee6ce2cf27c5root}
106383827f40a2d97261528087331b0bee6ce2cf27c5root
106483827f40a2d97261528087331b0bee6ce2cf27c5rootvoid
106583827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabCacheFinish(struct _WsbmSlabCache *cache)
106683827f40a2d97261528087331b0bee6ce2cf27c5root{
106783827f40a2d97261528087331b0bee6ce2cf27c5root    struct timeval time;
106883827f40a2d97261528087331b0bee6ce2cf27c5root
106983827f40a2d97261528087331b0bee6ce2cf27c5root    time = cache->nextCheck;
107083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&cache->mutex);
107183827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmTimeAdd(&time, &cache->checkInterval);
107283827f40a2d97261528087331b0bee6ce2cf27c5root    wsbmFreeTimeoutKBOsLocked(cache, &time);
107383827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&cache->mutex);
107483827f40a2d97261528087331b0bee6ce2cf27c5root
107583827f40a2d97261528087331b0bee6ce2cf27c5root    assert(cache->timeoutList.next == &cache->timeoutList);
107683827f40a2d97261528087331b0bee6ce2cf27c5root    assert(cache->unCached.next == &cache->unCached);
107783827f40a2d97261528087331b0bee6ce2cf27c5root    assert(cache->cached.next == &cache->cached);
107883827f40a2d97261528087331b0bee6ce2cf27c5root
107983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_FREE(&cache->mutex);
108083827f40a2d97261528087331b0bee6ce2cf27c5root    free(cache);
108183827f40a2d97261528087331b0bee6ce2cf27c5root}
108283827f40a2d97261528087331b0bee6ce2cf27c5root
108383827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
108483827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmInitSizeHeader(struct _WsbmSlabPool *slabPool, uint32_t size,
108583827f40a2d97261528087331b0bee6ce2cf27c5root		   struct _WsbmSlabSizeHeader *header)
108683827f40a2d97261528087331b0bee6ce2cf27c5root{
108783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_INIT(&header->mutex);
108883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
108983827f40a2d97261528087331b0bee6ce2cf27c5root
109083827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&header->slabs);
109183827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&header->freeSlabs);
109283827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMINITLISTHEAD(&header->delayedBuffers);
109383827f40a2d97261528087331b0bee6ce2cf27c5root
109483827f40a2d97261528087331b0bee6ce2cf27c5root    header->numDelayed = 0;
109583827f40a2d97261528087331b0bee6ce2cf27c5root    header->slabPool = slabPool;
109683827f40a2d97261528087331b0bee6ce2cf27c5root    header->bufSize = size;
109783827f40a2d97261528087331b0bee6ce2cf27c5root
109883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
109983827f40a2d97261528087331b0bee6ce2cf27c5root}
110083827f40a2d97261528087331b0bee6ce2cf27c5root
110183827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
110283827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmFinishSizeHeader(struct _WsbmSlabSizeHeader *header)
110383827f40a2d97261528087331b0bee6ce2cf27c5root{
110483827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmListHead *list, *next;
110583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabBuffer *sBuf;
110683827f40a2d97261528087331b0bee6ce2cf27c5root
110783827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_LOCK(&header->mutex);
110883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBMLISTFOREACHSAFE(list, next, &header->delayedBuffers) {
110983827f40a2d97261528087331b0bee6ce2cf27c5root	sBuf = WSBMLISTENTRY(list, struct _WsbmSlabBuffer, head);
111083827f40a2d97261528087331b0bee6ce2cf27c5root
111183827f40a2d97261528087331b0bee6ce2cf27c5root	if (sBuf->fence) {
111283827f40a2d97261528087331b0bee6ce2cf27c5root	    (void)wsbmFenceFinish(sBuf->fence, sBuf->fenceType, 0);
111383827f40a2d97261528087331b0bee6ce2cf27c5root	    wsbmFenceUnreference(&sBuf->fence);
111483827f40a2d97261528087331b0bee6ce2cf27c5root	}
111583827f40a2d97261528087331b0bee6ce2cf27c5root	header->numDelayed--;
111683827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmSlabFreeBufferLocked(sBuf);
111783827f40a2d97261528087331b0bee6ce2cf27c5root    }
111883827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_UNLOCK(&header->mutex);
111983827f40a2d97261528087331b0bee6ce2cf27c5root    WSBM_MUTEX_FREE(&header->mutex);
112083827f40a2d97261528087331b0bee6ce2cf27c5root}
112183827f40a2d97261528087331b0bee6ce2cf27c5root
112283827f40a2d97261528087331b0bee6ce2cf27c5rootstatic void
112383827f40a2d97261528087331b0bee6ce2cf27c5rootpool_takedown(struct _WsbmBufferPool *pool)
112483827f40a2d97261528087331b0bee6ce2cf27c5root{
112583827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool = slabPoolFromPool(pool);
11263795b36d0c937666a5bddc352c781d5e0beec26bThierry Strudel    unsigned int i;
112783827f40a2d97261528087331b0bee6ce2cf27c5root
112883827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < slabPool->numBuckets; ++i) {
112983827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmFinishSizeHeader(&slabPool->headers[i]);
113083827f40a2d97261528087331b0bee6ce2cf27c5root    }
113183827f40a2d97261528087331b0bee6ce2cf27c5root
113283827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool->headers);
113383827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool->bucketSizes);
113483827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool);
113583827f40a2d97261528087331b0bee6ce2cf27c5root}
113683827f40a2d97261528087331b0bee6ce2cf27c5root
113783827f40a2d97261528087331b0bee6ce2cf27c5rootstruct _WsbmBufferPool *
113883827f40a2d97261528087331b0bee6ce2cf27c5rootwsbmSlabPoolInit(int fd,
113983827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t devOffset,
114083827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t placement,
114183827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t validMask,
114283827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t smallestSize,
114383827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t numSizes,
114483827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t desiredNumBuffers,
114583827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t maxSlabSize,
114683827f40a2d97261528087331b0bee6ce2cf27c5root		 uint32_t pageAlignment, struct _WsbmSlabCache *cache)
114783827f40a2d97261528087331b0bee6ce2cf27c5root{
114883827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmBufferPool *pool;
114983827f40a2d97261528087331b0bee6ce2cf27c5root    struct _WsbmSlabPool *slabPool;
115083827f40a2d97261528087331b0bee6ce2cf27c5root    uint32_t i;
115183827f40a2d97261528087331b0bee6ce2cf27c5root
115283827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool = calloc(1, sizeof(*slabPool));
115383827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slabPool)
115483827f40a2d97261528087331b0bee6ce2cf27c5root	return NULL;
115583827f40a2d97261528087331b0bee6ce2cf27c5root
115683827f40a2d97261528087331b0bee6ce2cf27c5root    pool = &slabPool->pool;
115783827f40a2d97261528087331b0bee6ce2cf27c5root
115883827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->bucketSizes = calloc(numSizes, sizeof(*slabPool->bucketSizes));
115983827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slabPool->bucketSizes)
116083827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err0;
116183827f40a2d97261528087331b0bee6ce2cf27c5root
116283827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->headers = calloc(numSizes, sizeof(*slabPool->headers));
116383827f40a2d97261528087331b0bee6ce2cf27c5root    if (!slabPool->headers)
116483827f40a2d97261528087331b0bee6ce2cf27c5root	goto out_err1;
116583827f40a2d97261528087331b0bee6ce2cf27c5root
116683827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->devOffset = devOffset;
116783827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->cache = cache;
116883827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->proposedPlacement = placement;
116983827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->validMask = validMask;
117083827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->numBuckets = numSizes;
117183827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->pageSize = getpagesize();
117283827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->pageAlignment = pageAlignment;
117383827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->maxSlabSize = maxSlabSize;
117483827f40a2d97261528087331b0bee6ce2cf27c5root    slabPool->desiredNumBuffers = desiredNumBuffers;
117583827f40a2d97261528087331b0bee6ce2cf27c5root
117683827f40a2d97261528087331b0bee6ce2cf27c5root    for (i = 0; i < slabPool->numBuckets; ++i) {
117783827f40a2d97261528087331b0bee6ce2cf27c5root	slabPool->bucketSizes[i] = (smallestSize << i);
117883827f40a2d97261528087331b0bee6ce2cf27c5root	wsbmInitSizeHeader(slabPool, slabPool->bucketSizes[i],
117983827f40a2d97261528087331b0bee6ce2cf27c5root			   &slabPool->headers[i]);
118083827f40a2d97261528087331b0bee6ce2cf27c5root    }
118183827f40a2d97261528087331b0bee6ce2cf27c5root
118283827f40a2d97261528087331b0bee6ce2cf27c5root    pool->fd = fd;
118383827f40a2d97261528087331b0bee6ce2cf27c5root    pool->map = &pool_map;
118483827f40a2d97261528087331b0bee6ce2cf27c5root    pool->unmap = &pool_unmap;
118583827f40a2d97261528087331b0bee6ce2cf27c5root    pool->destroy = &pool_destroy;
118683827f40a2d97261528087331b0bee6ce2cf27c5root    pool->offset = &pool_offset;
118783827f40a2d97261528087331b0bee6ce2cf27c5root    pool->poolOffset = &pool_poolOffset;
118883827f40a2d97261528087331b0bee6ce2cf27c5root    pool->size = &pool_size;
118983827f40a2d97261528087331b0bee6ce2cf27c5root    pool->create = &pool_create;
119083827f40a2d97261528087331b0bee6ce2cf27c5root    pool->fence = &pool_fence;
119183827f40a2d97261528087331b0bee6ce2cf27c5root    pool->kernel = &pool_kernel;
119283827f40a2d97261528087331b0bee6ce2cf27c5root    pool->validate = &pool_validate;
119383827f40a2d97261528087331b0bee6ce2cf27c5root    pool->unvalidate = &pool_unvalidate;
119483827f40a2d97261528087331b0bee6ce2cf27c5root    pool->waitIdle = &pool_waitIdle;
119583827f40a2d97261528087331b0bee6ce2cf27c5root    pool->takeDown = &pool_takedown;
119683827f40a2d97261528087331b0bee6ce2cf27c5root    pool->releasefromcpu = &pool_releaseFromCpu;
119783827f40a2d97261528087331b0bee6ce2cf27c5root    pool->syncforcpu = &pool_syncForCpu;
119883827f40a2d97261528087331b0bee6ce2cf27c5root
119983827f40a2d97261528087331b0bee6ce2cf27c5root    return pool;
120083827f40a2d97261528087331b0bee6ce2cf27c5root
120183827f40a2d97261528087331b0bee6ce2cf27c5root  out_err1:
120283827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool->bucketSizes);
120383827f40a2d97261528087331b0bee6ce2cf27c5root  out_err0:
120483827f40a2d97261528087331b0bee6ce2cf27c5root    free(slabPool);
120583827f40a2d97261528087331b0bee6ce2cf27c5root
120683827f40a2d97261528087331b0bee6ce2cf27c5root    return NULL;
120783827f40a2d97261528087331b0bee6ce2cf27c5root}
1208