Home | History | Annotate | Download | only in common
      1 /*
      2 // Copyright(c)2014 IntelCorporation
      3 //
      4 // LicensedundertheApacheLicense,Version2.0(the"License");
      5 // youmaynotusethisfileexceptincompliancewiththeLicense.
      6 // YoumayobtainacopyoftheLicenseat
      7 //
      8 // http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software
     11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS,
     12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
     13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand
     14 // limitationsundertheLicense.
     15 */
     16 
     17 #include <string.h>
     18 #include <wsbm_pool.h>
     19 #include <wsbm_driver.h>
     20 #include <wsbm_manager.h>
     21 #include <wsbm_util.h>
     22 #include <drm/ttm/ttm_placement.h>
     23 #include <linux/psb_drm.h>
     24 #include <xf86drm.h>
     25 #include <HwcTrace.h>
     26 
     27 struct _WsbmBufferPool * mainPool = NULL;
     28 
     29 struct PsbWsbmValidateNode
     30 {
     31     struct  _ValidateNode base;
     32     struct psb_validate_arg arg;
     33 };
     34 
     35 static inline uint32_t align_to(uint32_t arg, uint32_t align)
     36 {
     37     return ((arg + (align - 1)) & (~(align - 1)));
     38 }
     39 
     40 static struct _ValidateNode * pvrAlloc(struct _WsbmVNodeFuncs * func,
     41                                        int typeId)
     42 {
     43     CTRACE();
     44     if(typeId == 0) {
     45         struct PsbWsbmValidateNode * vNode = malloc(sizeof(*vNode));
     46         if(!vNode) {
     47             ETRACE("failed to allocate memory");
     48             return NULL;
     49         }
     50 
     51         vNode->base.func = func;
     52         vNode->base.type_id = 0;
     53         return &vNode->base;
     54     } else {
     55         struct _ValidateNode * node = malloc(sizeof(*node));
     56         if(!node) {
     57             ETRACE("failed to allocate node");
     58             return NULL;
     59         }
     60 
     61         node->func = func;
     62         node->type_id = 1;
     63         return node;
     64     }
     65 }
     66 
     67 static void pvrFree(struct _ValidateNode * node)
     68 {
     69     CTRACE();
     70     if(node->type_id == 0) {
     71         free(containerOf(node, struct PsbWsbmValidateNode, base));
     72     } else {
     73         free(node);
     74     }
     75 }
     76 
     77 static void pvrClear(struct _ValidateNode * node)
     78 {
     79     CTRACE();
     80     if(node->type_id == 0) {
     81         struct PsbWsbmValidateNode * vNode =
     82             containerOf(node, struct PsbWsbmValidateNode, base);
     83         memset(&vNode->arg.d.req, 0, sizeof(vNode->arg.d.req));
     84     }
     85 }
     86 
     87 static struct _WsbmVNodeFuncs vNodeFuncs = {
     88     .alloc  = pvrAlloc,
     89     .free   = pvrFree,
     90     .clear  = pvrClear,
     91 };
     92 
     93 void psbWsbmTakedown()
     94 {
     95     CTRACE();
     96 
     97     if (mainPool) {
     98         wsbmPoolTakeDown(mainPool);
     99         mainPool = NULL;
    100     }
    101 
    102     if (wsbmIsInitialized()) {
    103         wsbmTakedown();
    104     }
    105 }
    106 
    107 int psbWsbmInitialize(int drmFD)
    108 {
    109     union drm_psb_extension_arg arg;
    110     const char drmExt[] = "psb_ttm_placement_alphadrop";
    111     int ret = 0;
    112 
    113     CTRACE();
    114 
    115     if (drmFD <= 0) {
    116         ETRACE("invalid drm fd %d", drmFD);
    117         return drmFD;
    118     }
    119 
    120     /*init wsbm*/
    121     ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs);
    122     if (ret) {
    123         ETRACE("failed to initialize Wsbm, error code %d", ret);
    124         return ret;
    125     }
    126 
    127     VTRACE("DRM_PSB_EXTENSION %d", DRM_PSB_EXTENSION);
    128 
    129     /*get devOffset via drm IOCTL*/
    130     strncpy(arg.extension, drmExt, sizeof(drmExt));
    131 
    132     ret = drmCommandWriteRead(drmFD, 6/*DRM_PSB_EXTENSION*/, &arg, sizeof(arg));
    133     if(ret || !arg.rep.exists) {
    134         ETRACE("failed to get device offset, error code %d", ret);
    135         goto out;
    136     }
    137 
    138     VTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset);
    139 
    140     mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
    141     if(!mainPool) {
    142         ETRACE("failed to initialize TTM Pool");
    143         ret = -EINVAL;
    144         goto out;
    145     }
    146 
    147     VTRACE("Wsbm initialization succeeded. mainPool %p", mainPool);
    148 
    149     return 0;
    150 
    151 out:
    152     psbWsbmTakedown();
    153     return ret;
    154 }
    155 
    156 int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
    157 {
    158     struct _WsbmBufferObject * wsbmBuf = NULL;
    159     int ret = 0;
    160     int offset = 0;
    161 
    162     ATRACE("size %d", align_to(size, 4096));
    163 
    164     if(!buf || !user_pt) {
    165         ETRACE("invalid parameter");
    166         return -EINVAL;
    167     }
    168 
    169     VTRACE("mainPool %p", mainPool);
    170 
    171     ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
    172                         DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED |
    173                         WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED);
    174     if(ret) {
    175         ETRACE("wsbmGenBuffers failed with error code %d", ret);
    176         return ret;
    177     }
    178 
    179     ret = wsbmBODataUB(wsbmBuf,
    180                        align_to(size, 4096), NULL, NULL, 0,
    181                        user_pt, -1);
    182 
    183     if(ret) {
    184         ETRACE("wsbmBOData failed with error code %d", ret);
    185         /*FIXME: should I unreference this buffer here?*/
    186         return ret;
    187     }
    188 
    189     *buf = wsbmBuf;
    190 
    191     VTRACE("ttm UB buffer allocated. %p", *buf);
    192     return 0;
    193 }
    194 
    195 int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align, void ** buf)
    196 {
    197     struct _WsbmBufferObject * wsbmBuf = NULL;
    198     int ret = 0;
    199     int offset = 0;
    200 
    201     ATRACE("size %d", align_to(size, 4096));
    202 
    203     if(!buf) {
    204         ETRACE("invalid parameter");
    205         return -EINVAL;
    206     }
    207 
    208     VTRACE("mainPool %p", mainPool);
    209 
    210     ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
    211                         (WSBM_PL_FLAG_VRAM | WSBM_PL_FLAG_TT |
    212                          WSBM_PL_FLAG_SHARED | WSBM_PL_FLAG_NO_EVICT));
    213     if(ret) {
    214         ETRACE("wsbmGenBuffers failed with error code %d", ret);
    215         return ret;
    216     }
    217 
    218     ret = wsbmBOData(wsbmBuf, align_to(size, 4096), NULL, NULL, 0);
    219     if(ret) {
    220         ETRACE("wsbmBOData failed with error code %d", ret);
    221         /*FIXME: should I unreference this buffer here?*/
    222         return ret;
    223     }
    224 
    225     /* wsbmBOReference(wsbmBuf); */ /* no need to add reference */
    226 
    227     *buf = wsbmBuf;
    228 
    229     VTRACE("ttm buffer allocated. %p", *buf);
    230     return 0;
    231 }
    232 
    233 int psbWsbmWrapTTMBuffer(uint64_t handle, void **buf)
    234 {
    235     int ret = 0;
    236     struct _WsbmBufferObject *wsbmBuf;
    237 
    238     if (!buf) {
    239         ETRACE("invalid parameter");
    240         return -EINVAL;
    241     }
    242 
    243     ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, 0,
    244                         (WSBM_PL_FLAG_VRAM | WSBM_PL_FLAG_TT |
    245                         /*WSBM_PL_FLAG_NO_EVICT |*/ WSBM_PL_FLAG_SHARED));
    246 
    247     if (ret) {
    248         ETRACE("wsbmGenBuffers failed with error code %d", ret);
    249         return ret;
    250     }
    251 
    252     ret = wsbmBOSetReferenced(wsbmBuf, handle);
    253     if (ret) {
    254         ETRACE("wsbmBOSetReferenced failed with error code %d", ret);
    255         return ret;
    256     }
    257 
    258     *buf = (void *)wsbmBuf;
    259 
    260     VTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
    261     return 0;
    262 }
    263 
    264 int psbWsbmWrapTTMBuffer2(uint64_t handle, void **buf)
    265 {
    266     int ret = 0;
    267     struct _WsbmBufferObject *wsbmBuf;
    268 
    269     if (!buf) {
    270         ETRACE("invalid parameter");
    271         return -EINVAL;
    272     }
    273 
    274     ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, 4096,
    275             (WSBM_PL_FLAG_SHARED | DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_UNCACHED));
    276 
    277     if (ret) {
    278         ETRACE("wsbmGenBuffers failed with error code %d", ret);
    279         return ret;
    280     }
    281 
    282     *buf = (void *)wsbmBuf;
    283 
    284     VTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
    285     return 0;
    286 }
    287 
    288 
    289 int psbWsbmCreateFromUB(void *buf, uint32_t size, void *vaddr)
    290 {
    291     int ret = 0;
    292     struct _WsbmBufferObject *wsbmBuf;
    293 
    294     if (!buf || !vaddr) {
    295         ETRACE("invalid parameter");
    296         return -EINVAL;
    297     }
    298 
    299     wsbmBuf = (struct _WsbmBufferObject *)buf;
    300     ret = wsbmBODataUB(wsbmBuf, size, NULL, NULL, 0, vaddr, -1);
    301     if (ret) {
    302         ETRACE("wsbmBODataUB failed with error code %d", ret);
    303         return ret;
    304     }
    305 
    306     return 0;
    307 }
    308 
    309 int psbWsbmUnReference(void *buf)
    310 {
    311     struct _WsbmBufferObject *wsbmBuf;
    312 
    313     if (!buf) {
    314         ETRACE("invalid parameter");
    315         return -EINVAL;
    316     }
    317 
    318     wsbmBuf = (struct _WsbmBufferObject *)buf;
    319 
    320     wsbmBOUnreference(&wsbmBuf);
    321 
    322     return 0;
    323 }
    324 
    325 int psbWsbmDestroyTTMBuffer(void * buf)
    326 {
    327     CTRACE();
    328 
    329     if(!buf) {
    330         ETRACE("invalid ttm buffer");
    331         return -EINVAL;
    332     }
    333 
    334     /*FIXME: should I unmap this buffer object first?*/
    335     wsbmBOUnmap((struct _WsbmBufferObject *)buf);
    336 
    337     wsbmBOUnreference((struct _WsbmBufferObject **)&buf);
    338 
    339     XTRACE();
    340 
    341     return 0;
    342 }
    343 
    344 void * psbWsbmGetCPUAddress(void * buf)
    345 {
    346     if(!buf) {
    347         ETRACE("invalid ttm buffer");
    348         return NULL;
    349     }
    350 
    351     VTRACE("buffer object %p", buf);
    352 
    353     void * address = wsbmBOMap((struct _WsbmBufferObject *)buf,
    354                                 WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
    355     if(!address) {
    356         ETRACE("failed to map buffer object");
    357         return NULL;
    358     }
    359 
    360     VTRACE("mapped successfully. %p, size %ld",
    361         address, wsbmBOSize((struct _WsbmBufferObject *)buf));
    362 
    363     return address;
    364 }
    365 
    366 uint32_t psbWsbmGetGttOffset(void * buf)
    367 {
    368     if(!buf) {
    369         ETRACE("invalid ttm buffer");
    370         return 0;
    371     }
    372 
    373     VTRACE("buffer object %p", buf);
    374 
    375     uint32_t offset =
    376         wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000;
    377 
    378     VTRACE("offset %#x", offset >> 12);
    379 
    380     return offset >> 12;
    381 }
    382 
    383 uint32_t psbWsbmGetKBufHandle(void *buf)
    384 {
    385     if (!buf) {
    386         ETRACE("invalid ttm buffer");
    387         return 0;
    388     }
    389 
    390     return (wsbmKBufHandle(wsbmKBuf((struct _WsbmBufferObject *)buf)));
    391 }
    392 
    393 uint32_t psbWsbmWaitIdle(void *buf)
    394 {
    395     if (!buf) {
    396         ETRACE("invalid ttm buffer");
    397         return -EINVAL;
    398     }
    399 
    400     wsbmBOWaitIdle(buf, 0);
    401     return 0;
    402 }
    403