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