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     unsigned int ioctl_offset = arg.rep.driver_ioctl_offset;
    140     ILOGTRACE("ioctl offset %#x", ioctl_offset);
    141 
    142     mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
    143     if(!mainPool) {
    144         ELOGTRACE("failed to initialize TTM Pool");
    145         ret = -EINVAL;
    146         goto out;
    147     }
    148 
    149     VLOGTRACE("Wsbm initialization succeeded. mainPool %p", mainPool);
    150 
    151     return 0;
    152 
    153 out:
    154     psbWsbmTakedown();
    155     return ret;
    156 }
    157 
    158 int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
    159 {
    160     struct _WsbmBufferObject * wsbmBuf = NULL;
    161     int ret = 0;
    162 
    163     ALOGTRACE("size %d", align_to(size, 4096));
    164 
    165     if(!buf || !user_pt) {
    166         ELOGTRACE("invalid parameter");
    167         return -EINVAL;
    168     }
    169 
    170     VLOGTRACE("mainPool %p", mainPool);
    171 
    172     ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
    173                         DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED |
    174                         WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED);
    175     if(ret) {
    176         ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
    177         return ret;
    178     }
    179 
    180     ret = wsbmBODataUB(wsbmBuf,
    181                        align_to(size, 4096), NULL, NULL, 0,
    182                        user_pt, -1);
    183 
    184     if(ret) {
    185         ELOGTRACE("wsbmBOData failed with error code %d", ret);
    186         /*FIXME: should I unreference this buffer here?*/
    187         return ret;
    188     }
    189 
    190     *buf = wsbmBuf;
    191 
    192     VLOGTRACE("ttm UB buffer allocated. %p", *buf);
    193     return 0;
    194 }
    195 
    196 int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align, void ** buf)
    197 {
    198     struct _WsbmBufferObject * wsbmBuf = NULL;
    199     int ret = 0;
    200 
    201     ALOGTRACE("size %d", align_to(size, 4096));
    202 
    203     if(!buf) {
    204         ELOGTRACE("invalid parameter");
    205         return -EINVAL;
    206     }
    207 
    208     VLOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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     VLOGTRACE("ttm buffer allocated. %p", *buf);
    230     return 0;
    231 }
    232 
    233 int psbWsbmWrapTTMBuffer(uint32_t handle, void **buf)
    234 {
    235     int ret = 0;
    236     struct _WsbmBufferObject *wsbmBuf;
    237 
    238     if (!buf) {
    239         ELOGTRACE("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         ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
    249         return ret;
    250     }
    251 
    252     ret = wsbmBOSetReferenced(wsbmBuf, handle);
    253     if (ret) {
    254         ELOGTRACE("wsbmBOSetReferenced failed with error code %d", ret);
    255         return ret;
    256     }
    257 
    258     *buf = (void *)wsbmBuf;
    259 
    260     VLOGTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
    261     return 0;
    262 }
    263 
    264 int psbWsbmWrapTTMBuffer2(uint32_t handle, void **buf)
    265 {
    266     int ret = 0;
    267     struct _WsbmBufferObject *wsbmBuf;
    268 
    269     if (!buf) {
    270         ELOGTRACE("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         ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
    279         return ret;
    280     }
    281 
    282     *buf = (void *)wsbmBuf;
    283 
    284     VLOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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         ELOGTRACE("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     XLOGTRACE();
    340 
    341     return 0;
    342 }
    343 
    344 void * psbWsbmGetCPUAddress(void * buf)
    345 {
    346     if(!buf) {
    347         ELOGTRACE("invalid ttm buffer");
    348         return NULL;
    349     }
    350 
    351     VLOGTRACE("buffer object %p", buf);
    352 
    353     void * address = wsbmBOMap((struct _WsbmBufferObject *)buf,
    354                                 WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
    355     if(!address) {
    356         ELOGTRACE("failed to map buffer object");
    357         return NULL;
    358     }
    359 
    360     unsigned long buf_size = wsbmBOSize((struct _WsbmBufferObject *)buf);
    361     VLOGTRACE("mapped successfully. %p, size %ld",
    362         address, buf_size);
    363 
    364     return address;
    365 }
    366 
    367 uint32_t psbWsbmGetGttOffset(void * buf)
    368 {
    369     if(!buf) {
    370         ELOGTRACE("invalid ttm buffer");
    371         return 0;
    372     }
    373 
    374     VLOGTRACE("buffer object %p", buf);
    375 
    376     uint32_t offset =
    377         wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000;
    378 
    379     uint32_t offset_tmp = offset >> 12;
    380     VLOGTRACE("offset %#x", offset_tmp);
    381 
    382     return offset >> 12;
    383 }
    384 
    385 uint32_t psbWsbmGetKBufHandle(void *buf)
    386 {
    387     if (!buf) {
    388         ELOGTRACE("invalid ttm buffer");
    389         return 0;
    390     }
    391 
    392     return (wsbmKBufHandle(wsbmKBuf((struct _WsbmBufferObject *)buf)));
    393 }
    394 
    395 uint32_t psbWsbmWaitIdle(void *buf)
    396 {
    397     if (!buf) {
    398         ELOGTRACE("invalid ttm buffer");
    399         return -EINVAL;
    400     }
    401 
    402     wsbmBOWaitIdle(buf, 0);
    403     return 0;
    404 }
    405