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 <wsbm_pool.h>
     18 #include <wsbm_driver.h>
     19 #include <wsbm_manager.h>
     20 #include <wsbm_util.h>
     21 #include <drm/ttm/ttm_placement.h>
     22 #include <linux/psb_drm.h>
     23 #include <xf86drm.h>
     24 #include <common/utils/HwcTrace.h>
     25 
     26 struct _WsbmBufferPool * mainPool = NULL;
     27 
     28 struct PsbWsbmValidateNode
     29 {
     30     struct  _ValidateNode base;
     31     struct psb_validate_arg arg;
     32 };
     33 
     34 static inline uint32_t align_to(uint32_t arg, uint32_t align)
     35 {
     36     return ((arg + (align - 1)) & (~(align - 1)));
     37 }
     38 
     39 static struct _ValidateNode * pvrAlloc(struct _WsbmVNodeFuncs * func,
     40                                        int typeId)
     41 {
     42     CTRACE();
     43     if(typeId == 0) {
     44         struct PsbWsbmValidateNode * vNode = malloc(sizeof(*vNode));
     45         if(!vNode) {
     46             ELOGTRACE("failed to allocate memory");
     47             return NULL;
     48         }
     49 
     50         vNode->base.func = func;
     51         vNode->base.type_id = 0;
     52         return &vNode->base;
     53     } else {
     54         struct _ValidateNode * node = malloc(sizeof(*node));
     55         if(!node) {
     56             ELOGTRACE("failed to allocate node");
     57             return NULL;
     58         }
     59 
     60         node->func = func;
     61         node->type_id = 1;
     62         return node;
     63     }
     64 }
     65 
     66 static void pvrFree(struct _ValidateNode * node)
     67 {
     68     CTRACE();
     69     if(node->type_id == 0) {
     70         free(containerOf(node, struct PsbWsbmValidateNode, base));
     71     } else {
     72         free(node);
     73     }
     74 }
     75 
     76 static void pvrClear(struct _ValidateNode * node)
     77 {
     78     CTRACE();
     79     if(node->type_id == 0) {
     80         struct PsbWsbmValidateNode * vNode =
     81             containerOf(node, struct PsbWsbmValidateNode, base);
     82         memset(&vNode->arg.d.req, 0, sizeof(vNode->arg.d.req));
     83     }
     84 }
     85 
     86 static struct _WsbmVNodeFuncs vNodeFuncs = {
     87     .alloc  = pvrAlloc,
     88     .free   = pvrFree,
     89     .clear  = pvrClear,
     90 };
     91 
     92 void psbWsbmTakedown()
     93 {
     94     CTRACE();
     95 
     96     if (mainPool) {
     97         wsbmPoolTakeDown(mainPool);
     98         mainPool = NULL;
     99     }
    100 
    101     if (wsbmIsInitialized()) {
    102         wsbmTakedown();
    103     }
    104 }
    105 
    106 int psbWsbmInitialize(int drmFD)
    107 {
    108     union drm_psb_extension_arg arg;
    109     const char drmExt[] = "psb_ttm_placement_alphadrop";
    110     int ret = 0;
    111 
    112     CTRACE();
    113 
    114     if (drmFD <= 0) {
    115         ELOGTRACE("invalid drm fd %d", drmFD);
    116         return drmFD;
    117     }
    118 
    119     /*init wsbm*/
    120     ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs);
    121     if (ret) {
    122         ELOGTRACE("failed to initialize Wsbm, error code %d", ret);
    123         return ret;
    124     }
    125 
    126     VLOGTRACE("DRM_PSB_EXTENSION %d", DRM_PSB_EXTENSION);
    127 
    128     /*get devOffset via drm IOCTL*/
    129     strncpy(arg.extension, drmExt, sizeof(drmExt));
    130 
    131     ret = drmCommandWriteRead(drmFD, 6/*DRM_PSB_EXTENSION*/, &arg, sizeof(arg));
    132     if(ret || !arg.rep.exists) {
    133         ELOGTRACE("failed to get device offset, error code %d", ret);
    134         goto out;
    135     }
    136 
    137     VLOGTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset);
    138 
    139     mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
    140     if(!mainPool) {
    141         ELOGTRACE("failed to initialize TTM Pool");
    142         ret = -EINVAL;
    143         goto out;
    144     }
    145 
    146     VLOGTRACE("Wsbm initialization succeeded. mainPool %p", mainPool);
    147 
    148     return 0;
    149 
    150 out:
    151     psbWsbmTakedown();
    152     return ret;
    153 }
    154 
    155 int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
    156 {
    157     struct _WsbmBufferObject * wsbmBuf = NULL;
    158     int ret = 0;
    159     int offset = 0;
    160 
    161     ALOGTRACE("size %d", align_to(size, 4096));
    162 
    163     if(!buf || !user_pt) {
    164         ELOGTRACE("invalid parameter");
    165         return -EINVAL;
    166     }
    167 
    168     VLOGTRACE("mainPool %p", mainPool);
    169 
    170     ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
    171                         DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED |
    172                         WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED);
    173     if(ret) {
    174         ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
    175         return ret;
    176     }
    177 
    178     ret = wsbmBODataUB(wsbmBuf,
    179                        align_to(size, 4096), NULL, NULL, 0,
    180                        user_pt);
    181 
    182     if(ret) {
    183         ELOGTRACE("wsbmBOData failed with error code %d", ret);
    184         /*FIXME: should I unreference this buffer here?*/
    185         return ret;
    186     }
    187 
    188     *buf = wsbmBuf;
    189 
    190     VLOGTRACE("ttm UB buffer allocated. %p", *buf);
    191     return 0;
    192 }
    193 
    194 int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align, void ** buf)
    195 {
    196     struct _WsbmBufferObject * wsbmBuf = NULL;
    197     int ret = 0;
    198     int offset = 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);
    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